| author | |
| committer | |
| log | 2dcf1a239250e60ec9d8865e16528049074ec4b0 |
| tree | b4aa4cc4c5e087ef72bf6e74dfd1a0c272a255c1 |
| parent | 7a8f391b0fa397eea4a9602a0132e0247d0f67b7 |
| parent | 9753e875453ceeb6f3683b434a7492e20b639d36 |
| signature | Commit is signed but in an unrecognized format. |
133 files changed, 11458 insertions(+), 4956 deletions(-)
.builds/freebsd.yml+1-1| ... | ... | @@ -4,7 +4,7 @@ packages: |
| 4 | 4 | - ninja |
| 5 | 5 | - llvm70 |
| 6 | 6 | sources: |
| 7 | - https://github.com/ziglang/zig.git | |
| 7 | - https://github.com/ziglang/zig | |
| 8 | 8 | tasks: |
| 9 | 9 | - build: | |
| 10 | 10 | cd zig && mkdir build && cd build |
.gitignore+3-3| ... | ... | @@ -10,6 +10,6 @@ |
| 10 | 10 | # -andrewrk |
| 11 | 11 | |
| 12 | 12 | zig-cache/ |
| 13 | build/ | |
| 14 | build-*/ | |
| 15 | docgen_tmp/ | |
| 13 | /build/ | |
| 14 | /build-*/ | |
| 15 | /docgen_tmp/ |
CMakeLists.txt+17| ... | ... | @@ -417,6 +417,7 @@ set(ZIG_SOURCES |
| 417 | 417 | "${CMAKE_SOURCE_DIR}/src/error.cpp" |
| 418 | 418 | "${CMAKE_SOURCE_DIR}/src/ir.cpp" |
| 419 | 419 | "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" |
| 420 | "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" | |
| 420 | 421 | "${CMAKE_SOURCE_DIR}/src/link.cpp" |
| 421 | 422 | "${CMAKE_SOURCE_DIR}/src/main.cpp" |
| 422 | 423 | "${CMAKE_SOURCE_DIR}/src/os.cpp" |
| ... | ... | @@ -432,6 +433,10 @@ set(BLAKE_SOURCES |
| 432 | 433 | ) |
| 433 | 434 | set(ZIG_CPP_SOURCES |
| 434 | 435 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" |
| 436 | "${CMAKE_SOURCE_DIR}/src/zig_clang.cpp" | |
| 437 | "${CMAKE_SOURCE_DIR}/src/zig_clang_driver.cpp" | |
| 438 | "${CMAKE_SOURCE_DIR}/src/zig_clang_cc1_main.cpp" | |
| 439 | "${CMAKE_SOURCE_DIR}/src/zig_clang_cc1as_main.cpp" | |
| 435 | 440 | "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp" |
| 436 | 441 | ) |
| 437 | 442 | |
| ... | ... | @@ -446,10 +451,12 @@ set(ZIG_STD_FILES |
| 446 | 451 | "buf_set.zig" |
| 447 | 452 | "buffer.zig" |
| 448 | 453 | "build.zig" |
| 454 | "build/fmt.zig" | |
| 449 | 455 | "c/darwin.zig" |
| 450 | 456 | "c/freebsd.zig" |
| 451 | 457 | "c/index.zig" |
| 452 | 458 | "c/linux.zig" |
| 459 | "c/netbsd.zig" | |
| 453 | 460 | "c/windows.zig" |
| 454 | 461 | "coff.zig" |
| 455 | 462 | "crypto/blake2.zig" |
| ... | ... | @@ -485,6 +492,7 @@ set(ZIG_STD_FILES |
| 485 | 492 | "fmt/errol/index.zig" |
| 486 | 493 | "fmt/errol/lookup.zig" |
| 487 | 494 | "fmt/index.zig" |
| 495 | "fmt/parse_float.zig" | |
| 488 | 496 | "hash/adler.zig" |
| 489 | 497 | "hash/crc.zig" |
| 490 | 498 | "hash/fnv.zig" |
| ... | ... | @@ -589,6 +597,8 @@ set(ZIG_STD_FILES |
| 589 | 597 | "os/linux/index.zig" |
| 590 | 598 | "os/linux/vdso.zig" |
| 591 | 599 | "os/linux/x86_64.zig" |
| 600 | "os/netbsd/errno.zig" | |
| 601 | "os/netbsd/index.zig" | |
| 592 | 602 | "os/path.zig" |
| 593 | 603 | "os/time.zig" |
| 594 | 604 | "os/uefi.zig" |
| ... | ... | @@ -603,6 +613,7 @@ set(ZIG_STD_FILES |
| 603 | 613 | "os/windows/util.zig" |
| 604 | 614 | "os/zen.zig" |
| 605 | 615 | "pdb.zig" |
| 616 | "priority_queue.zig" | |
| 606 | 617 | "rand/index.zig" |
| 607 | 618 | "rand/ziggurat.zig" |
| 608 | 619 | "segmented_list.zig" |
| ... | ... | @@ -611,6 +622,7 @@ set(ZIG_STD_FILES |
| 611 | 622 | "special/bootstrap_lib.zig" |
| 612 | 623 | "special/build_runner.zig" |
| 613 | 624 | "special/builtin.zig" |
| 625 | "special/compiler_rt/addXf3.zig" | |
| 614 | 626 | "special/compiler_rt/aulldiv.zig" |
| 615 | 627 | "special/compiler_rt/aullrem.zig" |
| 616 | 628 | "special/compiler_rt/comparetf2.zig" |
| ... | ... | @@ -653,6 +665,7 @@ set(ZIG_STD_FILES |
| 653 | 665 | "special/compiler_rt/udivmodti4.zig" |
| 654 | 666 | "special/compiler_rt/udivti3.zig" |
| 655 | 667 | "special/compiler_rt/umodti3.zig" |
| 668 | "special/fmt_runner.zig" | |
| 656 | 669 | "special/init-exe/build.zig" |
| 657 | 670 | "special/init-exe/src/main.zig" |
| 658 | 671 | "special/init-lib/build.zig" |
| ... | ... | @@ -906,3 +919,7 @@ foreach(file ${ZIG_STD_FILES}) |
| 906 | 919 | get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY) |
| 907 | 920 | install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}") |
| 908 | 921 | endforeach() |
| 922 | ||
| 923 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") | |
| 924 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") | |
| 925 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") |
README.md+40-22| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | A programming language designed for robustness, optimality, and |
| 4 | 4 | clarity. |
| 5 | 5 | |
| 6 | [ziglang.org](https://ziglang.org) | |
| 6 | [Download & Documentation](https://ziglang.org/download/) | |
| 7 | 7 | |
| 8 | 8 | ## Feature Highlights |
| 9 | 9 | |
| ... | ... | @@ -77,36 +77,54 @@ clarity. |
| 77 | 77 | - what sizes are the C integer types |
| 78 | 78 | - C ABI calling convention for this target |
| 79 | 79 | - bootstrap code and default panic handler |
| 80 | * `zig targets` is guaranteed to include this target. | |
| 80 | 81 | |
| 81 | 82 | #### Tier 4 Support |
| 82 | 83 | |
| 83 | 84 | * Support for these targets is entirely experimental. |
| 84 | 85 | * LLVM may have the target as an experimental target, which means that you |
| 85 | 86 | need to use Zig-provided binaries for the target to be available, or |
| 86 | build LLVM from source with special configure flags. | |
| 87 | build LLVM from source with special configure flags. `zig targets` will | |
| 88 | display the target if it is available. | |
| 89 | * This target may be considered deprecated by an official party, | |
| 90 | [such as macosx/i386](https://support.apple.com/en-us/HT208436) in which | |
| 91 | case this target will remain forever stuck in Tier 4. | |
| 92 | * This target may only support `--emit asm` and cannot emit object files. | |
| 87 | 93 | |
| 88 | 94 | #### Support Table |
| 89 | 95 | |
| 90 | | | freestanding | linux | macosx | windows | freebsd | UEFI | other | | |
| 91 | |--------|--------------|--------|--------|---------|---------|--------|--------| | |
| 92 | |x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 | | |
| 93 | |i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | | |
| 94 | |arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | |
| 95 | |arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | |
| 96 | |bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 97 | |hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 98 | |mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 99 | |powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 100 | |r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 101 | |amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 102 | |sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 103 | |s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 104 | |spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 105 | |lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | | |
| 106 | |wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | | |
| 107 | |wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | | |
| 108 | |riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | | |
| 109 | |riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | | |
| 96 | | | freestanding | linux | macosx | windows | freebsd | netbsd | UEFI | other | | |
| 97 | |-------------|--------------|--------|--------|---------|---------|------- | -------|--------| | |
| 98 | |x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | | |
| 99 | |i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | |
| 100 | |arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | |
| 101 | |arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | |
| 102 | |avr | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 103 | |bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 104 | |hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 105 | |mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 106 | |powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 107 | |amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 108 | |sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 109 | |s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 110 | |lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 | | |
| 111 | |wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | N/A | | |
| 112 | |wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | N/A | | |
| 113 | |riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 | | |
| 114 | |riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 | | |
| 115 | |xcore | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 116 | |nvptx | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 117 | |msp430 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 118 | |r600 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 119 | |arc | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 120 | |tce | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 121 | |le | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 122 | |amdil | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 123 | |hsail | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 124 | |spir | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 125 | |kalimba | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 126 | |shave | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 127 | |renderscript | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 | | |
| 110 | 128 | |
| 111 | 129 | ## Community |
| 112 | 130 |
build.zig+7-4| ... | ... | @@ -49,13 +49,14 @@ pub fn build(b: *Builder) !void { |
| 49 | 49 | .c_header_files = nextValue(&index, build_info), |
| 50 | 50 | .dia_guids_lib = nextValue(&index, build_info), |
| 51 | 51 | .llvm = undefined, |
| 52 | .no_rosegment = b.option(bool, "no-rosegment", "Workaround to enable valgrind builds") orelse false, | |
| 53 | 52 | }; |
| 54 | 53 | ctx.llvm = try findLLVM(b, ctx.llvm_config_exe); |
| 55 | 54 | |
| 56 | 55 | var test_stage2 = b.addTest("src-self-hosted/test.zig"); |
| 57 | 56 | test_stage2.setBuildMode(builtin.Mode.Debug); |
| 58 | 57 | |
| 58 | const fmt_build_zig = b.addFmt([][]const u8{"build.zig"}); | |
| 59 | ||
| 59 | 60 | var exe = b.addExecutable("zig", "src-self-hosted/main.zig"); |
| 60 | 61 | exe.setBuildMode(mode); |
| 61 | 62 | |
| ... | ... | @@ -107,6 +108,11 @@ pub fn build(b: *Builder) !void { |
| 107 | 108 | } |
| 108 | 109 | const modes = chosen_modes[0..chosen_mode_index]; |
| 109 | 110 | |
| 111 | // run stage1 `zig fmt` on this build.zig file just to make sure it works | |
| 112 | test_step.dependOn(&fmt_build_zig.step); | |
| 113 | const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); | |
| 114 | fmt_step.dependOn(&fmt_build_zig.step); | |
| 115 | ||
| 110 | 116 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes)); |
| 111 | 117 | |
| 112 | 118 | test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes)); |
| ... | ... | @@ -289,8 +295,6 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 { |
| 289 | 295 | } |
| 290 | 296 | |
| 291 | 297 | fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 292 | exe.setNoRoSegment(ctx.no_rosegment); | |
| 293 | ||
| 294 | 298 | exe.addIncludeDir("src"); |
| 295 | 299 | exe.addIncludeDir(ctx.cmake_binary_dir); |
| 296 | 300 | addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp"); |
| ... | ... | @@ -375,5 +379,4 @@ const Context = struct { |
| 375 | 379 | c_header_files: []const u8, |
| 376 | 380 | dia_guids_lib: []const u8, |
| 377 | 381 | llvm: LibraryDep, |
| 378 | no_rosegment: bool, | |
| 379 | 382 | }; |
cmake/Findclang.cmake+22| ... | ... | @@ -11,17 +11,28 @@ if(MSVC) |
| 11 | 11 | find_package(CLANG REQUIRED CONFIG) |
| 12 | 12 | |
| 13 | 13 | set(CLANG_LIBRARIES |
| 14 | clangFrontendTool | |
| 15 | clangCodeGen | |
| 14 | 16 | clangFrontend |
| 15 | 17 | clangDriver |
| 16 | 18 | clangSerialization |
| 17 | 19 | clangSema |
| 20 | clangStaticAnalyzerFrontend | |
| 21 | clangStaticAnalyzerCheckers | |
| 22 | clangStaticAnalyzerCore | |
| 18 | 23 | clangAnalysis |
| 24 | clangASTMatchers | |
| 19 | 25 | clangAST |
| 20 | 26 | clangParse |
| 21 | 27 | clangSema |
| 22 | 28 | clangBasic |
| 23 | 29 | clangEdit |
| 24 | 30 | clangLex |
| 31 | clangARCMigrate | |
| 32 | clangRewriteFrontend | |
| 33 | clangRewrite | |
| 34 | clangCrossTU | |
| 35 | clangIndex | |
| 25 | 36 | ) |
| 26 | 37 | |
| 27 | 38 | else() |
| ... | ... | @@ -50,17 +61,28 @@ else() |
| 50 | 61 | endif() |
| 51 | 62 | endmacro(FIND_AND_ADD_CLANG_LIB) |
| 52 | 63 | |
| 64 | FIND_AND_ADD_CLANG_LIB(clangFrontendTool) | |
| 65 | FIND_AND_ADD_CLANG_LIB(clangCodeGen) | |
| 53 | 66 | FIND_AND_ADD_CLANG_LIB(clangFrontend) |
| 54 | 67 | FIND_AND_ADD_CLANG_LIB(clangDriver) |
| 55 | 68 | FIND_AND_ADD_CLANG_LIB(clangSerialization) |
| 56 | 69 | FIND_AND_ADD_CLANG_LIB(clangSema) |
| 70 | FIND_AND_ADD_CLANG_LIB(clangStaticAnalyzerFrontend) | |
| 71 | FIND_AND_ADD_CLANG_LIB(clangStaticAnalyzerCheckers) | |
| 72 | FIND_AND_ADD_CLANG_LIB(clangStaticAnalyzerCore) | |
| 57 | 73 | FIND_AND_ADD_CLANG_LIB(clangAnalysis) |
| 74 | FIND_AND_ADD_CLANG_LIB(clangASTMatchers) | |
| 58 | 75 | FIND_AND_ADD_CLANG_LIB(clangAST) |
| 59 | 76 | FIND_AND_ADD_CLANG_LIB(clangParse) |
| 60 | 77 | FIND_AND_ADD_CLANG_LIB(clangSema) |
| 61 | 78 | FIND_AND_ADD_CLANG_LIB(clangBasic) |
| 62 | 79 | FIND_AND_ADD_CLANG_LIB(clangEdit) |
| 63 | 80 | FIND_AND_ADD_CLANG_LIB(clangLex) |
| 81 | FIND_AND_ADD_CLANG_LIB(clangARCMigrate) | |
| 82 | FIND_AND_ADD_CLANG_LIB(clangRewriteFrontend) | |
| 83 | FIND_AND_ADD_CLANG_LIB(clangRewrite) | |
| 84 | FIND_AND_ADD_CLANG_LIB(clangCrossTU) | |
| 85 | FIND_AND_ADD_CLANG_LIB(clangIndex) | |
| 64 | 86 | endif() |
| 65 | 87 | |
| 66 | 88 | include(FindPackageHandleStandardArgs) |
doc/docgen.zig+2-8| ... | ... | @@ -916,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 916 | 916 | std.zig.Token.Id.AngleBracketAngleBracketRightEqual, |
| 917 | 917 | std.zig.Token.Id.Tilde, |
| 918 | 918 | std.zig.Token.Id.BracketStarBracket, |
| 919 | std.zig.Token.Id.BracketStarCBracket, | |
| 919 | 920 | => try writeEscaped(out, src[token.start..token.end]), |
| 920 | 921 | |
| 921 | 922 | std.zig.Token.Id.Invalid => return parseError( |
| ... | ... | @@ -1104,14 +1105,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1104 | 1105 | }, |
| 1105 | 1106 | } |
| 1106 | 1107 | if (code.target_windows) { |
| 1107 | try test_args.appendSlice([][]const u8{ | |
| 1108 | "--target-os", | |
| 1109 | "windows", | |
| 1110 | "--target-arch", | |
| 1111 | "x86_64", | |
| 1112 | "--target-environ", | |
| 1113 | "msvc", | |
| 1114 | }); | |
| 1108 | try test_args.appendSlice([][]const u8{ "-target", "x86_64-windows" }); | |
| 1115 | 1109 | } |
| 1116 | 1110 | const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed"); |
| 1117 | 1111 | const escaped_stderr = try escapeHtml(allocator, result.stderr); |
doc/langref.html.in+541-142| ... | ... | @@ -8,13 +8,7 @@ |
| 8 | 8 | body{ |
| 9 | 9 | background-color:#111; |
| 10 | 10 | color: #bbb; |
| 11 | font-family: system-ui, | |
| 12 | /* Fallbacks for browsers that don't support system-ui */ | |
| 13 | /* https://caniuse.com/#search=system-ui */ | |
| 14 | -apple-system, /* iOS and macOS */ | |
| 15 | Roboto, /* Android */ | |
| 16 | "Segoe UI", /* Windows */ | |
| 17 | sans-serif; | |
| 11 | font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif; | |
| 18 | 12 | } |
| 19 | 13 | a { |
| 20 | 14 | color: #88f; |
| ... | ... | @@ -243,8 +237,9 @@ const Timestamp = struct { |
| 243 | 237 | {#header_close#} |
| 244 | 238 | {#header_open|Values#} |
| 245 | 239 | {#code_begin|exe|values#} |
| 246 | const std = @import("std"); | |
| 240 | // Top-level declarations are order-independent: | |
| 247 | 241 | const warn = std.debug.warn; |
| 242 | const std = @import("std"); | |
| 248 | 243 | const os = std.os; |
| 249 | 244 | const assert = std.debug.assert; |
| 250 | 245 | |
| ... | ... | @@ -262,7 +257,7 @@ pub fn main() void { |
| 262 | 257 | true and false, |
| 263 | 258 | true or false, |
| 264 | 259 | !true); |
| 265 | ||
| 260 | ||
| 266 | 261 | // optional |
| 267 | 262 | var optional_value: ?[]const u8 = null; |
| 268 | 263 | assert(optional_value == null); |
| ... | ... | @@ -281,7 +276,7 @@ pub fn main() void { |
| 281 | 276 | |
| 282 | 277 | warn("\nerror union 1\ntype: {}\nvalue: {}\n", |
| 283 | 278 | @typeName(@typeOf(number_or_error)), number_or_error); |
| 284 | ||
| 279 | ||
| 285 | 280 | number_or_error = 1234; |
| 286 | 281 | |
| 287 | 282 | warn("\nerror union 2\ntype: {}\nvalue: {}\n", |
| ... | ... | @@ -706,15 +701,21 @@ fn divide(a: i32, b: i32) i32 { |
| 706 | 701 | {#code_end#} |
| 707 | 702 | <p> |
| 708 | 703 | In this function, values {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are known only at runtime, |
| 709 | and thus this division operation is vulnerable to both integer overflow and | |
| 710 | division by zero. | |
| 704 | and thus this division operation is vulnerable to both {#link|Integer Overflow#} and | |
| 705 | {#link|Division by Zero#}. | |
| 711 | 706 | </p> |
| 712 | 707 | <p> |
| 713 | 708 | Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on |
| 714 | 709 | integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and |
| 715 | 710 | {#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets. |
| 716 | 711 | </p> |
| 717 | {#see_also|Integer Overflow|Division by Zero|Wrapping Operations#} | |
| 712 | <p> | |
| 713 | Zig supports arbitrary bit-width integers, referenced by using | |
| 714 | an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier | |
| 715 | {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an | |
| 716 | integer type is {#syntax#}65535{#endsyntax#}. | |
| 717 | </p> | |
| 718 | {#see_also|Wrapping Operations#} | |
| 718 | 719 | {#header_close#} |
| 719 | 720 | {#header_close#} |
| 720 | 721 | {#header_open|Floats#} |
| ... | ... | @@ -1651,7 +1652,7 @@ test "pointer slicing" { |
| 1651 | 1652 | assert(array[3] == 5); |
| 1652 | 1653 | } |
| 1653 | 1654 | {#code_end#} |
| 1654 | <p>Pointers work at compile-time too, as long as the code does not depend on | |
| 1655 | <p>Pointers work at compile-time too, as long as the code does not depend on | |
| 1655 | 1656 | an undefined memory layout:</p> |
| 1656 | 1657 | {#code_begin|test#} |
| 1657 | 1658 | const assert = @import("std").debug.assert; |
| ... | ... | @@ -1694,7 +1695,7 @@ test "comptime @intToPtr" { |
| 1694 | 1695 | } |
| 1695 | 1696 | } |
| 1696 | 1697 | {#code_end#} |
| 1697 | {#see_also|Optional Pointers#} | |
| 1698 | {#see_also|Optional Pointers|@intToPtr|@ptrToInt#} | |
| 1698 | 1699 | {#header_open|volatile#} |
| 1699 | 1700 | <p>Loads and stores are assumed to not have side effects. If a given load or store |
| 1700 | 1701 | should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}. |
| ... | ... | @@ -1823,7 +1824,9 @@ fn foo(bytes: []u8) u32 { |
| 1823 | 1824 | } |
| 1824 | 1825 | {#code_end#} |
| 1825 | 1826 | {#header_close#} |
| 1827 | {#see_also|C Pointers|Pointers to Zero Bit Types#} | |
| 1826 | 1828 | {#header_close#} |
| 1829 | ||
| 1827 | 1830 | {#header_open|Slices#} |
| 1828 | 1831 | {#code_begin|test_safety|index out of bounds#} |
| 1829 | 1832 | const assert = @import("std").debug.assert; |
| ... | ... | @@ -2043,14 +2046,211 @@ test "linked list" { |
| 2043 | 2046 | assert(list2.first.?.data == 1234); |
| 2044 | 2047 | } |
| 2045 | 2048 | {#code_end#} |
| 2049 | ||
| 2050 | {#header_open|extern struct#} | |
| 2051 | <p>An {#syntax#}extern struct{#endsyntax#} has in-memory layout guaranteed to match the | |
| 2052 | C ABI for the target.</p> | |
| 2053 | {#see_also|extern union|extern enum#} | |
| 2054 | {#header_close#} | |
| 2055 | ||
| 2046 | 2056 | {#header_open|packed struct#} |
| 2047 | <p>{#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout.</p> | |
| 2048 | <p>TODO bit fields</p> | |
| 2049 | <p>TODO alignment</p> | |
| 2050 | <p>TODO endianness</p> | |
| 2051 | <p>TODO @bitOffsetOf and @byteOffsetOf</p> | |
| 2052 | <p>TODO mention how volatile loads and stores of bit packed fields could be more efficient when | |
| 2053 | done by hand instead of with packed struct</p> | |
| 2057 | <p> | |
| 2058 | Unlike normal structs, {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout: | |
| 2059 | </p> | |
| 2060 | <ul> | |
| 2061 | <li>Fields remain in the order declared.</li> | |
| 2062 | <li>There is no padding between fields.</li> | |
| 2063 | <li>Zig supports arbitrary width {#link|Integers#} and although normally, integers with fewer | |
| 2064 | than 8 bits will still use 1 byte of memory, in packed structs, they use | |
| 2065 | exactly their bit width. | |
| 2066 | </li> | |
| 2067 | <li>{#syntax#}bool{#endsyntax#} fields use exactly 1 bit.</li> | |
| 2068 | <li>A {#link|packed enum#} field uses exactly the bit width of its integer tag type.</li> | |
| 2069 | <li>A {#link|packed union#} field uses exactly the bit width of the union field with | |
| 2070 | the largest bit width.</li> | |
| 2071 | <li>Non-byte-aligned fields are packed into the smallest possible | |
| 2072 | byte-aligned integers in accordance with the target endianness. | |
| 2073 | </li> | |
| 2074 | </ul> | |
| 2075 | <p> | |
| 2076 | This means that a {#syntax#}packed struct{#endsyntax#} can participate | |
| 2077 | in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory. | |
| 2078 | This even works at {#link|comptime#}: | |
| 2079 | </p> | |
| 2080 | {#code_begin|test#} | |
| 2081 | const std = @import("std"); | |
| 2082 | const builtin = @import("builtin"); | |
| 2083 | const assert = std.debug.assert; | |
| 2084 | ||
| 2085 | const Full = packed struct { | |
| 2086 | number: u16, | |
| 2087 | }; | |
| 2088 | const Divided = packed struct { | |
| 2089 | half1: u8, | |
| 2090 | quarter3: u4, | |
| 2091 | quarter4: u4, | |
| 2092 | }; | |
| 2093 | ||
| 2094 | test "@bitCast between packed structs" { | |
| 2095 | doTheTest(); | |
| 2096 | comptime doTheTest(); | |
| 2097 | } | |
| 2098 | ||
| 2099 | fn doTheTest() void { | |
| 2100 | assert(@sizeOf(Full) == 2); | |
| 2101 | assert(@sizeOf(Divided) == 2); | |
| 2102 | var full = Full{ .number = 0x1234 }; | |
| 2103 | var divided = @bitCast(Divided, full); | |
| 2104 | switch (builtin.endian) { | |
| 2105 | builtin.Endian.Big => { | |
| 2106 | assert(divided.half1 == 0x12); | |
| 2107 | assert(divided.quarter3 == 0x3); | |
| 2108 | assert(divided.quarter4 == 0x4); | |
| 2109 | }, | |
| 2110 | builtin.Endian.Little => { | |
| 2111 | assert(divided.half1 == 0x34); | |
| 2112 | assert(divided.quarter3 == 0x2); | |
| 2113 | assert(divided.quarter4 == 0x1); | |
| 2114 | }, | |
| 2115 | } | |
| 2116 | } | |
| 2117 | {#code_end#} | |
| 2118 | <p> | |
| 2119 | Zig allows the address to be taken of a non-byte-aligned field: | |
| 2120 | </p> | |
| 2121 | {#code_begin|test#} | |
| 2122 | const std = @import("std"); | |
| 2123 | const assert = std.debug.assert; | |
| 2124 | ||
| 2125 | const BitField = packed struct { | |
| 2126 | a: u3, | |
| 2127 | b: u3, | |
| 2128 | c: u2, | |
| 2129 | }; | |
| 2130 | ||
| 2131 | var foo = BitField{ | |
| 2132 | .a = 1, | |
| 2133 | .b = 2, | |
| 2134 | .c = 3, | |
| 2135 | }; | |
| 2136 | ||
| 2137 | test "pointer to non-byte-aligned field" { | |
| 2138 | const ptr = &foo.b; | |
| 2139 | assert(ptr.* == 2); | |
| 2140 | } | |
| 2141 | {#code_end#} | |
| 2142 | <p> | |
| 2143 | However, the pointer to a non-byte-aligned field has special properties and cannot | |
| 2144 | be passed when a normal pointer is expected: | |
| 2145 | </p> | |
| 2146 | {#code_begin|test_err|expected type#} | |
| 2147 | const std = @import("std"); | |
| 2148 | const assert = std.debug.assert; | |
| 2149 | ||
| 2150 | const BitField = packed struct { | |
| 2151 | a: u3, | |
| 2152 | b: u3, | |
| 2153 | c: u2, | |
| 2154 | }; | |
| 2155 | ||
| 2156 | var bit_field = BitField{ | |
| 2157 | .a = 1, | |
| 2158 | .b = 2, | |
| 2159 | .c = 3, | |
| 2160 | }; | |
| 2161 | ||
| 2162 | test "pointer to non-bit-aligned field" { | |
| 2163 | assert(bar(&bit_field.b) == 2); | |
| 2164 | } | |
| 2165 | ||
| 2166 | fn bar(x: *const u3) u3 { | |
| 2167 | return x.*; | |
| 2168 | } | |
| 2169 | {#code_end#} | |
| 2170 | <p> | |
| 2171 | In this case, the function {#syntax#}bar{#endsyntax#} cannot be called becuse the pointer | |
| 2172 | to the non-byte-aligned field mentions the bit offset, but the function expects a byte-aligned pointer. | |
| 2173 | </p> | |
| 2174 | <p> | |
| 2175 | Pointers to non-byte-aligned fields share the same address as the other fields within their host integer: | |
| 2176 | </p> | |
| 2177 | {#code_begin|test#} | |
| 2178 | const std = @import("std"); | |
| 2179 | const assert = std.debug.assert; | |
| 2180 | ||
| 2181 | const BitField = packed struct { | |
| 2182 | a: u3, | |
| 2183 | b: u3, | |
| 2184 | c: u2, | |
| 2185 | }; | |
| 2186 | ||
| 2187 | var bit_field = BitField{ | |
| 2188 | .a = 1, | |
| 2189 | .b = 2, | |
| 2190 | .c = 3, | |
| 2191 | }; | |
| 2192 | ||
| 2193 | test "pointer to non-bit-aligned field" { | |
| 2194 | assert(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.b)); | |
| 2195 | assert(@ptrToInt(&bit_field.a) == @ptrToInt(&bit_field.c)); | |
| 2196 | } | |
| 2197 | {#code_end#} | |
| 2198 | <p> | |
| 2199 | This can be observed with {#link|@bitOffsetOf#} and {#link|byteOffsetOf#}: | |
| 2200 | </p> | |
| 2201 | {#code_begin|test#} | |
| 2202 | const std = @import("std"); | |
| 2203 | const assert = std.debug.assert; | |
| 2204 | ||
| 2205 | const BitField = packed struct { | |
| 2206 | a: u3, | |
| 2207 | b: u3, | |
| 2208 | c: u2, | |
| 2209 | }; | |
| 2210 | ||
| 2211 | test "pointer to non-bit-aligned field" { | |
| 2212 | comptime { | |
| 2213 | assert(@bitOffsetOf(BitField, "a") == 0); | |
| 2214 | assert(@bitOffsetOf(BitField, "b") == 3); | |
| 2215 | assert(@bitOffsetOf(BitField, "c") == 6); | |
| 2216 | ||
| 2217 | assert(@byteOffsetOf(BitField, "a") == 0); | |
| 2218 | assert(@byteOffsetOf(BitField, "b") == 0); | |
| 2219 | assert(@byteOffsetOf(BitField, "c") == 0); | |
| 2220 | } | |
| 2221 | } | |
| 2222 | {#code_end#} | |
| 2223 | <p> | |
| 2224 | Packed structs have 1-byte alignment. However if you have an overaligned pointer to a packed struct, | |
| 2225 | Zig should correctly understand the alignment of fields. However there is | |
| 2226 | <a href="https://github.com/ziglang/zig/issues/1994">a bug</a>: | |
| 2227 | </p> | |
| 2228 | {#code_begin|test_err#} | |
| 2229 | const S = packed struct { | |
| 2230 | a: u32, | |
| 2231 | b: u32, | |
| 2232 | }; | |
| 2233 | test "overaligned pointer to packed struct" { | |
| 2234 | var foo: S align(4) = undefined; | |
| 2235 | const ptr: *align(4) S = &foo; | |
| 2236 | const ptr_to_b: *u32 = &ptr.b; | |
| 2237 | } | |
| 2238 | {#code_end#} | |
| 2239 | <p>When this bug is fixed, the above test in the documentation will unexpectedly pass, which will | |
| 2240 | cause the test suite to fail, notifying the bug fixer to update these docs. | |
| 2241 | </p> | |
| 2242 | <p> | |
| 2243 | It's also | |
| 2244 | <a href="https://github.com/ziglang/zig/issues/1512">planned to be able to set alignment of struct fields</a>. | |
| 2245 | </p> | |
| 2246 | <p> | |
| 2247 | Using packed structs with {#link|volatile#} is problematic, and may be a compile error in the future. | |
| 2248 | For details on this subscribe to | |
| 2249 | <a href="https://github.com/ziglang/zig/issues/1761">this issue</a>. | |
| 2250 | TODO update these docs with a recommendation on how to use packed structs with MMIO | |
| 2251 | (the use case for volatile packed structs) once this issue is resolved. | |
| 2252 | Don't worry, there will be a good solution for this use case in zig. | |
| 2253 | </p> | |
| 2054 | 2254 | {#header_close#} |
| 2055 | 2255 | {#header_open|struct Naming#} |
| 2056 | 2256 | <p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p> |
| ... | ... | @@ -2200,8 +2400,8 @@ export fn entry(foo: Foo) void { } |
| 2200 | 2400 | {#header_close#} |
| 2201 | 2401 | {#header_open|packed enum#} |
| 2202 | 2402 | <p>By default, the size of enums is not guaranteed.</p> |
| 2203 | <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the integer tag type | |
| 2204 | of the enum:</p> | |
| 2403 | <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the | |
| 2404 | integer tag type of the enum:</p> | |
| 2205 | 2405 | {#code_begin|test#} |
| 2206 | 2406 | const std = @import("std"); |
| 2207 | 2407 | |
| ... | ... | @@ -2214,131 +2414,179 @@ test "packed enum" { |
| 2214 | 2414 | std.debug.assert(@sizeOf(Number) == @sizeOf(u8)); |
| 2215 | 2415 | } |
| 2216 | 2416 | {#code_end#} |
| 2417 | <p>This makes the enum eligible to be in a {#link|packed struct#}.</p> | |
| 2217 | 2418 | {#header_close#} |
| 2218 | 2419 | {#see_also|@memberName|@memberCount|@tagName|@sizeOf#} |
| 2219 | 2420 | {#header_close#} |
| 2220 | 2421 | {#header_open|union#} |
| 2221 | {#code_begin|test|union#} | |
| 2222 | const assert = @import("std").debug.assert; | |
| 2223 | const mem = @import("std").mem; | |
| 2422 | <p> | |
| 2423 | A bare {#syntax#}union{#endsyntax#} defines a set of possible types that a value | |
| 2424 | can be as a list of fields. Only one field can be active at a time. | |
| 2425 | The in-memory representation of bare unions is not guaranteed. | |
| 2426 | Bare unions cannot be used to reinterpret memory. For that, use {#link|@ptrCast#}, | |
| 2427 | or use an {#link|extern union#} or a {#link|packed union#} which have | |
| 2428 | guaranteed in-memory layout. | |
| 2429 | {#link|Accessing the non-active field|Wrong Union Field Access#} is | |
| 2430 | safety-checked {#link|Undefined Behavior#}: | |
| 2431 | </p> | |
| 2432 | {#code_begin|test_err|inactive union field#} | |
| 2433 | const Payload = union { | |
| 2434 | Int: i64, | |
| 2435 | Float: f64, | |
| 2436 | Bool: bool, | |
| 2437 | }; | |
| 2438 | test "simple union" { | |
| 2439 | var payload = Payload{ .Int = 1234 }; | |
| 2440 | payload.Float = 12.34; | |
| 2441 | } | |
| 2442 | {#code_end#} | |
| 2443 | <p>You can activate another field by assigning the entire union:</p> | |
| 2444 | {#code_begin|test#} | |
| 2445 | const std = @import("std"); | |
| 2446 | const assert = std.debug.assert; | |
| 2224 | 2447 | |
| 2225 | // A union has only 1 active field at a time. | |
| 2226 | 2448 | const Payload = union { |
| 2227 | 2449 | Int: i64, |
| 2228 | 2450 | Float: f64, |
| 2229 | 2451 | Bool: bool, |
| 2230 | 2452 | }; |
| 2231 | 2453 | test "simple union" { |
| 2232 | var payload = Payload {.Int = 1234}; | |
| 2233 | // payload.Float = 12.34; // ERROR! field not active | |
| 2454 | var payload = Payload{ .Int = 1234 }; | |
| 2234 | 2455 | assert(payload.Int == 1234); |
| 2235 | // You can activate another field by assigning the entire union. | |
| 2236 | payload = Payload {.Float = 12.34}; | |
| 2456 | payload = Payload{ .Float = 12.34 }; | |
| 2237 | 2457 | assert(payload.Float == 12.34); |
| 2238 | 2458 | } |
| 2459 | {#code_end#} | |
| 2460 | <p> | |
| 2461 | In order to use {#link|switch#} with a union, it must be a {#link|Tagged union#}. | |
| 2462 | </p> | |
| 2463 | ||
| 2464 | {#header_open|Tagged union#} | |
| 2465 | <p>Unions can be declared with an enum tag type. | |
| 2466 | This turns the union into a <em>tagged</em> union, which makes it eligible | |
| 2467 | to use with {#link|switch#} expressions. One can use {#link|@TagType#} to | |
| 2468 | obtain the enum type from the union type. | |
| 2469 | </p> | |
| 2470 | {#code_begin|test#} | |
| 2471 | const std = @import("std"); | |
| 2472 | const assert = std.debug.assert; | |
| 2239 | 2473 | |
| 2240 | // Unions can be given an enum tag type: | |
| 2241 | const ComplexTypeTag = enum { Ok, NotOk }; | |
| 2474 | const ComplexTypeTag = enum { | |
| 2475 | Ok, | |
| 2476 | NotOk, | |
| 2477 | }; | |
| 2242 | 2478 | const ComplexType = union(ComplexTypeTag) { |
| 2243 | 2479 | Ok: u8, |
| 2244 | 2480 | NotOk: void, |
| 2245 | 2481 | }; |
| 2246 | 2482 | |
| 2247 | // Declare a specific instance of the union variant. | |
| 2248 | test "declare union value" { | |
| 2249 | const c = ComplexType { .Ok = 0 }; | |
| 2483 | test "switch on tagged union" { | |
| 2484 | const c = ComplexType{ .Ok = 42 }; | |
| 2250 | 2485 | assert(ComplexTypeTag(c) == ComplexTypeTag.Ok); |
| 2486 | ||
| 2487 | switch (c) { | |
| 2488 | ComplexTypeTag.Ok => |value| assert(value == 42), | |
| 2489 | ComplexTypeTag.NotOk => unreachable, | |
| 2490 | } | |
| 2251 | 2491 | } |
| 2252 | 2492 | |
| 2253 | // @TagType can be used to access the enum tag type of a union. | |
| 2254 | 2493 | test "@TagType" { |
| 2255 | 2494 | assert(@TagType(ComplexType) == ComplexTypeTag); |
| 2256 | 2495 | } |
| 2496 | {#code_end#} | |
| 2497 | <p>In order to modify the payload of a tagged union in a switch expression, | |
| 2498 | place a {#syntax#}*{#endsyntax#} before the variable name to make it a pointer: | |
| 2499 | </p> | |
| 2500 | {#code_begin|test#} | |
| 2501 | const std = @import("std"); | |
| 2502 | const assert = std.debug.assert; | |
| 2257 | 2503 | |
| 2258 | // Unions can be made to infer the enum tag type. | |
| 2259 | const Foo = union(enum) { | |
| 2260 | String: []const u8, | |
| 2261 | Number: u64, | |
| 2262 | ||
| 2263 | // void can be omitted when inferring enum tag type. | |
| 2264 | None, | |
| 2504 | const ComplexTypeTag = enum { | |
| 2505 | Ok, | |
| 2506 | NotOk, | |
| 2507 | }; | |
| 2508 | const ComplexType = union(ComplexTypeTag) { | |
| 2509 | Ok: u8, | |
| 2510 | NotOk: void, | |
| 2265 | 2511 | }; |
| 2266 | test "union variant switch" { | |
| 2267 | const p = Foo { .Number = 54 }; | |
| 2268 | const what_is_it = switch (p) { | |
| 2269 | // Capture by reference | |
| 2270 | Foo.String => |*x| blk: { | |
| 2271 | break :blk "this is a string"; | |
| 2272 | }, | |
| 2273 | 2512 | |
| 2274 | // Capture by value | |
| 2275 | Foo.Number => |x| blk: { | |
| 2276 | assert(x == 54); | |
| 2277 | break :blk "this is a number"; | |
| 2278 | }, | |
| 2513 | test "modify tagged union in switch" { | |
| 2514 | var c = ComplexType{ .Ok = 42 }; | |
| 2515 | assert(ComplexTypeTag(c) == ComplexTypeTag.Ok); | |
| 2279 | 2516 | |
| 2280 | Foo.None => blk: { | |
| 2281 | break :blk "this is a none"; | |
| 2282 | }, | |
| 2283 | }; | |
| 2284 | assert(mem.eql(u8, what_is_it, "this is a number")); | |
| 2285 | } | |
| 2517 | switch (c) { | |
| 2518 | ComplexTypeTag.Ok => |*value| value.* += 1, | |
| 2519 | ComplexTypeTag.NotOk => unreachable, | |
| 2520 | } | |
| 2286 | 2521 | |
| 2287 | // Unions can have methods just like structs and enums: | |
| 2522 | assert(c.Ok == 43); | |
| 2523 | } | |
| 2524 | {#code_end#} | |
| 2525 | <p> | |
| 2526 | Unions can be made to infer the enum tag type. | |
| 2527 | Further, unions can have methods just like structs and enums. | |
| 2528 | </p> | |
| 2529 | {#code_begin|test#} | |
| 2530 | const std = @import("std"); | |
| 2531 | const assert = std.debug.assert; | |
| 2288 | 2532 | |
| 2289 | 2533 | const Variant = union(enum) { |
| 2290 | 2534 | Int: i32, |
| 2291 | 2535 | Bool: bool, |
| 2292 | 2536 | |
| 2537 | // void can be omitted when inferring enum tag type. | |
| 2538 | None, | |
| 2539 | ||
| 2293 | 2540 | fn truthy(self: Variant) bool { |
| 2294 | 2541 | return switch (self) { |
| 2295 | 2542 | Variant.Int => |x_int| x_int != 0, |
| 2296 | 2543 | Variant.Bool => |x_bool| x_bool, |
| 2544 | Variant.None => false, | |
| 2297 | 2545 | }; |
| 2298 | 2546 | } |
| 2299 | 2547 | }; |
| 2300 | 2548 | |
| 2301 | 2549 | test "union method" { |
| 2302 | var v1 = Variant { .Int = 1 }; | |
| 2303 | var v2 = Variant { .Bool = false }; | |
| 2550 | var v1 = Variant{ .Int = 1 }; | |
| 2551 | var v2 = Variant{ .Bool = false }; | |
| 2304 | 2552 | |
| 2305 | 2553 | assert(v1.truthy()); |
| 2306 | 2554 | assert(!v2.truthy()); |
| 2307 | 2555 | } |
| 2556 | {#code_end#} | |
| 2557 | <p> | |
| 2558 | {#link|@tagName#} can be used to return a {#link|comptime#} | |
| 2559 | {#syntax#}[]const u8{#endsyntax#} value representing the field name: | |
| 2560 | </p> | |
| 2561 | {#code_begin|test#} | |
| 2562 | const std = @import("std"); | |
| 2563 | const assert = std.debug.assert; | |
| 2308 | 2564 | |
| 2309 | ||
| 2310 | const Small = union { | |
| 2311 | A: i32, | |
| 2312 | B: bool, | |
| 2313 | C: u8, | |
| 2314 | }; | |
| 2315 | ||
| 2316 | // @memberCount tells how many fields a union has: | |
| 2317 | test "@memberCount" { | |
| 2318 | assert(@memberCount(Small) == 3); | |
| 2319 | } | |
| 2320 | ||
| 2321 | // @memberName tells the name of a field in an enum: | |
| 2322 | test "@memberName" { | |
| 2323 | assert(mem.eql(u8, @memberName(Small, 1), "B")); | |
| 2324 | } | |
| 2325 | ||
| 2326 | // @tagName gives a []const u8 representation of an enum value, | |
| 2327 | // but only if the union has an enum tag type. | |
| 2328 | 2565 | const Small2 = union(enum) { |
| 2329 | 2566 | A: i32, |
| 2330 | 2567 | B: bool, |
| 2331 | 2568 | C: u8, |
| 2332 | 2569 | }; |
| 2333 | 2570 | test "@tagName" { |
| 2334 | assert(mem.eql(u8, @tagName(Small2.C), "C")); | |
| 2571 | assert(std.mem.eql(u8, @tagName(Small2.C), "C")); | |
| 2335 | 2572 | } |
| 2336 | 2573 | {#code_end#} |
| 2574 | {#header_close#} | |
| 2575 | ||
| 2576 | {#header_open|extern union#} | |
| 2337 | 2577 | <p> |
| 2338 | Unions with an enum tag are generated as a struct with a tag field and union field. Zig | |
| 2339 | sorts the order of the tag and union field by the largest alignment. | |
| 2578 | An {#syntax#}extern union{#endsyntax#} has memory layout guaranteed to be compatible with | |
| 2579 | the target C ABI. | |
| 2340 | 2580 | </p> |
| 2581 | {#see_also|extern struct#} | |
| 2582 | {#header_close#} | |
| 2583 | ||
| 2584 | {#header_open|packed union#} | |
| 2585 | <p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible | |
| 2586 | to be in a {#link|packed struct#}. | |
| 2587 | {#header_close#} | |
| 2341 | 2588 | {#header_close#} |
| 2589 | ||
| 2342 | 2590 | {#header_open|blocks#} |
| 2343 | 2591 | <p> |
| 2344 | 2592 | Blocks are used to limit the scope of variable declarations: |
| ... | ... | @@ -2371,7 +2619,36 @@ test "labeled break from labeled block expression" { |
| 2371 | 2619 | {#code_end#} |
| 2372 | 2620 | <p>Here, {#syntax#}blk{#endsyntax#} can be any name.</p> |
| 2373 | 2621 | {#see_also|Labeled while|Labeled for#} |
| 2622 | ||
| 2623 | {#header_open|Shadowing#} | |
| 2624 | <p>It is never allowed for an identifier to "hide" another one by using the same name:</p> | |
| 2625 | {#code_begin|test_err|redefinition#} | |
| 2626 | const pi = 3.14; | |
| 2627 | ||
| 2628 | test "inside test block" { | |
| 2629 | // Let's even go inside another block | |
| 2630 | { | |
| 2631 | var pi: i32 = 1234; | |
| 2632 | } | |
| 2633 | } | |
| 2634 | {#code_end#} | |
| 2635 | <p> | |
| 2636 | Because of this, when you read Zig code you can rely on an identifier always meaning the same thing, | |
| 2637 | within the scope it is defined. Note that you can, however use the same name if the scopes are separate: | |
| 2638 | </p> | |
| 2639 | {#code_begin|test#} | |
| 2640 | test "separate scopes" { | |
| 2641 | { | |
| 2642 | const pi = 3.14; | |
| 2643 | } | |
| 2644 | { | |
| 2645 | var pi: bool = true; | |
| 2646 | } | |
| 2647 | } | |
| 2648 | {#code_end#} | |
| 2649 | {#header_close#} | |
| 2374 | 2650 | {#header_close#} |
| 2651 | ||
| 2375 | 2652 | {#header_open|switch#} |
| 2376 | 2653 | {#code_begin|test|switch#} |
| 2377 | 2654 | const assert = @import("std").debug.assert; |
| ... | ... | @@ -2392,7 +2669,7 @@ test "switch simple" { |
| 2392 | 2669 | |
| 2393 | 2670 | // Ranges can be specified using the ... syntax. These are inclusive |
| 2394 | 2671 | // both ends. |
| 2395 | 5 ... 100 => 1, | |
| 2672 | 5...100 => 1, | |
| 2396 | 2673 | |
| 2397 | 2674 | // Branches can be arbitrarily complex. |
| 2398 | 2675 | 101 => blk: { |
| ... | ... | @@ -2418,14 +2695,47 @@ test "switch simple" { |
| 2418 | 2695 | assert(b == 1); |
| 2419 | 2696 | } |
| 2420 | 2697 | |
| 2421 | test "switch enum" { | |
| 2698 | // Switch expressions can be used outside a function: | |
| 2699 | const os_msg = switch (builtin.os) { | |
| 2700 | builtin.Os.linux => "we found a linux user", | |
| 2701 | else => "not a linux user", | |
| 2702 | }; | |
| 2703 | ||
| 2704 | // Inside a function, switch statements implicitly are compile-time | |
| 2705 | // evaluated if the target expression is compile-time known. | |
| 2706 | test "switch inside function" { | |
| 2707 | switch (builtin.os) { | |
| 2708 | builtin.Os.fuchsia => { | |
| 2709 | // On an OS other than fuchsia, block is not even analyzed, | |
| 2710 | // so this compile error is not triggered. | |
| 2711 | // On fuchsia this compile error would be triggered. | |
| 2712 | @compileError("fuchsia not supported"); | |
| 2713 | }, | |
| 2714 | else => {}, | |
| 2715 | } | |
| 2716 | } | |
| 2717 | {#code_end#} | |
| 2718 | <p> | |
| 2719 | {#syntax#}switch{#endsyntax#} can be used to capture the field values | |
| 2720 | of a {#link|Tagged union#}. Modifications to the field values can be | |
| 2721 | done by placing a {#syntax#}*{#endsyntax#} before the capture variable name, | |
| 2722 | turning it into a pointer. | |
| 2723 | </p> | |
| 2724 | {#code_begin|test#} | |
| 2725 | const assert = @import("std").debug.assert; | |
| 2726 | ||
| 2727 | test "switch on tagged union" { | |
| 2728 | const Point = struct { | |
| 2729 | x: u8, | |
| 2730 | y: u8, | |
| 2731 | }; | |
| 2422 | 2732 | const Item = union(enum) { |
| 2423 | 2733 | A: u32, |
| 2424 | C: struct { x: u8, y: u8 }, | |
| 2734 | C: Point, | |
| 2425 | 2735 | D, |
| 2426 | 2736 | }; |
| 2427 | 2737 | |
| 2428 | var a = Item { .A = 3 }; | |
| 2738 | var a = Item{ .C = Point{ .x = 1, .y = 2 } }; | |
| 2429 | 2739 | |
| 2430 | 2740 | // Switching on more complex enums is allowed. |
| 2431 | 2741 | const b = switch (a) { |
| ... | ... | @@ -2443,27 +2753,8 @@ test "switch enum" { |
| 2443 | 2753 | Item.D => 8, |
| 2444 | 2754 | }; |
| 2445 | 2755 | |
| 2446 | assert(b == 3); | |
| 2447 | } | |
| 2448 | ||
| 2449 | // Switch expressions can be used outside a function: | |
| 2450 | const os_msg = switch (builtin.os) { | |
| 2451 | builtin.Os.linux => "we found a linux user", | |
| 2452 | else => "not a linux user", | |
| 2453 | }; | |
| 2454 | ||
| 2455 | // Inside a function, switch statements implicitly are compile-time | |
| 2456 | // evaluated if the target expression is compile-time known. | |
| 2457 | test "switch inside function" { | |
| 2458 | switch (builtin.os) { | |
| 2459 | builtin.Os.fuchsia => { | |
| 2460 | // On an OS other than fuchsia, block is not even analyzed, | |
| 2461 | // so this compile error is not triggered. | |
| 2462 | // On fuchsia this compile error would be triggered. | |
| 2463 | @compileError("fuchsia not supported"); | |
| 2464 | }, | |
| 2465 | else => {}, | |
| 2466 | } | |
| 2756 | assert(b == 6); | |
| 2757 | assert(a.C.x == 2); | |
| 2467 | 2758 | } |
| 2468 | 2759 | {#code_end#} |
| 2469 | 2760 | {#see_also|comptime|enum|@compileError|Compile Variables#} |
| ... | ... | @@ -3134,7 +3425,6 @@ const assert = @import("std").debug.assert; |
| 3134 | 3425 | // Functions are declared like this |
| 3135 | 3426 | fn add(a: i8, b: i8) i8 { |
| 3136 | 3427 | if (a == 0) { |
| 3137 | // You can still return manually if needed. | |
| 3138 | 3428 | return b; |
| 3139 | 3429 | } |
| 3140 | 3430 | |
| ... | ... | @@ -3158,12 +3448,18 @@ fn abort() noreturn { |
| 3158 | 3448 | while (true) {} |
| 3159 | 3449 | } |
| 3160 | 3450 | |
| 3161 | // nakedcc makes a function not have any function prologue or epilogue. | |
| 3451 | // The nakedcc specifier makes a function not have any function prologue or epilogue. | |
| 3162 | 3452 | // This can be useful when integrating with assembly. |
| 3163 | 3453 | nakedcc fn _start() noreturn { |
| 3164 | 3454 | abort(); |
| 3165 | 3455 | } |
| 3166 | 3456 | |
| 3457 | // The inline specifier forces a function to be inlined at all call sites. | |
| 3458 | // If the function cannot be inlined, it is a compile-time error. | |
| 3459 | inline fn shiftLeftOne(a: u32) u32 { | |
| 3460 | return a << 1; | |
| 3461 | } | |
| 3462 | ||
| 3167 | 3463 | // The pub specifier allows the function to be visible when importing. |
| 3168 | 3464 | // Another file can use @import and call sub2 |
| 3169 | 3465 | pub fn sub2(a: i8, b: i8) i8 { return a - b; } |
| ... | ... | @@ -3731,7 +4027,7 @@ fn bang2() void { |
| 3731 | 4027 | Here, the stack trace does not explain how the control |
| 3732 | 4028 | flow in {#syntax#}bar{#endsyntax#} got to the {#syntax#}hello(){#endsyntax#} call. |
| 3733 | 4029 | One would have to open a debugger or further instrument the application |
| 3734 | in order to find out. The error return trace, on the other hand, | |
| 4030 | in order to find out. The error return trace, on the other hand, | |
| 3735 | 4031 | shows exactly how the error bubbled up. |
| 3736 | 4032 | </p> |
| 3737 | 4033 | <p> |
| ... | ... | @@ -3923,7 +4219,7 @@ test "optional type" { |
| 3923 | 4219 | cast it to a different type: |
| 3924 | 4220 | </p> |
| 3925 | 4221 | {#code_begin|syntax#} |
| 3926 | const optional_value: ?i32 = null; | |
| 4222 | const optional_value: ?i32 = null; | |
| 3927 | 4223 | {#code_end#} |
| 3928 | 4224 | {#header_close#} |
| 3929 | 4225 | {#header_open|Optional Pointers#} |
| ... | ... | @@ -3981,7 +4277,7 @@ test "implicit cast - invoke a type as a function" { |
| 3981 | 4277 | {#code_end#} |
| 3982 | 4278 | <p> |
| 3983 | 4279 | Implicit casts are only allowed when it is completely unambiguous how to get from one type to another, |
| 3984 | and the transformation is guaranteed to be safe. | |
| 4280 | and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}. | |
| 3985 | 4281 | </p> |
| 3986 | 4282 | {#header_open|Implicit Cast: Stricter Qualification#} |
| 3987 | 4283 | <p> |
| ... | ... | @@ -4228,9 +4524,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { |
| 4228 | 4524 | {#header_close#} |
| 4229 | 4525 | {#header_close#} |
| 4230 | 4526 | |
| 4231 | {#header_open|void#} | |
| 4527 | {#header_open|Zero Bit Types#} | |
| 4528 | <p>For some types, {#link|@sizeOf#} is 0:</p> | |
| 4529 | <ul> | |
| 4530 | <li>{#link|void#}</li> | |
| 4531 | <li>The {#link|Integers#} {#syntax#}u0{#endsyntax#} and {#syntax#}i0{#endsyntax#}.</li> | |
| 4532 | <li>{#link|Arrays#} and {#link|Vectors#} with len 0, or with an element type that is a zero bit type.</li> | |
| 4533 | <li>An {#link|enum#} with only 1 tag.</li> | |
| 4534 | <li>An {#link|struct#} with all fields being zero bit types.</li> | |
| 4535 | <li>A {#link|union#} with only 1 field which is a zero bit type.</li> | |
| 4536 | <li>{#link|Pointers to Zero Bit Types#} are themselves zero bit types.</li> | |
| 4537 | </ul> | |
| 4232 | 4538 | <p> |
| 4233 | {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is | |
| 4539 | These types can only ever have one possible value, and thus | |
| 4540 | require 0 bits to represent. Code that makes use of these types is | |
| 4234 | 4541 | not included in the final generated code: |
| 4235 | 4542 | </p> |
| 4236 | 4543 | {#code_begin|syntax#} |
| ... | ... | @@ -4240,8 +4547,8 @@ export fn entry() void { |
| 4240 | 4547 | x = y; |
| 4241 | 4548 | } |
| 4242 | 4549 | {#code_end#} |
| 4243 | <p>When this turns into LLVM IR, there is no code generated in the body of {#syntax#}entry{#endsyntax#}, | |
| 4244 | even in debug mode. For example, on x86_64:</p> | |
| 4550 | <p>When this turns into machine code, there is no code generated in the | |
| 4551 | body of {#syntax#}entry{#endsyntax#}, even in {#link|Debug#} mode. For example, on x86_64:</p> | |
| 4245 | 4552 | <pre><code>0000000000000010 &lt;entry&gt;: |
| 4246 | 4553 | 10:	55 	push %rbp |
| 4247 | 4554 | 11:	48 89 e5 	mov %rsp,%rbp |
| ... | ... | @@ -4249,6 +4556,8 @@ export fn entry() void { |
| 4249 | 4556 | 15:	c3 	retq </code></pre> |
| 4250 | 4557 | <p>These assembly instructions do not have any code associated with the void values - |
| 4251 | 4558 | they only perform the function call prologue and epilog.</p> |
| 4559 | ||
| 4560 | {#header_open|void#} | |
| 4252 | 4561 | <p> |
| 4253 | 4562 | {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a |
| 4254 | 4563 | {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#} |
| ... | ... | @@ -4320,6 +4629,38 @@ fn foo() i32 { |
| 4320 | 4629 | {#code_end#} |
| 4321 | 4630 | {#header_close#} |
| 4322 | 4631 | |
| 4632 | {#header_open|Pointers to Zero Bit Types#} | |
| 4633 | <p>Pointers to zero bit types also have zero bits. They always compare equal to each other:</p> | |
| 4634 | {#code_begin|test#} | |
| 4635 | const std = @import("std"); | |
| 4636 | const assert = std.debug.assert; | |
| 4637 | ||
| 4638 | test "pointer to empty struct" { | |
| 4639 | const Empty = struct {}; | |
| 4640 | var a = Empty{}; | |
| 4641 | var b = Empty{}; | |
| 4642 | var ptr_a = &a; | |
| 4643 | var ptr_b = &b; | |
| 4644 | comptime assert(ptr_a == ptr_b); | |
| 4645 | } | |
| 4646 | {#code_end#} | |
| 4647 | <p>The type being pointed to can only ever be one value; therefore loads and stores are | |
| 4648 | never generated. {#link|ptrToInt#} and {#link|intToPtr#} are not allowed:</p> | |
| 4649 | {#code_begin|test_err#} | |
| 4650 | const Empty = struct {}; | |
| 4651 | ||
| 4652 | test "@ptrToInt for pointer to zero bit type" { | |
| 4653 | var a = Empty{}; | |
| 4654 | _ = @ptrToInt(&a); | |
| 4655 | } | |
| 4656 | ||
| 4657 | test "@intToPtr for pointer to zero bit type" { | |
| 4658 | _ = @intToPtr(*Empty, 0x1); | |
| 4659 | } | |
| 4660 | {#code_end#} | |
| 4661 | {#header_close#} | |
| 4662 | {#header_close#} | |
| 4663 | ||
| 4323 | 4664 | {#header_open|comptime#} |
| 4324 | 4665 | <p> |
| 4325 | 4666 | Zig places importance on the concept of whether an expression is known at compile-time. |
| ... | ... | @@ -5101,7 +5442,7 @@ async fn testResumeFromSuspend(my_result: *i32) void { |
| 5101 | 5442 | <p> |
| 5102 | 5443 | {#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes |
| 5103 | 5444 | as an operand a promise handle. |
| 5104 | If the async function associated with the promise handle has already returned, | |
| 5445 | If the async function associated with the promise handle has already returned, | |
| 5105 | 5446 | then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value. |
| 5106 | 5447 | Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its |
| 5107 | 5448 | promise handle with the target coroutine. It becomes the target coroutine's responsibility |
| ... | ... | @@ -5185,7 +5526,7 @@ fn seq(c: u8) void { |
| 5185 | 5526 | </li> |
| 5186 | 5527 | </ul> |
| 5187 | 5528 | {#header_close#} |
| 5188 | ||
| 5529 | ||
| 5189 | 5530 | {#header_close#} |
| 5190 | 5531 | {#header_open|Builtin Functions#} |
| 5191 | 5532 | <p> |
| ... | ... | @@ -5540,13 +5881,13 @@ const warn = @import("std").debug.warn; |
| 5540 | 5881 | |
| 5541 | 5882 | const num1 = blk: { |
| 5542 | 5883 | var val1: i32 = 99; |
| 5543 | @compileLog("comptime val1 = ", val1); | |
| 5884 | @compileLog("comptime val1 = ", val1); | |
| 5544 | 5885 | val1 = val1 + 1; |
| 5545 | 5886 | break :blk val1; |
| 5546 | 5887 | }; |
| 5547 | 5888 | |
| 5548 | 5889 | test "main" { |
| 5549 | @compileLog("comptime in main"); | |
| 5890 | @compileLog("comptime in main"); | |
| 5550 | 5891 | |
| 5551 | 5892 | warn("Runtime in main, num1 = {}.\n", num1); |
| 5552 | 5893 | } |
| ... | ... | @@ -5556,10 +5897,10 @@ test "main" { |
| 5556 | 5897 | will ouput: |
| 5557 | 5898 | </p> |
| 5558 | 5899 | <p> |
| 5559 | If all {#syntax#}@compileLog{#endsyntax#} calls are removed or | |
| 5900 | If all {#syntax#}@compileLog{#endsyntax#} calls are removed or | |
| 5560 | 5901 | not encountered by analysis, the |
| 5561 | 5902 | program compiles successfully and the generated executable prints: |
| 5562 | </p> | |
| 5903 | </p> | |
| 5563 | 5904 | {#code_begin|test#} |
| 5564 | 5905 | const warn = @import("std").debug.warn; |
| 5565 | 5906 | |
| ... | ... | @@ -5658,12 +5999,13 @@ test "main" { |
| 5658 | 5999 | {#header_close#} |
| 5659 | 6000 | |
| 5660 | 6001 | {#header_open|@enumToInt#} |
| 5661 | <pre>{#syntax#}@enumToInt(enum_value: var) var{#endsyntax#}</pre> | |
| 6002 | <pre>{#syntax#}@enumToInt(enum_or_tagged_union: var) var{#endsyntax#}</pre> | |
| 5662 | 6003 | <p> |
| 5663 | Converts an enumeration value into its integer tag type. | |
| 6004 | Converts an enumeration value into its integer tag type. When a tagged union is passed, | |
| 6005 | the tag value is used as the enumeration value. | |
| 5664 | 6006 | </p> |
| 5665 | 6007 | <p> |
| 5666 | If the enum has only 1 possible value, the resut is a {#syntax#}comptime_int{#endsyntax#} | |
| 6008 | If there is only one possible enum value, the resut is a {#syntax#}comptime_int{#endsyntax#} | |
| 5667 | 6009 | known at {#link|comptime#}. |
| 5668 | 6010 | </p> |
| 5669 | 6011 | {#see_also|@intToEnum#} |
| ... | ... | @@ -6104,6 +6446,10 @@ test "call foo" { |
| 6104 | 6446 | <p> |
| 6105 | 6447 | Converts a pointer of one type to a pointer of another type. |
| 6106 | 6448 | </p> |
| 6449 | <p> | |
| 6450 | {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#} | |
| 6451 | to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}. | |
| 6452 | </p> | |
| 6107 | 6453 | {#header_close#} |
| 6108 | 6454 | |
| 6109 | 6455 | {#header_open|@ptrToInt#} |
| ... | ... | @@ -6293,10 +6639,15 @@ pub const FloatMode = enum { |
| 6293 | 6639 | <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre> |
| 6294 | 6640 | <p> |
| 6295 | 6641 | This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory. |
| 6642 | The result is a target-specific compile time constant. | |
| 6296 | 6643 | </p> |
| 6297 | 6644 | <p> |
| 6298 | The result is a target-specific compile time constant. | |
| 6645 | This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset | |
| 6646 | in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#}, | |
| 6647 | consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or | |
| 6648 | {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}. | |
| 6299 | 6649 | </p> |
| 6650 | {#see_also|@typeInfo#} | |
| 6300 | 6651 | {#header_close#} |
| 6301 | 6652 | |
| 6302 | 6653 | {#header_open|@sliceToBytes#} |
| ... | ... | @@ -6375,7 +6726,7 @@ fn List(comptime T: type) type { |
| 6375 | 6726 | <p> |
| 6376 | 6727 | When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the |
| 6377 | 6728 | current import. There is a proposal to remove the import type and use an empty struct |
| 6378 | type instead. See | |
| 6729 | type instead. See | |
| 6379 | 6730 | <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details. |
| 6380 | 6731 | </p> |
| 6381 | 6732 | {#header_close#} |
| ... | ... | @@ -6730,11 +7081,7 @@ pub fn build(b: *Builder) void { |
| 6730 | 7081 | {#header_open|Single Threaded Builds#} |
| 6731 | 7082 | <p>Zig has a compile option <code>--single-threaded</code> which has the following effects: |
| 6732 | 7083 | <ul> |
| 6733 | <li>{#link|@atomicLoad#} is emitted as a normal load.</li> | |
| 6734 | <li>{#link|@atomicRmw#} is emitted as a normal memory load, modify, store.</li> | |
| 6735 | <li>{#link|@fence#} becomes a no-op.</li> | |
| 6736 | <li>Variables which have Thread Local Storage instead become globals. TODO thread local variables | |
| 6737 | are not implemented yet.</li> | |
| 7084 | <li>Variables which have Thread Local Storage instead become globals.</li> | |
| 6738 | 7085 | <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead. |
| 6739 | 7086 | TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li> |
| 6740 | 7087 | <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#} |
| ... | ... | @@ -7343,12 +7690,30 @@ fn bar(f: *Foo) void { |
| 7343 | 7690 | f.float = 12.34; |
| 7344 | 7691 | } |
| 7345 | 7692 | {#code_end#} |
| 7693 | {#see_also|union|extern union#} | |
| 7346 | 7694 | {#header_close#} |
| 7347 | 7695 | |
| 7348 | {#header_open|Out of Bounds Float To Integer Cast#} | |
| 7696 | {#header_open|Out of Bounds Float to Integer Cast#} | |
| 7349 | 7697 | <p>TODO</p> |
| 7350 | 7698 | {#header_close#} |
| 7351 | 7699 | |
| 7700 | {#header_open|Pointer Cast Invalid Null#} | |
| 7701 | <p>At compile-time:</p> | |
| 7702 | {#code_begin|test_err|null pointer casted to type#} | |
| 7703 | comptime { | |
| 7704 | const opt_ptr: ?*i32 = null; | |
| 7705 | const ptr = @ptrCast(*i32, opt_ptr); | |
| 7706 | } | |
| 7707 | {#code_end#} | |
| 7708 | <p>At runtime:</p> | |
| 7709 | {#code_begin|exe_err#} | |
| 7710 | pub fn main() void { | |
| 7711 | var opt_ptr: ?*i32 = null; | |
| 7712 | var ptr = @ptrCast(*i32, opt_ptr); | |
| 7713 | } | |
| 7714 | {#code_end#} | |
| 7715 | {#header_close#} | |
| 7716 | ||
| 7352 | 7717 | {#header_close#} |
| 7353 | 7718 | {#header_open|Memory#} |
| 7354 | 7719 | <p>TODO: explain no default allocator in zig</p> |
| ... | ... | @@ -7439,6 +7804,7 @@ pub fn main() void { |
| 7439 | 7804 | {#code_end#} |
| 7440 | 7805 | {#see_also|String Literals#} |
| 7441 | 7806 | {#header_close#} |
| 7807 | ||
| 7442 | 7808 | {#header_open|Import from C Header File#} |
| 7443 | 7809 | <p> |
| 7444 | 7810 | The {#syntax#}@cImport{#endsyntax#} builtin function can be used |
| ... | ... | @@ -7477,6 +7843,36 @@ const c = @cImport({ |
| 7477 | 7843 | {#code_end#} |
| 7478 | 7844 | {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#} |
| 7479 | 7845 | {#header_close#} |
| 7846 | ||
| 7847 | {#header_open|C Pointers#} | |
| 7848 | <p> | |
| 7849 | This type is to be avoided whenever possible. The only valid reason for using a C pointer is in | |
| 7850 | auto-generated code from translating C code. | |
| 7851 | </p> | |
| 7852 | <p> | |
| 7853 | When importing C header files, it is ambiguous whether pointers should be translated as | |
| 7854 | single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}). | |
| 7855 | C pointers are a compromise so that Zig code can utilize translated header files directly. | |
| 7856 | </p> | |
| 7857 | <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p> | |
| 7858 | <ul> | |
| 7859 | <li>Supports all the syntax of the other two pointer types.</li> | |
| 7860 | <li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}. | |
| 7861 | When a C pointer is implicitly casted to a non-optional pointer, safety-checked | |
| 7862 | {#link|Undefined Behavior#} occurs if the address is 0. | |
| 7863 | </li> | |
| 7864 | <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked | |
| 7865 | {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of | |
| 7866 | null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer | |
| 7867 | is unnecessary as one can use normal {#link|Optional Pointers#}. | |
| 7868 | </li> | |
| 7869 | <li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li> | |
| 7870 | <li>Supports comparison with integers.</li> | |
| 7871 | <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#} | |
| 7872 | please!</li> | |
| 7873 | </ul> | |
| 7874 | {#header_close#} | |
| 7875 | ||
| 7480 | 7876 | {#header_open|Exporting a C Library#} |
| 7481 | 7877 | <p> |
| 7482 | 7878 | One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages |
| ... | ... | @@ -7729,7 +8125,7 @@ Environments: |
| 7729 | 8125 | coreclr |
| 7730 | 8126 | opencl</code></pre> |
| 7731 | 8127 | <p> |
| 7732 | The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem | |
| 8128 | The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system | |
| 7733 | 8129 | abstractions, and thus takes additional work to support more platforms. |
| 7734 | 8130 | Not all standard library code requires operating system abstractions, however, |
| 7735 | 8131 | so things such as generic data structures work an all above platforms. |
| ... | ... | @@ -8164,7 +8560,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET |
| 8164 | 8560 | PtrTypeStart |
| 8165 | 8561 | &lt;- ASTERISK |
| 8166 | 8562 | / ASTERISK2 |
| 8167 | / LBRACKET ASTERISK RBRACKET | |
| 8563 | / PTRUNKNOWN | |
| 8564 | / PTRC | |
| 8168 | 8565 | |
| 8169 | 8566 | # ContainerDecl specific |
| 8170 | 8567 | ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE |
| ... | ... | @@ -8262,7 +8659,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip |
| 8262 | 8659 | LARROW2EQUAL &lt;- '&lt;&lt;=' skip |
| 8263 | 8660 | LARROWEQUAL &lt;- '&lt;=' skip |
| 8264 | 8661 | LBRACE &lt;- '{' skip |
| 8265 | LBRACKET &lt;- '[' skip | |
| 8662 | LBRACKET &lt;- '[' ![*] skip | |
| 8266 | 8663 | LPAREN &lt;- '(' skip |
| 8267 | 8664 | MINUS &lt;- '-' ![%=&gt;] skip |
| 8268 | 8665 | MINUSEQUAL &lt;- '-=' skip |
| ... | ... | @@ -8279,6 +8676,8 @@ PLUS2 &lt;- '++' skip |
| 8279 | 8676 | PLUSEQUAL &lt;- '+=' skip |
| 8280 | 8677 | PLUSPERCENT &lt;- '+%' ![=] skip |
| 8281 | 8678 | PLUSPERCENTEQUAL &lt;- '+%=' skip |
| 8679 | PTRC &lt;- '[*c]' skip | |
| 8680 | PTRUNKNOWN &lt;- '[*]' skip | |
| 8282 | 8681 | QUESTIONMARK &lt;- '?' skip |
| 8283 | 8682 | RARROW &lt;- '&gt;' ![&gt;=] skip |
| 8284 | 8683 | RARROW2 &lt;- '&gt;&gt;' ![=] skip |
example/mix_o_files/build.zig+3-3| ... | ... | @@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder; |
| 3 | 3 | pub fn build(b: *Builder) void { |
| 4 | 4 | const obj = b.addObject("base64", "base64.zig"); |
| 5 | 5 | |
| 6 | const exe = b.addCExecutable("test"); | |
| 7 | exe.addCompileFlags([][]const u8{"-std=c99"}); | |
| 8 | exe.addSourceFile("test.c"); | |
| 6 | const exe = b.addExecutable("test", null); | |
| 7 | exe.addCSourceFile("test.c",[][]const u8{"-std=c99"}); | |
| 9 | 8 | exe.addObject(obj); |
| 9 | exe.linkSystemLibrary("c"); | |
| 10 | 10 | |
| 11 | 11 | b.default_step.dependOn(&exe.step); |
| 12 | 12 |
example/shared_library/build.zig+3-3| ... | ... | @@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder; |
| 3 | 3 | pub fn build(b: *Builder) void { |
| 4 | 4 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); |
| 5 | 5 | |
| 6 | const exe = b.addCExecutable("test"); | |
| 7 | exe.addCompileFlags([][]const u8{"-std=c99"}); | |
| 8 | exe.addSourceFile("test.c"); | |
| 6 | const exe = b.addExecutable("test", null); | |
| 7 | exe.addCSourceFile("test.c", [][]const u8{"-std=c99"}); | |
| 9 | 8 | exe.linkLibrary(lib); |
| 9 | exe.linkSystemLibrary("c"); | |
| 10 | 10 | |
| 11 | 11 | b.default_step.dependOn(&exe.step); |
| 12 | 12 |
example/shared_library/mathtest.zig-9| ... | ... | @@ -1,12 +1,3 @@ |
| 1 | // TODO Remove this workaround | |
| 2 | comptime { | |
| 3 | const builtin = @import("builtin"); | |
| 4 | if (builtin.os == builtin.Os.macosx) { | |
| 5 | @export("__mh_execute_header", _mh_execute_header, builtin.GlobalLinkage.Weak); | |
| 6 | } | |
| 7 | } | |
| 8 | var _mh_execute_header = extern struct {x: usize}{.x = 0}; | |
| 9 | ||
| 10 | 1 | export fn add(a: i32, b: i32) i32 { |
| 11 | 2 | return a + b; |
| 12 | 3 | } |
src-self-hosted/codegen.zig+21-21| ... | ... | @@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) |
| 137 | 137 | |
| 138 | 138 | pub const ObjectFile = struct { |
| 139 | 139 | comp: *Compilation, |
| 140 | module: llvm.ModuleRef, | |
| 141 | builder: llvm.BuilderRef, | |
| 140 | module: *llvm.Module, | |
| 141 | builder: *llvm.Builder, | |
| 142 | 142 | dibuilder: *llvm.DIBuilder, |
| 143 | context: llvm.ContextRef, | |
| 143 | context: *llvm.Context, | |
| 144 | 144 | lock: event.Lock, |
| 145 | 145 | arena: *std.mem.Allocator, |
| 146 | 146 | |
| ... | ... | @@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) |
| 323 | 323 | |
| 324 | 324 | fn addLLVMAttr( |
| 325 | 325 | ofile: *ObjectFile, |
| 326 | val: llvm.ValueRef, | |
| 326 | val: *llvm.Value, | |
| 327 | 327 | attr_index: llvm.AttributeIndex, |
| 328 | 328 | attr_name: []const u8, |
| 329 | 329 | ) !void { |
| ... | ... | @@ -335,7 +335,7 @@ fn addLLVMAttr( |
| 335 | 335 | |
| 336 | 336 | fn addLLVMAttrStr( |
| 337 | 337 | ofile: *ObjectFile, |
| 338 | val: llvm.ValueRef, | |
| 338 | val: *llvm.Value, | |
| 339 | 339 | attr_index: llvm.AttributeIndex, |
| 340 | 340 | attr_name: []const u8, |
| 341 | 341 | attr_val: []const u8, |
| ... | ... | @@ -351,7 +351,7 @@ fn addLLVMAttrStr( |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | 353 | fn addLLVMAttrInt( |
| 354 | val: llvm.ValueRef, | |
| 354 | val: *llvm.Value, | |
| 355 | 355 | attr_index: llvm.AttributeIndex, |
| 356 | 356 | attr_name: []const u8, |
| 357 | 357 | attr_val: u64, |
| ... | ... | @@ -362,25 +362,25 @@ fn addLLVMAttrInt( |
| 362 | 362 | llvm.AddAttributeAtIndex(val, attr_index, llvm_attr); |
| 363 | 363 | } |
| 364 | 364 | |
| 365 | fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void { | |
| 365 | fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void { | |
| 366 | 366 | return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name); |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void { | |
| 369 | fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void { | |
| 370 | 370 | return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val); |
| 371 | 371 | } |
| 372 | 372 | |
| 373 | fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void { | |
| 373 | fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void { | |
| 374 | 374 | return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val); |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | fn renderLoadUntyped( |
| 378 | 378 | ofile: *ObjectFile, |
| 379 | ptr: llvm.ValueRef, | |
| 379 | ptr: *llvm.Value, | |
| 380 | 380 | alignment: Type.Pointer.Align, |
| 381 | 381 | vol: Type.Pointer.Vol, |
| 382 | 382 | name: [*]const u8, |
| 383 | ) !llvm.ValueRef { | |
| 383 | ) !*llvm.Value { | |
| 384 | 384 | const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory; |
| 385 | 385 | switch (vol) { |
| 386 | 386 | Type.Pointer.Vol.Non => {}, |
| ... | ... | @@ -390,11 +390,11 @@ fn renderLoadUntyped( |
| 390 | 390 | return result; |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef { | |
| 393 | fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value { | |
| 394 | 394 | return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name); |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef { | |
| 397 | pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value { | |
| 398 | 398 | const child_type = ptr_type.key.child_type; |
| 399 | 399 | if (!child_type.hasBits()) { |
| 400 | 400 | return null; |
| ... | ... | @@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po |
| 407 | 407 | |
| 408 | 408 | pub fn renderStoreUntyped( |
| 409 | 409 | ofile: *ObjectFile, |
| 410 | value: llvm.ValueRef, | |
| 411 | ptr: llvm.ValueRef, | |
| 410 | value: *llvm.Value, | |
| 411 | ptr: *llvm.Value, | |
| 412 | 412 | alignment: Type.Pointer.Align, |
| 413 | 413 | vol: Type.Pointer.Vol, |
| 414 | ) !llvm.ValueRef { | |
| 414 | ) !*llvm.Value { | |
| 415 | 415 | const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory; |
| 416 | 416 | switch (vol) { |
| 417 | 417 | Type.Pointer.Vol.Non => {}, |
| ... | ... | @@ -423,10 +423,10 @@ pub fn renderStoreUntyped( |
| 423 | 423 | |
| 424 | 424 | pub fn renderStore( |
| 425 | 425 | ofile: *ObjectFile, |
| 426 | value: llvm.ValueRef, | |
| 427 | ptr: llvm.ValueRef, | |
| 426 | value: *llvm.Value, | |
| 427 | ptr: *llvm.Value, | |
| 428 | 428 | ptr_type: *Type.Pointer, |
| 429 | ) !llvm.ValueRef { | |
| 429 | ) !*llvm.Value { | |
| 430 | 430 | return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol); |
| 431 | 431 | } |
| 432 | 432 | |
| ... | ... | @@ -435,7 +435,7 @@ pub fn renderAlloca( |
| 435 | 435 | var_type: *Type, |
| 436 | 436 | name: []const u8, |
| 437 | 437 | alignment: Type.Pointer.Align, |
| 438 | ) !llvm.ValueRef { | |
| 438 | ) !*llvm.Value { | |
| 439 | 439 | const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context); |
| 440 | 440 | const name_with_null = try std.cstr.addNullByte(ofile.arena, name); |
| 441 | 441 | const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory; |
| ... | ... | @@ -443,7 +443,7 @@ pub fn renderAlloca( |
| 443 | 443 | return result; |
| 444 | 444 | } |
| 445 | 445 | |
| 446 | pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 { | |
| 446 | pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 { | |
| 447 | 447 | return switch (alignment) { |
| 448 | 448 | Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type), |
| 449 | 449 | Type.Pointer.Align.Override => |a| a, |
src-self-hosted/compilation.zig+11-11| ... | ... | @@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB |
| 37 | 37 | /// Data that is local to the event loop. |
| 38 | 38 | pub const ZigCompiler = struct { |
| 39 | 39 | loop: *event.Loop, |
| 40 | llvm_handle_pool: std.atomic.Stack(llvm.ContextRef), | |
| 40 | llvm_handle_pool: std.atomic.Stack(*llvm.Context), | |
| 41 | 41 | lld_lock: event.Lock, |
| 42 | 42 | |
| 43 | 43 | /// TODO pool these so that it doesn't have to lock |
| ... | ... | @@ -60,7 +60,7 @@ pub const ZigCompiler = struct { |
| 60 | 60 | return ZigCompiler{ |
| 61 | 61 | .loop = loop, |
| 62 | 62 | .lld_lock = event.Lock.init(loop), |
| 63 | .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(), | |
| 63 | .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(), | |
| 64 | 64 | .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)), |
| 65 | 65 | .native_libc = event.Future(LibCInstallation).init(loop), |
| 66 | 66 | }; |
| ... | ... | @@ -70,7 +70,7 @@ pub const ZigCompiler = struct { |
| 70 | 70 | fn deinit(self: *ZigCompiler) void { |
| 71 | 71 | self.lld_lock.deinit(); |
| 72 | 72 | while (self.llvm_handle_pool.pop()) |node| { |
| 73 | c.LLVMContextDispose(node.data); | |
| 73 | llvm.ContextDispose(node.data); | |
| 74 | 74 | self.loop.allocator.destroy(node); |
| 75 | 75 | } |
| 76 | 76 | } |
| ... | ... | @@ -80,11 +80,11 @@ pub const ZigCompiler = struct { |
| 80 | 80 | pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle { |
| 81 | 81 | if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node }; |
| 82 | 82 | |
| 83 | const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory; | |
| 84 | errdefer c.LLVMContextDispose(context_ref); | |
| 83 | const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory; | |
| 84 | errdefer llvm.ContextDispose(context_ref); | |
| 85 | 85 | |
| 86 | const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node); | |
| 87 | node.* = std.atomic.Stack(llvm.ContextRef).Node{ | |
| 86 | const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node); | |
| 87 | node.* = std.atomic.Stack(*llvm.Context).Node{ | |
| 88 | 88 | .next = undefined, |
| 89 | 89 | .data = context_ref, |
| 90 | 90 | }; |
| ... | ... | @@ -114,7 +114,7 @@ pub const ZigCompiler = struct { |
| 114 | 114 | }; |
| 115 | 115 | |
| 116 | 116 | pub const LlvmHandle = struct { |
| 117 | node: *std.atomic.Stack(llvm.ContextRef).Node, | |
| 117 | node: *std.atomic.Stack(*llvm.Context).Node, | |
| 118 | 118 | |
| 119 | 119 | pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void { |
| 120 | 120 | zig_compiler.llvm_handle_pool.push(self.node); |
| ... | ... | @@ -128,7 +128,7 @@ pub const Compilation = struct { |
| 128 | 128 | llvm_triple: Buffer, |
| 129 | 129 | root_src_path: ?[]const u8, |
| 130 | 130 | target: Target, |
| 131 | llvm_target: llvm.TargetRef, | |
| 131 | llvm_target: *llvm.Target, | |
| 132 | 132 | build_mode: builtin.Mode, |
| 133 | 133 | zig_lib_dir: []const u8, |
| 134 | 134 | zig_std_dir: []const u8, |
| ... | ... | @@ -212,8 +212,8 @@ pub const Compilation = struct { |
| 212 | 212 | false_value: *Value.Bool, |
| 213 | 213 | noreturn_value: *Value.NoReturn, |
| 214 | 214 | |
| 215 | target_machine: llvm.TargetMachineRef, | |
| 216 | target_data_ref: llvm.TargetDataRef, | |
| 215 | target_machine: *llvm.TargetMachine, | |
| 216 | target_data_ref: *llvm.TargetData, | |
| 217 | 217 | target_layout_str: [*]u8, |
| 218 | 218 | target_ptr_bits: u32, |
| 219 | 219 |
src-self-hosted/ir.zig+10-10| ... | ... | @@ -67,7 +67,7 @@ pub const Inst = struct { |
| 67 | 67 | parent: ?*Inst, |
| 68 | 68 | |
| 69 | 69 | /// populated durign codegen |
| 70 | llvm_value: ?llvm.ValueRef, | |
| 70 | llvm_value: ?*llvm.Value, | |
| 71 | 71 | |
| 72 | 72 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
| 73 | 73 | if (base.id == comptime typeToId(T)) { |
| ... | ... | @@ -129,7 +129,7 @@ pub const Inst = struct { |
| 129 | 129 | } |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) { | |
| 132 | pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) { | |
| 133 | 133 | switch (base.id) { |
| 134 | 134 | Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val), |
| 135 | 135 | Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val), |
| ... | ... | @@ -313,10 +313,10 @@ pub const Inst = struct { |
| 313 | 313 | return new_inst; |
| 314 | 314 | } |
| 315 | 315 | |
| 316 | pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | |
| 316 | pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { | |
| 317 | 317 | const fn_ref = self.params.fn_ref.llvm_value.?; |
| 318 | 318 | |
| 319 | const args = try ofile.arena.alloc(llvm.ValueRef, self.params.args.len); | |
| 319 | const args = try ofile.arena.alloc(*llvm.Value, self.params.args.len); | |
| 320 | 320 | for (self.params.args) |arg, i| { |
| 321 | 321 | args[i] = arg.llvm_value.?; |
| 322 | 322 | } |
| ... | ... | @@ -360,7 +360,7 @@ pub const Inst = struct { |
| 360 | 360 | return new_inst; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | |
| 363 | pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { | |
| 364 | 364 | return self.base.val.KnownValue.getLlvmConst(ofile); |
| 365 | 365 | } |
| 366 | 366 | }; |
| ... | ... | @@ -392,7 +392,7 @@ pub const Inst = struct { |
| 392 | 392 | return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value }); |
| 393 | 393 | } |
| 394 | 394 | |
| 395 | pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | |
| 395 | pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { | |
| 396 | 396 | const value = self.params.return_value.llvm_value; |
| 397 | 397 | const return_type = self.params.return_value.getKnownType(); |
| 398 | 398 | |
| ... | ... | @@ -540,7 +540,7 @@ pub const Inst = struct { |
| 540 | 540 | } |
| 541 | 541 | } |
| 542 | 542 | |
| 543 | pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) llvm.ValueRef { | |
| 543 | pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value { | |
| 544 | 544 | switch (self.params.var_scope.data) { |
| 545 | 545 | Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass |
| 546 | 546 | Scope.Var.Data.Param => |param| return param.llvm_value, |
| ... | ... | @@ -596,7 +596,7 @@ pub const Inst = struct { |
| 596 | 596 | return new_inst; |
| 597 | 597 | } |
| 598 | 598 | |
| 599 | pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | |
| 599 | pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { | |
| 600 | 600 | const child_type = self.base.getKnownType(); |
| 601 | 601 | if (!child_type.hasBits()) { |
| 602 | 602 | return null; |
| ... | ... | @@ -935,8 +935,8 @@ pub const BasicBlock = struct { |
| 935 | 935 | ref_instruction: ?*Inst, |
| 936 | 936 | |
| 937 | 937 | /// for codegen |
| 938 | llvm_block: llvm.BasicBlockRef, | |
| 939 | llvm_exit_block: llvm.BasicBlockRef, | |
| 938 | llvm_block: *llvm.BasicBlock, | |
| 939 | llvm_exit_block: *llvm.BasicBlock, | |
| 940 | 940 | |
| 941 | 941 | /// the basic block that is derived from this one in analysis |
| 942 | 942 | child: ?*BasicBlock, |
src-self-hosted/libc_installation.zig+13-13| ... | ... | @@ -154,8 +154,8 @@ pub const LibCInstallation = struct { |
| 154 | 154 | c.ZigFindWindowsSdkError.None => { |
| 155 | 155 | windows_sdk = sdk; |
| 156 | 156 | |
| 157 | if (sdk.msvc_lib_dir_ptr) |ptr| { | |
| 158 | self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]); | |
| 157 | if (sdk.msvc_lib_dir_ptr != 0) { | |
| 158 | self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); | |
| 159 | 159 | } |
| 160 | 160 | try group.call(findNativeKernel32LibDir, self, loop, sdk); |
| 161 | 161 | try group.call(findNativeIncludeDirWindows, self, loop, sdk); |
| ... | ... | @@ -172,7 +172,7 @@ pub const LibCInstallation = struct { |
| 172 | 172 | try group.call(findNativeStaticLibDir, self, loop); |
| 173 | 173 | try group.call(findNativeDynamicLinker, self, loop); |
| 174 | 174 | }, |
| 175 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 175 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 176 | 176 | self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); |
| 177 | 177 | }, |
| 178 | 178 | else => @compileError("unimplemented: find libc for this OS"), |
| ... | ... | @@ -283,7 +283,7 @@ pub const LibCInstallation = struct { |
| 283 | 283 | switch (builtin.arch) { |
| 284 | 284 | builtin.Arch.i386 => try stream.write("x86"), |
| 285 | 285 | builtin.Arch.x86_64 => try stream.write("x64"), |
| 286 | builtin.Arch.aarch64v8 => try stream.write("arm"), | |
| 286 | builtin.Arch.aarch64 => try stream.write("arm"), | |
| 287 | 287 | else => return error.UnsupportedArchitecture, |
| 288 | 288 | } |
| 289 | 289 | const ucrt_lib_path = try std.os.path.join( |
| ... | ... | @@ -361,7 +361,7 @@ pub const LibCInstallation = struct { |
| 361 | 361 | switch (builtin.arch) { |
| 362 | 362 | builtin.Arch.i386 => try stream.write("x86\\"), |
| 363 | 363 | builtin.Arch.x86_64 => try stream.write("x64\\"), |
| 364 | builtin.Arch.aarch64v8 => try stream.write("arm\\"), | |
| 364 | builtin.Arch.aarch64 => try stream.write("arm\\"), | |
| 365 | 365 | else => return error.UnsupportedArchitecture, |
| 366 | 366 | } |
| 367 | 367 | const kernel32_path = try std.os.path.join( |
| ... | ... | @@ -437,20 +437,20 @@ const Search = struct { |
| 437 | 437 | |
| 438 | 438 | fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search { |
| 439 | 439 | var search_end: usize = 0; |
| 440 | if (sdk.path10_ptr) |path10_ptr| { | |
| 441 | if (sdk.version10_ptr) |ver10_ptr| { | |
| 440 | if (sdk.path10_ptr != 0) { | |
| 441 | if (sdk.version10_ptr != 0) { | |
| 442 | 442 | search_buf[search_end] = Search{ |
| 443 | .path = path10_ptr[0..sdk.path10_len], | |
| 444 | .version = ver10_ptr[0..sdk.version10_len], | |
| 443 | .path = sdk.path10_ptr[0..sdk.path10_len], | |
| 444 | .version = sdk.version10_ptr[0..sdk.version10_len], | |
| 445 | 445 | }; |
| 446 | 446 | search_end += 1; |
| 447 | 447 | } |
| 448 | 448 | } |
| 449 | if (sdk.path81_ptr) |path81_ptr| { | |
| 450 | if (sdk.version81_ptr) |ver81_ptr| { | |
| 449 | if (sdk.path81_ptr != 0) { | |
| 450 | if (sdk.version81_ptr != 0) { | |
| 451 | 451 | search_buf[search_end] = Search{ |
| 452 | .path = path81_ptr[0..sdk.path81_len], | |
| 453 | .version = ver81_ptr[0..sdk.version81_len], | |
| 452 | .path = sdk.path81_ptr[0..sdk.path81_len], | |
| 453 | .version = sdk.version81_ptr[0..sdk.version81_len], | |
| 454 | 454 | }; |
| 455 | 455 | search_end += 1; |
| 456 | 456 | } |
src-self-hosted/link.zig+2-6| ... | ... | @@ -145,10 +145,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 145 | 145 | // lj->args.append("-T"); |
| 146 | 146 | // lj->args.append(g->linker_script); |
| 147 | 147 | //} |
| 148 | ||
| 149 | //if (g->no_rosegment_workaround) { | |
| 150 | // lj->args.append("--no-rosegment"); | |
| 151 | //} | |
| 152 | 148 | try ctx.args.append(c"--gc-sections"); |
| 153 | 149 | |
| 154 | 150 | //lj->args.append("-m"); |
| ... | ... | @@ -330,7 +326,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { |
| 330 | 326 | switch (ctx.comp.target.getArch()) { |
| 331 | 327 | builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"), |
| 332 | 328 | builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"), |
| 333 | builtin.Arch.aarch64v8 => try ctx.args.append(c"-MACHINE:ARM"), | |
| 329 | builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"), | |
| 334 | 330 | else => return error.UnsupportedLinkArchitecture, |
| 335 | 331 | } |
| 336 | 332 | |
| ... | ... | @@ -556,7 +552,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 556 | 552 | } |
| 557 | 553 | }, |
| 558 | 554 | DarwinPlatform.Kind.IPhoneOS => { |
| 559 | if (ctx.comp.target.getArch() == builtin.Arch.aarch64v8) { | |
| 555 | if (ctx.comp.target.getArch() == builtin.Arch.aarch64) { | |
| 560 | 556 | // iOS does not need any crt1 files for arm64 |
| 561 | 557 | } else if (platform.versionLessThan(3, 1)) { |
| 562 | 558 | try ctx.args.append(c"-lcrt1.o"); |
src-self-hosted/llvm.zig+129-52| ... | ... | @@ -11,45 +11,31 @@ const assert = @import("std").debug.assert; |
| 11 | 11 | pub const AttributeIndex = c_uint; |
| 12 | 12 | pub const Bool = c_int; |
| 13 | 13 | |
| 14 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); | |
| 15 | pub const ContextRef = removeNullability(c.LLVMContextRef); | |
| 16 | pub const ModuleRef = removeNullability(c.LLVMModuleRef); | |
| 17 | pub const ValueRef = removeNullability(c.LLVMValueRef); | |
| 18 | pub const TypeRef = removeNullability(c.LLVMTypeRef); | |
| 19 | pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef); | |
| 20 | pub const AttributeRef = removeNullability(c.LLVMAttributeRef); | |
| 21 | pub const TargetRef = removeNullability(c.LLVMTargetRef); | |
| 22 | pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef); | |
| 23 | pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef); | |
| 14 | pub const Builder = c.LLVMBuilderRef.Child.Child; | |
| 15 | pub const Context = c.LLVMContextRef.Child.Child; | |
| 16 | pub const Module = c.LLVMModuleRef.Child.Child; | |
| 17 | pub const Value = c.LLVMValueRef.Child.Child; | |
| 18 | pub const Type = c.LLVMTypeRef.Child.Child; | |
| 19 | pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child; | |
| 20 | pub const Attribute = c.LLVMAttributeRef.Child.Child; | |
| 21 | pub const Target = c.LLVMTargetRef.Child.Child; | |
| 22 | pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child; | |
| 23 | pub const TargetData = c.LLVMTargetDataRef.Child.Child; | |
| 24 | 24 | pub const DIBuilder = c.ZigLLVMDIBuilder; |
| 25 | pub const DIFile = c.ZigLLVMDIFile; | |
| 26 | pub const DICompileUnit = c.ZigLLVMDICompileUnit; | |
| 25 | 27 | |
| 26 | 28 | pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType; |
| 27 | 29 | pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex; |
| 28 | pub const AddFunction = c.LLVMAddFunction; | |
| 29 | pub const AddGlobal = c.LLVMAddGlobal; | |
| 30 | 30 | pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag; |
| 31 | 31 | pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag; |
| 32 | pub const ArrayType = c.LLVMArrayType; | |
| 33 | pub const BuildLoad = c.LLVMBuildLoad; | |
| 34 | 32 | pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation; |
| 35 | 33 | pub const ConstAllOnes = c.LLVMConstAllOnes; |
| 36 | 34 | pub const ConstArray = c.LLVMConstArray; |
| 37 | 35 | pub const ConstBitCast = c.LLVMConstBitCast; |
| 38 | pub const ConstInt = c.LLVMConstInt; | |
| 39 | 36 | pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision; |
| 40 | 37 | pub const ConstNeg = c.LLVMConstNeg; |
| 41 | pub const ConstNull = c.LLVMConstNull; | |
| 42 | pub const ConstStringInContext = c.LLVMConstStringInContext; | |
| 43 | 38 | pub const ConstStructInContext = c.LLVMConstStructInContext; |
| 44 | pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData; | |
| 45 | pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext; | |
| 46 | pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit; | |
| 47 | pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder; | |
| 48 | pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute; | |
| 49 | pub const CreateFile = c.ZigLLVMCreateFile; | |
| 50 | pub const CreateStringAttribute = c.LLVMCreateStringAttribute; | |
| 51 | pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout; | |
| 52 | pub const CreateTargetMachine = c.LLVMCreateTargetMachine; | |
| 53 | 39 | pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize; |
| 54 | 40 | pub const DisposeBuilder = c.LLVMDisposeBuilder; |
| 55 | 41 | pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder; |
| ... | ... | @@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule; |
| 62 | 48 | pub const FP128TypeInContext = c.LLVMFP128TypeInContext; |
| 63 | 49 | pub const FloatTypeInContext = c.LLVMFloatTypeInContext; |
| 64 | 50 | pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName; |
| 65 | pub const GetHostCPUName = c.ZigLLVMGetHostCPUName; | |
| 66 | 51 | pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext; |
| 67 | pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures; | |
| 68 | 52 | pub const GetUndef = c.LLVMGetUndef; |
| 69 | 53 | pub const HalfTypeInContext = c.LLVMHalfTypeInContext; |
| 70 | 54 | pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers; |
| ... | ... | @@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext; |
| 81 | 65 | pub const Int8TypeInContext = c.LLVMInt8TypeInContext; |
| 82 | 66 | pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext; |
| 83 | 67 | pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext; |
| 84 | pub const IntTypeInContext = c.LLVMIntTypeInContext; | |
| 85 | 68 | pub const LabelTypeInContext = c.LLVMLabelTypeInContext; |
| 86 | 69 | pub const MDNodeInContext = c.LLVMMDNodeInContext; |
| 87 | 70 | pub const MDStringInContext = c.LLVMMDStringInContext; |
| 88 | 71 | pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext; |
| 89 | pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext; | |
| 90 | 72 | pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext; |
| 91 | pub const PointerType = c.LLVMPointerType; | |
| 92 | 73 | pub const SetAlignment = c.LLVMSetAlignment; |
| 93 | 74 | pub const SetDataLayout = c.LLVMSetDataLayout; |
| 94 | 75 | pub const SetGlobalConstant = c.LLVMSetGlobalConstant; |
| ... | ... | @@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr; |
| 99 | 80 | pub const SetVolatile = c.LLVMSetVolatile; |
| 100 | 81 | pub const StructTypeInContext = c.LLVMStructTypeInContext; |
| 101 | 82 | pub const TokenTypeInContext = c.LLVMTokenTypeInContext; |
| 102 | pub const VoidTypeInContext = c.LLVMVoidTypeInContext; | |
| 103 | 83 | pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext; |
| 104 | 84 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; |
| 105 | 85 | |
| 86 | pub const AddGlobal = LLVMAddGlobal; | |
| 87 | extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value; | |
| 88 | ||
| 89 | pub const ConstStringInContext = LLVMConstStringInContext; | |
| 90 | extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value; | |
| 91 | ||
| 92 | pub const ConstInt = LLVMConstInt; | |
| 93 | extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value; | |
| 94 | ||
| 95 | pub const BuildLoad = LLVMBuildLoad; | |
| 96 | extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value; | |
| 97 | ||
| 98 | pub const ConstNull = LLVMConstNull; | |
| 99 | extern fn LLVMConstNull(Ty: *Type) ?*Value; | |
| 100 | ||
| 101 | pub const CreateStringAttribute = LLVMCreateStringAttribute; | |
| 102 | extern fn LLVMCreateStringAttribute( | |
| 103 | C: *Context, | |
| 104 | K: [*]const u8, | |
| 105 | KLength: c_uint, | |
| 106 | V: [*]const u8, | |
| 107 | VLength: c_uint, | |
| 108 | ) ?*Attribute; | |
| 109 | ||
| 110 | pub const CreateEnumAttribute = LLVMCreateEnumAttribute; | |
| 111 | extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute; | |
| 112 | ||
| 113 | pub const AddFunction = LLVMAddFunction; | |
| 114 | extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value; | |
| 115 | ||
| 116 | pub const CreateCompileUnit = ZigLLVMCreateCompileUnit; | |
| 117 | extern fn ZigLLVMCreateCompileUnit( | |
| 118 | dibuilder: *DIBuilder, | |
| 119 | lang: c_uint, | |
| 120 | difile: *DIFile, | |
| 121 | producer: [*]const u8, | |
| 122 | is_optimized: bool, | |
| 123 | flags: [*]const u8, | |
| 124 | runtime_version: c_uint, | |
| 125 | split_name: [*]const u8, | |
| 126 | dwo_id: u64, | |
| 127 | emit_debug_info: bool, | |
| 128 | ) ?*DICompileUnit; | |
| 129 | ||
| 130 | pub const CreateFile = ZigLLVMCreateFile; | |
| 131 | extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile; | |
| 132 | ||
| 133 | pub const ArrayType = LLVMArrayType; | |
| 134 | extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type; | |
| 135 | ||
| 136 | pub const CreateDIBuilder = ZigLLVMCreateDIBuilder; | |
| 137 | extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder; | |
| 138 | ||
| 139 | pub const PointerType = LLVMPointerType; | |
| 140 | extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type; | |
| 141 | ||
| 142 | pub const CreateBuilderInContext = LLVMCreateBuilderInContext; | |
| 143 | extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder; | |
| 144 | ||
| 145 | pub const IntTypeInContext = LLVMIntTypeInContext; | |
| 146 | extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type; | |
| 147 | ||
| 148 | pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext; | |
| 149 | extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module; | |
| 150 | ||
| 151 | pub const VoidTypeInContext = LLVMVoidTypeInContext; | |
| 152 | extern fn LLVMVoidTypeInContext(C: *Context) ?*Type; | |
| 153 | ||
| 154 | pub const ContextCreate = LLVMContextCreate; | |
| 155 | extern fn LLVMContextCreate() ?*Context; | |
| 156 | ||
| 157 | pub const ContextDispose = LLVMContextDispose; | |
| 158 | extern fn LLVMContextDispose(C: *Context) void; | |
| 159 | ||
| 160 | pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData; | |
| 161 | extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8; | |
| 162 | ||
| 163 | pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout; | |
| 164 | extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData; | |
| 165 | ||
| 166 | pub const CreateTargetMachine = LLVMCreateTargetMachine; | |
| 167 | extern fn LLVMCreateTargetMachine( | |
| 168 | T: *Target, | |
| 169 | Triple: [*]const u8, | |
| 170 | CPU: [*]const u8, | |
| 171 | Features: [*]const u8, | |
| 172 | Level: CodeGenOptLevel, | |
| 173 | Reloc: RelocMode, | |
| 174 | CodeModel: CodeModel, | |
| 175 | ) ?*TargetMachine; | |
| 176 | ||
| 177 | pub const GetHostCPUName = LLVMGetHostCPUName; | |
| 178 | extern fn LLVMGetHostCPUName() ?[*]u8; | |
| 179 | ||
| 180 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | |
| 181 | extern fn ZigLLVMGetNativeFeatures() ?[*]u8; | |
| 182 | ||
| 106 | 183 | pub const GetElementType = LLVMGetElementType; |
| 107 | extern fn LLVMGetElementType(Ty: TypeRef) TypeRef; | |
| 184 | extern fn LLVMGetElementType(Ty: *Type) *Type; | |
| 108 | 185 | |
| 109 | 186 | pub const TypeOf = LLVMTypeOf; |
| 110 | extern fn LLVMTypeOf(Val: ValueRef) TypeRef; | |
| 187 | extern fn LLVMTypeOf(Val: *Value) *Type; | |
| 111 | 188 | |
| 112 | 189 | pub const BuildStore = LLVMBuildStore; |
| 113 | extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef; | |
| 190 | extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value; | |
| 114 | 191 | |
| 115 | 192 | pub const BuildAlloca = LLVMBuildAlloca; |
| 116 | extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef; | |
| 193 | extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value; | |
| 117 | 194 | |
| 118 | 195 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; |
| 119 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef; | |
| 196 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value; | |
| 120 | 197 | |
| 121 | 198 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; |
| 122 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool; | |
| 199 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool; | |
| 123 | 200 | |
| 124 | 201 | pub const VerifyModule = LLVMVerifyModule; |
| 125 | extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; | |
| 202 | extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; | |
| 126 | 203 | |
| 127 | 204 | pub const GetInsertBlock = LLVMGetInsertBlock; |
| 128 | extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef; | |
| 205 | extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock; | |
| 129 | 206 | |
| 130 | 207 | pub const FunctionType = LLVMFunctionType; |
| 131 | 208 | extern fn LLVMFunctionType( |
| 132 | ReturnType: TypeRef, | |
| 133 | ParamTypes: [*]TypeRef, | |
| 209 | ReturnType: *Type, | |
| 210 | ParamTypes: [*]*Type, | |
| 134 | 211 | ParamCount: c_uint, |
| 135 | 212 | IsVarArg: Bool, |
| 136 | ) ?TypeRef; | |
| 213 | ) ?*Type; | |
| 137 | 214 | |
| 138 | 215 | pub const GetParam = LLVMGetParam; |
| 139 | extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef; | |
| 216 | extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; | |
| 140 | 217 | |
| 141 | 218 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; |
| 142 | extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef; | |
| 219 | extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock; | |
| 143 | 220 | |
| 144 | 221 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; |
| 145 | extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void; | |
| 222 | extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void; | |
| 146 | 223 | |
| 147 | 224 | pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction; |
| 148 | 225 | pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction; |
| ... | ... | @@ -190,17 +267,17 @@ pub const FnInline = extern enum { |
| 190 | 267 | }; |
| 191 | 268 | |
| 192 | 269 | fn removeNullability(comptime T: type) type { |
| 193 | comptime assert(@typeId(T) == builtin.TypeId.Optional); | |
| 194 | return T.Child; | |
| 270 | comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C); | |
| 271 | return *T.Child; | |
| 195 | 272 | } |
| 196 | 273 | |
| 197 | 274 | pub const BuildRet = LLVMBuildRet; |
| 198 | extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef; | |
| 275 | extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value; | |
| 199 | 276 | |
| 200 | 277 | pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; |
| 201 | 278 | extern fn ZigLLVMTargetMachineEmitToFile( |
| 202 | targ_machine_ref: TargetMachineRef, | |
| 203 | module_ref: ModuleRef, | |
| 279 | targ_machine_ref: *TargetMachine, | |
| 280 | module_ref: *Module, | |
| 204 | 281 | filename: [*]const u8, |
| 205 | 282 | output_type: EmitOutputType, |
| 206 | 283 | error_message: *[*]u8, |
| ... | ... | @@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile( |
| 209 | 286 | ) bool; |
| 210 | 287 | |
| 211 | 288 | pub const BuildCall = ZigLLVMBuildCall; |
| 212 | extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef; | |
| 289 | extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value; | |
| 213 | 290 | |
| 214 | 291 | pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage; |
src-self-hosted/main.zig+10-14| ... | ... | @@ -24,7 +24,7 @@ var stderr_file: os.File = undefined; |
| 24 | 24 | var stderr: *io.OutStream(os.File.WriteError) = undefined; |
| 25 | 25 | var stdout: *io.OutStream(os.File.WriteError) = undefined; |
| 26 | 26 | |
| 27 | const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB | |
| 27 | pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB | |
| 28 | 28 | |
| 29 | 29 | const usage = |
| 30 | 30 | \\usage: zig [command] [options] |
| ... | ... | @@ -154,9 +154,7 @@ const usage_build_generic = |
| 154 | 154 | \\ release-small optimize for small binary, safety off |
| 155 | 155 | \\ --static Output will be statically linked |
| 156 | 156 | \\ --strip Exclude debug symbols |
| 157 | \\ --target-arch [name] Specify target architecture | |
| 158 | \\ --target-environ [name] Specify target environment | |
| 159 | \\ --target-os [name] Specify target operating system | |
| 157 | \\ -target [name] <arch><sub>-<os>-<abi> see the targets command | |
| 160 | 158 | \\ --verbose-tokenize Turn on compiler debug output for tokenization |
| 161 | 159 | \\ --verbose-ast-tree Turn on compiler debug output for parsing into an AST (tree view) |
| 162 | 160 | \\ --verbose-ast-fmt Turn on compiler debug output for parsing into an AST (render source) |
| ... | ... | @@ -220,9 +218,7 @@ const args_build_generic = []Flag{ |
| 220 | 218 | Flag.Bool("--pkg-end"), |
| 221 | 219 | Flag.Bool("--static"), |
| 222 | 220 | Flag.Bool("--strip"), |
| 223 | Flag.Arg1("--target-arch"), | |
| 224 | Flag.Arg1("--target-environ"), | |
| 225 | Flag.Arg1("--target-os"), | |
| 221 | Flag.Arg1("-target"), | |
| 226 | 222 | Flag.Bool("--verbose-tokenize"), |
| 227 | 223 | Flag.Bool("--verbose-ast-tree"), |
| 228 | 224 | Flag.Bool("--verbose-ast-fmt"), |
| ... | ... | @@ -510,7 +506,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void { |
| 510 | 506 | return buildOutputType(allocator, args, Compilation.Kind.Obj); |
| 511 | 507 | } |
| 512 | 508 | |
| 513 | const usage_fmt = | |
| 509 | pub const usage_fmt = | |
| 514 | 510 | \\usage: zig fmt [file]... |
| 515 | 511 | \\ |
| 516 | 512 | \\ Formats the input files and modifies them in-place. |
| ... | ... | @@ -527,7 +523,7 @@ const usage_fmt = |
| 527 | 523 | \\ |
| 528 | 524 | ; |
| 529 | 525 | |
| 530 | const args_fmt_spec = []Flag{ | |
| 526 | pub const args_fmt_spec = []Flag{ | |
| 531 | 527 | Flag.Bool("--help"), |
| 532 | 528 | Flag.Bool("--check"), |
| 533 | 529 | Flag.Option("--color", []const []const u8{ |
| ... | ... | @@ -839,15 +835,15 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void { |
| 839 | 835 | } |
| 840 | 836 | try stdout.write("\n"); |
| 841 | 837 | |
| 842 | try stdout.write("Environments:\n"); | |
| 838 | try stdout.write("C ABIs:\n"); | |
| 843 | 839 | { |
| 844 | 840 | comptime var i: usize = 0; |
| 845 | inline while (i < @memberCount(builtin.Environ)) : (i += 1) { | |
| 846 | comptime const environ_tag = @memberName(builtin.Environ, i); | |
| 841 | inline while (i < @memberCount(builtin.Abi)) : (i += 1) { | |
| 842 | comptime const abi_tag = @memberName(builtin.Abi, i); | |
| 847 | 843 | // NOTE: Cannot use empty string, see #918. |
| 848 | comptime const native_str = if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n"; | |
| 844 | comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n"; | |
| 849 | 845 | |
| 850 | try stdout.print(" {}{}", environ_tag, native_str); | |
| 846 | try stdout.print(" {}{}", abi_tag, native_str); | |
| 851 | 847 | } |
| 852 | 848 | } |
| 853 | 849 | } |
src-self-hosted/scope.zig+1-1| ... | ... | @@ -362,7 +362,7 @@ pub const Scope = struct { |
| 362 | 362 | pub const Param = struct { |
| 363 | 363 | index: usize, |
| 364 | 364 | typ: *Type, |
| 365 | llvm_value: llvm.ValueRef, | |
| 365 | llvm_value: *llvm.Value, | |
| 366 | 366 | }; |
| 367 | 367 | |
| 368 | 368 | pub fn createParam( |
src-self-hosted/target.zig+47-234| ... | ... | @@ -16,7 +16,7 @@ pub const Target = union(enum) { |
| 16 | 16 | pub const Cross = struct { |
| 17 | 17 | arch: builtin.Arch, |
| 18 | 18 | os: builtin.Os, |
| 19 | environ: builtin.Environ, | |
| 19 | abi: builtin.Abi, | |
| 20 | 20 | object_format: builtin.ObjectFormat, |
| 21 | 21 | }; |
| 22 | 22 | |
| ... | ... | @@ -49,16 +49,16 @@ pub const Target = union(enum) { |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | pub fn getArch(self: Target) builtin.Arch { |
| 52 | return switch (self) { | |
| 53 | Target.Native => builtin.arch, | |
| 54 | @TagType(Target).Cross => |t| t.arch, | |
| 55 | }; | |
| 52 | switch (self) { | |
| 53 | Target.Native => return builtin.arch, | |
| 54 | @TagType(Target).Cross => |t| return t.arch, | |
| 55 | } | |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | pub fn getEnviron(self: Target) builtin.Environ { | |
| 58 | pub fn getAbi(self: Target) builtin.Abi { | |
| 59 | 59 | return switch (self) { |
| 60 | Target.Native => builtin.environ, | |
| 61 | @TagType(Target).Cross => |t| t.environ, | |
| 60 | Target.Native => builtin.abi, | |
| 61 | @TagType(Target).Cross => |t| t.abi, | |
| 62 | 62 | }; |
| 63 | 63 | } |
| 64 | 64 | |
| ... | ... | @@ -93,50 +93,10 @@ pub const Target = union(enum) { |
| 93 | 93 | /// TODO expose the arch and subarch separately |
| 94 | 94 | pub fn isArmOrThumb(self: Target) bool { |
| 95 | 95 | return switch (self.getArch()) { |
| 96 | builtin.Arch.armv8_5a, | |
| 97 | builtin.Arch.armv8_4a, | |
| 98 | builtin.Arch.armv8_3a, | |
| 99 | builtin.Arch.armv8_2a, | |
| 100 | builtin.Arch.armv8_1a, | |
| 101 | builtin.Arch.armv8, | |
| 102 | builtin.Arch.armv8r, | |
| 103 | builtin.Arch.armv8m_baseline, | |
| 104 | builtin.Arch.armv8m_mainline, | |
| 105 | builtin.Arch.armv7, | |
| 106 | builtin.Arch.armv7em, | |
| 107 | builtin.Arch.armv7m, | |
| 108 | builtin.Arch.armv7s, | |
| 109 | builtin.Arch.armv7k, | |
| 110 | builtin.Arch.armv7ve, | |
| 111 | builtin.Arch.armv6, | |
| 112 | builtin.Arch.armv6m, | |
| 113 | builtin.Arch.armv6k, | |
| 114 | builtin.Arch.armv6t2, | |
| 115 | builtin.Arch.armv5, | |
| 116 | builtin.Arch.armv5te, | |
| 117 | builtin.Arch.armv4t, | |
| 118 | builtin.Arch.armebv8_5a, | |
| 119 | builtin.Arch.armebv8_4a, | |
| 120 | builtin.Arch.armebv8_3a, | |
| 121 | builtin.Arch.armebv8_2a, | |
| 122 | builtin.Arch.armebv8_1a, | |
| 123 | builtin.Arch.armebv8, | |
| 124 | builtin.Arch.armebv8r, | |
| 125 | builtin.Arch.armebv8m_baseline, | |
| 126 | builtin.Arch.armebv8m_mainline, | |
| 127 | builtin.Arch.armebv7, | |
| 128 | builtin.Arch.armebv7em, | |
| 129 | builtin.Arch.armebv7m, | |
| 130 | builtin.Arch.armebv7s, | |
| 131 | builtin.Arch.armebv7k, | |
| 132 | builtin.Arch.armebv7ve, | |
| 133 | builtin.Arch.armebv6, | |
| 134 | builtin.Arch.armebv6m, | |
| 135 | builtin.Arch.armebv6k, | |
| 136 | builtin.Arch.armebv6t2, | |
| 137 | builtin.Arch.armebv5, | |
| 138 | builtin.Arch.armebv5te, | |
| 139 | builtin.Arch.armebv4t, | |
| 96 | builtin.Arch.arm, | |
| 97 | builtin.Arch.armeb, | |
| 98 | builtin.Arch.aarch64, | |
| 99 | builtin.Arch.aarch64_be, | |
| 140 | 100 | builtin.Arch.thumb, |
| 141 | 101 | builtin.Arch.thumbeb, |
| 142 | 102 | => true, |
| ... | ... | @@ -159,14 +119,14 @@ pub const Target = union(enum) { |
| 159 | 119 | // LLVM WebAssembly output support requires the target to be activated at |
| 160 | 120 | // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly. |
| 161 | 121 | // |
| 162 | // LLVM determines the output format based on the environment suffix, | |
| 122 | // LLVM determines the output format based on the abi suffix, | |
| 163 | 123 | // defaulting to an object based on the architecture. The default format in |
| 164 | 124 | // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to |
| 165 | 125 | // explicitly set this ourself in order for it to work. |
| 166 | 126 | // |
| 167 | 127 | // This is fixed in LLVM 7 and you will be able to get wasm output by |
| 168 | 128 | // using the target triple `wasm32-unknown-unknown-unknown`. |
| 169 | const env_name = if (self.isWasm()) "wasm" else @tagName(self.getEnviron()); | |
| 129 | const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi()); | |
| 170 | 130 | |
| 171 | 131 | var out = &std.io.BufferOutStream.init(&result).stream; |
| 172 | 132 | try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name); |
| ... | ... | @@ -185,50 +145,8 @@ pub const Target = union(enum) { |
| 185 | 145 | => return 16, |
| 186 | 146 | |
| 187 | 147 | builtin.Arch.arc, |
| 188 | builtin.Arch.armv8_5a, | |
| 189 | builtin.Arch.armv8_4a, | |
| 190 | builtin.Arch.armv8_3a, | |
| 191 | builtin.Arch.armv8_2a, | |
| 192 | builtin.Arch.armv8_1a, | |
| 193 | builtin.Arch.armv8, | |
| 194 | builtin.Arch.armv8r, | |
| 195 | builtin.Arch.armv8m_baseline, | |
| 196 | builtin.Arch.armv8m_mainline, | |
| 197 | builtin.Arch.armv7, | |
| 198 | builtin.Arch.armv7em, | |
| 199 | builtin.Arch.armv7m, | |
| 200 | builtin.Arch.armv7s, | |
| 201 | builtin.Arch.armv7k, | |
| 202 | builtin.Arch.armv7ve, | |
| 203 | builtin.Arch.armv6, | |
| 204 | builtin.Arch.armv6m, | |
| 205 | builtin.Arch.armv6k, | |
| 206 | builtin.Arch.armv6t2, | |
| 207 | builtin.Arch.armv5, | |
| 208 | builtin.Arch.armv5te, | |
| 209 | builtin.Arch.armv4t, | |
| 210 | builtin.Arch.armebv8_5a, | |
| 211 | builtin.Arch.armebv8_4a, | |
| 212 | builtin.Arch.armebv8_3a, | |
| 213 | builtin.Arch.armebv8_2a, | |
| 214 | builtin.Arch.armebv8_1a, | |
| 215 | builtin.Arch.armebv8, | |
| 216 | builtin.Arch.armebv8r, | |
| 217 | builtin.Arch.armebv8m_baseline, | |
| 218 | builtin.Arch.armebv8m_mainline, | |
| 219 | builtin.Arch.armebv7, | |
| 220 | builtin.Arch.armebv7em, | |
| 221 | builtin.Arch.armebv7m, | |
| 222 | builtin.Arch.armebv7s, | |
| 223 | builtin.Arch.armebv7k, | |
| 224 | builtin.Arch.armebv7ve, | |
| 225 | builtin.Arch.armebv6, | |
| 226 | builtin.Arch.armebv6m, | |
| 227 | builtin.Arch.armebv6k, | |
| 228 | builtin.Arch.armebv6t2, | |
| 229 | builtin.Arch.armebv5, | |
| 230 | builtin.Arch.armebv5te, | |
| 231 | builtin.Arch.armebv4t, | |
| 148 | builtin.Arch.arm, | |
| 149 | builtin.Arch.armeb, | |
| 232 | 150 | builtin.Arch.hexagon, |
| 233 | 151 | builtin.Arch.le32, |
| 234 | 152 | builtin.Arch.mipsr6, |
| ... | ... | @@ -248,35 +166,17 @@ pub const Target = union(enum) { |
| 248 | 166 | builtin.Arch.amdil, |
| 249 | 167 | builtin.Arch.hsail, |
| 250 | 168 | builtin.Arch.spir, |
| 251 | builtin.Arch.kalimbav3, | |
| 252 | builtin.Arch.kalimbav4, | |
| 253 | builtin.Arch.kalimbav5, | |
| 169 | builtin.Arch.kalimba, | |
| 254 | 170 | builtin.Arch.shave, |
| 255 | 171 | builtin.Arch.lanai, |
| 256 | 172 | builtin.Arch.wasm32, |
| 257 | 173 | builtin.Arch.renderscript32, |
| 258 | 174 | => return 32, |
| 259 | 175 | |
| 260 | builtin.Arch.aarch64v8_5a, | |
| 261 | builtin.Arch.aarch64v8_4a, | |
| 262 | builtin.Arch.aarch64v8_3a, | |
| 263 | builtin.Arch.aarch64v8_2a, | |
| 264 | builtin.Arch.aarch64v8_1a, | |
| 265 | builtin.Arch.aarch64v8, | |
| 266 | builtin.Arch.aarch64v8r, | |
| 267 | builtin.Arch.aarch64v8m_baseline, | |
| 268 | builtin.Arch.aarch64v8m_mainline, | |
| 269 | builtin.Arch.aarch64_bev8_5a, | |
| 270 | builtin.Arch.aarch64_bev8_4a, | |
| 271 | builtin.Arch.aarch64_bev8_3a, | |
| 272 | builtin.Arch.aarch64_bev8_2a, | |
| 273 | builtin.Arch.aarch64_bev8_1a, | |
| 274 | builtin.Arch.aarch64_bev8, | |
| 275 | builtin.Arch.aarch64_bev8r, | |
| 276 | builtin.Arch.aarch64_bev8m_baseline, | |
| 277 | builtin.Arch.aarch64_bev8m_mainline, | |
| 278 | builtin.Arch.mips64r6, | |
| 279 | builtin.Arch.mips64elr6, | |
| 176 | builtin.Arch.aarch64, | |
| 177 | builtin.Arch.aarch64_be, | |
| 178 | builtin.Arch.mips64, | |
| 179 | builtin.Arch.mips64el, | |
| 280 | 180 | builtin.Arch.powerpc64, |
| 281 | 181 | builtin.Arch.powerpc64le, |
| 282 | 182 | builtin.Arch.riscv64, |
| ... | ... | @@ -298,17 +198,17 @@ pub const Target = union(enum) { |
| 298 | 198 | } |
| 299 | 199 | |
| 300 | 200 | pub fn getFloatAbi(self: Target) FloatAbi { |
| 301 | return switch (self.getEnviron()) { | |
| 302 | builtin.Environ.gnueabihf, | |
| 303 | builtin.Environ.eabihf, | |
| 304 | builtin.Environ.musleabihf, | |
| 201 | return switch (self.getAbi()) { | |
| 202 | builtin.Abi.gnueabihf, | |
| 203 | builtin.Abi.eabihf, | |
| 204 | builtin.Abi.musleabihf, | |
| 305 | 205 | => FloatAbi.Hard, |
| 306 | 206 | else => FloatAbi.Soft, |
| 307 | 207 | }; |
| 308 | 208 | } |
| 309 | 209 | |
| 310 | 210 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { |
| 311 | const env = self.getEnviron(); | |
| 211 | const env = self.getAbi(); | |
| 312 | 212 | const arch = self.getArch(); |
| 313 | 213 | const os = self.getOs(); |
| 314 | 214 | switch (os) { |
| ... | ... | @@ -317,21 +217,21 @@ pub const Target = union(enum) { |
| 317 | 217 | }, |
| 318 | 218 | builtin.Os.linux => { |
| 319 | 219 | switch (env) { |
| 320 | builtin.Environ.android => { | |
| 220 | builtin.Abi.android => { | |
| 321 | 221 | if (self.is64bit()) { |
| 322 | 222 | return "/system/bin/linker64"; |
| 323 | 223 | } else { |
| 324 | 224 | return "/system/bin/linker"; |
| 325 | 225 | } |
| 326 | 226 | }, |
| 327 | builtin.Environ.gnux32 => { | |
| 227 | builtin.Abi.gnux32 => { | |
| 328 | 228 | if (arch == builtin.Arch.x86_64) { |
| 329 | 229 | return "/libx32/ld-linux-x32.so.2"; |
| 330 | 230 | } |
| 331 | 231 | }, |
| 332 | builtin.Environ.musl, | |
| 333 | builtin.Environ.musleabi, | |
| 334 | builtin.Environ.musleabihf, | |
| 232 | builtin.Abi.musl, | |
| 233 | builtin.Abi.musleabi, | |
| 234 | builtin.Abi.musleabihf, | |
| 335 | 235 | => { |
| 336 | 236 | if (arch == builtin.Arch.x86_64) { |
| 337 | 237 | return "/lib/ld-musl-x86_64.so.1"; |
| ... | ... | @@ -345,73 +245,18 @@ pub const Target = union(enum) { |
| 345 | 245 | builtin.Arch.sparcel, |
| 346 | 246 | => return "/lib/ld-linux.so.2", |
| 347 | 247 | |
| 348 | builtin.Arch.aarch64v8_5a, | |
| 349 | builtin.Arch.aarch64v8_4a, | |
| 350 | builtin.Arch.aarch64v8_3a, | |
| 351 | builtin.Arch.aarch64v8_2a, | |
| 352 | builtin.Arch.aarch64v8_1a, | |
| 353 | builtin.Arch.aarch64v8, | |
| 354 | builtin.Arch.aarch64v8r, | |
| 355 | builtin.Arch.aarch64v8m_baseline, | |
| 356 | builtin.Arch.aarch64v8m_mainline, | |
| 357 | => return "/lib/ld-linux-aarch64.so.1", | |
| 358 | ||
| 359 | builtin.Arch.aarch64_bev8_5a, | |
| 360 | builtin.Arch.aarch64_bev8_4a, | |
| 361 | builtin.Arch.aarch64_bev8_3a, | |
| 362 | builtin.Arch.aarch64_bev8_2a, | |
| 363 | builtin.Arch.aarch64_bev8_1a, | |
| 364 | builtin.Arch.aarch64_bev8, | |
| 365 | builtin.Arch.aarch64_bev8r, | |
| 366 | builtin.Arch.aarch64_bev8m_baseline, | |
| 367 | builtin.Arch.aarch64_bev8m_mainline, | |
| 368 | => return "/lib/ld-linux-aarch64_be.so.1", | |
| 369 | ||
| 370 | builtin.Arch.armv8_5a, | |
| 371 | builtin.Arch.armv8_4a, | |
| 372 | builtin.Arch.armv8_3a, | |
| 373 | builtin.Arch.armv8_2a, | |
| 374 | builtin.Arch.armv8_1a, | |
| 375 | builtin.Arch.armv8, | |
| 376 | builtin.Arch.armv8r, | |
| 377 | builtin.Arch.armv8m_baseline, | |
| 378 | builtin.Arch.armv8m_mainline, | |
| 379 | builtin.Arch.armv7, | |
| 380 | builtin.Arch.armv7em, | |
| 381 | builtin.Arch.armv7m, | |
| 382 | builtin.Arch.armv7s, | |
| 383 | builtin.Arch.armv7k, | |
| 384 | builtin.Arch.armv7ve, | |
| 385 | builtin.Arch.armv6, | |
| 386 | builtin.Arch.armv6m, | |
| 387 | builtin.Arch.armv6k, | |
| 388 | builtin.Arch.armv6t2, | |
| 389 | builtin.Arch.armv5, | |
| 390 | builtin.Arch.armv5te, | |
| 391 | builtin.Arch.armv4t, | |
| 248 | builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1", | |
| 249 | ||
| 250 | builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1", | |
| 251 | ||
| 252 | builtin.Arch.arm, | |
| 392 | 253 | builtin.Arch.thumb, |
| 393 | builtin.Arch.armebv8_5a, | |
| 394 | builtin.Arch.armebv8_4a, | |
| 395 | builtin.Arch.armebv8_3a, | |
| 396 | builtin.Arch.armebv8_2a, | |
| 397 | builtin.Arch.armebv8_1a, | |
| 398 | builtin.Arch.armebv8, | |
| 399 | builtin.Arch.armebv8r, | |
| 400 | builtin.Arch.armebv8m_baseline, | |
| 401 | builtin.Arch.armebv8m_mainline, | |
| 402 | builtin.Arch.armebv7, | |
| 403 | builtin.Arch.armebv7em, | |
| 404 | builtin.Arch.armebv7m, | |
| 405 | builtin.Arch.armebv7s, | |
| 406 | builtin.Arch.armebv7k, | |
| 407 | builtin.Arch.armebv7ve, | |
| 408 | builtin.Arch.armebv6, | |
| 409 | builtin.Arch.armebv6m, | |
| 410 | builtin.Arch.armebv6k, | |
| 411 | builtin.Arch.armebv6t2, | |
| 412 | builtin.Arch.armebv5, | |
| 413 | builtin.Arch.armebv5te, | |
| 414 | builtin.Arch.armebv4t, | |
| 254 | => return switch (self.getFloatAbi()) { | |
| 255 | FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", | |
| 256 | else => return "/lib/ld-linux.so.3", | |
| 257 | }, | |
| 258 | ||
| 259 | builtin.Arch.armeb, | |
| 415 | 260 | builtin.Arch.thumbeb, |
| 416 | 261 | => return switch (self.getFloatAbi()) { |
| 417 | 262 | FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", |
| ... | ... | @@ -454,9 +299,7 @@ pub const Target = union(enum) { |
| 454 | 299 | builtin.Arch.hsail64, |
| 455 | 300 | builtin.Arch.spir, |
| 456 | 301 | builtin.Arch.spir64, |
| 457 | builtin.Arch.kalimbav3, | |
| 458 | builtin.Arch.kalimbav4, | |
| 459 | builtin.Arch.kalimbav5, | |
| 302 | builtin.Arch.kalimba, | |
| 460 | 303 | builtin.Arch.shave, |
| 461 | 304 | builtin.Arch.lanai, |
| 462 | 305 | builtin.Arch.wasm32, |
| ... | ... | @@ -470,8 +313,8 @@ pub const Target = union(enum) { |
| 470 | 313 | } |
| 471 | 314 | } |
| 472 | 315 | |
| 473 | pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef { | |
| 474 | var result: llvm.TargetRef = undefined; | |
| 316 | pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target { | |
| 317 | var result: *llvm.Target = undefined; | |
| 475 | 318 | var err_msg: [*]u8 = undefined; |
| 476 | 319 | if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) { |
| 477 | 320 | std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg); |
| ... | ... | @@ -582,39 +425,9 @@ pub const Target = union(enum) { |
| 582 | 425 | pub fn getDarwinArchString(self: Target) []const u8 { |
| 583 | 426 | const arch = self.getArch(); |
| 584 | 427 | switch (arch) { |
| 585 | builtin.Arch.aarch64v8_5a, | |
| 586 | builtin.Arch.aarch64v8_4a, | |
| 587 | builtin.Arch.aarch64v8_3a, | |
| 588 | builtin.Arch.aarch64v8_2a, | |
| 589 | builtin.Arch.aarch64v8_1a, | |
| 590 | builtin.Arch.aarch64v8, | |
| 591 | builtin.Arch.aarch64v8r, | |
| 592 | builtin.Arch.aarch64v8m_baseline, | |
| 593 | builtin.Arch.aarch64v8m_mainline, | |
| 594 | => return "arm64", | |
| 428 | builtin.Arch.aarch64 => return "arm64", | |
| 595 | 429 | builtin.Arch.thumb, |
| 596 | builtin.Arch.armv8_5a, | |
| 597 | builtin.Arch.armv8_4a, | |
| 598 | builtin.Arch.armv8_3a, | |
| 599 | builtin.Arch.armv8_2a, | |
| 600 | builtin.Arch.armv8_1a, | |
| 601 | builtin.Arch.armv8, | |
| 602 | builtin.Arch.armv8r, | |
| 603 | builtin.Arch.armv8m_baseline, | |
| 604 | builtin.Arch.armv8m_mainline, | |
| 605 | builtin.Arch.armv7, | |
| 606 | builtin.Arch.armv7em, | |
| 607 | builtin.Arch.armv7m, | |
| 608 | builtin.Arch.armv7s, | |
| 609 | builtin.Arch.armv7k, | |
| 610 | builtin.Arch.armv7ve, | |
| 611 | builtin.Arch.armv6, | |
| 612 | builtin.Arch.armv6m, | |
| 613 | builtin.Arch.armv6k, | |
| 614 | builtin.Arch.armv6t2, | |
| 615 | builtin.Arch.armv5, | |
| 616 | builtin.Arch.armv5te, | |
| 617 | builtin.Arch.armv4t, | |
| 430 | builtin.Arch.arm, | |
| 618 | 431 | => return "arm", |
| 619 | 432 | builtin.Arch.powerpc => return "ppc", |
| 620 | 433 | builtin.Arch.powerpc64 => return "ppc64", |
src-self-hosted/type.zig+23-21| ... | ... | @@ -51,8 +51,8 @@ pub const Type = struct { |
| 51 | 51 | pub fn getLlvmType( |
| 52 | 52 | base: *Type, |
| 53 | 53 | allocator: *Allocator, |
| 54 | llvm_context: llvm.ContextRef, | |
| 55 | ) (error{OutOfMemory}!llvm.TypeRef) { | |
| 54 | llvm_context: *llvm.Context, | |
| 55 | ) (error{OutOfMemory}!*llvm.Type) { | |
| 56 | 56 | switch (base.id) { |
| 57 | 57 | Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context), |
| 58 | 58 | Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context), |
| ... | ... | @@ -196,7 +196,7 @@ pub const Type = struct { |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | 198 | /// If you have an llvm conext handy, you can use it here. |
| 199 | pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 { | |
| 199 | pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 { | |
| 200 | 200 | if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*; |
| 201 | 201 | |
| 202 | 202 | base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable); |
| ... | ... | @@ -205,7 +205,7 @@ pub const Type = struct { |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | 207 | /// Lower level function that does the work. See getAbiAlignment. |
| 208 | async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 { | |
| 208 | async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 { | |
| 209 | 209 | const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context); |
| 210 | 210 | return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type)); |
| 211 | 211 | } |
| ... | ... | @@ -218,7 +218,7 @@ pub const Type = struct { |
| 218 | 218 | comp.gpa().destroy(self); |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 221 | pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 222 | 222 | @panic("TODO"); |
| 223 | 223 | } |
| 224 | 224 | }; |
| ... | ... | @@ -496,13 +496,13 @@ pub const Type = struct { |
| 496 | 496 | comp.gpa().destroy(self); |
| 497 | 497 | } |
| 498 | 498 | |
| 499 | pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | |
| 499 | pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { | |
| 500 | 500 | const normal = &self.key.data.Normal; |
| 501 | 501 | const llvm_return_type = switch (normal.return_type.id) { |
| 502 | 502 | Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory, |
| 503 | 503 | else => try normal.return_type.getLlvmType(allocator, llvm_context), |
| 504 | 504 | }; |
| 505 | const llvm_param_types = try allocator.alloc(llvm.TypeRef, normal.params.len); | |
| 505 | const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len); | |
| 506 | 506 | defer allocator.free(llvm_param_types); |
| 507 | 507 | for (llvm_param_types) |*llvm_param_type, i| { |
| 508 | 508 | llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context); |
| ... | ... | @@ -559,7 +559,7 @@ pub const Type = struct { |
| 559 | 559 | comp.gpa().destroy(self); |
| 560 | 560 | } |
| 561 | 561 | |
| 562 | pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 562 | pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 563 | 563 | @panic("TODO"); |
| 564 | 564 | } |
| 565 | 565 | }; |
| ... | ... | @@ -658,7 +658,7 @@ pub const Type = struct { |
| 658 | 658 | comp.gpa().destroy(self); |
| 659 | 659 | } |
| 660 | 660 | |
| 661 | pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | |
| 661 | pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { | |
| 662 | 662 | return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory; |
| 663 | 663 | } |
| 664 | 664 | }; |
| ... | ... | @@ -670,7 +670,7 @@ pub const Type = struct { |
| 670 | 670 | comp.gpa().destroy(self); |
| 671 | 671 | } |
| 672 | 672 | |
| 673 | pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 673 | pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 674 | 674 | @panic("TODO"); |
| 675 | 675 | } |
| 676 | 676 | }; |
| ... | ... | @@ -794,6 +794,7 @@ pub const Type = struct { |
| 794 | 794 | Size.One => "*", |
| 795 | 795 | Size.Many => "[*]", |
| 796 | 796 | Size.Slice => "[]", |
| 797 | Size.C => "[*c]", | |
| 797 | 798 | }; |
| 798 | 799 | const mut_str = switch (self.key.mut) { |
| 799 | 800 | Mut.Const => "const ", |
| ... | ... | @@ -835,7 +836,7 @@ pub const Type = struct { |
| 835 | 836 | return self; |
| 836 | 837 | } |
| 837 | 838 | |
| 838 | pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | |
| 839 | pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { | |
| 839 | 840 | const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context); |
| 840 | 841 | return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory; |
| 841 | 842 | } |
| ... | ... | @@ -903,7 +904,7 @@ pub const Type = struct { |
| 903 | 904 | return self; |
| 904 | 905 | } |
| 905 | 906 | |
| 906 | pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | |
| 907 | pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { | |
| 907 | 908 | const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context); |
| 908 | 909 | return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory; |
| 909 | 910 | } |
| ... | ... | @@ -916,7 +917,7 @@ pub const Type = struct { |
| 916 | 917 | comp.gpa().destroy(self); |
| 917 | 918 | } |
| 918 | 919 | |
| 919 | pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 920 | pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 920 | 921 | @panic("TODO"); |
| 921 | 922 | } |
| 922 | 923 | }; |
| ... | ... | @@ -966,7 +967,7 @@ pub const Type = struct { |
| 966 | 967 | comp.gpa().destroy(self); |
| 967 | 968 | } |
| 968 | 969 | |
| 969 | pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 970 | pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 970 | 971 | @panic("TODO"); |
| 971 | 972 | } |
| 972 | 973 | }; |
| ... | ... | @@ -978,7 +979,7 @@ pub const Type = struct { |
| 978 | 979 | comp.gpa().destroy(self); |
| 979 | 980 | } |
| 980 | 981 | |
| 981 | pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 982 | pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 982 | 983 | @panic("TODO"); |
| 983 | 984 | } |
| 984 | 985 | }; |
| ... | ... | @@ -990,7 +991,7 @@ pub const Type = struct { |
| 990 | 991 | comp.gpa().destroy(self); |
| 991 | 992 | } |
| 992 | 993 | |
| 993 | pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 994 | pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 994 | 995 | @panic("TODO"); |
| 995 | 996 | } |
| 996 | 997 | }; |
| ... | ... | @@ -1002,7 +1003,7 @@ pub const Type = struct { |
| 1002 | 1003 | comp.gpa().destroy(self); |
| 1003 | 1004 | } |
| 1004 | 1005 | |
| 1005 | pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 1006 | pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 1006 | 1007 | @panic("TODO"); |
| 1007 | 1008 | } |
| 1008 | 1009 | }; |
| ... | ... | @@ -1014,7 +1015,7 @@ pub const Type = struct { |
| 1014 | 1015 | comp.gpa().destroy(self); |
| 1015 | 1016 | } |
| 1016 | 1017 | |
| 1017 | pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 1018 | pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 1018 | 1019 | @panic("TODO"); |
| 1019 | 1020 | } |
| 1020 | 1021 | }; |
| ... | ... | @@ -1034,7 +1035,7 @@ pub const Type = struct { |
| 1034 | 1035 | comp.gpa().destroy(self); |
| 1035 | 1036 | } |
| 1036 | 1037 | |
| 1037 | pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 1038 | pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 1038 | 1039 | @panic("TODO"); |
| 1039 | 1040 | } |
| 1040 | 1041 | }; |
| ... | ... | @@ -1054,7 +1055,7 @@ pub const Type = struct { |
| 1054 | 1055 | comp.gpa().destroy(self); |
| 1055 | 1056 | } |
| 1056 | 1057 | |
| 1057 | pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 1058 | pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 1058 | 1059 | @panic("TODO"); |
| 1059 | 1060 | } |
| 1060 | 1061 | }; |
| ... | ... | @@ -1066,7 +1067,7 @@ pub const Type = struct { |
| 1066 | 1067 | comp.gpa().destroy(self); |
| 1067 | 1068 | } |
| 1068 | 1069 | |
| 1069 | pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | |
| 1070 | pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | |
| 1070 | 1071 | @panic("TODO"); |
| 1071 | 1072 | } |
| 1072 | 1073 | }; |
| ... | ... | @@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 { |
| 1088 | 1089 | builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed), |
| 1089 | 1090 | builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"), |
| 1090 | 1091 | builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"), |
| 1092 | builtin.TypeInfo.Pointer.Size.C => unreachable, | |
| 1091 | 1093 | } |
| 1092 | 1094 | }, |
| 1093 | 1095 | builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed), |
src-self-hosted/value.zig+9-9| ... | ... | @@ -57,7 +57,7 @@ pub const Value = struct { |
| 57 | 57 | std.debug.warn("{}", @tagName(base.id)); |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) { | |
| 60 | pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) { | |
| 61 | 61 | switch (base.id) { |
| 62 | 62 | Id.Type => unreachable, |
| 63 | 63 | Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile), |
| ... | ... | @@ -153,7 +153,7 @@ pub const Value = struct { |
| 153 | 153 | comp.gpa().destroy(self); |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef { | |
| 156 | pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value { | |
| 157 | 157 | const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| 158 | 158 | const llvm_fn = llvm.AddFunction( |
| 159 | 159 | ofile.module, |
| ... | ... | @@ -238,7 +238,7 @@ pub const Value = struct { |
| 238 | 238 | /// We know that the function definition will end up in an .o file somewhere. |
| 239 | 239 | /// Here, all we have to do is generate a global prototype. |
| 240 | 240 | /// TODO cache the prototype per ObjectFile |
| 241 | pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?llvm.ValueRef { | |
| 241 | pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?*llvm.Value { | |
| 242 | 242 | const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| 243 | 243 | const llvm_fn = llvm.AddFunction( |
| 244 | 244 | ofile.module, |
| ... | ... | @@ -283,8 +283,8 @@ pub const Value = struct { |
| 283 | 283 | comp.gpa().destroy(self); |
| 284 | 284 | } |
| 285 | 285 | |
| 286 | pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef { | |
| 287 | const llvm_type = llvm.Int1TypeInContext(ofile.context); | |
| 286 | pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value { | |
| 287 | const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory; | |
| 288 | 288 | if (self.x) { |
| 289 | 289 | return llvm.ConstAllOnes(llvm_type); |
| 290 | 290 | } else { |
| ... | ... | @@ -381,7 +381,7 @@ pub const Value = struct { |
| 381 | 381 | comp.gpa().destroy(self); |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef { | |
| 384 | pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value { | |
| 385 | 385 | const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| 386 | 386 | // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr |
| 387 | 387 | switch (self.special) { |
| ... | ... | @@ -391,7 +391,7 @@ pub const Value = struct { |
| 391 | 391 | const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?; |
| 392 | 392 | const ptr_bit_count = ofile.comp.target_ptr_bits; |
| 393 | 393 | const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory; |
| 394 | const indices = []llvm.ValueRef{ | |
| 394 | const indices = []*llvm.Value{ | |
| 395 | 395 | llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory, |
| 396 | 396 | llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory, |
| 397 | 397 | }; |
| ... | ... | @@ -459,7 +459,7 @@ pub const Value = struct { |
| 459 | 459 | comp.gpa().destroy(self); |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef { | |
| 462 | pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value { | |
| 463 | 463 | switch (self.special) { |
| 464 | 464 | Special.Undefined => { |
| 465 | 465 | const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| ... | ... | @@ -534,7 +534,7 @@ pub const Value = struct { |
| 534 | 534 | return self; |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef { | |
| 537 | pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value { | |
| 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); |
src/all_types.hpp+112-50| ... | ... | @@ -18,6 +18,7 @@ |
| 18 | 18 | #include "bigfloat.hpp" |
| 19 | 19 | #include "target.hpp" |
| 20 | 20 | #include "tokenizer.hpp" |
| 21 | #include "libc_installation.hpp" | |
| 21 | 22 | |
| 22 | 23 | struct AstNode; |
| 23 | 24 | struct ImportTableEntry; |
| ... | ... | @@ -630,24 +631,12 @@ struct AstNodeUnwrapOptional { |
| 630 | 631 | AstNode *expr; |
| 631 | 632 | }; |
| 632 | 633 | |
| 633 | enum CastOp { | |
| 634 | CastOpNoCast, // signifies the function call expression is not a cast | |
| 635 | CastOpNoop, // fn call expr is a cast, but does nothing | |
| 636 | CastOpIntToFloat, | |
| 637 | CastOpFloatToInt, | |
| 638 | CastOpBoolToInt, | |
| 639 | CastOpResizeSlice, | |
| 640 | CastOpNumLitToConcrete, | |
| 641 | CastOpErrSet, | |
| 642 | CastOpBitCast, | |
| 643 | CastOpPtrOfArrayToSlice, | |
| 644 | }; | |
| 645 | ||
| 646 | 634 | struct AstNodeFnCallExpr { |
| 647 | 635 | AstNode *fn_ref_expr; |
| 648 | 636 | ZigList<AstNode *> params; |
| 649 | 637 | bool is_builtin; |
| 650 | 638 | bool is_async; |
| 639 | bool seen; // used by @compileLog | |
| 651 | 640 | AstNode *async_allocator; |
| 652 | 641 | }; |
| 653 | 642 | |
| ... | ... | @@ -691,15 +680,17 @@ struct AstNodePointerType { |
| 691 | 680 | AstNode *align_expr; |
| 692 | 681 | BigInt *bit_offset_start; |
| 693 | 682 | BigInt *host_int_bytes; |
| 683 | AstNode *op_expr; | |
| 684 | Token *allow_zero_token; | |
| 694 | 685 | bool is_const; |
| 695 | 686 | bool is_volatile; |
| 696 | AstNode *op_expr; | |
| 697 | 687 | }; |
| 698 | 688 | |
| 699 | 689 | struct AstNodeArrayType { |
| 700 | 690 | AstNode *size; |
| 701 | 691 | AstNode *child_type; |
| 702 | 692 | AstNode *align_expr; |
| 693 | Token *allow_zero_token; | |
| 703 | 694 | bool is_const; |
| 704 | 695 | bool is_volatile; |
| 705 | 696 | }; |
| ... | ... | @@ -1038,6 +1029,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); |
| 1038 | 1029 | enum PtrLen { |
| 1039 | 1030 | PtrLenUnknown, |
| 1040 | 1031 | PtrLenSingle, |
| 1032 | PtrLenC, | |
| 1041 | 1033 | }; |
| 1042 | 1034 | |
| 1043 | 1035 | struct ZigTypePointer { |
| ... | ... | @@ -1049,6 +1041,7 @@ struct ZigTypePointer { |
| 1049 | 1041 | uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned |
| 1050 | 1042 | bool is_const; |
| 1051 | 1043 | bool is_volatile; |
| 1044 | bool allow_zero; | |
| 1052 | 1045 | }; |
| 1053 | 1046 | |
| 1054 | 1047 | struct ZigTypeInt { |
| ... | ... | @@ -1247,6 +1240,12 @@ enum ZigTypeId { |
| 1247 | 1240 | ZigTypeIdVector, |
| 1248 | 1241 | }; |
| 1249 | 1242 | |
| 1243 | enum OnePossibleValue { | |
| 1244 | OnePossibleValueInvalid, | |
| 1245 | OnePossibleValueNo, | |
| 1246 | OnePossibleValueYes, | |
| 1247 | }; | |
| 1248 | ||
| 1250 | 1249 | struct ZigType { |
| 1251 | 1250 | ZigTypeId id; |
| 1252 | 1251 | Buf name; |
| ... | ... | @@ -1254,9 +1253,6 @@ struct ZigType { |
| 1254 | 1253 | LLVMTypeRef type_ref; |
| 1255 | 1254 | ZigLLVMDIType *di_type; |
| 1256 | 1255 | |
| 1257 | bool zero_bits; // this is denormalized data | |
| 1258 | bool gen_h_loop_flag; | |
| 1259 | ||
| 1260 | 1256 | union { |
| 1261 | 1257 | ZigTypePointer pointer; |
| 1262 | 1258 | ZigTypeInt integral; |
| ... | ... | @@ -1282,6 +1278,11 @@ struct ZigType { |
| 1282 | 1278 | // If we generate a constant name value for this type, we memoize it here. |
| 1283 | 1279 | // The type of this is array |
| 1284 | 1280 | ConstExprValue *cached_const_name_val; |
| 1281 | ||
| 1282 | OnePossibleValue one_possible_value; | |
| 1283 | ||
| 1284 | bool zero_bits; // this is denormalized data | |
| 1285 | bool gen_h_loop_flag; | |
| 1285 | 1286 | }; |
| 1286 | 1287 | |
| 1287 | 1288 | struct PackageTableEntry { |
| ... | ... | @@ -1340,15 +1341,11 @@ struct ZigFn { |
| 1340 | 1341 | // in the case of async functions this is the implicit return type according to the |
| 1341 | 1342 | // zig source code, not according to zig ir |
| 1342 | 1343 | ZigType *src_implicit_return_type; |
| 1343 | bool is_test; | |
| 1344 | FnInline fn_inline; | |
| 1345 | FnAnalState anal_state; | |
| 1346 | 1344 | IrExecutable ir_executable; |
| 1347 | 1345 | IrExecutable analyzed_executable; |
| 1348 | 1346 | size_t prealloc_bbc; |
| 1349 | 1347 | AstNode **param_source_nodes; |
| 1350 | 1348 | Buf **param_names; |
| 1351 | uint32_t align_bytes; | |
| 1352 | 1349 | |
| 1353 | 1350 | AstNode *fn_no_inline_set_node; |
| 1354 | 1351 | AstNode *fn_static_eval_set_node; |
| ... | ... | @@ -1358,13 +1355,22 @@ struct ZigFn { |
| 1358 | 1355 | |
| 1359 | 1356 | Buf *section_name; |
| 1360 | 1357 | AstNode *set_alignstack_node; |
| 1361 | uint32_t alignstack_value; | |
| 1362 | 1358 | |
| 1363 | 1359 | AstNode *set_cold_node; |
| 1364 | bool is_cold; | |
| 1365 | 1360 | |
| 1366 | 1361 | ZigList<FnExport> export_list; |
| 1362 | ||
| 1363 | LLVMValueRef valgrind_client_request_array; | |
| 1364 | ||
| 1365 | FnInline fn_inline; | |
| 1366 | FnAnalState anal_state; | |
| 1367 | ||
| 1368 | uint32_t align_bytes; | |
| 1369 | uint32_t alignstack_value; | |
| 1370 | ||
| 1367 | 1371 | bool calls_or_awaits_errorable_fn; |
| 1372 | bool is_cold; | |
| 1373 | bool is_test; | |
| 1368 | 1374 | }; |
| 1369 | 1375 | |
| 1370 | 1376 | uint32_t fn_table_entry_hash(ZigFn*); |
| ... | ... | @@ -1484,6 +1490,7 @@ enum PanicMsgId { |
| 1484 | 1490 | PanicMsgIdBadUnionField, |
| 1485 | 1491 | PanicMsgIdBadEnumValue, |
| 1486 | 1492 | PanicMsgIdFloatToInt, |
| 1493 | PanicMsgIdPtrCastNull, | |
| 1487 | 1494 | |
| 1488 | 1495 | PanicMsgIdCount, |
| 1489 | 1496 | }; |
| ... | ... | @@ -1498,11 +1505,12 @@ struct TypeId { |
| 1498 | 1505 | struct { |
| 1499 | 1506 | ZigType *child_type; |
| 1500 | 1507 | PtrLen ptr_len; |
| 1501 | bool is_const; | |
| 1502 | bool is_volatile; | |
| 1503 | 1508 | uint32_t alignment; |
| 1504 | 1509 | uint32_t bit_offset_in_host; |
| 1505 | 1510 | uint32_t host_int_bytes; |
| 1511 | bool is_const; | |
| 1512 | bool is_volatile; | |
| 1513 | bool allow_zero; | |
| 1506 | 1514 | } pointer; |
| 1507 | 1515 | struct { |
| 1508 | 1516 | ZigType *child_type; |
| ... | ... | @@ -1605,6 +1613,17 @@ struct LinkLib { |
| 1605 | 1613 | bool provided_explicitly; |
| 1606 | 1614 | }; |
| 1607 | 1615 | |
| 1616 | enum ValgrindSupport { | |
| 1617 | ValgrindSupportAuto, | |
| 1618 | ValgrindSupportDisabled, | |
| 1619 | ValgrindSupportEnabled, | |
| 1620 | }; | |
| 1621 | ||
| 1622 | struct CFile { | |
| 1623 | ZigList<const char *> args; | |
| 1624 | const char *source_path; | |
| 1625 | }; | |
| 1626 | ||
| 1608 | 1627 | // When adding fields, check if they should be added to the hash computation in build_with_cache |
| 1609 | 1628 | struct CodeGen { |
| 1610 | 1629 | //////////////////////////// Runtime State |
| ... | ... | @@ -1660,7 +1679,7 @@ struct CodeGen { |
| 1660 | 1679 | HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; |
| 1661 | 1680 | HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; |
| 1662 | 1681 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1663 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; | |
| 1682 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names; | |
| 1664 | 1683 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; |
| 1665 | 1684 | HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table; |
| 1666 | 1685 | HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache; |
| ... | ... | @@ -1732,12 +1751,16 @@ struct CodeGen { |
| 1732 | 1751 | Buf triple_str; |
| 1733 | 1752 | Buf global_asm; |
| 1734 | 1753 | Buf *out_h_path; |
| 1754 | Buf *out_lib_path; | |
| 1735 | 1755 | Buf artifact_dir; |
| 1736 | 1756 | Buf output_file_path; |
| 1737 | 1757 | Buf o_file_output_path; |
| 1738 | 1758 | Buf *wanted_output_file_path; |
| 1739 | 1759 | Buf cache_dir; |
| 1740 | 1760 | |
| 1761 | Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir. | |
| 1762 | Buf *zig_std_special_dir; // Cannot be overridden; derived from zig_lib_dir. | |
| 1763 | ||
| 1741 | 1764 | IrInstruction *invalid_instruction; |
| 1742 | 1765 | IrInstruction *unreach_instruction; |
| 1743 | 1766 | |
| ... | ... | @@ -1752,6 +1775,7 @@ struct CodeGen { |
| 1752 | 1775 | ZigFn *cur_fn; |
| 1753 | 1776 | ZigFn *main_fn; |
| 1754 | 1777 | ZigFn *panic_fn; |
| 1778 | TldFn *panic_tld_fn; | |
| 1755 | 1779 | AstNode *root_export_decl; |
| 1756 | 1780 | |
| 1757 | 1781 | CacheHash cache_hash; |
| ... | ... | @@ -1760,7 +1784,8 @@ struct CodeGen { |
| 1760 | 1784 | unsigned pointer_size_bytes; |
| 1761 | 1785 | uint32_t target_os_index; |
| 1762 | 1786 | uint32_t target_arch_index; |
| 1763 | uint32_t target_environ_index; | |
| 1787 | uint32_t target_sub_arch_index; | |
| 1788 | uint32_t target_abi_index; | |
| 1764 | 1789 | uint32_t target_oformat_index; |
| 1765 | 1790 | bool is_big_endian; |
| 1766 | 1791 | bool have_pub_main; |
| ... | ... | @@ -1778,13 +1803,17 @@ struct CodeGen { |
| 1778 | 1803 | bool verbose_ir; |
| 1779 | 1804 | bool verbose_llvm_ir; |
| 1780 | 1805 | bool verbose_cimport; |
| 1806 | bool verbose_cc; | |
| 1781 | 1807 | bool error_during_imports; |
| 1782 | 1808 | bool generate_error_name_table; |
| 1783 | 1809 | bool enable_cache; |
| 1784 | 1810 | bool enable_time_report; |
| 1785 | 1811 | bool system_linker_hack; |
| 1812 | bool reported_bad_link_libc_error; | |
| 1786 | 1813 | |
| 1787 | 1814 | //////////////////////////// Participates in Input Parameter Cache Hash |
| 1815 | /////// Note: there is a separate cache hash for builtin.zig, when adding fields, | |
| 1816 | /////// consider if they need to go into both. | |
| 1788 | 1817 | ZigList<LinkLib *> link_libs_list; |
| 1789 | 1818 | // add -framework [name] args to linker |
| 1790 | 1819 | ZigList<Buf *> darwin_frameworks; |
| ... | ... | @@ -1793,8 +1822,11 @@ struct CodeGen { |
| 1793 | 1822 | ZigList<Buf *> forbidden_libs; |
| 1794 | 1823 | ZigList<Buf *> link_objects; |
| 1795 | 1824 | ZigList<Buf *> assembly_files; |
| 1825 | ZigList<CFile *> c_source_files; | |
| 1796 | 1826 | ZigList<const char *> lib_dirs; |
| 1797 | 1827 | |
| 1828 | ZigLibCInstallation *libc; | |
| 1829 | ||
| 1798 | 1830 | size_t version_major; |
| 1799 | 1831 | size_t version_minor; |
| 1800 | 1832 | size_t version_patch; |
| ... | ... | @@ -1803,15 +1835,14 @@ struct CodeGen { |
| 1803 | 1835 | EmitFileType emit_file_type; |
| 1804 | 1836 | BuildMode build_mode; |
| 1805 | 1837 | OutType out_type; |
| 1806 | ZigTarget zig_target; | |
| 1838 | const ZigTarget *zig_target; | |
| 1807 | 1839 | TargetSubsystem subsystem; |
| 1840 | ValgrindSupport valgrind_support; | |
| 1808 | 1841 | bool is_static; |
| 1809 | 1842 | bool strip_debug_symbols; |
| 1810 | 1843 | bool is_test_build; |
| 1811 | 1844 | bool is_single_threaded; |
| 1812 | bool is_native_target; | |
| 1813 | 1845 | bool linker_rdynamic; |
| 1814 | bool no_rosegment_workaround; | |
| 1815 | 1846 | bool each_lib_rpath; |
| 1816 | 1847 | bool disable_pic; |
| 1817 | 1848 | |
| ... | ... | @@ -1821,31 +1852,21 @@ struct CodeGen { |
| 1821 | 1852 | Buf *test_filter; |
| 1822 | 1853 | Buf *test_name_prefix; |
| 1823 | 1854 | PackageTableEntry *root_package; |
| 1855 | Buf *zig_lib_dir; | |
| 1856 | Buf *zig_std_dir; | |
| 1824 | 1857 | |
| 1825 | 1858 | const char **llvm_argv; |
| 1826 | 1859 | size_t llvm_argv_len; |
| 1827 | 1860 | |
| 1828 | 1861 | const char **clang_argv; |
| 1829 | 1862 | size_t clang_argv_len; |
| 1830 | ||
| 1831 | //////////////////////////// Unsorted | |
| 1832 | ||
| 1833 | Buf *libc_lib_dir; | |
| 1834 | Buf *libc_static_lib_dir; | |
| 1835 | Buf *libc_include_dir; | |
| 1836 | Buf *msvc_lib_dir; | |
| 1837 | Buf *kernel32_lib_dir; | |
| 1838 | Buf *zig_lib_dir; | |
| 1839 | Buf *zig_std_dir; | |
| 1840 | Buf *zig_c_headers_dir; | |
| 1841 | Buf *zig_std_special_dir; | |
| 1842 | Buf *dynamic_linker; | |
| 1843 | ZigWindowsSDK *win_sdk; | |
| 1844 | 1863 | }; |
| 1845 | 1864 | |
| 1846 | 1865 | enum VarLinkage { |
| 1847 | 1866 | VarLinkageInternal, |
| 1848 | VarLinkageExport, | |
| 1867 | VarLinkageExportStrong, | |
| 1868 | VarLinkageExportWeak, | |
| 1869 | VarLinkageExportLinkOnce, | |
| 1849 | 1870 | VarLinkageExternal, |
| 1850 | 1871 | }; |
| 1851 | 1872 | |
| ... | ... | @@ -2084,6 +2105,11 @@ struct IrBasicBlock { |
| 2084 | 2105 | IrInstruction *must_be_comptime_source_instr; |
| 2085 | 2106 | }; |
| 2086 | 2107 | |
| 2108 | enum LVal { | |
| 2109 | LValNone, | |
| 2110 | LValPtr, | |
| 2111 | }; | |
| 2112 | ||
| 2087 | 2113 | // These instructions are in transition to having "pass 1" instructions |
| 2088 | 2114 | // and "pass 2" instructions. The pass 1 instructions are suffixed with Src |
| 2089 | 2115 | // and pass 2 are suffixed with Gen. |
| ... | ... | @@ -2106,6 +2132,7 @@ enum IrInstructionId { |
| 2106 | 2132 | IrInstructionIdUnOp, |
| 2107 | 2133 | IrInstructionIdBinOp, |
| 2108 | 2134 | IrInstructionIdLoadPtr, |
| 2135 | IrInstructionIdLoadPtrGen, | |
| 2109 | 2136 | IrInstructionIdStorePtr, |
| 2110 | 2137 | IrInstructionIdFieldPtr, |
| 2111 | 2138 | IrInstructionIdStructFieldPtr, |
| ... | ... | @@ -2116,6 +2143,7 @@ enum IrInstructionId { |
| 2116 | 2143 | IrInstructionIdConst, |
| 2117 | 2144 | IrInstructionIdReturn, |
| 2118 | 2145 | IrInstructionIdCast, |
| 2146 | IrInstructionIdResizeSlice, | |
| 2119 | 2147 | IrInstructionIdContainerInitList, |
| 2120 | 2148 | IrInstructionIdContainerInitFields, |
| 2121 | 2149 | IrInstructionIdStructInit, |
| ... | ... | @@ -2183,6 +2211,7 @@ enum IrInstructionId { |
| 2183 | 2211 | IrInstructionIdPtrCastSrc, |
| 2184 | 2212 | IrInstructionIdPtrCastGen, |
| 2185 | 2213 | IrInstructionIdBitCast, |
| 2214 | IrInstructionIdBitCastGen, | |
| 2186 | 2215 | IrInstructionIdWidenOrShorten, |
| 2187 | 2216 | IrInstructionIdIntToPtr, |
| 2188 | 2217 | IrInstructionIdPtrToInt, |
| ... | ... | @@ -2347,6 +2376,7 @@ struct IrInstructionUnOp { |
| 2347 | 2376 | |
| 2348 | 2377 | IrUnOp op_id; |
| 2349 | 2378 | IrInstruction *value; |
| 2379 | LVal lval; | |
| 2350 | 2380 | }; |
| 2351 | 2381 | |
| 2352 | 2382 | enum IrBinOp { |
| ... | ... | @@ -2399,6 +2429,13 @@ struct IrInstructionLoadPtr { |
| 2399 | 2429 | IrInstruction *ptr; |
| 2400 | 2430 | }; |
| 2401 | 2431 | |
| 2432 | struct IrInstructionLoadPtrGen { | |
| 2433 | IrInstruction base; | |
| 2434 | ||
| 2435 | IrInstruction *ptr; | |
| 2436 | LLVMValueRef tmp_ptr; | |
| 2437 | }; | |
| 2438 | ||
| 2402 | 2439 | struct IrInstructionStorePtr { |
| 2403 | 2440 | IrInstruction base; |
| 2404 | 2441 | |
| ... | ... | @@ -2476,6 +2513,18 @@ struct IrInstructionReturn { |
| 2476 | 2513 | IrInstruction *value; |
| 2477 | 2514 | }; |
| 2478 | 2515 | |
| 2516 | enum CastOp { | |
| 2517 | CastOpNoCast, // signifies the function call expression is not a cast | |
| 2518 | CastOpNoop, // fn call expr is a cast, but does nothing | |
| 2519 | CastOpIntToFloat, | |
| 2520 | CastOpFloatToInt, | |
| 2521 | CastOpBoolToInt, | |
| 2522 | CastOpNumLitToConcrete, | |
| 2523 | CastOpErrSet, | |
| 2524 | CastOpBitCast, | |
| 2525 | CastOpPtrOfArrayToSlice, | |
| 2526 | }; | |
| 2527 | ||
| 2479 | 2528 | // TODO get rid of this instruction, replace with instructions for each op code |
| 2480 | 2529 | struct IrInstructionCast { |
| 2481 | 2530 | IrInstruction base; |
| ... | ... | @@ -2486,6 +2535,13 @@ struct IrInstructionCast { |
| 2486 | 2535 | LLVMValueRef tmp_ptr; |
| 2487 | 2536 | }; |
| 2488 | 2537 | |
| 2538 | struct IrInstructionResizeSlice { | |
| 2539 | IrInstruction base; | |
| 2540 | ||
| 2541 | IrInstruction *operand; | |
| 2542 | LLVMValueRef tmp_ptr; | |
| 2543 | }; | |
| 2544 | ||
| 2489 | 2545 | struct IrInstructionContainerInitList { |
| 2490 | 2546 | IrInstruction base; |
| 2491 | 2547 | |
| ... | ... | @@ -2591,6 +2647,7 @@ struct IrInstructionPtrType { |
| 2591 | 2647 | PtrLen ptr_len; |
| 2592 | 2648 | bool is_const; |
| 2593 | 2649 | bool is_volatile; |
| 2650 | bool allow_zero; | |
| 2594 | 2651 | }; |
| 2595 | 2652 | |
| 2596 | 2653 | struct IrInstructionPromiseType { |
| ... | ... | @@ -2606,6 +2663,7 @@ struct IrInstructionSliceType { |
| 2606 | 2663 | IrInstruction *child_type; |
| 2607 | 2664 | bool is_const; |
| 2608 | 2665 | bool is_volatile; |
| 2666 | bool allow_zero; | |
| 2609 | 2667 | }; |
| 2610 | 2668 | |
| 2611 | 2669 | struct IrInstructionAsm { |
| ... | ... | @@ -2994,12 +3052,14 @@ struct IrInstructionPtrCastSrc { |
| 2994 | 3052 | |
| 2995 | 3053 | IrInstruction *dest_type; |
| 2996 | 3054 | IrInstruction *ptr; |
| 3055 | bool safety_check_on; | |
| 2997 | 3056 | }; |
| 2998 | 3057 | |
| 2999 | 3058 | struct IrInstructionPtrCastGen { |
| 3000 | 3059 | IrInstruction base; |
| 3001 | 3060 | |
| 3002 | 3061 | IrInstruction *ptr; |
| 3062 | bool safety_check_on; | |
| 3003 | 3063 | }; |
| 3004 | 3064 | |
| 3005 | 3065 | struct IrInstructionBitCast { |
| ... | ... | @@ -3009,6 +3069,13 @@ struct IrInstructionBitCast { |
| 3009 | 3069 | IrInstruction *value; |
| 3010 | 3070 | }; |
| 3011 | 3071 | |
| 3072 | struct IrInstructionBitCastGen { | |
| 3073 | IrInstruction base; | |
| 3074 | ||
| 3075 | IrInstruction *operand; | |
| 3076 | LLVMValueRef tmp_ptr; | |
| 3077 | }; | |
| 3078 | ||
| 3012 | 3079 | struct IrInstructionWidenOrShorten { |
| 3013 | 3080 | IrInstruction base; |
| 3014 | 3081 | |
| ... | ... | @@ -3079,11 +3146,6 @@ struct IrInstructionTypeName { |
| 3079 | 3146 | IrInstruction *type_value; |
| 3080 | 3147 | }; |
| 3081 | 3148 | |
| 3082 | enum LVal { | |
| 3083 | LValNone, | |
| 3084 | LValPtr, | |
| 3085 | }; | |
| 3086 | ||
| 3087 | 3149 | struct IrInstructionDeclRef { |
| 3088 | 3150 | IrInstruction base; |
| 3089 | 3151 |
src/analyze.cpp+246-294| ... | ... | @@ -356,7 +356,7 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) { |
| 356 | 356 | } |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); | |
| 359 | return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); | |
| 360 | 360 | } |
| 361 | 361 | |
| 362 | 362 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) { |
| ... | ... | @@ -365,19 +365,19 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) { |
| 365 | 365 | if (!type_has_bits(type_entry)) |
| 366 | 366 | return 0; |
| 367 | 367 | |
| 368 | if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) { | |
| 369 | uint64_t result = 0; | |
| 370 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | |
| 371 | result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry); | |
| 368 | if (type_entry->id == ZigTypeIdStruct) { | |
| 369 | if (type_entry->data.structure.layout == ContainerLayoutPacked) { | |
| 370 | uint64_t result = 0; | |
| 371 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | |
| 372 | result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry); | |
| 373 | } | |
| 374 | return result; | |
| 375 | } else if (type_entry->data.structure.layout == ContainerLayoutExtern) { | |
| 376 | return type_size(g, type_entry) * 8; | |
| 372 | 377 | } |
| 373 | return result; | |
| 374 | 378 | } else if (type_entry->id == ZigTypeIdArray) { |
| 375 | 379 | ZigType *child_type = type_entry->data.array.child_type; |
| 376 | if (child_type->id == ZigTypeIdStruct && | |
| 377 | child_type->data.structure.layout == ContainerLayoutPacked) | |
| 378 | { | |
| 379 | return type_entry->data.array.len * type_size_bits(g, child_type); | |
| 380 | } | |
| 380 | return type_entry->data.array.len * type_size_bits(g, child_type); | |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | 383 | return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref); |
| ... | ... | @@ -417,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { |
| 417 | 417 | return entry; |
| 418 | 418 | } |
| 419 | 419 | |
| 420 | static const char *ptr_len_to_star_str(PtrLen ptr_len) { | |
| 421 | switch (ptr_len) { | |
| 422 | case PtrLenSingle: | |
| 423 | return "*"; | |
| 424 | case PtrLenUnknown: | |
| 425 | return "[*]"; | |
| 426 | case PtrLenC: | |
| 427 | return "[*c]"; | |
| 428 | } | |
| 429 | zig_unreachable(); | |
| 430 | } | |
| 431 | ||
| 420 | 432 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 421 | 433 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, |
| 422 | 434 | uint32_t bit_offset_in_host, uint32_t host_int_bytes) |
| 423 | 435 | { |
| 436 | // TODO when implementing https://github.com/ziglang/zig/issues/1953 | |
| 437 | // move this to a parameter | |
| 438 | bool allow_zero = (ptr_len == PtrLenC); | |
| 424 | 439 | assert(!type_is_invalid(child_type)); |
| 425 | 440 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); |
| 426 | 441 | |
| ... | ... | @@ -440,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 440 | 455 | |
| 441 | 456 | TypeId type_id = {}; |
| 442 | 457 | ZigType **parent_pointer = nullptr; |
| 443 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { | |
| 458 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) { | |
| 444 | 459 | type_id.id = ZigTypeIdPointer; |
| 445 | 460 | type_id.data.pointer.child_type = child_type; |
| 446 | 461 | type_id.data.pointer.is_const = is_const; |
| ... | ... | @@ -449,6 +464,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 449 | 464 | type_id.data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 450 | 465 | type_id.data.pointer.host_int_bytes = host_int_bytes; |
| 451 | 466 | type_id.data.pointer.ptr_len = ptr_len; |
| 467 | type_id.data.pointer.allow_zero = allow_zero; | |
| 452 | 468 | |
| 453 | 469 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 454 | 470 | if (existing_entry) |
| ... | ... | @@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 466 | 482 | |
| 467 | 483 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); |
| 468 | 484 | |
| 469 | const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]"; | |
| 485 | const char *star_str = ptr_len_to_star_str(ptr_len); | |
| 470 | 486 | const char *const_str = is_const ? "const " : ""; |
| 471 | 487 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| 488 | const char *allow_zero_str; | |
| 489 | if (ptr_len == PtrLenC) { | |
| 490 | assert(allow_zero); | |
| 491 | allow_zero_str = ""; | |
| 492 | } else { | |
| 493 | allow_zero_str = allow_zero ? "allowzero " : ""; | |
| 494 | } | |
| 472 | 495 | buf_resize(&entry->name, 0); |
| 473 | 496 | if (host_int_bytes == 0 && byte_alignment == 0) { |
| 474 | buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 497 | buf_appendf(&entry->name, "%s%s%s%s%s", | |
| 498 | star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | |
| 475 | 499 | } else if (host_int_bytes == 0) { |
| 476 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment, | |
| 477 | const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 500 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, | |
| 501 | const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | |
| 478 | 502 | } else if (byte_alignment == 0) { |
| 479 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, | |
| 480 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 503 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, | |
| 504 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, | |
| 505 | buf_ptr(&child_type->name)); | |
| 481 | 506 | } else { |
| 482 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment, | |
| 483 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 507 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, | |
| 508 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, | |
| 509 | buf_ptr(&child_type->name)); | |
| 484 | 510 | } |
| 485 | 511 | |
| 486 | 512 | assert(child_type->id != ZigTypeIdInvalid); |
| ... | ... | @@ -488,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 488 | 514 | entry->zero_bits = !type_has_bits(child_type); |
| 489 | 515 | |
| 490 | 516 | if (!entry->zero_bits) { |
| 491 | if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) { | |
| 517 | if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || | |
| 518 | bit_offset_in_host != 0 || allow_zero) | |
| 519 | { | |
| 492 | 520 | ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false, |
| 493 | 521 | PtrLenSingle, 0, 0, host_int_bytes); |
| 494 | 522 | entry->type_ref = peer_type->type_ref; |
| ... | ... | @@ -522,6 +550,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 522 | 550 | entry->data.pointer.explicit_alignment = byte_alignment; |
| 523 | 551 | entry->data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 524 | 552 | entry->data.pointer.host_int_bytes = host_int_bytes; |
| 553 | entry->data.pointer.allow_zero = allow_zero; | |
| 525 | 554 | |
| 526 | 555 | if (parent_pointer) { |
| 527 | 556 | *parent_pointer = entry; |
| ... | ... | @@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 838 | 867 | |
| 839 | 868 | ZigType *child_type = ptr_type->data.pointer.child_type; |
| 840 | 869 | if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || |
| 841 | ptr_type->data.pointer.explicit_alignment != 0) | |
| 870 | ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero) | |
| 842 | 871 | { |
| 843 | 872 | ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, |
| 844 | 873 | PtrLenUnknown, 0, 0, 0); |
| ... | ... | @@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 861 | 890 | ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; |
| 862 | 891 | assert(child_ptr_type->id == ZigTypeIdPointer); |
| 863 | 892 | if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || |
| 864 | child_ptr_type->data.pointer.explicit_alignment != 0) | |
| 893 | child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero) | |
| 865 | 894 | { |
| 866 | 895 | ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; |
| 867 | 896 | ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false, |
| ... | ... | @@ -1073,10 +1102,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 1073 | 1102 | if (type_is_c_abi_int(g, fn_type_id->return_type)) { |
| 1074 | 1103 | return false; |
| 1075 | 1104 | } |
| 1076 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { | |
| 1105 | if (g->zig_target->arch == ZigLLVM_x86_64) { | |
| 1077 | 1106 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); |
| 1078 | 1107 | return abi_class == X64CABIClass_MEMORY; |
| 1079 | } else if (target_is_arm(&g->zig_target)) { | |
| 1108 | } else if (target_is_arm(g->zig_target)) { | |
| 1080 | 1109 | return type_size(g, fn_type_id->return_type) > 16; |
| 1081 | 1110 | } |
| 1082 | 1111 | zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481"); |
| ... | ... | @@ -1300,7 +1329,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no |
| 1300 | 1329 | size_t backward_branch_count = 0; |
| 1301 | 1330 | return ir_eval_const_value(g, scope, node, type_entry, |
| 1302 | 1331 | &backward_branch_count, default_backward_branch_quota, |
| 1303 | nullptr, nullptr, node, type_name, nullptr); | |
| 1332 | nullptr, nullptr, node, type_name, nullptr, nullptr); | |
| 1304 | 1333 | } |
| 1305 | 1334 | |
| 1306 | 1335 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| ... | ... | @@ -1415,7 +1444,10 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1415 | 1444 | return true; |
| 1416 | 1445 | } |
| 1417 | 1446 | |
| 1418 | static bool type_allowed_in_packed_struct(ZigType *type_entry) { | |
| 1447 | static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType *type_entry, | |
| 1448 | AstNode *source_node) | |
| 1449 | { | |
| 1450 | Error err; | |
| 1419 | 1451 | switch (type_entry->id) { |
| 1420 | 1452 | case ZigTypeIdInvalid: |
| 1421 | 1453 | zig_unreachable(); |
| ... | ... | @@ -1432,32 +1464,79 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { |
| 1432 | 1464 | case ZigTypeIdArgTuple: |
| 1433 | 1465 | case ZigTypeIdOpaque: |
| 1434 | 1466 | case ZigTypeIdPromise: |
| 1435 | return false; | |
| 1467 | add_node_error(g, source_node, | |
| 1468 | buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", | |
| 1469 | buf_ptr(&type_entry->name))); | |
| 1470 | return ErrorSemanticAnalyzeFail; | |
| 1436 | 1471 | case ZigTypeIdVoid: |
| 1437 | 1472 | case ZigTypeIdBool: |
| 1438 | 1473 | case ZigTypeIdInt: |
| 1439 | 1474 | case ZigTypeIdFloat: |
| 1440 | 1475 | case ZigTypeIdPointer: |
| 1441 | case ZigTypeIdArray: | |
| 1442 | 1476 | case ZigTypeIdFn: |
| 1443 | 1477 | case ZigTypeIdVector: |
| 1444 | return true; | |
| 1478 | return ErrorNone; | |
| 1479 | case ZigTypeIdArray: { | |
| 1480 | ZigType *elem_type = type_entry->data.array.child_type; | |
| 1481 | if ((err = emit_error_unless_type_allowed_in_packed_struct(g, elem_type, source_node))) | |
| 1482 | return err; | |
| 1483 | if (type_size(g, type_entry) * 8 == type_size_bits(g, type_entry)) | |
| 1484 | return ErrorNone; | |
| 1485 | add_node_error(g, source_node, | |
| 1486 | buf_sprintf("array of '%s' not allowed in packed struct due to padding bits", | |
| 1487 | buf_ptr(&elem_type->name))); | |
| 1488 | return ErrorSemanticAnalyzeFail; | |
| 1489 | } | |
| 1445 | 1490 | case ZigTypeIdStruct: |
| 1446 | return type_entry->data.structure.layout == ContainerLayoutPacked; | |
| 1491 | switch (type_entry->data.structure.layout) { | |
| 1492 | case ContainerLayoutPacked: | |
| 1493 | case ContainerLayoutExtern: | |
| 1494 | return ErrorNone; | |
| 1495 | case ContainerLayoutAuto: | |
| 1496 | add_node_error(g, source_node, | |
| 1497 | buf_sprintf("non-packed, non-extern struct '%s' not allowed in packed struct; no guaranteed in-memory representation", | |
| 1498 | buf_ptr(&type_entry->name))); | |
| 1499 | return ErrorSemanticAnalyzeFail; | |
| 1500 | } | |
| 1501 | zig_unreachable(); | |
| 1447 | 1502 | case ZigTypeIdUnion: |
| 1448 | return type_entry->data.unionation.layout == ContainerLayoutPacked; | |
| 1503 | switch (type_entry->data.unionation.layout) { | |
| 1504 | case ContainerLayoutPacked: | |
| 1505 | case ContainerLayoutExtern: | |
| 1506 | return ErrorNone; | |
| 1507 | case ContainerLayoutAuto: | |
| 1508 | add_node_error(g, source_node, | |
| 1509 | buf_sprintf("non-packed, non-extern union '%s' not allowed in packed struct; no guaranteed in-memory representation", | |
| 1510 | buf_ptr(&type_entry->name))); | |
| 1511 | return ErrorSemanticAnalyzeFail; | |
| 1512 | } | |
| 1513 | zig_unreachable(); | |
| 1449 | 1514 | case ZigTypeIdOptional: |
| 1450 | { | |
| 1451 | ZigType *child_type = type_entry->data.maybe.child_type; | |
| 1452 | return type_is_codegen_pointer(child_type); | |
| 1515 | if (get_codegen_ptr_type(type_entry) != nullptr) { | |
| 1516 | return ErrorNone; | |
| 1517 | } else { | |
| 1518 | add_node_error(g, source_node, | |
| 1519 | buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", | |
| 1520 | buf_ptr(&type_entry->name))); | |
| 1521 | return ErrorSemanticAnalyzeFail; | |
| 1453 | 1522 | } |
| 1454 | case ZigTypeIdEnum: | |
| 1455 | return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; | |
| 1523 | case ZigTypeIdEnum: { | |
| 1524 | AstNode *decl_node = type_entry->data.enumeration.decl_node; | |
| 1525 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | |
| 1526 | return ErrorNone; | |
| 1527 | } | |
| 1528 | ErrorMsg *msg = add_node_error(g, source_node, | |
| 1529 | buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", | |
| 1530 | buf_ptr(&type_entry->name))); | |
| 1531 | add_error_note(g, msg, decl_node, | |
| 1532 | buf_sprintf("enum declaration does not specify an integer tag type")); | |
| 1533 | return ErrorSemanticAnalyzeFail; | |
| 1534 | } | |
| 1456 | 1535 | } |
| 1457 | 1536 | zig_unreachable(); |
| 1458 | 1537 | } |
| 1459 | 1538 | |
| 1460 | static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | |
| 1539 | bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | |
| 1461 | 1540 | switch (type_entry->id) { |
| 1462 | 1541 | case ZigTypeIdInvalid: |
| 1463 | 1542 | zig_unreachable(); |
| ... | ... | @@ -1583,7 +1662,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1583 | 1662 | } |
| 1584 | 1663 | } else if (param_node->data.param_decl.var_token != nullptr) { |
| 1585 | 1664 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 1586 | add_node_error(g, param_node->data.param_decl.type, | |
| 1665 | add_node_error(g, param_node, | |
| 1587 | 1666 | buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'", |
| 1588 | 1667 | calling_convention_name(fn_type_id.cc))); |
| 1589 | 1668 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -2022,11 +2101,8 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2022 | 2101 | type_struct_field->gen_index = gen_field_index; |
| 2023 | 2102 | |
| 2024 | 2103 | if (packed) { |
| 2025 | if (!type_allowed_in_packed_struct(field_type)) { | |
| 2026 | AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); | |
| 2027 | add_node_error(g, field_source_node, | |
| 2028 | buf_sprintf("packed structs cannot contain fields of type '%s'", | |
| 2029 | buf_ptr(&field_type->name))); | |
| 2104 | AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); | |
| 2105 | if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) { | |
| 2030 | 2106 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2031 | 2107 | break; |
| 2032 | 2108 | } |
| ... | ... | @@ -2650,6 +2726,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2650 | 2726 | buf_sprintf("enums, not structs, support field assignment")); |
| 2651 | 2727 | } |
| 2652 | 2728 | |
| 2729 | if (field_type->id == ZigTypeIdOpaque) { | |
| 2730 | add_node_error(g, field_node->data.struct_field.type, | |
| 2731 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); | |
| 2732 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | |
| 2733 | continue; | |
| 2734 | } | |
| 2735 | ||
| 2653 | 2736 | switch (type_requires_comptime(g, field_type)) { |
| 2654 | 2737 | case ReqCompTimeYes: |
| 2655 | 2738 | struct_type->data.structure.requires_comptime = true; |
| ... | ... | @@ -2828,7 +2911,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 2828 | 2911 | union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum || |
| 2829 | 2912 | enum_type_node != nullptr; |
| 2830 | 2913 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); |
| 2831 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); | |
| 2914 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease); | |
| 2832 | 2915 | ZigType *tag_type; |
| 2833 | 2916 | bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); |
| 2834 | 2917 | bool *covered_enum_fields; |
| ... | ... | @@ -2934,6 +3017,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 2934 | 3017 | } |
| 2935 | 3018 | union_field->type_entry = field_type; |
| 2936 | 3019 | |
| 3020 | if (field_type->id == ZigTypeIdOpaque) { | |
| 3021 | add_node_error(g, field_node->data.struct_field.type, | |
| 3022 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions")); | |
| 3023 | union_type->data.unionation.is_invalid = true; | |
| 3024 | continue; | |
| 3025 | } | |
| 3026 | ||
| 2937 | 3027 | switch (type_requires_comptime(g, field_type)) { |
| 2938 | 3028 | case ReqCompTimeInvalid: |
| 2939 | 3029 | union_type->data.unionation.is_invalid = true; |
| ... | ... | @@ -3182,36 +3272,19 @@ static bool scope_is_root_decls(Scope *scope) { |
| 3182 | 3272 | zig_unreachable(); |
| 3183 | 3273 | } |
| 3184 | 3274 | |
| 3185 | static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) { | |
| 3186 | add_node_error(g, proto_node, | |
| 3187 | buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'", | |
| 3188 | buf_ptr(&fn_type->name))); | |
| 3189 | } | |
| 3190 | ||
| 3191 | static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) { | |
| 3192 | AstNode *proto_node = panic_fn->proto_node; | |
| 3193 | assert(proto_node->type == NodeTypeFnProto); | |
| 3194 | ZigType *fn_type = panic_fn->type_entry; | |
| 3195 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | |
| 3196 | if (fn_type_id->param_count != 2) { | |
| 3197 | return wrong_panic_prototype(g, proto_node, fn_type); | |
| 3198 | } | |
| 3199 | ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, | |
| 3200 | PtrLenUnknown, 0, 0, 0); | |
| 3201 | ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr); | |
| 3202 | if (fn_type_id->param_info[0].type != const_u8_slice) { | |
| 3203 | return wrong_panic_prototype(g, proto_node, fn_type); | |
| 3204 | } | |
| 3275 | void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) { | |
| 3276 | ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn"); | |
| 3277 | assert(panic_fn_type_val != nullptr); | |
| 3278 | assert(panic_fn_type_val->type->id == ZigTypeIdMetaType); | |
| 3279 | ZigType *panic_fn_type = panic_fn_type_val->data.x_type; | |
| 3205 | 3280 | |
| 3206 | ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g)); | |
| 3207 | if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) { | |
| 3208 | return wrong_panic_prototype(g, proto_node, fn_type); | |
| 3209 | } | |
| 3281 | AstNode *fake_decl = allocate<AstNode>(1); | |
| 3282 | *fake_decl = *panic_fn->proto_node; | |
| 3283 | fake_decl->type = NodeTypeSymbol; | |
| 3284 | fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name; | |
| 3210 | 3285 | |
| 3211 | ZigType *actual_return_type = fn_type_id->return_type; | |
| 3212 | if (actual_return_type != g->builtin_types.entry_unreachable) { | |
| 3213 | return wrong_panic_prototype(g, proto_node, fn_type); | |
| 3214 | } | |
| 3286 | // call this for the side effects of casting to panic_fn_type | |
| 3287 | analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr); | |
| 3215 | 3288 | } |
| 3216 | 3289 | |
| 3217 | 3290 | ZigType *get_test_fn_type(CodeGen *g) { |
| ... | ... | @@ -3231,16 +3304,16 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi |
| 3231 | 3304 | g->have_c_main = true; |
| 3232 | 3305 | g->subsystem = TargetSubsystemConsole; |
| 3233 | 3306 | } else if (buf_eql_str(symbol_name, "WinMain") && |
| 3234 | g->zig_target.os == OsWindows) | |
| 3307 | g->zig_target->os == OsWindows) | |
| 3235 | 3308 | { |
| 3236 | 3309 | g->have_winmain = true; |
| 3237 | 3310 | g->subsystem = TargetSubsystemWindows; |
| 3238 | 3311 | } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && |
| 3239 | g->zig_target.os == OsWindows) | |
| 3312 | g->zig_target->os == OsWindows) | |
| 3240 | 3313 | { |
| 3241 | 3314 | g->have_winmain_crt_startup = true; |
| 3242 | 3315 | } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && |
| 3243 | g->zig_target.os == OsWindows) | |
| 3316 | g->zig_target->os == OsWindows) | |
| 3244 | 3317 | { |
| 3245 | 3318 | g->have_dllmain_crt_startup = true; |
| 3246 | 3319 | } |
| ... | ... | @@ -3306,18 +3379,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3306 | 3379 | if (!fn_table_entry->type_entry->data.fn.is_generic) { |
| 3307 | 3380 | if (fn_def_node) |
| 3308 | 3381 | g->fn_defs.append(fn_table_entry); |
| 3382 | } | |
| 3309 | 3383 | |
| 3310 | if (scope_is_root_decls(tld_fn->base.parent_scope) && | |
| 3311 | (import == g->root_import || import->package == g->panic_package)) | |
| 3384 | if (scope_is_root_decls(tld_fn->base.parent_scope) && | |
| 3385 | (import == g->root_import || import->package == g->panic_package)) | |
| 3386 | { | |
| 3387 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { | |
| 3388 | g->main_fn = fn_table_entry; | |
| 3389 | } else if ((import->package == g->panic_package || g->have_pub_panic) && | |
| 3390 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) | |
| 3312 | 3391 | { |
| 3313 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { | |
| 3314 | g->main_fn = fn_table_entry; | |
| 3315 | } else if ((import->package == g->panic_package || g->have_pub_panic) && | |
| 3316 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) | |
| 3317 | { | |
| 3318 | g->panic_fn = fn_table_entry; | |
| 3319 | typecheck_panic_fn(g, fn_table_entry); | |
| 3320 | } | |
| 3392 | g->panic_fn = fn_table_entry; | |
| 3393 | g->panic_tld_fn = tld_fn; | |
| 3321 | 3394 | } |
| 3322 | 3395 | } |
| 3323 | 3396 | } else if (source_node->type == NodeTypeTestDecl) { |
| ... | ... | @@ -3366,9 +3439,9 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 3366 | 3439 | if (is_export) { |
| 3367 | 3440 | g->resolve_queue.append(tld); |
| 3368 | 3441 | |
| 3369 | auto entry = g->exported_symbol_names.put_unique(tld->name, tld->source_node); | |
| 3442 | auto entry = g->exported_symbol_names.put_unique(tld->name, tld); | |
| 3370 | 3443 | if (entry) { |
| 3371 | AstNode *other_source_node = entry->value; | |
| 3444 | AstNode *other_source_node = entry->value->source_node; | |
| 3372 | 3445 | ErrorMsg *msg = add_node_error(g, tld->source_node, |
| 3373 | 3446 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name))); |
| 3374 | 3447 | add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here")); |
| ... | ... | @@ -3698,7 +3771,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3698 | 3771 | |
| 3699 | 3772 | VarLinkage linkage; |
| 3700 | 3773 | if (is_export) { |
| 3701 | linkage = VarLinkageExport; | |
| 3774 | linkage = VarLinkageExportStrong; | |
| 3702 | 3775 | } else if (is_extern) { |
| 3703 | 3776 | linkage = VarLinkageExternal; |
| 3704 | 3777 | } else { |
| ... | ... | @@ -4041,7 +4114,9 @@ ZigType *get_src_ptr_type(ZigType *type) { |
| 4041 | 4114 | if (type->id == ZigTypeIdFn) return type; |
| 4042 | 4115 | if (type->id == ZigTypeIdPromise) return type; |
| 4043 | 4116 | if (type->id == ZigTypeIdOptional) { |
| 4044 | if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type; | |
| 4117 | if (type->data.maybe.child_type->id == ZigTypeIdPointer) { | |
| 4118 | return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type; | |
| 4119 | } | |
| 4045 | 4120 | if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type; |
| 4046 | 4121 | if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type; |
| 4047 | 4122 | } |
| ... | ... | @@ -4055,6 +4130,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) { |
| 4055 | 4130 | return ty; |
| 4056 | 4131 | } |
| 4057 | 4132 | |
| 4133 | bool type_is_nonnull_ptr(ZigType *type) { | |
| 4134 | return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type); | |
| 4135 | } | |
| 4136 | ||
| 4058 | 4137 | bool type_is_codegen_pointer(ZigType *type) { |
| 4059 | 4138 | return get_codegen_ptr_type(type) == type; |
| 4060 | 4139 | } |
| ... | ... | @@ -4572,185 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4572 | 4651 | zig_unreachable(); |
| 4573 | 4652 | } |
| 4574 | 4653 | |
| 4575 | static ZigWindowsSDK *get_windows_sdk(CodeGen *g) { | |
| 4576 | if (g->win_sdk == nullptr) { | |
| 4577 | if (zig_find_windows_sdk(&g->win_sdk)) { | |
| 4578 | fprintf(stderr, "unable to determine windows sdk path\n"); | |
| 4579 | exit(1); | |
| 4580 | } | |
| 4581 | } | |
| 4582 | assert(g->win_sdk != nullptr); | |
| 4583 | return g->win_sdk; | |
| 4584 | } | |
| 4585 | ||
| 4586 | ||
| 4587 | static Buf *get_linux_libc_lib_path(const char *o_file) { | |
| 4588 | const char *cc_exe = getenv("CC"); | |
| 4589 | cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; | |
| 4590 | ZigList<const char *> args = {}; | |
| 4591 | args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file))); | |
| 4592 | Termination term; | |
| 4593 | Buf *out_stderr = buf_alloc(); | |
| 4594 | Buf *out_stdout = buf_alloc(); | |
| 4595 | Error err; | |
| 4596 | if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { | |
| 4597 | zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err)); | |
| 4598 | } | |
| 4599 | if (term.how != TerminationIdClean || term.code != 0) { | |
| 4600 | zig_panic("unable to determine libc lib path: executing C compiler command failed"); | |
| 4601 | } | |
| 4602 | if (buf_ends_with_str(out_stdout, "\n")) { | |
| 4603 | buf_resize(out_stdout, buf_len(out_stdout) - 1); | |
| 4604 | } | |
| 4605 | if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) { | |
| 4606 | zig_panic("unable to determine libc lib path: C compiler could not find %s", o_file); | |
| 4607 | } | |
| 4608 | Buf *result = buf_alloc(); | |
| 4609 | os_path_dirname(out_stdout, result); | |
| 4610 | return result; | |
| 4611 | } | |
| 4612 | ||
| 4613 | static Buf *get_posix_libc_include_path(void) { | |
| 4614 | const char *cc_exe = getenv("CC"); | |
| 4615 | cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; | |
| 4616 | ZigList<const char *> args = {}; | |
| 4617 | args.append("-E"); | |
| 4618 | args.append("-Wp,-v"); | |
| 4619 | args.append("-xc"); | |
| 4620 | args.append("/dev/null"); | |
| 4621 | Termination term; | |
| 4622 | Buf *out_stderr = buf_alloc(); | |
| 4623 | Buf *out_stdout = buf_alloc(); | |
| 4624 | Error err; | |
| 4625 | if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { | |
| 4626 | zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err)); | |
| 4627 | } | |
| 4628 | if (term.how != TerminationIdClean || term.code != 0) { | |
| 4629 | zig_panic("unable to determine libc include path: executing C compiler command failed"); | |
| 4630 | } | |
| 4631 | char *prev_newline = buf_ptr(out_stderr); | |
| 4632 | ZigList<const char *> search_paths = {}; | |
| 4633 | for (;;) { | |
| 4634 | char *newline = strchr(prev_newline, '\n'); | |
| 4635 | if (newline == nullptr) { | |
| 4636 | break; | |
| 4637 | } | |
| 4638 | *newline = 0; | |
| 4639 | if (prev_newline[0] == ' ') { | |
| 4640 | search_paths.append(prev_newline); | |
| 4641 | } | |
| 4642 | prev_newline = newline + 1; | |
| 4643 | } | |
| 4644 | if (search_paths.length == 0) { | |
| 4645 | zig_panic("unable to determine libc include path: even C compiler does not know where libc headers are"); | |
| 4646 | } | |
| 4647 | for (size_t i = 0; i < search_paths.length; i += 1) { | |
| 4648 | // search in reverse order | |
| 4649 | const char *search_path = search_paths.items[search_paths.length - i - 1]; | |
| 4650 | // cut off spaces | |
| 4651 | while (*search_path == ' ') { | |
| 4652 | search_path += 1; | |
| 4653 | } | |
| 4654 | Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path); | |
| 4655 | bool exists; | |
| 4656 | if ((err = os_file_exists(stdlib_path, &exists))) { | |
| 4657 | exists = false; | |
| 4658 | } | |
| 4659 | if (exists) { | |
| 4660 | return buf_create_from_str(search_path); | |
| 4661 | } | |
| 4662 | } | |
| 4663 | zig_panic("unable to determine libc include path: stdlib.h not found in C compiler search paths"); | |
| 4664 | } | |
| 4665 | ||
| 4666 | void find_libc_include_path(CodeGen *g) { | |
| 4667 | if (g->libc_include_dir == nullptr) { | |
| 4668 | if (!g->is_native_target) { | |
| 4669 | return; | |
| 4670 | } | |
| 4671 | ||
| 4672 | if (g->zig_target.os == OsWindows) { | |
| 4673 | ZigWindowsSDK *sdk = get_windows_sdk(g); | |
| 4674 | g->libc_include_dir = buf_alloc(); | |
| 4675 | if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) { | |
| 4676 | fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); | |
| 4677 | exit(1); | |
| 4678 | } | |
| 4679 | } else if (g->zig_target.os == OsLinux || | |
| 4680 | g->zig_target.os == OsMacOSX || | |
| 4681 | g->zig_target.os == OsFreeBSD) | |
| 4682 | { | |
| 4683 | g->libc_include_dir = get_posix_libc_include_path(); | |
| 4684 | } else { | |
| 4685 | fprintf(stderr, "Unable to determine libc include path.\n" | |
| 4686 | "TODO: implement finding libc at runtime for other operating systems.\n" | |
| 4687 | "in the meantime, you can use as a workaround: --libc-include-dir\n"); | |
| 4688 | exit(1); | |
| 4689 | } | |
| 4690 | } | |
| 4691 | assert(buf_len(g->libc_include_dir) != 0); | |
| 4692 | } | |
| 4693 | ||
| 4694 | void find_libc_lib_path(CodeGen *g) { | |
| 4695 | // later we can handle this better by reporting an error via the normal mechanism | |
| 4696 | if (g->libc_lib_dir == nullptr || | |
| 4697 | (g->zig_target.os == OsWindows && (g->msvc_lib_dir == nullptr || g->kernel32_lib_dir == nullptr))) | |
| 4698 | { | |
| 4699 | if (g->zig_target.os == OsWindows) { | |
| 4700 | ZigWindowsSDK *sdk = get_windows_sdk(g); | |
| 4701 | ||
| 4702 | if (g->msvc_lib_dir == nullptr) { | |
| 4703 | if (sdk->msvc_lib_dir_ptr == nullptr) { | |
| 4704 | fprintf(stderr, "Unable to determine vcruntime path. --msvc-lib-dir"); | |
| 4705 | exit(1); | |
| 4706 | } | |
| 4707 | g->msvc_lib_dir = buf_create_from_mem(sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); | |
| 4708 | } | |
| 4709 | ||
| 4710 | if (g->libc_lib_dir == nullptr) { | |
| 4711 | Buf* ucrt_lib_path = buf_alloc(); | |
| 4712 | if (os_get_win32_ucrt_lib_path(sdk, ucrt_lib_path, g->zig_target.arch.arch)) { | |
| 4713 | fprintf(stderr, "Unable to determine ucrt path. --libc-lib-dir"); | |
| 4714 | exit(1); | |
| 4715 | } | |
| 4716 | g->libc_lib_dir = ucrt_lib_path; | |
| 4717 | } | |
| 4718 | ||
| 4719 | if (g->kernel32_lib_dir == nullptr) { | |
| 4720 | Buf* kern_lib_path = buf_alloc(); | |
| 4721 | if (os_get_win32_kern32_path(sdk, kern_lib_path, g->zig_target.arch.arch)) { | |
| 4722 | fprintf(stderr, "Unable to determine kernel32 path. --kernel32-lib-dir"); | |
| 4723 | exit(1); | |
| 4724 | } | |
| 4725 | g->kernel32_lib_dir = kern_lib_path; | |
| 4726 | } | |
| 4727 | ||
| 4728 | } else if (g->zig_target.os == OsLinux) { | |
| 4729 | g->libc_lib_dir = get_linux_libc_lib_path("crt1.o"); | |
| 4730 | } else if (g->zig_target.os == OsFreeBSD) { | |
| 4731 | g->libc_lib_dir = buf_create_from_str("/usr/lib"); | |
| 4732 | } else { | |
| 4733 | zig_panic("Unable to determine libc lib path."); | |
| 4734 | } | |
| 4735 | } else { | |
| 4736 | assert(buf_len(g->libc_lib_dir) != 0); | |
| 4737 | } | |
| 4738 | ||
| 4739 | if (g->libc_static_lib_dir == nullptr) { | |
| 4740 | if ((g->zig_target.os == OsWindows) && (g->msvc_lib_dir != NULL)) { | |
| 4741 | return; | |
| 4742 | } else if (g->zig_target.os == OsLinux) { | |
| 4743 | g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o"); | |
| 4744 | } else if (g->zig_target.os == OsFreeBSD) { | |
| 4745 | g->libc_static_lib_dir = buf_create_from_str("/usr/lib"); | |
| 4746 | } else { | |
| 4747 | zig_panic("Unable to determine libc static lib path."); | |
| 4748 | } | |
| 4749 | } else { | |
| 4750 | assert(buf_len(g->libc_static_lib_dir) != 0); | |
| 4751 | } | |
| 4752 | } | |
| 4753 | ||
| 4754 | 4654 | static uint32_t hash_ptr(void *ptr) { |
| 4755 | 4655 | return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX); |
| 4756 | 4656 | } |
| ... | ... | @@ -5229,6 +5129,10 @@ bool type_has_bits(ZigType *type_entry) { |
| 5229 | 5129 | // Whether you can infer the value based solely on the type. |
| 5230 | 5130 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 5231 | 5131 | assert(type_entry != nullptr); |
| 5132 | ||
| 5133 | if (type_entry->one_possible_value != OnePossibleValueInvalid) | |
| 5134 | return type_entry->one_possible_value; | |
| 5135 | ||
| 5232 | 5136 | Error err; |
| 5233 | 5137 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) |
| 5234 | 5138 | return OnePossibleValueInvalid; |
| ... | ... | @@ -5276,8 +5180,14 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 5276 | 5180 | case ZigTypeIdInt: |
| 5277 | 5181 | case ZigTypeIdVector: |
| 5278 | 5182 | return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; |
| 5279 | case ZigTypeIdPointer: | |
| 5280 | return type_has_one_possible_value(g, type_entry->data.pointer.child_type); | |
| 5183 | case ZigTypeIdPointer: { | |
| 5184 | ZigType *elem_type = type_entry->data.pointer.child_type; | |
| 5185 | // If the recursive function call asks, then we are not one possible value. | |
| 5186 | type_entry->one_possible_value = OnePossibleValueNo; | |
| 5187 | // Now update it to be the value of the recursive call. | |
| 5188 | type_entry->one_possible_value = type_has_one_possible_value(g, elem_type); | |
| 5189 | return type_entry->one_possible_value; | |
| 5190 | } | |
| 5281 | 5191 | case ZigTypeIdUnion: |
| 5282 | 5192 | if (type_entry->data.unionation.src_field_count > 1) |
| 5283 | 5193 | return OnePossibleValueNo; |
| ... | ... | @@ -6010,16 +5920,20 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const |
| 6010 | 5920 | } |
| 6011 | 5921 | } |
| 6012 | 5922 | |
| 6013 | static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) { | |
| 6014 | switch (const_val->data.x_array.special) { | |
| 5923 | static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) { | |
| 5924 | ConstArrayValue *array = &const_val->data.x_array; | |
| 5925 | switch (array->special) { | |
| 6015 | 5926 | case ConstArraySpecialUndef: |
| 6016 | 5927 | buf_append_str(buf, "undefined"); |
| 6017 | 5928 | return; |
| 6018 | 5929 | case ConstArraySpecialBuf: { |
| 6019 | Buf *array_buf = const_val->data.x_array.data.s_buf; | |
| 5930 | Buf *array_buf = array->data.s_buf; | |
| 5931 | const char *base = &buf_ptr(array_buf)[start]; | |
| 5932 | assert(start + len <= buf_len(array_buf)); | |
| 5933 | ||
| 6020 | 5934 | buf_append_char(buf, '"'); |
| 6021 | for (size_t i = 0; i < buf_len(array_buf); i += 1) { | |
| 6022 | uint8_t c = buf_ptr(array_buf)[i]; | |
| 5935 | for (size_t i = 0; i < len; i += 1) { | |
| 5936 | uint8_t c = base[i]; | |
| 6023 | 5937 | if (c == '"') { |
| 6024 | 5938 | buf_append_str(buf, "\\\""); |
| 6025 | 5939 | } else { |
| ... | ... | @@ -6030,12 +5944,13 @@ static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_v |
| 6030 | 5944 | return; |
| 6031 | 5945 | } |
| 6032 | 5946 | case ConstArraySpecialNone: { |
| 6033 | buf_appendf(buf, "%s{", buf_ptr(&const_val->type->name)); | |
| 5947 | ConstExprValue *base = &array->data.s_none.elements[start]; | |
| 5948 | assert(start + len <= const_val->type->data.array.len); | |
| 5949 | ||
| 5950 | buf_appendf(buf, "%s{", buf_ptr(type_name)); | |
| 6034 | 5951 | for (uint64_t i = 0; i < len; i += 1) { |
| 6035 | if (i != 0) | |
| 6036 | buf_appendf(buf, ","); | |
| 6037 | ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i]; | |
| 6038 | render_const_value(g, buf, child_value); | |
| 5952 | if (i != 0) buf_appendf(buf, ","); | |
| 5953 | render_const_value(g, buf, &base[i]); | |
| 6039 | 5954 | } |
| 6040 | 5955 | buf_appendf(buf, "}"); |
| 6041 | 5956 | return; |
| ... | ... | @@ -6124,10 +6039,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 6124 | 6039 | } |
| 6125 | 6040 | case ZigTypeIdPointer: |
| 6126 | 6041 | return render_const_val_ptr(g, buf, const_val, type_entry); |
| 6127 | case ZigTypeIdVector: | |
| 6128 | return render_const_val_array(g, buf, const_val, type_entry->data.vector.len); | |
| 6129 | case ZigTypeIdArray: | |
| 6130 | return render_const_val_array(g, buf, const_val, type_entry->data.array.len); | |
| 6042 | case ZigTypeIdArray: { | |
| 6043 | uint64_t len = type_entry->data.array.len; | |
| 6044 | render_const_val_array(g, buf, &type_entry->name, const_val, 0, len); | |
| 6045 | return; | |
| 6046 | } | |
| 6047 | case ZigTypeIdVector: { | |
| 6048 | uint32_t len = type_entry->data.vector.len; | |
| 6049 | render_const_val_array(g, buf, &type_entry->name, const_val, 0, len); | |
| 6050 | return; | |
| 6051 | } | |
| 6131 | 6052 | case ZigTypeIdNull: |
| 6132 | 6053 | { |
| 6133 | 6054 | buf_appendf(buf, "null"); |
| ... | ... | @@ -6169,7 +6090,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 6169 | 6090 | } |
| 6170 | 6091 | case ZigTypeIdStruct: |
| 6171 | 6092 | { |
| 6172 | buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name)); | |
| 6093 | if (is_slice(type_entry)) { | |
| 6094 | ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index]; | |
| 6095 | size_t len = bigint_as_unsigned(&len_val->data.x_bigint); | |
| 6096 | ||
| 6097 | ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; | |
| 6098 | if (ptr_val->special == ConstValSpecialUndef) { | |
| 6099 | assert(len == 0); | |
| 6100 | buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name)); | |
| 6101 | return; | |
| 6102 | } | |
| 6103 | assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); | |
| 6104 | ConstExprValue *array = ptr_val->data.x_ptr.data.base_array.array_val; | |
| 6105 | size_t start = ptr_val->data.x_ptr.data.base_array.elem_index; | |
| 6106 | ||
| 6107 | render_const_val_array(g, buf, &type_entry->name, array, start, len); | |
| 6108 | } else { | |
| 6109 | buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name)); | |
| 6110 | } | |
| 6173 | 6111 | return; |
| 6174 | 6112 | } |
| 6175 | 6113 | case ZigTypeIdEnum: |
| ... | ... | @@ -6193,8 +6131,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 6193 | 6131 | } |
| 6194 | 6132 | case ZigTypeIdUnion: |
| 6195 | 6133 | { |
| 6196 | uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag); | |
| 6197 | TypeUnionField *field = &type_entry->data.unionation.fields[tag]; | |
| 6134 | const BigInt *tag = &const_val->data.x_union.tag; | |
| 6135 | TypeUnionField *field = find_union_field_by_tag(type_entry, tag); | |
| 6198 | 6136 | buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name)); |
| 6199 | 6137 | render_const_value(g, buf, const_val->data.x_union.payload); |
| 6200 | 6138 | buf_append_str(buf, "}"); |
| ... | ... | @@ -6277,6 +6215,7 @@ uint32_t type_id_hash(TypeId x) { |
| 6277 | 6215 | ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) + |
| 6278 | 6216 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + |
| 6279 | 6217 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + |
| 6218 | (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) + | |
| 6280 | 6219 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + |
| 6281 | 6220 | (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + |
| 6282 | 6221 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); |
| ... | ... | @@ -6327,6 +6266,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6327 | 6266 | a.data.pointer.ptr_len == b.data.pointer.ptr_len && |
| 6328 | 6267 | a.data.pointer.is_const == b.data.pointer.is_const && |
| 6329 | 6268 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && |
| 6269 | a.data.pointer.allow_zero == b.data.pointer.allow_zero && | |
| 6330 | 6270 | a.data.pointer.alignment == b.data.pointer.alignment && |
| 6331 | 6271 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && |
| 6332 | 6272 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; |
| ... | ... | @@ -6626,12 +6566,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { |
| 6626 | 6566 | if (is_libc && g->libc_link_lib != nullptr) |
| 6627 | 6567 | return g->libc_link_lib; |
| 6628 | 6568 | |
| 6629 | if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD) { | |
| 6630 | fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n" | |
| 6631 | "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n"); | |
| 6632 | exit(1); | |
| 6633 | } | |
| 6634 | ||
| 6635 | 6569 | for (size_t i = 0; i < g->link_libs_list.length; i += 1) { |
| 6636 | 6570 | LinkLib *existing_lib = g->link_libs_list.at(i); |
| 6637 | 6571 | if (buf_eql_buf(existing_lib->name, name)) { |
| ... | ... | @@ -6860,3 +6794,21 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no |
| 6860 | 6794 | |
| 6861 | 6795 | return ErrorNone; |
| 6862 | 6796 | } |
| 6797 | ||
| 6798 | const char *container_string(ContainerKind kind) { | |
| 6799 | switch (kind) { | |
| 6800 | case ContainerKindEnum: return "enum"; | |
| 6801 | case ContainerKindStruct: return "struct"; | |
| 6802 | case ContainerKindUnion: return "union"; | |
| 6803 | } | |
| 6804 | zig_unreachable(); | |
| 6805 | } | |
| 6806 | ||
| 6807 | bool ptr_allows_addr_zero(ZigType *ptr_type) { | |
| 6808 | if (ptr_type->id == ZigTypeIdPointer) { | |
| 6809 | return ptr_type->data.pointer.allow_zero; | |
| 6810 | } else if (ptr_type->id == ZigTypeIdOptional) { | |
| 6811 | return true; | |
| 6812 | } | |
| 6813 | return false; | |
| 6814 | } |
src/analyze.hpp+5-8| ... | ... | @@ -40,11 +40,11 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type); |
| 40 | 40 | ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type); |
| 41 | 41 | ZigType *get_test_fn_type(CodeGen *g); |
| 42 | 42 | bool handle_is_ptr(ZigType *type_entry); |
| 43 | void find_libc_include_path(CodeGen *g); | |
| 44 | void find_libc_lib_path(CodeGen *g); | |
| 45 | 43 | |
| 46 | 44 | bool type_has_bits(ZigType *type_entry); |
| 47 | ||
| 45 | bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry); | |
| 46 | bool ptr_allows_addr_zero(ZigType *ptr_type); | |
| 47 | bool type_is_nonnull_ptr(ZigType *type); | |
| 48 | 48 | |
| 49 | 49 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); |
| 50 | 50 | |
| ... | ... | @@ -215,6 +215,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); |
| 215 | 215 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); |
| 216 | 216 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); |
| 217 | 217 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); |
| 218 | const char *container_string(ContainerKind kind); | |
| 218 | 219 | |
| 219 | 220 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); |
| 220 | 221 | |
| ... | ... | @@ -225,14 +226,10 @@ enum ReqCompTime { |
| 225 | 226 | }; |
| 226 | 227 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); |
| 227 | 228 | |
| 228 | enum OnePossibleValue { | |
| 229 | OnePossibleValueInvalid, | |
| 230 | OnePossibleValueNo, | |
| 231 | OnePossibleValueYes, | |
| 232 | }; | |
| 233 | 229 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); |
| 234 | 230 | |
| 235 | 231 | Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, |
| 236 | 232 | ConstExprValue *const_val, ZigType *wanted_type); |
| 237 | 233 | |
| 234 | void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn); | |
| 238 | 235 | #endif |
src/ast_render.cpp+14-13| ... | ... | @@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) { |
| 136 | 136 | return (tok == nullptr) ? "" : "threadlocal "; |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | const char *container_string(ContainerKind kind) { | |
| 140 | switch (kind) { | |
| 141 | case ContainerKindEnum: return "enum"; | |
| 142 | case ContainerKindStruct: return "struct"; | |
| 143 | case ContainerKindUnion: return "union"; | |
| 139 | static const char *token_to_ptr_len_str(Token *tok) { | |
| 140 | assert(tok != nullptr); | |
| 141 | switch (tok->id) { | |
| 142 | case TokenIdStar: | |
| 143 | case TokenIdStarStar: | |
| 144 | return "*"; | |
| 145 | case TokenIdBracketStarBracket: | |
| 146 | return "[*]"; | |
| 147 | case TokenIdBracketStarCBracket: | |
| 148 | return "[*c]"; | |
| 149 | default: | |
| 150 | zig_unreachable(); | |
| 144 | 151 | } |
| 145 | zig_unreachable(); | |
| 146 | 152 | } |
| 147 | 153 | |
| 148 | 154 | static const char *node_type_str(NodeType node_type) { |
| ... | ... | @@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 644 | 650 | case NodeTypePointerType: |
| 645 | 651 | { |
| 646 | 652 | if (!grouped) fprintf(ar->f, "("); |
| 647 | const char *star = "[*]"; | |
| 648 | if (node->data.pointer_type.star_token != nullptr && | |
| 649 | (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar)) | |
| 650 | { | |
| 651 | star = "*"; | |
| 652 | } | |
| 653 | fprintf(ar->f, "%s", star); | |
| 653 | const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token); | |
| 654 | fprintf(ar->f, "%s", ptr_len_str); | |
| 654 | 655 | if (node->data.pointer_type.align_expr != nullptr) { |
| 655 | 656 | fprintf(ar->f, "align("); |
| 656 | 657 | render_node_grouped(ar, node->data.pointer_type.align_expr); |
src/ast_render.hpp-3| ... | ... | @@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent); |
| 17 | 17 | |
| 18 | 18 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); |
| 19 | 19 | |
| 20 | const char *container_string(ContainerKind kind); | |
| 21 | ||
| 22 | 20 | #endif |
| 23 |
src/bigint.cpp-1| ... | ... | @@ -1665,7 +1665,6 @@ int64_t bigint_as_signed(const BigInt *bigint) { |
| 1665 | 1665 | return 0; |
| 1666 | 1666 | } else if (bigint->digit_count == 1) { |
| 1667 | 1667 | if (bigint->is_negative) { |
| 1668 | // TODO this code path is untested | |
| 1669 | 1668 | if (bigint->data.digit <= 9223372036854775808ULL) { |
| 1670 | 1669 | return (-((int64_t)(bigint->data.digit - 1))) - 1; |
| 1671 | 1670 | } else { |
src/buffer.hpp+1-3| ... | ... | @@ -132,9 +132,7 @@ void buf_appendf(Buf *buf, const char *format, ...) |
| 132 | 132 | |
| 133 | 133 | static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) { |
| 134 | 134 | assert(buf->list.length); |
| 135 | if (buf_len(buf) != mem_len) | |
| 136 | return false; | |
| 137 | return memcmp(buf_ptr(buf), mem, mem_len) == 0; | |
| 135 | return mem_eql_mem(buf_ptr(buf), buf_len(buf), mem, mem_len); | |
| 138 | 136 | } |
| 139 | 137 | |
| 140 | 138 | static inline bool buf_eql_str(Buf *buf, const char *str) { |
src/cache_hash.cpp+34| ... | ... | @@ -414,6 +414,39 @@ Error cache_add_file(CacheHash *ch, Buf *path) { |
| 414 | 414 | return cache_add_file_fetch(ch, resolved_path, nullptr); |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) { | |
| 418 | Error err; | |
| 419 | Buf *contents = buf_alloc(); | |
| 420 | if ((err = os_fetch_file_path(dep_file_path, contents, false))) { | |
| 421 | if (verbose) { | |
| 422 | fprintf(stderr, "unable to read .d file: %s\n", err_str(err)); | |
| 423 | } | |
| 424 | return ErrorReadingDepFile; | |
| 425 | } | |
| 426 | SplitIterator it = memSplit(buf_to_slice(contents), str("\n")); | |
| 427 | // skip first line | |
| 428 | SplitIterator_next(&it); | |
| 429 | for (;;) { | |
| 430 | Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&it); | |
| 431 | if (!opt_line.is_some) | |
| 432 | break; | |
| 433 | if (opt_line.value.len == 0) | |
| 434 | continue; | |
| 435 | SplitIterator line_it = memSplit(opt_line.value, str(" \t")); | |
| 436 | Slice<uint8_t> filename; | |
| 437 | if (!SplitIterator_next(&line_it).unwrap(&filename)) | |
| 438 | continue; | |
| 439 | Buf *filename_buf = buf_create_from_slice(filename); | |
| 440 | if ((err = cache_add_file(ch, filename_buf))) { | |
| 441 | if (verbose) { | |
| 442 | fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err)); | |
| 443 | } | |
| 444 | return err; | |
| 445 | } | |
| 446 | } | |
| 447 | return ErrorNone; | |
| 448 | } | |
| 449 | ||
| 417 | 450 | static Error write_manifest_file(CacheHash *ch) { |
| 418 | 451 | Error err; |
| 419 | 452 | Buf contents = BUF_INIT; |
| ... | ... | @@ -464,3 +497,4 @@ void cache_release(CacheHash *ch) { |
| 464 | 497 | |
| 465 | 498 | os_file_close(ch->manifest_file); |
| 466 | 499 | } |
| 500 |
src/cache_hash.hpp+2| ... | ... | @@ -56,6 +56,8 @@ Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest); |
| 56 | 56 | // If you did not get a cache hit, call this function for every file |
| 57 | 57 | // that is depended on, and then finish with cache_final. |
| 58 | 58 | Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path); |
| 59 | // This opens a file created by -MD -MF args to Clang | |
| 60 | Error ATTRIBUTE_MUST_USE cache_add_dep_file(CacheHash *ch, Buf *path, bool verbose); | |
| 59 | 61 | |
| 60 | 62 | // This variant of cache_add_file returns the file contents. |
| 61 | 63 | // Also the file path argument must be already resolved. |
src/codegen.cpp+679-228| ... | ... | @@ -29,9 +29,9 @@ static void init_darwin_native(CodeGen *g) { |
| 29 | 29 | |
| 30 | 30 | // Allow conflicts among OSX and iOS, but choose the default platform. |
| 31 | 31 | if (osx_target && ios_target) { |
| 32 | if (g->zig_target.arch.arch == ZigLLVM_arm || | |
| 33 | g->zig_target.arch.arch == ZigLLVM_aarch64 || | |
| 34 | g->zig_target.arch.arch == ZigLLVM_thumb) | |
| 32 | if (g->zig_target->arch == ZigLLVM_arm || | |
| 33 | g->zig_target->arch == ZigLLVM_aarch64 || | |
| 34 | g->zig_target->arch == ZigLLVM_thumb) | |
| 35 | 35 | { |
| 36 | 36 | osx_target = nullptr; |
| 37 | 37 | } else { |
| ... | ... | @@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) { |
| 43 | 43 | g->mmacosx_version_min = buf_create_from_str(osx_target); |
| 44 | 44 | } else if (ios_target) { |
| 45 | 45 | g->mios_version_min = buf_create_from_str(ios_target); |
| 46 | } else if (g->zig_target.os != OsIOS) { | |
| 46 | } else if (g->zig_target->os != OsIOS) { | |
| 47 | 47 | g->mmacosx_version_min = buf_create_from_str("10.10"); |
| 48 | 48 | } |
| 49 | 49 | } |
| ... | ... | @@ -88,13 +88,15 @@ static const char *symbols_that_llvm_depends_on[] = { |
| 88 | 88 | }; |
| 89 | 89 | |
| 90 | 90 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, |
| 91 | Buf *zig_lib_dir, Buf *override_std_dir) | |
| 91 | Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc) | |
| 92 | 92 | { |
| 93 | 93 | CodeGen *g = allocate<CodeGen>(1); |
| 94 | 94 | |
| 95 | 95 | codegen_add_time_event(g, "Initialize"); |
| 96 | 96 | |
| 97 | g->libc = libc; | |
| 97 | 98 | g->zig_lib_dir = zig_lib_dir; |
| 99 | g->zig_target = target; | |
| 98 | 100 | |
| 99 | 101 | if (override_std_dir == nullptr) { |
| 100 | 102 | g->zig_std_dir = buf_alloc(); |
| ... | ... | @@ -149,43 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 149 | 151 | g->zig_std_special_dir = buf_alloc(); |
| 150 | 152 | os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); |
| 151 | 153 | |
| 152 | if (target) { | |
| 153 | // cross compiling, so we can't rely on all the configured stuff since | |
| 154 | // that's for native compilation | |
| 155 | g->zig_target = *target; | |
| 156 | resolve_target_object_format(&g->zig_target); | |
| 157 | g->dynamic_linker = nullptr; | |
| 158 | g->libc_lib_dir = nullptr; | |
| 159 | g->libc_static_lib_dir = nullptr; | |
| 160 | g->libc_include_dir = nullptr; | |
| 161 | g->msvc_lib_dir = nullptr; | |
| 162 | g->kernel32_lib_dir = nullptr; | |
| 154 | assert(target != nullptr); | |
| 155 | if (!target->is_native) { | |
| 163 | 156 | g->each_lib_rpath = false; |
| 164 | 157 | } else { |
| 165 | // native compilation, we can rely on the configuration stuff | |
| 166 | g->is_native_target = true; | |
| 167 | get_native_target(&g->zig_target); | |
| 168 | g->dynamic_linker = nullptr; // find it at runtime | |
| 169 | g->libc_lib_dir = nullptr; // find it at runtime | |
| 170 | g->libc_static_lib_dir = nullptr; // find it at runtime | |
| 171 | g->libc_include_dir = nullptr; // find it at runtime | |
| 172 | g->msvc_lib_dir = nullptr; // find it at runtime | |
| 173 | g->kernel32_lib_dir = nullptr; // find it at runtime | |
| 174 | 158 | g->each_lib_rpath = true; |
| 175 | 159 | |
| 176 | if (g->zig_target.os == OsMacOSX || | |
| 177 | g->zig_target.os == OsIOS) | |
| 178 | { | |
| 160 | if (target_is_darwin(g->zig_target)) { | |
| 179 | 161 | init_darwin_native(g); |
| 180 | 162 | } |
| 181 | 163 | |
| 182 | 164 | } |
| 183 | 165 | |
| 184 | // On Darwin/MacOS/iOS, we always link libSystem which contains libc. | |
| 185 | if (g->zig_target.os == OsMacOSX || | |
| 186 | g->zig_target.os == OsIOS || | |
| 187 | 	g->zig_target.os == OsFreeBSD) | |
| 188 | { | |
| 166 | if (target_requires_libc(g->zig_target)) { | |
| 189 | 167 | g->libc_link_lib = create_link_lib(buf_create_from_str("c")); |
| 190 | 168 | g->link_libs_list.append(g->libc_link_lib); |
| 191 | 169 | } |
| ... | ... | @@ -197,6 +175,10 @@ void codegen_set_output_h_path(CodeGen *g, Buf *h_path) { |
| 197 | 175 | g->out_h_path = h_path; |
| 198 | 176 | } |
| 199 | 177 | |
| 178 | void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path) { | |
| 179 | g->out_lib_path = lib_path; | |
| 180 | } | |
| 181 | ||
| 200 | 182 | void codegen_set_output_path(CodeGen *g, Buf *path) { |
| 201 | 183 | g->wanted_output_file_path = path; |
| 202 | 184 | } |
| ... | ... | @@ -253,30 +235,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { |
| 253 | 235 | g->root_out_name = out_name; |
| 254 | 236 | } |
| 255 | 237 | |
| 256 | void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) { | |
| 257 | g->libc_lib_dir = libc_lib_dir; | |
| 258 | } | |
| 259 | ||
| 260 | void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir) { | |
| 261 | g->libc_static_lib_dir = libc_static_lib_dir; | |
| 262 | } | |
| 263 | ||
| 264 | void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) { | |
| 265 | g->libc_include_dir = libc_include_dir; | |
| 266 | } | |
| 267 | ||
| 268 | void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) { | |
| 269 | g->msvc_lib_dir = msvc_lib_dir; | |
| 270 | } | |
| 271 | ||
| 272 | void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) { | |
| 273 | g->kernel32_lib_dir = kernel32_lib_dir; | |
| 274 | } | |
| 275 | ||
| 276 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) { | |
| 277 | g->dynamic_linker = dynamic_linker; | |
| 278 | } | |
| 279 | ||
| 280 | 238 | void codegen_add_lib_dir(CodeGen *g, const char *dir) { |
| 281 | 239 | g->lib_dirs.append(dir); |
| 282 | 240 | } |
| ... | ... | @@ -389,11 +347,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 389 | 347 | case CallingConventionC: return LLVMCCallConv; |
| 390 | 348 | case CallingConventionCold: |
| 391 | 349 | // cold calling convention only works on x86. |
| 392 | if (g->zig_target.arch.arch == ZigLLVM_x86 || | |
| 393 | g->zig_target.arch.arch == ZigLLVM_x86_64) | |
| 350 | if (g->zig_target->arch == ZigLLVM_x86 || | |
| 351 | g->zig_target->arch == ZigLLVM_x86_64) | |
| 394 | 352 | { |
| 395 | 353 | // cold calling convention is not supported on windows |
| 396 | if (g->zig_target.os == OsWindows) { | |
| 354 | if (g->zig_target->os == OsWindows) { | |
| 397 | 355 | return LLVMCCallConv; |
| 398 | 356 | } else { |
| 399 | 357 | return LLVMColdCallConv; |
| ... | ... | @@ -406,7 +364,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 406 | 364 | zig_unreachable(); |
| 407 | 365 | case CallingConventionStdcall: |
| 408 | 366 | // stdcall calling convention only works on x86. |
| 409 | if (g->zig_target.arch.arch == ZigLLVM_x86) { | |
| 367 | if (g->zig_target->arch == ZigLLVM_x86) { | |
| 410 | 368 | return LLVMX86StdcallCallConv; |
| 411 | 369 | } else { |
| 412 | 370 | return LLVMCCallConv; |
| ... | ... | @@ -418,7 +376,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 418 | 376 | } |
| 419 | 377 | |
| 420 | 378 | static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { |
| 421 | if (g->zig_target.os == OsWindows) { | |
| 379 | if (g->zig_target->os == OsWindows) { | |
| 422 | 380 | addLLVMFnAttr(fn_val, "uwtable"); |
| 423 | 381 | } |
| 424 | 382 | } |
| ... | ... | @@ -454,13 +412,13 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { |
| 454 | 412 | } |
| 455 | 413 | |
| 456 | 414 | static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) { |
| 457 | if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) { | |
| 415 | if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) { | |
| 458 | 416 | LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass); |
| 459 | 417 | } |
| 460 | 418 | } |
| 461 | 419 | |
| 462 | 420 | static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) { |
| 463 | if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) { | |
| 421 | if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) { | |
| 464 | 422 | // TODO come up with a good explanation/understanding for why we never do |
| 465 | 423 | // DLLImportStorageClass. Empirically it only causes problems. But let's have |
| 466 | 424 | // this documented and then clean up the code accordingly. |
| ... | ... | @@ -505,7 +463,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 505 | 463 | bool external_linkage = linkage != GlobalLinkageIdInternal; |
| 506 | 464 | CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc; |
| 507 | 465 | if (cc == CallingConventionStdcall && external_linkage && |
| 508 | g->zig_target.arch.arch == ZigLLVM_x86) | |
| 466 | g->zig_target->arch == ZigLLVM_x86) | |
| 509 | 467 | { |
| 510 | 468 | // prevent llvm name mangling |
| 511 | 469 | symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); |
| ... | ... | @@ -520,10 +478,23 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 520 | 478 | fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); |
| 521 | 479 | return fn_table_entry->llvm_value; |
| 522 | 480 | } else { |
| 523 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | |
| 481 | auto entry = g->exported_symbol_names.maybe_get(symbol_name); | |
| 482 | if (entry == nullptr) { | |
| 483 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | |
| 484 | } else { | |
| 485 | assert(entry->value->id == TldIdFn); | |
| 486 | TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value); | |
| 487 | tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), | |
| 488 | tld_fn->fn_entry->type_entry->data.fn.raw_type_ref); | |
| 489 | fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, | |
| 490 | LLVMPointerType(fn_llvm_type, 0)); | |
| 491 | return fn_table_entry->llvm_value; | |
| 492 | } | |
| 524 | 493 | } |
| 525 | 494 | } else { |
| 526 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | |
| 495 | if (fn_table_entry->llvm_value == nullptr) { | |
| 496 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | |
| 497 | } | |
| 527 | 498 | |
| 528 | 499 | for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) { |
| 529 | 500 | FnExport *fn_export = &fn_table_entry->export_list.items[i]; |
| ... | ... | @@ -617,9 +588,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 617 | 588 | unsigned init_gen_i = 0; |
| 618 | 589 | if (!type_has_bits(return_type)) { |
| 619 | 590 | // nothing to do |
| 620 | } else if (type_is_codegen_pointer(return_type)) { | |
| 591 | } else if (type_is_nonnull_ptr(return_type)) { | |
| 621 | 592 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 622 | 593 | } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { |
| 594 | // Sret pointers must not be address 0 | |
| 623 | 595 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 624 | 596 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); |
| 625 | 597 | if (cc_want_sret_attr(cc)) { |
| ... | ... | @@ -637,6 +609,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 637 | 609 | |
| 638 | 610 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| 639 | 611 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 612 | // Error return trace memory is in the stack, which is impossible to be at address 0 | |
| 613 | // on any architecture. | |
| 640 | 614 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); |
| 641 | 615 | } |
| 642 | 616 | |
| ... | ... | @@ -950,6 +924,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 950 | 924 | return buf_create_from_str("invalid enum value"); |
| 951 | 925 | case PanicMsgIdFloatToInt: |
| 952 | 926 | return buf_create_from_str("integer part of floating point value out of bounds"); |
| 927 | case PanicMsgIdPtrCastNull: | |
| 928 | return buf_create_from_str("cast causes pointer to be null"); | |
| 953 | 929 | } |
| 954 | 930 | zig_unreachable(); |
| 955 | 931 | } |
| ... | ... | @@ -1244,6 +1220,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { |
| 1244 | 1220 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 1245 | 1221 | addLLVMFnAttr(fn_val, "nounwind"); |
| 1246 | 1222 | add_uwtable_attr(g, fn_val); |
| 1223 | // Error return trace memory is in the stack, which is impossible to be at address 0 | |
| 1224 | // on any architecture. | |
| 1247 | 1225 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 1248 | 1226 | if (g->build_mode == BuildModeDebug) { |
| 1249 | 1227 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| ... | ... | @@ -1318,9 +1296,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { |
| 1318 | 1296 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 1319 | 1297 | addLLVMFnAttr(fn_val, "nounwind"); |
| 1320 | 1298 | add_uwtable_attr(g, fn_val); |
| 1299 | // Error return trace memory is in the stack, which is impossible to be at address 0 | |
| 1300 | // on any architecture. | |
| 1321 | 1301 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 1322 | 1302 | addLLVMArgAttr(fn_val, (unsigned)0, "noalias"); |
| 1323 | 1303 | addLLVMArgAttr(fn_val, (unsigned)0, "writeonly"); |
| 1304 | // Error return trace memory is in the stack, which is impossible to be at address 0 | |
| 1305 | // on any architecture. | |
| 1324 | 1306 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); |
| 1325 | 1307 | addLLVMArgAttr(fn_val, (unsigned)1, "noalias"); |
| 1326 | 1308 | addLLVMArgAttr(fn_val, (unsigned)1, "readonly"); |
| ... | ... | @@ -1448,6 +1430,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 1448 | 1430 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 1449 | 1431 | addLLVMFnAttr(fn_val, "nounwind"); |
| 1450 | 1432 | add_uwtable_attr(g, fn_val); |
| 1433 | // Error return trace memory is in the stack, which is impossible to be at address 0 | |
| 1434 | // on any architecture. | |
| 1451 | 1435 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 1452 | 1436 | if (g->build_mode == BuildModeDebug) { |
| 1453 | 1437 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| ... | ... | @@ -2049,7 +2033,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2049 | 2033 | case FnWalkIdAttrs: { |
| 2050 | 2034 | ZigType *ptr_type = get_codegen_ptr_type(ty); |
| 2051 | 2035 | if (ptr_type != nullptr) { |
| 2052 | if (ty->id != ZigTypeIdOptional) { | |
| 2036 | if (type_is_nonnull_ptr(ty)) { | |
| 2053 | 2037 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); |
| 2054 | 2038 | } |
| 2055 | 2039 | if (ptr_type->data.pointer.is_const) { |
| ... | ... | @@ -2093,6 +2077,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2093 | 2077 | assert(handle_is_ptr(ty)); |
| 2094 | 2078 | switch (fn_walk->id) { |
| 2095 | 2079 | case FnWalkIdAttrs: |
| 2080 | // arrays passed to C ABI functions may not be at address 0 | |
| 2096 | 2081 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); |
| 2097 | 2082 | addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); |
| 2098 | 2083 | fn_walk->data.attrs.gen_i += 1; |
| ... | ... | @@ -2123,7 +2108,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2123 | 2108 | return true; |
| 2124 | 2109 | } |
| 2125 | 2110 | |
| 2126 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { | |
| 2111 | if (g->zig_target->arch == ZigLLVM_x86_64) { | |
| 2127 | 2112 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty); |
| 2128 | 2113 | size_t ty_size = type_size(g, ty); |
| 2129 | 2114 | if (abi_class == X64CABIClass_MEMORY) { |
| ... | ... | @@ -2132,6 +2117,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2132 | 2117 | case FnWalkIdAttrs: |
| 2133 | 2118 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval"); |
| 2134 | 2119 | addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); |
| 2120 | // Byvalue parameters must not have address 0 | |
| 2135 | 2121 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); |
| 2136 | 2122 | fn_walk->data.attrs.gen_i += 1; |
| 2137 | 2123 | break; |
| ... | ... | @@ -2264,7 +2250,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2264 | 2250 | if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) { |
| 2265 | 2251 | addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly"); |
| 2266 | 2252 | } |
| 2267 | if (param_type->id == ZigTypeIdPointer) { | |
| 2253 | if (get_codegen_ptr_type(param_type) != nullptr) { | |
| 2254 | addLLVMArgAttrInt(llvm_fn, (unsigned)gen_index, "align", get_ptr_align(g, param_type)); | |
| 2255 | } | |
| 2256 | if (type_is_nonnull_ptr(param_type)) { | |
| 2268 | 2257 | addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull"); |
| 2269 | 2258 | } |
| 2270 | 2259 | break; |
| ... | ... | @@ -2657,7 +2646,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2657 | 2646 | (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) || |
| 2658 | 2647 | (op1->value.type->id == ZigTypeIdPointer && |
| 2659 | 2648 | (op_id == IrBinOpAdd || op_id == IrBinOpSub) && |
| 2660 | op1->value.type->data.pointer.ptr_len == PtrLenUnknown) | |
| 2649 | op1->value.type->data.pointer.ptr_len != PtrLenSingle) | |
| 2661 | 2650 | ); |
| 2662 | 2651 | ZigType *operand_type = op1->value.type; |
| 2663 | 2652 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; |
| ... | ... | @@ -2716,7 +2705,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2716 | 2705 | AddSubMulMul; |
| 2717 | 2706 | |
| 2718 | 2707 | if (scalar_type->id == ZigTypeIdPointer) { |
| 2719 | assert(scalar_type->data.pointer.ptr_len == PtrLenUnknown); | |
| 2708 | assert(scalar_type->data.pointer.ptr_len != PtrLenSingle); | |
| 2720 | 2709 | LLVMValueRef subscript_value; |
| 2721 | 2710 | if (operand_type->id == ZigTypeIdVector) |
| 2722 | 2711 | zig_panic("TODO: Implement vector operations on pointers."); |
| ... | ... | @@ -2863,6 +2852,76 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in |
| 2863 | 2852 | } |
| 2864 | 2853 | } |
| 2865 | 2854 | |
| 2855 | static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, | |
| 2856 | IrInstructionResizeSlice *instruction) | |
| 2857 | { | |
| 2858 | ZigType *actual_type = instruction->operand->value.type; | |
| 2859 | ZigType *wanted_type = instruction->base.value.type; | |
| 2860 | LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); | |
| 2861 | assert(expr_val); | |
| 2862 | ||
| 2863 | assert(instruction->tmp_ptr); | |
| 2864 | assert(wanted_type->id == ZigTypeIdStruct); | |
| 2865 | assert(wanted_type->data.structure.is_slice); | |
| 2866 | assert(actual_type->id == ZigTypeIdStruct); | |
| 2867 | assert(actual_type->data.structure.is_slice); | |
| 2868 | ||
| 2869 | ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; | |
| 2870 | ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; | |
| 2871 | ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; | |
| 2872 | ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; | |
| 2873 | ||
| 2874 | ||
| 2875 | size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index; | |
| 2876 | size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index; | |
| 2877 | size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index; | |
| 2878 | size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index; | |
| 2879 | ||
| 2880 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); | |
| 2881 | LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); | |
| 2882 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, | |
| 2883 | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); | |
| 2884 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | |
| 2885 | (unsigned)wanted_ptr_index, ""); | |
| 2886 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); | |
| 2887 | ||
| 2888 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); | |
| 2889 | LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); | |
| 2890 | uint64_t src_size = type_size(g, actual_child_type); | |
| 2891 | uint64_t dest_size = type_size(g, wanted_child_type); | |
| 2892 | ||
| 2893 | LLVMValueRef new_len; | |
| 2894 | if (dest_size == 1) { | |
| 2895 | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); | |
| 2896 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); | |
| 2897 | } else if (src_size == 1) { | |
| 2898 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); | |
| 2899 | if (ir_want_runtime_safety(g, &instruction->base)) { | |
| 2900 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); | |
| 2901 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); | |
| 2902 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); | |
| 2903 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); | |
| 2904 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); | |
| 2905 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | |
| 2906 | ||
| 2907 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | |
| 2908 | gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); | |
| 2909 | ||
| 2910 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | |
| 2911 | } | |
| 2912 | new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); | |
| 2913 | } else { | |
| 2914 | zig_unreachable(); | |
| 2915 | } | |
| 2916 | ||
| 2917 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | |
| 2918 | (unsigned)wanted_len_index, ""); | |
| 2919 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); | |
| 2920 | ||
| 2921 | ||
| 2922 | return instruction->tmp_ptr; | |
| 2923 | } | |
| 2924 | ||
| 2866 | 2925 | static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2867 | 2926 | IrInstructionCast *cast_instruction) |
| 2868 | 2927 | { |
| ... | ... | @@ -2877,69 +2936,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2877 | 2936 | zig_unreachable(); |
| 2878 | 2937 | case CastOpNoop: |
| 2879 | 2938 | return expr_val; |
| 2880 | case CastOpResizeSlice: | |
| 2881 | { | |
| 2882 | assert(cast_instruction->tmp_ptr); | |
| 2883 | assert(wanted_type->id == ZigTypeIdStruct); | |
| 2884 | assert(wanted_type->data.structure.is_slice); | |
| 2885 | assert(actual_type->id == ZigTypeIdStruct); | |
| 2886 | assert(actual_type->data.structure.is_slice); | |
| 2887 | ||
| 2888 | ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; | |
| 2889 | ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; | |
| 2890 | ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; | |
| 2891 | ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; | |
| 2892 | ||
| 2893 | ||
| 2894 | size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index; | |
| 2895 | size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index; | |
| 2896 | size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index; | |
| 2897 | size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index; | |
| 2898 | ||
| 2899 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); | |
| 2900 | LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); | |
| 2901 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, | |
| 2902 | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); | |
| 2903 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | |
| 2904 | (unsigned)wanted_ptr_index, ""); | |
| 2905 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); | |
| 2906 | ||
| 2907 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); | |
| 2908 | LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); | |
| 2909 | uint64_t src_size = type_size(g, actual_child_type); | |
| 2910 | uint64_t dest_size = type_size(g, wanted_child_type); | |
| 2911 | ||
| 2912 | LLVMValueRef new_len; | |
| 2913 | if (dest_size == 1) { | |
| 2914 | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); | |
| 2915 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); | |
| 2916 | } else if (src_size == 1) { | |
| 2917 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); | |
| 2918 | if (ir_want_runtime_safety(g, &cast_instruction->base)) { | |
| 2919 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); | |
| 2920 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); | |
| 2921 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); | |
| 2922 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); | |
| 2923 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); | |
| 2924 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | |
| 2925 | ||
| 2926 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | |
| 2927 | gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); | |
| 2928 | ||
| 2929 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | |
| 2930 | } | |
| 2931 | new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); | |
| 2932 | } else { | |
| 2933 | zig_unreachable(); | |
| 2934 | } | |
| 2935 | ||
| 2936 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | |
| 2937 | (unsigned)wanted_len_index, ""); | |
| 2938 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); | |
| 2939 | ||
| 2940 | ||
| 2941 | return cast_instruction->tmp_ptr; | |
| 2942 | } | |
| 2943 | 2939 | case CastOpIntToFloat: |
| 2944 | 2940 | assert(actual_type->id == ZigTypeIdInt); |
| 2945 | 2941 | if (actual_type->data.integral.is_signed) { |
| ... | ... | @@ -3028,15 +3024,51 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, |
| 3028 | 3024 | return nullptr; |
| 3029 | 3025 | } |
| 3030 | 3026 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 3031 | return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); | |
| 3027 | LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); | |
| 3028 | bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); | |
| 3029 | if (!want_safety_check || ptr_allows_addr_zero(wanted_type)) | |
| 3030 | return result_ptr; | |
| 3031 | ||
| 3032 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr)); | |
| 3033 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, ""); | |
| 3034 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail"); | |
| 3035 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk"); | |
| 3036 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | |
| 3037 | ||
| 3038 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | |
| 3039 | gen_safety_crash(g, PanicMsgIdPtrCastNull); | |
| 3040 | ||
| 3041 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | |
| 3042 | return result_ptr; | |
| 3032 | 3043 | } |
| 3033 | 3044 | |
| 3034 | 3045 | static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, |
| 3035 | IrInstructionBitCast *instruction) | |
| 3046 | IrInstructionBitCastGen *instruction) | |
| 3036 | 3047 | { |
| 3037 | 3048 | ZigType *wanted_type = instruction->base.value.type; |
| 3038 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | |
| 3039 | return LLVMBuildBitCast(g->builder, value, wanted_type->type_ref, ""); | |
| 3049 | ZigType *actual_type = instruction->operand->value.type; | |
| 3050 | LLVMValueRef value = ir_llvm_value(g, instruction->operand); | |
| 3051 | ||
| 3052 | bool wanted_is_ptr = handle_is_ptr(wanted_type); | |
| 3053 | bool actual_is_ptr = handle_is_ptr(actual_type); | |
| 3054 | if (wanted_is_ptr == actual_is_ptr) { | |
| 3055 | // We either bitcast the value directly or bitcast the pointer which does a pointer cast | |
| 3056 | LLVMTypeRef wanted_type_ref = wanted_is_ptr ? | |
| 3057 | LLVMPointerType(wanted_type->type_ref, 0) : wanted_type->type_ref; | |
| 3058 | return LLVMBuildBitCast(g->builder, value, wanted_type_ref, ""); | |
| 3059 | } else if (actual_is_ptr) { | |
| 3060 | LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(wanted_type->type_ref, 0); | |
| 3061 | LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, ""); | |
| 3062 | uint32_t alignment = get_abi_alignment(g, actual_type); | |
| 3063 | return gen_load_untyped(g, bitcasted_ptr, alignment, false, ""); | |
| 3064 | } else { | |
| 3065 | assert(instruction->tmp_ptr != nullptr); | |
| 3066 | LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(actual_type->type_ref, 0); | |
| 3067 | LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, ""); | |
| 3068 | uint32_t alignment = get_abi_alignment(g, wanted_type); | |
| 3069 | gen_store_untyped(g, value, bitcasted_ptr, alignment, false); | |
| 3070 | return instruction->tmp_ptr; | |
| 3071 | } | |
| 3040 | 3072 | } |
| 3041 | 3073 | |
| 3042 | 3074 | static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable, |
| ... | ... | @@ -3167,7 +3199,8 @@ static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstruc |
| 3167 | 3199 | static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) { |
| 3168 | 3200 | IrUnOp op_id = un_op_instruction->op_id; |
| 3169 | 3201 | LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value); |
| 3170 | ZigType *expr_type = un_op_instruction->value->value.type; | |
| 3202 | ZigType *operand_type = un_op_instruction->value->value.type; | |
| 3203 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; | |
| 3171 | 3204 | |
| 3172 | 3205 | switch (op_id) { |
| 3173 | 3206 | case IrUnOpInvalid: |
| ... | ... | @@ -3177,16 +3210,16 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst |
| 3177 | 3210 | case IrUnOpNegation: |
| 3178 | 3211 | case IrUnOpNegationWrap: |
| 3179 | 3212 | { |
| 3180 | if (expr_type->id == ZigTypeIdFloat) { | |
| 3213 | if (scalar_type->id == ZigTypeIdFloat) { | |
| 3181 | 3214 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base)); |
| 3182 | 3215 | return LLVMBuildFNeg(g->builder, expr, ""); |
| 3183 | } else if (expr_type->id == ZigTypeIdInt) { | |
| 3216 | } else if (scalar_type->id == ZigTypeIdInt) { | |
| 3184 | 3217 | if (op_id == IrUnOpNegationWrap) { |
| 3185 | 3218 | return LLVMBuildNeg(g->builder, expr, ""); |
| 3186 | 3219 | } else if (ir_want_runtime_safety(g, &un_op_instruction->base)) { |
| 3187 | 3220 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); |
| 3188 | return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr); | |
| 3189 | } else if (expr_type->data.integral.is_signed) { | |
| 3221 | return gen_overflow_op(g, operand_type, AddSubMulSub, zero, expr); | |
| 3222 | } else if (scalar_type->data.integral.is_signed) { | |
| 3190 | 3223 | return LLVMBuildNSWNeg(g->builder, expr, ""); |
| 3191 | 3224 | } else { |
| 3192 | 3225 | return LLVMBuildNUWNeg(g->builder, expr, ""); |
| ... | ... | @@ -3237,7 +3270,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 3237 | 3270 | return nullptr; |
| 3238 | 3271 | } |
| 3239 | 3272 | |
| 3240 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) { | |
| 3273 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) { | |
| 3241 | 3274 | ZigType *child_type = instruction->base.value.type; |
| 3242 | 3275 | if (!type_has_bits(child_type)) |
| 3243 | 3276 | return nullptr; |
| ... | ... | @@ -3252,7 +3285,6 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3252 | 3285 | |
| 3253 | 3286 | bool big_endian = g->is_big_endian; |
| 3254 | 3287 | |
| 3255 | assert(!handle_is_ptr(child_type)); | |
| 3256 | 3288 | LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); |
| 3257 | 3289 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| 3258 | 3290 | assert(host_bit_count == host_int_bytes * 8); |
| ... | ... | @@ -3264,7 +3296,16 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3264 | 3296 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); |
| 3265 | 3297 | LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); |
| 3266 | 3298 | |
| 3267 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); | |
| 3299 | if (!handle_is_ptr(child_type)) | |
| 3300 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); | |
| 3301 | ||
| 3302 | assert(instruction->tmp_ptr != nullptr); | |
| 3303 | LLVMTypeRef same_size_int = LLVMIntType(size_in_bits); | |
| 3304 | LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, ""); | |
| 3305 | LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, | |
| 3306 | LLVMPointerType(same_size_int, 0), ""); | |
| 3307 | LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr); | |
| 3308 | return instruction->tmp_ptr; | |
| 3268 | 3309 | } |
| 3269 | 3310 | |
| 3270 | 3311 | static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { |
| ... | ... | @@ -3307,6 +3348,77 @@ static bool value_is_all_undef(ConstExprValue *const_val) { |
| 3307 | 3348 | zig_unreachable(); |
| 3308 | 3349 | } |
| 3309 | 3350 | |
| 3351 | static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default_value, LLVMValueRef request, | |
| 3352 | LLVMValueRef a1, LLVMValueRef a2, LLVMValueRef a3, LLVMValueRef a4, LLVMValueRef a5) | |
| 3353 | { | |
| 3354 | if (!target_has_valgrind_support(g->zig_target)) { | |
| 3355 | return default_value; | |
| 3356 | } | |
| 3357 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; | |
| 3358 | bool asm_has_side_effects = true; | |
| 3359 | bool asm_is_alignstack = false; | |
| 3360 | if (g->zig_target->arch == ZigLLVM_x86_64) { | |
| 3361 | if (g->zig_target->os == OsLinux || target_is_darwin(g->zig_target) || g->zig_target->os == OsSolaris || | |
| 3362 | (g->zig_target->os == OsWindows && g->zig_target->abi != ZigLLVM_MSVC)) | |
| 3363 | { | |
| 3364 | if (g->cur_fn->valgrind_client_request_array == nullptr) { | |
| 3365 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | |
| 3366 | LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(g->cur_fn->llvm_value); | |
| 3367 | LLVMValueRef first_inst = LLVMGetFirstInstruction(entry_block); | |
| 3368 | LLVMPositionBuilderBefore(g->builder, first_inst); | |
| 3369 | LLVMTypeRef array_type_ref = LLVMArrayType(usize_type_ref, 6); | |
| 3370 | g->cur_fn->valgrind_client_request_array = LLVMBuildAlloca(g->builder, array_type_ref, ""); | |
| 3371 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | |
| 3372 | } | |
| 3373 | LLVMValueRef array_ptr = g->cur_fn->valgrind_client_request_array; | |
| 3374 | LLVMValueRef array_elements[] = {request, a1, a2, a3, a4, a5}; | |
| 3375 | LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false); | |
| 3376 | for (unsigned i = 0; i < 6; i += 1) { | |
| 3377 | LLVMValueRef indexes[] = { | |
| 3378 | zero, | |
| 3379 | LLVMConstInt(usize_type_ref, i, false), | |
| 3380 | }; | |
| 3381 | LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, ""); | |
| 3382 | LLVMBuildStore(g->builder, array_elements[i], elem_ptr); | |
| 3383 | } | |
| 3384 | ||
| 3385 | Buf *asm_template = buf_create_from_str( | |
| 3386 | "rolq $$3, %rdi ; rolq $$13, %rdi\n" | |
| 3387 | "rolq $$61, %rdi ; rolq $$51, %rdi\n" | |
| 3388 | "xchgq %rbx,%rbx\n" | |
| 3389 | ); | |
| 3390 | Buf *asm_constraints = buf_create_from_str( | |
| 3391 | "={rdx},{rax},0,~{cc},~{memory}" | |
| 3392 | ); | |
| 3393 | unsigned input_and_output_count = 2; | |
| 3394 | LLVMValueRef array_ptr_as_usize = LLVMBuildPtrToInt(g->builder, array_ptr, usize_type_ref, ""); | |
| 3395 | LLVMValueRef param_values[] = { array_ptr_as_usize, default_value }; | |
| 3396 | LLVMTypeRef param_types[] = {usize_type_ref, usize_type_ref}; | |
| 3397 | LLVMTypeRef function_type = LLVMFunctionType(usize_type_ref, param_types, | |
| 3398 | input_and_output_count, false); | |
| 3399 | LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template), | |
| 3400 | buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack, | |
| 3401 | LLVMInlineAsmDialectATT); | |
| 3402 | return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); | |
| 3403 | } | |
| 3404 | } | |
| 3405 | zig_unreachable(); | |
| 3406 | } | |
| 3407 | ||
| 3408 | static bool want_valgrind_support(CodeGen *g) { | |
| 3409 | if (!target_has_valgrind_support(g->zig_target)) | |
| 3410 | return false; | |
| 3411 | switch (g->valgrind_support) { | |
| 3412 | case ValgrindSupportDisabled: | |
| 3413 | return false; | |
| 3414 | case ValgrindSupportEnabled: | |
| 3415 | return true; | |
| 3416 | case ValgrindSupportAuto: | |
| 3417 | return g->build_mode == BuildModeDebug; | |
| 3418 | } | |
| 3419 | zig_unreachable(); | |
| 3420 | } | |
| 3421 | ||
| 3310 | 3422 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { |
| 3311 | 3423 | assert(type_has_bits(value_type)); |
| 3312 | 3424 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref); |
| ... | ... | @@ -3319,6 +3431,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ |
| 3319 | 3431 | ZigType *usize = g->builtin_types.entry_usize; |
| 3320 | 3432 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); |
| 3321 | 3433 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); |
| 3434 | // then tell valgrind that the memory is undefined even though we just memset it | |
| 3435 | if (want_valgrind_support(g)) { | |
| 3436 | static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; | |
| 3437 | LLVMValueRef zero = LLVMConstInt(usize->type_ref, 0, false); | |
| 3438 | LLVMValueRef req = LLVMConstInt(usize->type_ref, VG_USERREQ__MAKE_MEM_UNDEFINED, false); | |
| 3439 | LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->type_ref, ""); | |
| 3440 | gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero); | |
| 3441 | } | |
| 3322 | 3442 | } |
| 3323 | 3443 | |
| 3324 | 3444 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { |
| ... | ... | @@ -3479,7 +3599,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { |
| 3479 | 3599 | LLVMValueRef write_register_fn_val = get_write_register_fn_val(g); |
| 3480 | 3600 | |
| 3481 | 3601 | if (g->sp_md_node == nullptr) { |
| 3482 | Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target.arch)); | |
| 3602 | Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(g->zig_target->arch)); | |
| 3483 | 3603 | LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1); |
| 3484 | 3604 | g->sp_md_node = LLVMMDNode(&str_node, 1); |
| 3485 | 3605 | } |
| ... | ... | @@ -5337,6 +5457,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5337 | 5457 | case IrInstructionIdDeclVarSrc: |
| 5338 | 5458 | case IrInstructionIdPtrCastSrc: |
| 5339 | 5459 | case IrInstructionIdCmpxchgSrc: |
| 5460 | case IrInstructionIdLoadPtr: | |
| 5461 | case IrInstructionIdBitCast: | |
| 5340 | 5462 | zig_unreachable(); |
| 5341 | 5463 | |
| 5342 | 5464 | case IrInstructionIdDeclVarGen: |
| ... | ... | @@ -5355,8 +5477,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5355 | 5477 | return ir_render_br(g, executable, (IrInstructionBr *)instruction); |
| 5356 | 5478 | case IrInstructionIdUnOp: |
| 5357 | 5479 | return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction); |
| 5358 | case IrInstructionIdLoadPtr: | |
| 5359 | return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction); | |
| 5480 | case IrInstructionIdLoadPtrGen: | |
| 5481 | return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction); | |
| 5360 | 5482 | case IrInstructionIdStorePtr: |
| 5361 | 5483 | return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction); |
| 5362 | 5484 | case IrInstructionIdVarPtr: |
| ... | ... | @@ -5433,8 +5555,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5433 | 5555 | return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction); |
| 5434 | 5556 | case IrInstructionIdPtrCastGen: |
| 5435 | 5557 | return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction); |
| 5436 | case IrInstructionIdBitCast: | |
| 5437 | return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction); | |
| 5558 | case IrInstructionIdBitCastGen: | |
| 5559 | return ir_render_bit_cast(g, executable, (IrInstructionBitCastGen *)instruction); | |
| 5438 | 5560 | case IrInstructionIdWidenOrShorten: |
| 5439 | 5561 | return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction); |
| 5440 | 5562 | case IrInstructionIdPtrToInt: |
| ... | ... | @@ -5509,6 +5631,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5509 | 5631 | return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); |
| 5510 | 5632 | case IrInstructionIdAssertZero: |
| 5511 | 5633 | return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction); |
| 5634 | case IrInstructionIdResizeSlice: | |
| 5635 | return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction); | |
| 5512 | 5636 | } |
| 5513 | 5637 | zig_unreachable(); |
| 5514 | 5638 | } |
| ... | ... | @@ -5711,8 +5835,32 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 5711 | 5835 | LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref); |
| 5712 | 5836 | return LLVMConstZExt(ptr_size_int_val, big_int_type_ref); |
| 5713 | 5837 | } |
| 5714 | case ZigTypeIdArray: | |
| 5715 | zig_panic("TODO bit pack an array"); | |
| 5838 | case ZigTypeIdArray: { | |
| 5839 | LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false); | |
| 5840 | if (const_val->data.x_array.special == ConstArraySpecialUndef) { | |
| 5841 | return val; | |
| 5842 | } | |
| 5843 | expand_undef_array(g, const_val); | |
| 5844 | bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type | |
| 5845 | uint32_t packed_bits_size = type_size_bits(g, type_entry->data.array.child_type); | |
| 5846 | size_t used_bits = 0; | |
| 5847 | for (size_t i = 0; i < type_entry->data.array.len; i += 1) { | |
| 5848 | ConstExprValue *elem_val = &const_val->data.x_array.data.s_none.elements[i]; | |
| 5849 | LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val); | |
| 5850 | ||
| 5851 | if (is_big_endian) { | |
| 5852 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false); | |
| 5853 | val = LLVMConstShl(val, shift_amt); | |
| 5854 | val = LLVMConstOr(val, child_val); | |
| 5855 | } else { | |
| 5856 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); | |
| 5857 | LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); | |
| 5858 | val = LLVMConstOr(val, child_val_shifted); | |
| 5859 | used_bits += packed_bits_size; | |
| 5860 | } | |
| 5861 | } | |
| 5862 | return val; | |
| 5863 | } | |
| 5716 | 5864 | case ZigTypeIdVector: |
| 5717 | 5865 | zig_panic("TODO bit pack a vector"); |
| 5718 | 5866 | case ZigTypeIdUnion: |
| ... | ... | @@ -6387,6 +6535,22 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) { |
| 6387 | 6535 | } |
| 6388 | 6536 | } |
| 6389 | 6537 | |
| 6538 | static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) { | |
| 6539 | switch (var_linkage) { | |
| 6540 | case VarLinkageInternal: | |
| 6541 | return LLVMInternalLinkage; | |
| 6542 | case VarLinkageExportStrong: | |
| 6543 | return LLVMExternalLinkage; | |
| 6544 | case VarLinkageExportWeak: | |
| 6545 | return LLVMWeakODRLinkage; | |
| 6546 | case VarLinkageExportLinkOnce: | |
| 6547 | return LLVMLinkOnceODRLinkage; | |
| 6548 | case VarLinkageExternal: | |
| 6549 | return LLVMExternalLinkage; | |
| 6550 | } | |
| 6551 | zig_unreachable(); | |
| 6552 | } | |
| 6553 | ||
| 6390 | 6554 | static void do_code_gen(CodeGen *g) { |
| 6391 | 6555 | assert(!g->errors.length); |
| 6392 | 6556 | |
| ... | ... | @@ -6467,21 +6631,21 @@ static void do_code_gen(CodeGen *g) { |
| 6467 | 6631 | global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name)); |
| 6468 | 6632 | // TODO debug info for the extern variable |
| 6469 | 6633 | |
| 6470 | LLVMSetLinkage(global_value, LLVMExternalLinkage); | |
| 6634 | LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage)); | |
| 6471 | 6635 | maybe_import_dll(g, global_value, GlobalLinkageIdStrong); |
| 6472 | 6636 | LLVMSetAlignment(global_value, var->align_bytes); |
| 6473 | 6637 | LLVMSetGlobalConstant(global_value, var->gen_is_const); |
| 6474 | 6638 | set_global_tls(g, var, global_value); |
| 6475 | 6639 | } |
| 6476 | 6640 | } else { |
| 6477 | bool exported = (var->linkage == VarLinkageExport); | |
| 6641 | bool exported = (var->linkage != VarLinkageInternal); | |
| 6478 | 6642 | const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported)); |
| 6479 | 6643 | render_const_val(g, var->const_value, mangled_name); |
| 6480 | 6644 | render_const_val_global(g, var->const_value, mangled_name); |
| 6481 | 6645 | global_value = var->const_value->global_refs->llvm_global; |
| 6482 | 6646 | |
| 6483 | 6647 | if (exported) { |
| 6484 | LLVMSetLinkage(global_value, LLVMExternalLinkage); | |
| 6648 | LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage)); | |
| 6485 | 6649 | maybe_export_dll(g, global_value, GlobalLinkageIdStrong); |
| 6486 | 6650 | } |
| 6487 | 6651 | if (tld_var->section_name) { |
| ... | ... | @@ -6584,6 +6748,15 @@ static void do_code_gen(CodeGen *g) { |
| 6584 | 6748 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { |
| 6585 | 6749 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; |
| 6586 | 6750 | slot = &cmpxchg_instruction->tmp_ptr; |
| 6751 | } else if (instruction->id == IrInstructionIdResizeSlice) { | |
| 6752 | IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction; | |
| 6753 | slot = &resize_slice_instruction->tmp_ptr; | |
| 6754 | } else if (instruction->id == IrInstructionIdLoadPtrGen) { | |
| 6755 | IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction; | |
| 6756 | slot = &load_ptr_inst->tmp_ptr; | |
| 6757 | } else if (instruction->id == IrInstructionIdBitCastGen) { | |
| 6758 | IrInstructionBitCastGen *bit_cast_inst = (IrInstructionBitCastGen *)instruction; | |
| 6759 | slot = &bit_cast_inst->tmp_ptr; | |
| 6587 | 6760 | } else if (instruction->id == IrInstructionIdVectorToArray) { |
| 6588 | 6761 | IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction; |
| 6589 | 6762 | alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type); |
| ... | ... | @@ -6839,7 +7012,7 @@ static void define_builtin_types(CodeGen *g) { |
| 6839 | 7012 | |
| 6840 | 7013 | for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) { |
| 6841 | 7014 | const CIntTypeInfo *info = &c_int_type_infos[i]; |
| 6842 | uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id); | |
| 7015 | uint32_t size_in_bits = target_c_type_size_in_bits(g->zig_target, info->id); | |
| 6843 | 7016 | bool is_signed = info->is_signed; |
| 6844 | 7017 | |
| 6845 | 7018 | ZigType *entry = new_type_table_entry(ZigTypeIdInt); |
| ... | ... | @@ -7106,6 +7279,9 @@ static const char *build_mode_to_str(BuildMode build_mode) { |
| 7106 | 7279 | Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7107 | 7280 | Buf *contents = buf_alloc(); |
| 7108 | 7281 | |
| 7282 | // NOTE: when editing this file, you may need to make modifications to the | |
| 7283 | // cache input parameters in define_builtin_compile_vars | |
| 7284 | ||
| 7109 | 7285 | // Modifications to this struct must be coordinated with code that does anything with |
| 7110 | 7286 | // g->stack_trace_type. There are hard-coded references to the field indexes. |
| 7111 | 7287 | buf_append_str(contents, |
| ... | ... | @@ -7114,16 +7290,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7114 | 7290 | " instruction_addresses: []usize,\n" |
| 7115 | 7291 | "};\n\n"); |
| 7116 | 7292 | |
| 7293 | buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n"); | |
| 7294 | ||
| 7117 | 7295 | const char *cur_os = nullptr; |
| 7118 | 7296 | { |
| 7119 | 7297 | buf_appendf(contents, "pub const Os = enum {\n"); |
| 7120 | 7298 | uint32_t field_count = (uint32_t)target_os_count(); |
| 7121 | 7299 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 7122 | Os os_type = get_target_os(i); | |
| 7123 | const char *name = get_target_os_name(os_type); | |
| 7300 | Os os_type = target_os_enum(i); | |
| 7301 | const char *name = target_os_name(os_type); | |
| 7124 | 7302 | buf_appendf(contents, " %s,\n", name); |
| 7125 | 7303 | |
| 7126 | if (os_type == g->zig_target.os) { | |
| 7304 | if (os_type == g->zig_target->os) { | |
| 7127 | 7305 | g->target_os_index = i; |
| 7128 | 7306 | cur_os = name; |
| 7129 | 7307 | } |
| ... | ... | @@ -7134,56 +7312,81 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7134 | 7312 | |
| 7135 | 7313 | const char *cur_arch = nullptr; |
| 7136 | 7314 | { |
| 7137 | buf_appendf(contents, "pub const Arch = enum {\n"); | |
| 7315 | buf_appendf(contents, "pub const Arch = union(enum) {\n"); | |
| 7138 | 7316 | uint32_t field_count = (uint32_t)target_arch_count(); |
| 7139 | for (uint32_t i = 0; i < field_count; i += 1) { | |
| 7140 | const ArchType *arch_type = get_target_arch(i); | |
| 7141 | Buf *arch_name = buf_alloc(); | |
| 7142 | buf_resize(arch_name, 50); | |
| 7143 | get_arch_name(buf_ptr(arch_name), arch_type); | |
| 7144 | buf_resize(arch_name, strlen(buf_ptr(arch_name))); | |
| 7145 | ||
| 7146 | buf_appendf(contents, " %s,\n", buf_ptr(arch_name)); | |
| 7317 | for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) { | |
| 7318 | ZigLLVM_ArchType arch = target_arch_enum(arch_i); | |
| 7319 | const char *arch_name = target_arch_name(arch); | |
| 7320 | SubArchList sub_arch_list = target_subarch_list(arch); | |
| 7321 | if (sub_arch_list == SubArchListNone) { | |
| 7322 | buf_appendf(contents, " %s,\n", arch_name); | |
| 7323 | if (arch == g->zig_target->arch) { | |
| 7324 | g->target_arch_index = arch_i; | |
| 7325 | cur_arch = buf_ptr(buf_sprintf("Arch.%s", arch_name)); | |
| 7326 | } | |
| 7327 | } else { | |
| 7328 | const char *sub_arch_list_name = target_subarch_list_name(sub_arch_list); | |
| 7329 | buf_appendf(contents, " %s: %s,\n", arch_name, sub_arch_list_name); | |
| 7330 | if (arch == g->zig_target->arch) { | |
| 7331 | size_t sub_count = target_subarch_count(sub_arch_list); | |
| 7332 | for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) { | |
| 7333 | ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); | |
| 7334 | if (sub == g->zig_target->sub_arch) { | |
| 7335 | g->target_sub_arch_index = sub_i; | |
| 7336 | cur_arch = buf_ptr(buf_sprintf("Arch{ .%s = Arch.%s.%s }", | |
| 7337 | arch_name, sub_arch_list_name, target_subarch_name(sub))); | |
| 7338 | } | |
| 7339 | } | |
| 7340 | } | |
| 7341 | } | |
| 7342 | } | |
| 7147 | 7343 | |
| 7148 | if (arch_type->arch == g->zig_target.arch.arch && | |
| 7149 | arch_type->sub_arch == g->zig_target.arch.sub_arch) | |
| 7150 | { | |
| 7151 | g->target_arch_index = i; | |
| 7152 | cur_arch = buf_ptr(arch_name); | |
| 7344 | uint32_t list_count = target_subarch_list_count(); | |
| 7345 | // start at index 1 to skip None | |
| 7346 | for (uint32_t list_i = 1; list_i < list_count; list_i += 1) { | |
| 7347 | SubArchList sub_arch_list = target_subarch_list_enum(list_i); | |
| 7348 | const char *subarch_list_name = target_subarch_list_name(sub_arch_list); | |
| 7349 | buf_appendf(contents, " pub const %s = enum {\n", subarch_list_name); | |
| 7350 | size_t sub_count = target_subarch_count(sub_arch_list); | |
| 7351 | for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) { | |
| 7352 | ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); | |
| 7353 | buf_appendf(contents, " %s,\n", target_subarch_name(sub)); | |
| 7153 | 7354 | } |
| 7355 | buf_appendf(contents, " };\n"); | |
| 7154 | 7356 | } |
| 7155 | 7357 | buf_appendf(contents, "};\n\n"); |
| 7156 | 7358 | } |
| 7157 | 7359 | assert(cur_arch != nullptr); |
| 7158 | 7360 | |
| 7159 | const char *cur_environ = nullptr; | |
| 7361 | const char *cur_abi = nullptr; | |
| 7160 | 7362 | { |
| 7161 | buf_appendf(contents, "pub const Environ = enum {\n"); | |
| 7162 | uint32_t field_count = (uint32_t)target_environ_count(); | |
| 7363 | buf_appendf(contents, "pub const Abi = enum {\n"); | |
| 7364 | uint32_t field_count = (uint32_t)target_abi_count(); | |
| 7163 | 7365 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 7164 | ZigLLVM_EnvironmentType environ_type = get_target_environ(i); | |
| 7165 | const char *name = ZigLLVMGetEnvironmentTypeName(environ_type); | |
| 7366 | ZigLLVM_EnvironmentType abi = target_abi_enum(i); | |
| 7367 | const char *name = target_abi_name(abi); | |
| 7166 | 7368 | buf_appendf(contents, " %s,\n", name); |
| 7167 | 7369 | |
| 7168 | if (environ_type == g->zig_target.env_type) { | |
| 7169 | g->target_environ_index = i; | |
| 7170 | cur_environ = name; | |
| 7370 | if (abi == g->zig_target->abi) { | |
| 7371 | g->target_abi_index = i; | |
| 7372 | cur_abi = name; | |
| 7171 | 7373 | } |
| 7172 | 7374 | } |
| 7173 | 7375 | buf_appendf(contents, "};\n\n"); |
| 7174 | 7376 | } |
| 7175 | assert(cur_environ != nullptr); | |
| 7377 | assert(cur_abi != nullptr); | |
| 7176 | 7378 | |
| 7177 | 7379 | const char *cur_obj_fmt = nullptr; |
| 7178 | 7380 | { |
| 7179 | 7381 | buf_appendf(contents, "pub const ObjectFormat = enum {\n"); |
| 7180 | 7382 | uint32_t field_count = (uint32_t)target_oformat_count(); |
| 7181 | 7383 | for (uint32_t i = 0; i < field_count; i += 1) { |
| 7182 | ZigLLVM_ObjectFormatType oformat = get_target_oformat(i); | |
| 7183 | const char *name = get_target_oformat_name(oformat); | |
| 7384 | ZigLLVM_ObjectFormatType oformat = target_oformat_enum(i); | |
| 7385 | const char *name = target_oformat_name(oformat); | |
| 7184 | 7386 | buf_appendf(contents, " %s,\n", name); |
| 7185 | 7387 | |
| 7186 | if (oformat == g->zig_target.oformat) { | |
| 7388 | ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target); | |
| 7389 | if (oformat == target_oformat) { | |
| 7187 | 7390 | g->target_oformat_index = i; |
| 7188 | 7391 | cur_obj_fmt = name; |
| 7189 | 7392 | } |
| ... | ... | @@ -7294,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7294 | 7497 | " One,\n" |
| 7295 | 7498 | " Many,\n" |
| 7296 | 7499 | " Slice,\n" |
| 7500 | " C,\n" | |
| 7297 | 7501 | " };\n" |
| 7298 | 7502 | " };\n" |
| 7299 | 7503 | "\n" |
| ... | ... | @@ -7466,12 +7670,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7466 | 7670 | buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); |
| 7467 | 7671 | buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); |
| 7468 | 7672 | buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); |
| 7469 | buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); | |
| 7470 | buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ); | |
| 7673 | buf_appendf(contents, "pub const arch = %s;\n", cur_arch); | |
| 7674 | buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); | |
| 7471 | 7675 | buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt); |
| 7472 | 7676 | buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); |
| 7473 | 7677 | buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr)); |
| 7474 | 7678 | buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing)); |
| 7679 | buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g))); | |
| 7475 | 7680 | |
| 7476 | 7681 | buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n"); |
| 7477 | 7682 | |
| ... | ... | @@ -7500,14 +7705,15 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 7500 | 7705 | cache_int(&cache_hash, g->build_mode); |
| 7501 | 7706 | cache_bool(&cache_hash, g->is_test_build); |
| 7502 | 7707 | cache_bool(&cache_hash, g->is_single_threaded); |
| 7503 | cache_int(&cache_hash, g->zig_target.arch.arch); | |
| 7504 | cache_int(&cache_hash, g->zig_target.arch.sub_arch); | |
| 7505 | cache_int(&cache_hash, g->zig_target.vendor); | |
| 7506 | cache_int(&cache_hash, g->zig_target.os); | |
| 7507 | cache_int(&cache_hash, g->zig_target.env_type); | |
| 7508 | cache_int(&cache_hash, g->zig_target.oformat); | |
| 7708 | cache_int(&cache_hash, g->zig_target->is_native); | |
| 7709 | cache_int(&cache_hash, g->zig_target->arch); | |
| 7710 | cache_int(&cache_hash, g->zig_target->sub_arch); | |
| 7711 | cache_int(&cache_hash, g->zig_target->vendor); | |
| 7712 | cache_int(&cache_hash, g->zig_target->os); | |
| 7713 | cache_int(&cache_hash, g->zig_target->abi); | |
| 7509 | 7714 | cache_bool(&cache_hash, g->have_err_ret_tracing); |
| 7510 | 7715 | cache_bool(&cache_hash, g->libc_link_lib != nullptr); |
| 7716 | cache_bool(&cache_hash, g->valgrind_support); | |
| 7511 | 7717 | |
| 7512 | 7718 | Buf digest = BUF_INIT; |
| 7513 | 7719 | buf_resize(&digest, 0); |
| ... | ... | @@ -7576,11 +7782,11 @@ static void init(CodeGen *g) { |
| 7576 | 7782 | assert(g->root_out_name); |
| 7577 | 7783 | g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name)); |
| 7578 | 7784 | |
| 7579 | get_target_triple(&g->triple_str, &g->zig_target); | |
| 7785 | get_target_triple(&g->triple_str, g->zig_target); | |
| 7580 | 7786 | |
| 7581 | 7787 | LLVMSetTarget(g->module, buf_ptr(&g->triple_str)); |
| 7582 | 7788 | |
| 7583 | if (g->zig_target.oformat == ZigLLVM_COFF) { | |
| 7789 | if (target_object_format(g->zig_target) == ZigLLVM_COFF) { | |
| 7584 | 7790 | ZigLLVMAddModuleCodeViewFlag(g->module); |
| 7585 | 7791 | } else { |
| 7586 | 7792 | ZigLLVMAddModuleDebugInfoFlag(g->module); |
| ... | ... | @@ -7608,11 +7814,11 @@ static void init(CodeGen *g) { |
| 7608 | 7814 | |
| 7609 | 7815 | const char *target_specific_cpu_args; |
| 7610 | 7816 | const char *target_specific_features; |
| 7611 | if (g->is_native_target) { | |
| 7817 | if (g->zig_target->is_native) { | |
| 7612 | 7818 | // LLVM creates invalid binaries on Windows sometimes. |
| 7613 | 7819 | // See https://github.com/ziglang/zig/issues/508 |
| 7614 | 7820 | // As a workaround we do not use target native features on Windows. |
| 7615 | if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) { | |
| 7821 | if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) { | |
| 7616 | 7822 | target_specific_cpu_args = ""; |
| 7617 | 7823 | target_specific_features = ""; |
| 7618 | 7824 | } else { |
| ... | ... | @@ -7685,9 +7891,59 @@ static void init(CodeGen *g) { |
| 7685 | 7891 | } |
| 7686 | 7892 | } |
| 7687 | 7893 | |
| 7688 | void codegen_translate_c(CodeGen *g, Buf *full_path) { | |
| 7689 | find_libc_include_path(g); | |
| 7894 | static void detect_libc(CodeGen *g) { | |
| 7895 | Error err; | |
| 7896 | ||
| 7897 | if (g->libc != nullptr || g->libc_link_lib == nullptr) | |
| 7898 | return; | |
| 7899 | ||
| 7900 | if (g->zig_target->is_native) { | |
| 7901 | g->libc = allocate<ZigLibCInstallation>(1); | |
| 7902 | ||
| 7903 | // Look for zig-cache/native_libc.txt | |
| 7904 | Buf *native_libc_txt = buf_alloc(); | |
| 7905 | os_path_join(&g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt); | |
| 7906 | if ((err = zig_libc_parse(g->libc, native_libc_txt, g->zig_target, false))) { | |
| 7907 | if ((err = zig_libc_find_native(g->libc, true))) { | |
| 7908 | fprintf(stderr, | |
| 7909 | "Unable to link against libc: Unable to find libc installation: %s\n" | |
| 7910 | "See `zig libc --help` for more details.\n", err_str(err)); | |
| 7911 | exit(1); | |
| 7912 | } | |
| 7913 | if ((err = os_make_path(&g->cache_dir))) { | |
| 7914 | fprintf(stderr, "Unable to create %s directory: %s\n", | |
| 7915 | buf_ptr(&g->cache_dir), err_str(err)); | |
| 7916 | exit(1); | |
| 7917 | } | |
| 7918 | Buf *native_libc_tmp = buf_sprintf("%s.tmp", buf_ptr(native_libc_txt)); | |
| 7919 | FILE *file = fopen(buf_ptr(native_libc_tmp), "wb"); | |
| 7920 | if (file == nullptr) { | |
| 7921 | fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno)); | |
| 7922 | exit(1); | |
| 7923 | } | |
| 7924 | zig_libc_render(g->libc, file); | |
| 7925 | if (fclose(file) != 0) { | |
| 7926 | fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno)); | |
| 7927 | exit(1); | |
| 7928 | } | |
| 7929 | if ((err = os_rename(native_libc_tmp, native_libc_txt))) { | |
| 7930 | fprintf(stderr, "Unable to create %s: %s\n", buf_ptr(native_libc_txt), err_str(err)); | |
| 7931 | exit(1); | |
| 7932 | } | |
| 7933 | } | |
| 7934 | } else if ((g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) && | |
| 7935 | !target_is_darwin(g->zig_target)) | |
| 7936 | { | |
| 7937 | // Currently darwin is the only platform that we can link libc on when not compiling natively, | |
| 7938 | // without a cross compiling libc kit. | |
| 7939 | fprintf(stderr, | |
| 7940 | "Cannot link against libc for non-native OS '%s' without providing a libc installation file.\n" | |
| 7941 | "See `zig libc --help` for more details.\n", target_os_name(g->zig_target->os)); | |
| 7942 | exit(1); | |
| 7943 | } | |
| 7944 | } | |
| 7690 | 7945 | |
| 7946 | void codegen_translate_c(CodeGen *g, Buf *full_path) { | |
| 7691 | 7947 | Buf *src_basename = buf_alloc(); |
| 7692 | 7948 | Buf *src_dirname = buf_alloc(); |
| 7693 | 7949 | os_path_split(full_path, src_dirname, src_basename); |
| ... | ... | @@ -7698,6 +7954,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) { |
| 7698 | 7954 | g->root_import = import; |
| 7699 | 7955 | import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import); |
| 7700 | 7956 | |
| 7957 | detect_libc(g); | |
| 7958 | ||
| 7701 | 7959 | init(g); |
| 7702 | 7960 | |
| 7703 | 7961 | import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); |
| ... | ... | @@ -7857,14 +8115,14 @@ static void gen_root_source(CodeGen *g) { |
| 7857 | 8115 | } |
| 7858 | 8116 | report_errors_and_maybe_exit(g); |
| 7859 | 8117 | |
| 7860 | if (!g->is_test_build && g->zig_target.os != OsFreestanding && | |
| 7861 | g->zig_target.os != OsUefi && | |
| 8118 | if (!g->is_test_build && g->zig_target->os != OsFreestanding && | |
| 8119 | g->zig_target->os != OsUefi && | |
| 7862 | 8120 | !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup && |
| 7863 | 8121 | ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) |
| 7864 | 8122 | { |
| 7865 | 8123 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig"); |
| 7866 | 8124 | } |
| 7867 | if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup && | |
| 8125 | if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup && | |
| 7868 | 8126 | g->out_type == OutTypeLib && !g->is_static) |
| 7869 | 8127 | { |
| 7870 | 8128 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig"); |
| ... | ... | @@ -7882,6 +8140,8 @@ static void gen_root_source(CodeGen *g) { |
| 7882 | 8140 | } |
| 7883 | 8141 | } |
| 7884 | 8142 | |
| 8143 | typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn); | |
| 8144 | ||
| 7885 | 8145 | report_errors_and_maybe_exit(g); |
| 7886 | 8146 | |
| 7887 | 8147 | } |
| ... | ... | @@ -7904,6 +8164,168 @@ static void gen_global_asm(CodeGen *g) { |
| 7904 | 8164 | } |
| 7905 | 8165 | } |
| 7906 | 8166 | |
| 8167 | static void print_zig_cc_cmd(const char *zig_exe, ZigList<const char *> *args) { | |
| 8168 | fprintf(stderr, "%s", zig_exe); | |
| 8169 | for (size_t arg_i = 0; arg_i < args->length; arg_i += 1) { | |
| 8170 | fprintf(stderr, " %s", args->at(arg_i)); | |
| 8171 | } | |
| 8172 | fprintf(stderr, "\n"); | |
| 8173 | } | |
| 8174 | ||
| 8175 | static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { | |
| 8176 | Error err; | |
| 8177 | ||
| 8178 | Buf *c_source_file = buf_create_from_str(c_file->source_path); | |
| 8179 | Buf *c_source_basename = buf_alloc(); | |
| 8180 | os_path_split(c_source_file, nullptr, c_source_basename); | |
| 8181 | Buf *out_obj_name = buf_sprintf("%s%s", buf_ptr(c_source_basename), target_o_file_ext(g->zig_target)); | |
| 8182 | Buf *out_obj_path = buf_alloc(); | |
| 8183 | os_path_join(&g->cache_dir, out_obj_name, out_obj_path); | |
| 8184 | Buf *out_dep_name = buf_sprintf("%s.d", buf_ptr(c_source_file)); | |
| 8185 | Buf *out_dep_path = buf_alloc(); | |
| 8186 | os_path_join(&g->cache_dir, out_dep_name, out_dep_path); | |
| 8187 | ||
| 8188 | Termination term; | |
| 8189 | ZigList<const char *> args = {}; | |
| 8190 | args.append("cc"); | |
| 8191 | ||
| 8192 | if (g->enable_cache) { | |
| 8193 | args.append("-MD"); | |
| 8194 | args.append("-MF"); | |
| 8195 | args.append(buf_ptr(out_dep_path)); | |
| 8196 | } | |
| 8197 | ||
| 8198 | args.append("-nostdinc"); | |
| 8199 | args.append("-fno-spell-checking"); | |
| 8200 | ||
| 8201 | switch (g->err_color) { | |
| 8202 | case ErrColorAuto: | |
| 8203 | break; | |
| 8204 | case ErrColorOff: | |
| 8205 | args.append("-fno-color-diagnostics"); | |
| 8206 | args.append("-fno-caret-diagnostics"); | |
| 8207 | break; | |
| 8208 | case ErrColorOn: | |
| 8209 | args.append("-fcolor-diagnostics"); | |
| 8210 | args.append("-fcaret-diagnostics"); | |
| 8211 | break; | |
| 8212 | } | |
| 8213 | ||
| 8214 | args.append("-isystem"); | |
| 8215 | args.append(buf_ptr(g->zig_c_headers_dir)); | |
| 8216 | ||
| 8217 | if (g->libc != nullptr) { | |
| 8218 | args.append("-isystem"); | |
| 8219 | args.append(buf_ptr(&g->libc->include_dir)); | |
| 8220 | ||
| 8221 | if (!buf_eql_buf(&g->libc->include_dir, &g->libc->sys_include_dir)) { | |
| 8222 | args.append("-isystem"); | |
| 8223 | args.append(buf_ptr(&g->libc->sys_include_dir)); | |
| 8224 | } | |
| 8225 | } | |
| 8226 | ||
| 8227 | if (g->zig_target->is_native) { | |
| 8228 | args.append("-march=native"); | |
| 8229 | } else { | |
| 8230 | args.append("-target"); | |
| 8231 | args.append(buf_ptr(&g->triple_str)); | |
| 8232 | } | |
| 8233 | ||
| 8234 | if (!g->strip_debug_symbols) { | |
| 8235 | args.append("-g"); | |
| 8236 | } | |
| 8237 | switch (g->build_mode) { | |
| 8238 | case BuildModeDebug: | |
| 8239 | if (g->libc_link_lib != nullptr) { | |
| 8240 | args.append("-fstack-protector-strong"); | |
| 8241 | args.append("--param"); | |
| 8242 | args.append("ssp-buffer-size=4"); | |
| 8243 | } else { | |
| 8244 | args.append("-fno-stack-protector"); | |
| 8245 | } | |
| 8246 | break; | |
| 8247 | case BuildModeSafeRelease: | |
| 8248 | args.append("-O2"); | |
| 8249 | if (g->libc_link_lib != nullptr) { | |
| 8250 | args.append("-D_FORTIFY_SOURCE=2"); | |
| 8251 | args.append("-fstack-protector-strong"); | |
| 8252 | args.append("--param"); | |
| 8253 | args.append("ssp-buffer-size=4"); | |
| 8254 | } else { | |
| 8255 | args.append("-fno-stack-protector"); | |
| 8256 | } | |
| 8257 | break; | |
| 8258 | case BuildModeFastRelease: | |
| 8259 | args.append("-O2"); | |
| 8260 | args.append("-fno-stack-protector"); | |
| 8261 | break; | |
| 8262 | case BuildModeSmallRelease: | |
| 8263 | args.append("-Os"); | |
| 8264 | args.append("-fno-stack-protector"); | |
| 8265 | break; | |
| 8266 | } | |
| 8267 | ||
| 8268 | args.append("-o"); | |
| 8269 | args.append(buf_ptr(out_obj_path)); | |
| 8270 | ||
| 8271 | args.append("-c"); | |
| 8272 | args.append(buf_ptr(c_source_file)); | |
| 8273 | ||
| 8274 | if (!g->disable_pic && target_supports_fpic(g->zig_target)) { | |
| 8275 | args.append("-fPIC"); | |
| 8276 | } | |
| 8277 | ||
| 8278 | for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { | |
| 8279 | args.append(g->clang_argv[arg_i]); | |
| 8280 | } | |
| 8281 | ||
| 8282 | for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) { | |
| 8283 | args.append(c_file->args.at(arg_i)); | |
| 8284 | } | |
| 8285 | ||
| 8286 | if (g->verbose_cc) { | |
| 8287 | print_zig_cc_cmd("zig", &args); | |
| 8288 | } | |
| 8289 | os_spawn_process(buf_ptr(self_exe_path), args, &term); | |
| 8290 | if (term.how != TerminationIdClean || term.code != 0) { | |
| 8291 | fprintf(stderr, "\nThe following command failed:\n"); | |
| 8292 | print_zig_cc_cmd(buf_ptr(self_exe_path), &args); | |
| 8293 | exit(1); | |
| 8294 | } | |
| 8295 | ||
| 8296 | g->link_objects.append(out_obj_path); | |
| 8297 | ||
| 8298 | if (g->enable_cache) { | |
| 8299 | // add the files depended on to the cache system | |
| 8300 | if ((err = cache_add_file(&g->cache_hash, c_source_file))) { | |
| 8301 | fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(c_source_file), err_str(err)); | |
| 8302 | exit(1); | |
| 8303 | } | |
| 8304 | if ((err = cache_add_dep_file(&g->cache_hash, out_dep_path, true))) { | |
| 8305 | fprintf(stderr, "failed to add C source dependencies to cache: %s\n", err_str(err)); | |
| 8306 | exit(1); | |
| 8307 | } | |
| 8308 | } | |
| 8309 | } | |
| 8310 | ||
| 8311 | static void gen_c_objects(CodeGen *g) { | |
| 8312 | Error err; | |
| 8313 | ||
| 8314 | if (g->c_source_files.length == 0) | |
| 8315 | return; | |
| 8316 | ||
| 8317 | Buf *self_exe_path = buf_alloc(); | |
| 8318 | if ((err = os_self_exe_path(self_exe_path))) { | |
| 8319 | fprintf(stderr, "Unable to get self exe path: %s\n", err_str(err)); | |
| 8320 | exit(1); | |
| 8321 | } | |
| 8322 | ||
| 8323 | for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) { | |
| 8324 | CFile *c_file = g->c_source_files.at(c_file_i); | |
| 8325 | gen_c_object(g, self_exe_path, c_file); | |
| 8326 | } | |
| 8327 | } | |
| 8328 | ||
| 7907 | 8329 | void codegen_add_object(CodeGen *g, Buf *object_path) { |
| 7908 | 8330 | g->link_objects.append(object_path); |
| 7909 | 8331 | } |
| ... | ... | @@ -8410,31 +8832,39 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 8410 | 8832 | } |
| 8411 | 8833 | cache_buf(ch, compiler_id); |
| 8412 | 8834 | cache_buf(ch, g->root_out_name); |
| 8835 | cache_buf(ch, g->zig_lib_dir); | |
| 8836 | cache_buf(ch, g->zig_std_dir); | |
| 8413 | 8837 | cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length); |
| 8414 | 8838 | cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length); |
| 8415 | 8839 | cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length); |
| 8416 | 8840 | cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length); |
| 8417 | 8841 | cache_list_of_file(ch, g->link_objects.items, g->link_objects.length); |
| 8418 | 8842 | cache_list_of_file(ch, g->assembly_files.items, g->assembly_files.length); |
| 8843 | for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) { | |
| 8844 | CFile *c_file = g->c_source_files.at(c_file_i); | |
| 8845 | cache_file(ch, buf_create_from_str(c_file->source_path)); | |
| 8846 | for (size_t opt_i = 0; opt_i < c_file->args.length; opt_i += 1) { | |
| 8847 | cache_buf(ch, buf_create_from_str(c_file->args.at(opt_i))); | |
| 8848 | } | |
| 8849 | } | |
| 8419 | 8850 | cache_int(ch, g->emit_file_type); |
| 8420 | 8851 | cache_int(ch, g->build_mode); |
| 8421 | 8852 | cache_int(ch, g->out_type); |
| 8422 | cache_int(ch, g->zig_target.arch.arch); | |
| 8423 | cache_int(ch, g->zig_target.arch.sub_arch); | |
| 8424 | cache_int(ch, g->zig_target.vendor); | |
| 8425 | cache_int(ch, g->zig_target.os); | |
| 8426 | cache_int(ch, g->zig_target.env_type); | |
| 8427 | cache_int(ch, g->zig_target.oformat); | |
| 8853 | cache_bool(ch, g->zig_target->is_native); | |
| 8854 | cache_int(ch, g->zig_target->arch); | |
| 8855 | cache_int(ch, g->zig_target->sub_arch); | |
| 8856 | cache_int(ch, g->zig_target->vendor); | |
| 8857 | cache_int(ch, g->zig_target->os); | |
| 8858 | cache_int(ch, g->zig_target->abi); | |
| 8428 | 8859 | cache_int(ch, g->subsystem); |
| 8429 | 8860 | cache_bool(ch, g->is_static); |
| 8430 | 8861 | cache_bool(ch, g->strip_debug_symbols); |
| 8431 | 8862 | cache_bool(ch, g->is_test_build); |
| 8432 | 8863 | cache_bool(ch, g->is_single_threaded); |
| 8433 | cache_bool(ch, g->is_native_target); | |
| 8434 | 8864 | cache_bool(ch, g->linker_rdynamic); |
| 8435 | cache_bool(ch, g->no_rosegment_workaround); | |
| 8436 | 8865 | cache_bool(ch, g->each_lib_rpath); |
| 8437 | 8866 | cache_bool(ch, g->disable_pic); |
| 8867 | cache_bool(ch, g->valgrind_support); | |
| 8438 | 8868 | cache_buf_opt(ch, g->mmacosx_version_min); |
| 8439 | 8869 | cache_buf_opt(ch, g->mios_version_min); |
| 8440 | 8870 | cache_usize(ch, g->version_major); |
| ... | ... | @@ -8445,6 +8875,16 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 8445 | 8875 | cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len); |
| 8446 | 8876 | cache_list_of_str(ch, g->clang_argv, g->clang_argv_len); |
| 8447 | 8877 | cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length); |
| 8878 | if (g->libc) { | |
| 8879 | cache_buf(ch, &g->libc->include_dir); | |
| 8880 | cache_buf(ch, &g->libc->sys_include_dir); | |
| 8881 | cache_buf(ch, &g->libc->crt_dir); | |
| 8882 | cache_buf(ch, &g->libc->lib_dir); | |
| 8883 | cache_buf(ch, &g->libc->static_lib_dir); | |
| 8884 | cache_buf(ch, &g->libc->msvc_lib_dir); | |
| 8885 | cache_buf(ch, &g->libc->kernel32_lib_dir); | |
| 8886 | cache_buf(ch, &g->libc->dynamic_linker_path); | |
| 8887 | } | |
| 8448 | 8888 | |
| 8449 | 8889 | buf_resize(digest, 0); |
| 8450 | 8890 | if ((err = cache_hit(ch, digest))) |
| ... | ... | @@ -8459,19 +8899,19 @@ static void resolve_out_paths(CodeGen *g) { |
| 8459 | 8899 | switch (g->emit_file_type) { |
| 8460 | 8900 | case EmitFileTypeBinary: |
| 8461 | 8901 | { |
| 8462 | const char *o_ext = target_o_file_ext(&g->zig_target); | |
| 8902 | const char *o_ext = target_o_file_ext(g->zig_target); | |
| 8463 | 8903 | buf_append_str(o_basename, o_ext); |
| 8464 | 8904 | break; |
| 8465 | 8905 | } |
| 8466 | 8906 | case EmitFileTypeAssembly: |
| 8467 | 8907 | { |
| 8468 | const char *asm_ext = target_asm_file_ext(&g->zig_target); | |
| 8908 | const char *asm_ext = target_asm_file_ext(g->zig_target); | |
| 8469 | 8909 | buf_append_str(o_basename, asm_ext); |
| 8470 | 8910 | break; |
| 8471 | 8911 | } |
| 8472 | 8912 | case EmitFileTypeLLVMIr: |
| 8473 | 8913 | { |
| 8474 | const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target); | |
| 8914 | const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); | |
| 8475 | 8915 | buf_append_str(o_basename, llvm_ir_ext); |
| 8476 | 8916 | break; |
| 8477 | 8917 | } |
| ... | ... | @@ -8497,7 +8937,7 @@ static void resolve_out_paths(CodeGen *g) { |
| 8497 | 8937 | |
| 8498 | 8938 | Buf basename = BUF_INIT; |
| 8499 | 8939 | buf_init_from_buf(&basename, g->root_out_name); |
| 8500 | buf_append_str(&basename, target_exe_file_ext(&g->zig_target)); | |
| 8940 | buf_append_str(&basename, target_exe_file_ext(g->zig_target)); | |
| 8501 | 8941 | if (g->enable_cache || g->is_test_build) { |
| 8502 | 8942 | os_path_join(&g->artifact_dir, &basename, &g->output_file_path); |
| 8503 | 8943 | } else { |
| ... | ... | @@ -8510,7 +8950,7 @@ static void resolve_out_paths(CodeGen *g) { |
| 8510 | 8950 | } else { |
| 8511 | 8951 | Buf basename = BUF_INIT; |
| 8512 | 8952 | buf_init_from_buf(&basename, g->root_out_name); |
| 8513 | buf_append_str(&basename, target_lib_file_ext(&g->zig_target, g->is_static, | |
| 8953 | buf_append_str(&basename, target_lib_file_ext(g->zig_target, g->is_static, | |
| 8514 | 8954 | g->version_major, g->version_minor, g->version_patch)); |
| 8515 | 8955 | if (g->enable_cache) { |
| 8516 | 8956 | os_path_join(&g->artifact_dir, &basename, &g->output_file_path); |
| ... | ... | @@ -8523,11 +8963,12 @@ static void resolve_out_paths(CodeGen *g) { |
| 8523 | 8963 | } |
| 8524 | 8964 | } |
| 8525 | 8965 | |
| 8526 | ||
| 8527 | 8966 | void codegen_build_and_link(CodeGen *g) { |
| 8528 | 8967 | Error err; |
| 8529 | 8968 | assert(g->out_type != OutTypeUnknown); |
| 8530 | 8969 | |
| 8970 | detect_libc(g); | |
| 8971 | ||
| 8531 | 8972 | Buf *stage1_dir = get_stage1_cache_path(); |
| 8532 | 8973 | Buf *artifact_dir = buf_alloc(); |
| 8533 | 8974 | Buf digest = BUF_INIT; |
| ... | ... | @@ -8559,6 +9000,7 @@ void codegen_build_and_link(CodeGen *g) { |
| 8559 | 9000 | |
| 8560 | 9001 | gen_global_asm(g); |
| 8561 | 9002 | gen_root_source(g); |
| 9003 | gen_c_objects(g); | |
| 8562 | 9004 | |
| 8563 | 9005 | if (g->enable_cache) { |
| 8564 | 9006 | if ((err = cache_final(&g->cache_hash, &digest))) { |
| ... | ... | @@ -8576,16 +9018,25 @@ void codegen_build_and_link(CodeGen *g) { |
| 8576 | 9018 | resolve_out_paths(g); |
| 8577 | 9019 | |
| 8578 | 9020 | codegen_add_time_event(g, "Code Generation"); |
| 8579 | do_code_gen(g); | |
| 8580 | codegen_add_time_event(g, "LLVM Emit Output"); | |
| 8581 | zig_llvm_emit_output(g); | |
| 9021 | if (g->out_type == OutTypeObj && g->c_source_files.length == 1) { | |
| 9022 | assert(g->link_objects.length == 1); | |
| 9023 | if ((err = os_rename(g->link_objects.pop(), &g->o_file_output_path))) { | |
| 9024 | fprintf(stderr, "unable to move object to '%s': %s\n", | |
| 9025 | buf_ptr(&g->o_file_output_path), err_str(err)); | |
| 9026 | exit(1); | |
| 9027 | } | |
| 9028 | } else { | |
| 9029 | do_code_gen(g); | |
| 9030 | codegen_add_time_event(g, "LLVM Emit Output"); | |
| 9031 | zig_llvm_emit_output(g); | |
| 8582 | 9032 | |
| 8583 | if (g->out_h_path != nullptr) { | |
| 8584 | codegen_add_time_event(g, "Generate .h"); | |
| 8585 | gen_h_file(g); | |
| 8586 | } | |
| 8587 | if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) { | |
| 8588 | codegen_link(g); | |
| 9033 | if (g->out_h_path != nullptr) { | |
| 9034 | codegen_add_time_event(g, "Generate .h"); | |
| 9035 | gen_h_file(g); | |
| 9036 | } | |
| 9037 | if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) { | |
| 9038 | codegen_link(g); | |
| 9039 | } | |
| 8589 | 9040 | } |
| 8590 | 9041 | } |
| 8591 | 9042 |
src/codegen.hpp+3-7| ... | ... | @@ -11,11 +11,12 @@ |
| 11 | 11 | #include "parser.hpp" |
| 12 | 12 | #include "errmsg.hpp" |
| 13 | 13 | #include "target.hpp" |
| 14 | #include "libc_installation.hpp" | |
| 14 | 15 | |
| 15 | 16 | #include <stdio.h> |
| 16 | 17 | |
| 17 | 18 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, |
| 18 | Buf *zig_lib_dir, Buf *override_std_dir); | |
| 19 | Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc); | |
| 19 | 20 | |
| 20 | 21 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 21 | 22 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); |
| ... | ... | @@ -27,12 +28,6 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static); |
| 27 | 28 | void codegen_set_strip(CodeGen *codegen, bool strip); |
| 28 | 29 | void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); |
| 29 | 30 | void codegen_set_out_name(CodeGen *codegen, Buf *out_name); |
| 30 | void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir); | |
| 31 | void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir); | |
| 32 | void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); | |
| 33 | void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir); | |
| 34 | void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir); | |
| 35 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); | |
| 36 | 31 | void codegen_add_lib_dir(CodeGen *codegen, const char *dir); |
| 37 | 32 | void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); |
| 38 | 33 | LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); |
| ... | ... | @@ -46,6 +41,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter); |
| 46 | 41 | void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); |
| 47 | 42 | void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); |
| 48 | 43 | void codegen_set_output_h_path(CodeGen *g, Buf *h_path); |
| 44 | void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path); | |
| 49 | 45 | void codegen_set_output_path(CodeGen *g, Buf *path); |
| 50 | 46 | void codegen_add_time_event(CodeGen *g, const char *name); |
| 51 | 47 | void codegen_print_timing_report(CodeGen *g, FILE *f); |
src/error.cpp+9| ... | ... | @@ -34,6 +34,15 @@ const char *err_str(Error err) { |
| 34 | 34 | case ErrorPipeBusy: return "pipe busy"; |
| 35 | 35 | case ErrorPrimitiveTypeNotFound: return "primitive type not found"; |
| 36 | 36 | case ErrorCacheUnavailable: return "cache unavailable"; |
| 37 | case ErrorPathTooLong: return "path too long"; | |
| 38 | case ErrorCCompilerCannotFindFile: return "C compiler cannot find file"; | |
| 39 | case ErrorReadingDepFile: return "failed to read .d file"; | |
| 40 | case ErrorMissingArchitecture: return "missing architecture"; | |
| 41 | case ErrorMissingOperatingSystem: return "missing operating system"; | |
| 42 | case ErrorUnknownArchitecture: return "unrecognized architecture"; | |
| 43 | case ErrorUnknownOperatingSystem: return "unrecognized operating system"; | |
| 44 | case ErrorUnknownABI: return "unrecognized C ABI"; | |
| 45 | case ErrorInvalidFilename: return "invalid filename"; | |
| 37 | 46 | } |
| 38 | 47 | return "(invalid error)"; |
| 39 | 48 | } |
src/error.hpp+9| ... | ... | @@ -36,6 +36,15 @@ enum Error { |
| 36 | 36 | ErrorPipeBusy, |
| 37 | 37 | ErrorPrimitiveTypeNotFound, |
| 38 | 38 | ErrorCacheUnavailable, |
| 39 | ErrorPathTooLong, | |
| 40 | ErrorCCompilerCannotFindFile, | |
| 41 | ErrorReadingDepFile, | |
| 42 | ErrorMissingArchitecture, | |
| 43 | ErrorMissingOperatingSystem, | |
| 44 | ErrorUnknownArchitecture, | |
| 45 | ErrorUnknownOperatingSystem, | |
| 46 | ErrorUnknownABI, | |
| 47 | ErrorInvalidFilename, | |
| 39 | 48 | }; |
| 40 | 49 | |
| 41 | 50 | const char *err_str(Error err); |
src/ir.cpp+1042-367| ... | ... | @@ -61,7 +61,7 @@ enum ConstCastResultId { |
| 61 | 61 | ConstCastResultIdType, |
| 62 | 62 | ConstCastResultIdUnresolvedInferredErrSet, |
| 63 | 63 | ConstCastResultIdAsyncAllocatorType, |
| 64 | ConstCastResultIdNullWrapPtr | |
| 64 | ConstCastResultIdBadAllowsZero, | |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | 67 | struct ConstCastOnly; |
| ... | ... | @@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch; |
| 83 | 83 | struct ConstCastErrUnionPayloadMismatch; |
| 84 | 84 | struct ConstCastErrSetMismatch; |
| 85 | 85 | struct ConstCastTypeMismatch; |
| 86 | struct ConstCastBadAllowsZero; | |
| 86 | 87 | |
| 87 | 88 | struct ConstCastOnly { |
| 88 | 89 | ConstCastResultId id; |
| ... | ... | @@ -99,6 +100,7 @@ struct ConstCastOnly { |
| 99 | 100 | ConstCastOnly *null_wrap_ptr_child; |
| 100 | 101 | ConstCastArg fn_arg; |
| 101 | 102 | ConstCastArgNoAlias arg_no_alias; |
| 103 | ConstCastBadAllowsZero *bad_allows_zero; | |
| 102 | 104 | } data; |
| 103 | 105 | }; |
| 104 | 106 | |
| ... | ... | @@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch { |
| 141 | 143 | ZigList<ErrorTableEntry *> missing_errors; |
| 142 | 144 | }; |
| 143 | 145 | |
| 146 | struct ConstCastBadAllowsZero { | |
| 147 | ZigType *wanted_type; | |
| 148 | ZigType *actual_type; | |
| 149 | }; | |
| 150 | ||
| 151 | ||
| 144 | 152 | enum UndefAllowed { |
| 145 | 153 | UndefOk, |
| 146 | 154 | UndefBad, |
| ... | ... | @@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 164 | 172 | static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, |
| 165 | 173 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| 166 | 174 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| 167 | ZigType *dest_type, IrInstruction *dest_type_src); | |
| 175 | ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on); | |
| 168 | 176 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); |
| 169 | 177 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); |
| 170 | 178 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); |
| 171 | 179 | static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry); |
| 180 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | |
| 181 | ZigType *ptr_type); | |
| 182 | static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | |
| 183 | ZigType *dest_type); | |
| 172 | 184 | |
| 173 | 185 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 174 | 186 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | ... | @@ -186,10 +198,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c |
| 186 | 198 | result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index]; |
| 187 | 199 | break; |
| 188 | 200 | } |
| 189 | case ConstPtrSpecialBaseStruct: | |
| 190 | result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[ | |
| 191 | const_val->data.x_ptr.data.base_struct.field_index]; | |
| 201 | case ConstPtrSpecialBaseStruct: { | |
| 202 | ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val; | |
| 203 | result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index]; | |
| 192 | 204 | break; |
| 205 | } | |
| 193 | 206 | case ConstPtrSpecialBaseErrorUnionCode: |
| 194 | 207 | result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set; |
| 195 | 208 | break; |
| ... | ... | @@ -218,20 +231,55 @@ static bool is_opt_err_set(ZigType *ty) { |
| 218 | 231 | (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet); |
| 219 | 232 | } |
| 220 | 233 | |
| 234 | // This function returns true when you can change the type of a ConstExprValue and the | |
| 235 | // value remains meaningful. | |
| 221 | 236 | static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 222 | 237 | if (a == b) |
| 223 | 238 | return true; |
| 224 | 239 | |
| 225 | if (a->id == b->id) | |
| 226 | return true; | |
| 227 | ||
| 228 | 240 | if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr) |
| 229 | 241 | return true; |
| 230 | 242 | |
| 231 | 243 | if (is_opt_err_set(a) && is_opt_err_set(b)) |
| 232 | 244 | return true; |
| 233 | 245 | |
| 234 | return false; | |
| 246 | if (a->id != b->id) | |
| 247 | return false; | |
| 248 | ||
| 249 | switch (a->id) { | |
| 250 | case ZigTypeIdInvalid: | |
| 251 | case ZigTypeIdUnreachable: | |
| 252 | zig_unreachable(); | |
| 253 | case ZigTypeIdMetaType: | |
| 254 | case ZigTypeIdVoid: | |
| 255 | case ZigTypeIdBool: | |
| 256 | case ZigTypeIdComptimeFloat: | |
| 257 | case ZigTypeIdComptimeInt: | |
| 258 | case ZigTypeIdPointer: | |
| 259 | case ZigTypeIdUndefined: | |
| 260 | case ZigTypeIdNull: | |
| 261 | case ZigTypeIdNamespace: | |
| 262 | case ZigTypeIdBoundFn: | |
| 263 | case ZigTypeIdErrorSet: | |
| 264 | case ZigTypeIdOpaque: | |
| 265 | return true; | |
| 266 | case ZigTypeIdFloat: | |
| 267 | return a->data.floating.bit_count == b->data.floating.bit_count; | |
| 268 | case ZigTypeIdInt: | |
| 269 | return a->data.integral.is_signed == b->data.integral.is_signed; | |
| 270 | case ZigTypeIdArray: | |
| 271 | case ZigTypeIdStruct: | |
| 272 | case ZigTypeIdOptional: | |
| 273 | case ZigTypeIdErrorUnion: | |
| 274 | case ZigTypeIdEnum: | |
| 275 | case ZigTypeIdUnion: | |
| 276 | case ZigTypeIdFn: | |
| 277 | case ZigTypeIdArgTuple: | |
| 278 | case ZigTypeIdPromise: | |
| 279 | case ZigTypeIdVector: | |
| 280 | return false; | |
| 281 | } | |
| 282 | zig_unreachable(); | |
| 235 | 283 | } |
| 236 | 284 | |
| 237 | 285 | static bool ir_should_inline(IrExecutable *exec, Scope *scope) { |
| ... | ... | @@ -368,6 +416,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) { |
| 368 | 416 | return IrInstructionIdLoadPtr; |
| 369 | 417 | } |
| 370 | 418 | |
| 419 | static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtrGen *) { | |
| 420 | return IrInstructionIdLoadPtrGen; | |
| 421 | } | |
| 422 | ||
| 371 | 423 | static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) { |
| 372 | 424 | return IrInstructionIdStorePtr; |
| 373 | 425 | } |
| ... | ... | @@ -408,6 +460,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) { |
| 408 | 460 | return IrInstructionIdCast; |
| 409 | 461 | } |
| 410 | 462 | |
| 463 | static constexpr IrInstructionId ir_instruction_id(IrInstructionResizeSlice *) { | |
| 464 | return IrInstructionIdResizeSlice; | |
| 465 | } | |
| 466 | ||
| 411 | 467 | static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) { |
| 412 | 468 | return IrInstructionIdContainerInitList; |
| 413 | 469 | } |
| ... | ... | @@ -688,6 +744,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) { |
| 688 | 744 | return IrInstructionIdBitCast; |
| 689 | 745 | } |
| 690 | 746 | |
| 747 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) { | |
| 748 | return IrInstructionIdBitCastGen; | |
| 749 | } | |
| 750 | ||
| 691 | 751 | static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) { |
| 692 | 752 | return IrInstructionIdWidenOrShorten; |
| 693 | 753 | } |
| ... | ... | @@ -1291,14 +1351,23 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s |
| 1291 | 1351 | return &ptr_type_of_instruction->base; |
| 1292 | 1352 | } |
| 1293 | 1353 | |
| 1294 | static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { | |
| 1295 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node); | |
| 1296 | br_instruction->op_id = op_id; | |
| 1297 | br_instruction->value = value; | |
| 1354 | static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, | |
| 1355 | IrInstruction *value, LVal lval) | |
| 1356 | { | |
| 1357 | IrInstructionUnOp *instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node); | |
| 1358 | instruction->op_id = op_id; | |
| 1359 | instruction->value = value; | |
| 1360 | instruction->lval = lval; | |
| 1298 | 1361 | |
| 1299 | 1362 | ir_ref_instruction(value, irb->current_basic_block); |
| 1300 | 1363 | |
| 1301 | return &br_instruction->base; | |
| 1364 | return &instruction->base; | |
| 1365 | } | |
| 1366 | ||
| 1367 | static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, | |
| 1368 | IrInstruction *value) | |
| 1369 | { | |
| 1370 | return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone); | |
| 1302 | 1371 | } |
| 1303 | 1372 | |
| 1304 | 1373 | static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| ... | ... | @@ -1418,6 +1487,19 @@ static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *sourc |
| 1418 | 1487 | return &decl_var_instruction->base; |
| 1419 | 1488 | } |
| 1420 | 1489 | |
| 1490 | static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 1491 | IrInstruction *operand, ZigType *ty) | |
| 1492 | { | |
| 1493 | IrInstructionResizeSlice *instruction = ir_build_instruction<IrInstructionResizeSlice>(&ira->new_irb, | |
| 1494 | source_instruction->scope, source_instruction->source_node); | |
| 1495 | instruction->base.value.type = ty; | |
| 1496 | instruction->operand = operand; | |
| 1497 | ||
| 1498 | ir_ref_instruction(operand, ira->new_irb.current_basic_block); | |
| 1499 | ||
| 1500 | return &instruction->base; | |
| 1501 | } | |
| 1502 | ||
| 1421 | 1503 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1422 | 1504 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) |
| 1423 | 1505 | { |
| ... | ... | @@ -2190,12 +2272,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo |
| 2190 | 2272 | } |
| 2191 | 2273 | |
| 2192 | 2274 | static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2193 | IrInstruction *dest_type, IrInstruction *ptr) | |
| 2275 | IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on) | |
| 2194 | 2276 | { |
| 2195 | 2277 | IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>( |
| 2196 | 2278 | irb, scope, source_node); |
| 2197 | 2279 | instruction->dest_type = dest_type; |
| 2198 | 2280 | instruction->ptr = ptr; |
| 2281 | instruction->safety_check_on = safety_check_on; | |
| 2199 | 2282 | |
| 2200 | 2283 | ir_ref_instruction(dest_type, irb->current_basic_block); |
| 2201 | 2284 | ir_ref_instruction(ptr, irb->current_basic_block); |
| ... | ... | @@ -2204,12 +2287,26 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod |
| 2204 | 2287 | } |
| 2205 | 2288 | |
| 2206 | 2289 | static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, |
| 2207 | ZigType *ptr_type, IrInstruction *ptr) | |
| 2290 | ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on) | |
| 2208 | 2291 | { |
| 2209 | 2292 | IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>( |
| 2210 | 2293 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); |
| 2211 | 2294 | instruction->base.value.type = ptr_type; |
| 2212 | 2295 | instruction->ptr = ptr; |
| 2296 | instruction->safety_check_on = safety_check_on; | |
| 2297 | ||
| 2298 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); | |
| 2299 | ||
| 2300 | return &instruction->base; | |
| 2301 | } | |
| 2302 | ||
| 2303 | static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 2304 | IrInstruction *ptr, ZigType *ty) | |
| 2305 | { | |
| 2306 | IrInstructionLoadPtrGen *instruction = ir_build_instruction<IrInstructionLoadPtrGen>( | |
| 2307 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | |
| 2308 | instruction->base.value.type = ty; | |
| 2309 | instruction->ptr = ptr; | |
| 2213 | 2310 | |
| 2214 | 2311 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); |
| 2215 | 2312 | |
| ... | ... | @@ -2224,12 +2321,25 @@ static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *s |
| 2224 | 2321 | instruction->dest_type = dest_type; |
| 2225 | 2322 | instruction->value = value; |
| 2226 | 2323 | |
| 2227 | if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); | |
| 2324 | ir_ref_instruction(dest_type, irb->current_basic_block); | |
| 2228 | 2325 | ir_ref_instruction(value, irb->current_basic_block); |
| 2229 | 2326 | |
| 2230 | 2327 | return &instruction->base; |
| 2231 | 2328 | } |
| 2232 | 2329 | |
| 2330 | static IrInstruction *ir_build_bit_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 2331 | IrInstruction *operand, ZigType *ty) | |
| 2332 | { | |
| 2333 | IrInstructionBitCastGen *instruction = ir_build_instruction<IrInstructionBitCastGen>( | |
| 2334 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | |
| 2335 | instruction->base.value.type = ty; | |
| 2336 | instruction->operand = operand; | |
| 2337 | ||
| 2338 | ir_ref_instruction(operand, ira->new_irb.current_basic_block); | |
| 2339 | ||
| 2340 | return &instruction->base; | |
| 2341 | } | |
| 2342 | ||
| 2233 | 2343 | static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2234 | 2344 | IrInstruction *target) |
| 2235 | 2345 | { |
| ... | ... | @@ -2458,7 +2568,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode * |
| 2458 | 2568 | |
| 2459 | 2569 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 2460 | 2570 | |
| 2461 | return &instruction->base; | |
| 2571 | return &instruction->base; | |
| 2462 | 2572 | } |
| 2463 | 2573 | |
| 2464 | 2574 | static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| ... | ... | @@ -3651,6 +3761,22 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode |
| 3651 | 3761 | return ir_build_const_null(irb, scope, node); |
| 3652 | 3762 | } |
| 3653 | 3763 | |
| 3764 | static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) { | |
| 3765 | ScopeDecls *scope_decls = nullptr; | |
| 3766 | while (scope != nullptr) { | |
| 3767 | if (scope->id == ScopeIdDecls) { | |
| 3768 | scope_decls = reinterpret_cast<ScopeDecls *>(scope); | |
| 3769 | } | |
| 3770 | scope = scope->parent; | |
| 3771 | } | |
| 3772 | TldVar *tld_var = allocate<TldVar>(1); | |
| 3773 | init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); | |
| 3774 | tld_var->base.resolution = TldResolutionInvalid; | |
| 3775 | tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, | |
| 3776 | &g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid); | |
| 3777 | scope_decls->decl_table.put(var_name, &tld_var->base); | |
| 3778 | } | |
| 3779 | ||
| 3654 | 3780 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 3655 | 3781 | Error err; |
| 3656 | 3782 | assert(node->type == NodeTypeSymbol); |
| ... | ... | @@ -3704,8 +3830,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3704 | 3830 | return irb->codegen->invalid_instruction; |
| 3705 | 3831 | } |
| 3706 | 3832 | |
| 3707 | // TODO put a variable of same name with invalid type in global scope | |
| 3833 | // put a variable of same name with invalid type in global scope | |
| 3708 | 3834 | // so that future references to this same name will find a variable with an invalid type |
| 3835 | populate_invalid_variable_in_scope(irb->codegen, scope, node, variable_name); | |
| 3709 | 3836 | add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| 3710 | 3837 | return irb->codegen->invalid_instruction; |
| 3711 | 3838 | } |
| ... | ... | @@ -4493,7 +4620,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4493 | 4620 | if (arg1_value == irb->codegen->invalid_instruction) |
| 4494 | 4621 | return arg1_value; |
| 4495 | 4622 | |
| 4496 | IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value); | |
| 4623 | IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); | |
| 4497 | 4624 | return ir_lval_wrap(irb, scope, ptr_cast, lval); |
| 4498 | 4625 | } |
| 4499 | 4626 | case BuiltinFnIdBitCast: |
| ... | ... | @@ -5019,10 +5146,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction * |
| 5019 | 5146 | return ir_build_ref(irb, scope, value->source_node, value, false, false); |
| 5020 | 5147 | } |
| 5021 | 5148 | |
| 5149 | static PtrLen star_token_to_ptr_len(TokenId token_id) { | |
| 5150 | switch (token_id) { | |
| 5151 | case TokenIdStar: | |
| 5152 | case TokenIdStarStar: | |
| 5153 | return PtrLenSingle; | |
| 5154 | case TokenIdBracketStarBracket: | |
| 5155 | return PtrLenUnknown; | |
| 5156 | case TokenIdBracketStarCBracket: | |
| 5157 | return PtrLenC; | |
| 5158 | default: | |
| 5159 | zig_unreachable(); | |
| 5160 | } | |
| 5161 | } | |
| 5162 | ||
| 5022 | 5163 | static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 5023 | 5164 | assert(node->type == NodeTypePointerType); |
| 5024 | PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar || | |
| 5025 | node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown; | |
| 5165 | PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id); | |
| 5026 | 5166 | bool is_const = node->data.pointer_type.is_const; |
| 5027 | 5167 | bool is_volatile = node->data.pointer_type.is_volatile; |
| 5028 | 5168 | AstNode *expr_node = node->data.pointer_type.op_expr; |
| ... | ... | @@ -6715,14 +6855,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode |
| 6715 | 6855 | IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 |
| 6716 | 6856 | |
| 6717 | 6857 | // TODO relies on Zig not re-ordering fields |
| 6718 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst); | |
| 6858 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst, | |
| 6859 | false); | |
| 6719 | 6860 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); |
| 6720 | 6861 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 6721 | 6862 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 6722 | 6863 | atomic_state_field_name); |
| 6723 | 6864 | |
| 6724 | 6865 | // set the is_canceled bit |
| 6725 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6866 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6726 | 6867 | usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr, |
| 6727 | 6868 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6728 | 6869 | |
| ... | ... | @@ -6793,14 +6934,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode |
| 6793 | 6934 | get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void)); |
| 6794 | 6935 | |
| 6795 | 6936 | // TODO relies on Zig not re-ordering fields |
| 6796 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst); | |
| 6937 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst, | |
| 6938 | false); | |
| 6797 | 6939 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); |
| 6798 | 6940 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 6799 | 6941 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 6800 | 6942 | atomic_state_field_name); |
| 6801 | 6943 | |
| 6802 | 6944 | // clear the is_suspended bit |
| 6803 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6945 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6804 | 6946 | usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr, |
| 6805 | 6947 | AtomicRmwOp_and, AtomicOrderSeqCst); |
| 6806 | 6948 | |
| ... | ... | @@ -6916,7 +7058,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6916 | 7058 | |
| 6917 | 7059 | IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle); |
| 6918 | 7060 | IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false); |
| 6919 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 7061 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6920 | 7062 | usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr, |
| 6921 | 7063 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6922 | 7064 | |
| ... | ... | @@ -6959,7 +7101,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6959 | 7101 | |
| 6960 | 7102 | |
| 6961 | 7103 | ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block); |
| 6962 | IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 7104 | IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6963 | 7105 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr, |
| 6964 | 7106 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6965 | 7107 | IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false); |
| ... | ... | @@ -6991,7 +7133,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6991 | 7133 | |
| 6992 | 7134 | ir_set_cursor_at_end_and_append_block(irb, cleanup_block); |
| 6993 | 7135 | IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false); |
| 6994 | IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 7136 | IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | |
| 6995 | 7137 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr, |
| 6996 | 7138 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6997 | 7139 | IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false); |
| ... | ... | @@ -7194,7 +7336,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7194 | 7336 | if (value == irb->codegen->invalid_instruction) |
| 7195 | 7337 | return value; |
| 7196 | 7338 | |
| 7197 | return ir_build_un_op(irb, scope, node, IrUnOpDereference, value); | |
| 7339 | // We essentially just converted any lvalue from &(x.*) to (&x).*; | |
| 7340 | // this inhibits checking that x is a pointer later, so we directly | |
| 7341 | // record whether the pointer check is needed | |
| 7342 | return ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval); | |
| 7198 | 7343 | } |
| 7199 | 7344 | case NodeTypeUnwrapOptional: { |
| 7200 | 7345 | AstNode *expr_node = node->data.unwrap_optional.expr; |
| ... | ... | @@ -7338,7 +7483,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7338 | 7483 | |
| 7339 | 7484 | u8_ptr_type = ir_build_const_type(irb, coro_scope, node, |
| 7340 | 7485 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| 7341 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr); | |
| 7486 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, | |
| 7487 | coro_promise_ptr, false); | |
| 7342 | 7488 | coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr); |
| 7343 | 7489 | coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); |
| 7344 | 7490 | IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node); |
| ... | ... | @@ -7362,7 +7508,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7362 | 7508 | ir_build_return(irb, coro_scope, node, undef); |
| 7363 | 7509 | |
| 7364 | 7510 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); |
| 7365 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr); | |
| 7511 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr, | |
| 7512 | false); | |
| 7366 | 7513 | irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr); |
| 7367 | 7514 | |
| 7368 | 7515 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| ... | ... | @@ -7440,9 +7587,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7440 | 7587 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, |
| 7441 | 7588 | false, false, PtrLenUnknown, 0, 0, 0)); |
| 7442 | 7589 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); |
| 7443 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); | |
| 7444 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, | |
| 7445 | irb->exec->coro_result_field_ptr); | |
| 7590 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, | |
| 7591 | result_ptr, false); | |
| 7592 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, | |
| 7593 | u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false); | |
| 7446 | 7594 | IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node, |
| 7447 | 7595 | fn_entry->type_entry->data.fn.fn_type_id.return_type); |
| 7448 | 7596 | IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst); |
| ... | ... | @@ -7492,7 +7640,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7492 | 7640 | IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, |
| 7493 | 7641 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, |
| 7494 | 7642 | false, false, PtrLenUnknown, 0, 0, 0)); |
| 7495 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); | |
| 7643 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, | |
| 7644 | coro_mem_ptr_maybe, false); | |
| 7496 | 7645 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); |
| 7497 | 7646 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); |
| 7498 | 7647 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); |
| ... | ... | @@ -8619,7 +8768,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp |
| 8619 | 8768 | return err_set_type; |
| 8620 | 8769 | } |
| 8621 | 8770 | |
| 8622 | ||
| 8623 | 8771 | static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type, |
| 8624 | 8772 | ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable) |
| 8625 | 8773 | { |
| ... | ... | @@ -8632,53 +8780,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8632 | 8780 | if (wanted_type == actual_type) |
| 8633 | 8781 | return result; |
| 8634 | 8782 | |
| 8635 | // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively | |
| 8636 | // but not if we want a mutable pointer | |
| 8637 | // and not if the actual pointer has zero bits | |
| 8638 | if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional && | |
| 8639 | wanted_type->data.maybe.child_type->id == ZigTypeIdPointer && | |
| 8640 | actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type)) | |
| 8641 | { | |
| 8642 | ConstCastOnly child = types_match_const_cast_only(ira, | |
| 8643 | wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable); | |
| 8644 | if (child.id == ConstCastResultIdInvalid) | |
| 8645 | return child; | |
| 8646 | if (child.id != ConstCastResultIdOk) { | |
| 8647 | result.id = ConstCastResultIdNullWrapPtr; | |
| 8648 | result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1); | |
| 8649 | *result.data.null_wrap_ptr_child = child; | |
| 8650 | } | |
| 8651 | return result; | |
| 8652 | } | |
| 8653 | ||
| 8654 | // pointer const | |
| 8655 | if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) { | |
| 8656 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | |
| 8657 | actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const); | |
| 8783 | // If pointers have the same representation in memory, they can be "const-casted". | |
| 8784 | // `const` attribute can be gained | |
| 8785 | // `volatile` attribute can be gained | |
| 8786 | // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer) | |
| 8787 | // but only if !wanted_is_mutable | |
| 8788 | // alignment can be decreased | |
| 8789 | // bit offset attributes must match exactly | |
| 8790 | // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one | |
| 8791 | ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type); | |
| 8792 | ZigType *actual_ptr_type = get_src_ptr_type(actual_type); | |
| 8793 | bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type); | |
| 8794 | bool actual_allows_zero = ptr_allows_addr_zero(actual_type); | |
| 8795 | bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC; | |
| 8796 | bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC; | |
| 8797 | bool wanted_opt_or_ptr = wanted_ptr_type != nullptr && | |
| 8798 | (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional); | |
| 8799 | bool actual_opt_or_ptr = actual_ptr_type != nullptr && | |
| 8800 | (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional); | |
| 8801 | if (wanted_opt_or_ptr && actual_opt_or_ptr) { | |
| 8802 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, | |
| 8803 | actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const); | |
| 8658 | 8804 | if (child.id == ConstCastResultIdInvalid) |
| 8659 | 8805 | return child; |
| 8660 | 8806 | if (child.id != ConstCastResultIdOk) { |
| 8661 | 8807 | result.id = ConstCastResultIdPointerChild; |
| 8662 | 8808 | result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1); |
| 8663 | 8809 | result.data.pointer_mismatch->child = child; |
| 8664 | result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type; | |
| 8665 | result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type; | |
| 8810 | result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type; | |
| 8811 | result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type; | |
| 8812 | return result; | |
| 8813 | } | |
| 8814 | bool ok_allows_zero = (wanted_allows_zero && | |
| 8815 | (actual_allows_zero || !wanted_is_mutable)) || | |
| 8816 | (!wanted_allows_zero && !actual_allows_zero); | |
| 8817 | if (!ok_allows_zero) { | |
| 8818 | result.id = ConstCastResultIdBadAllowsZero; | |
| 8819 | result.data.bad_allows_zero = allocate_nonzero<ConstCastBadAllowsZero>(1); | |
| 8820 | result.data.bad_allows_zero->wanted_type = wanted_type; | |
| 8821 | result.data.bad_allows_zero->actual_type = actual_type; | |
| 8666 | 8822 | return result; |
| 8667 | 8823 | } |
| 8668 | if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { | |
| 8824 | if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { | |
| 8669 | 8825 | result.id = ConstCastResultIdInvalid; |
| 8670 | 8826 | return result; |
| 8671 | 8827 | } |
| 8672 | if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { | |
| 8828 | if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { | |
| 8673 | 8829 | result.id = ConstCastResultIdInvalid; |
| 8674 | 8830 | return result; |
| 8675 | 8831 | } |
| 8676 | if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) && | |
| 8677 | (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && | |
| 8678 | (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) && | |
| 8679 | actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host && | |
| 8680 | actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes && | |
| 8681 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type)) | |
| 8832 | bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len; | |
| 8833 | if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) && | |
| 8834 | type_has_bits(wanted_type) == type_has_bits(actual_type) && | |
| 8835 | (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && | |
| 8836 | (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && | |
| 8837 | actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host && | |
| 8838 | actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes && | |
| 8839 | get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type)) | |
| 8682 | 8840 | { |
| 8683 | 8841 | return result; |
| 8684 | 8842 | } |
| ... | ... | @@ -8912,7 +9070,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * |
| 8912 | 9070 | *errors = reallocate(*errors, old_errors_count, *errors_count); |
| 8913 | 9071 | } |
| 8914 | 9072 | |
| 8915 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) { | |
| 9073 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, | |
| 9074 | IrInstruction **instructions, size_t instruction_count) | |
| 9075 | { | |
| 8916 | 9076 | Error err; |
| 8917 | 9077 | assert(instruction_count >= 1); |
| 8918 | 9078 | IrInstruction *prev_inst = instructions[0]; |
| ... | ... | @@ -9229,6 +9389,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 9229 | 9389 | continue; |
| 9230 | 9390 | } |
| 9231 | 9391 | |
| 9392 | if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC && | |
| 9393 | (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt)) | |
| 9394 | { | |
| 9395 | continue; | |
| 9396 | } | |
| 9397 | ||
| 9398 | if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC && | |
| 9399 | (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt)) | |
| 9400 | { | |
| 9401 | prev_inst = cur_inst; | |
| 9402 | continue; | |
| 9403 | } | |
| 9404 | ||
| 9405 | if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) { | |
| 9406 | if (prev_type->data.pointer.ptr_len == PtrLenC && | |
| 9407 | types_match_const_cast_only(ira, prev_type->data.pointer.child_type, | |
| 9408 | cur_type->data.pointer.child_type, source_node, | |
| 9409 | !prev_type->data.pointer.is_const).id == ConstCastResultIdOk) | |
| 9410 | { | |
| 9411 | continue; | |
| 9412 | } | |
| 9413 | if (cur_type->data.pointer.ptr_len == PtrLenC && | |
| 9414 | types_match_const_cast_only(ira, cur_type->data.pointer.child_type, | |
| 9415 | prev_type->data.pointer.child_type, source_node, | |
| 9416 | !cur_type->data.pointer.is_const).id == ConstCastResultIdOk) | |
| 9417 | { | |
| 9418 | prev_inst = cur_inst; | |
| 9419 | continue; | |
| 9420 | } | |
| 9421 | } | |
| 9422 | ||
| 9232 | 9423 | if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) { |
| 9233 | 9424 | continue; |
| 9234 | 9425 | } |
| ... | ... | @@ -9534,9 +9725,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9534 | 9725 | } |
| 9535 | 9726 | const_val->type = new_type; |
| 9536 | 9727 | break; |
| 9537 | case CastOpResizeSlice: | |
| 9538 | // can't do it | |
| 9539 | zig_unreachable(); | |
| 9540 | 9728 | case CastOpIntToFloat: |
| 9541 | 9729 | { |
| 9542 | 9730 | assert(new_type->id == ZigTypeIdFloat); |
| ... | ... | @@ -9600,9 +9788,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z |
| 9600 | 9788 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 9601 | 9789 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) |
| 9602 | 9790 | { |
| 9603 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && | |
| 9604 | cast_op != CastOpResizeSlice) | |
| 9605 | { | |
| 9791 | if (instr_is_comptime(value) || !type_has_bits(wanted_type)) { | |
| 9606 | 9792 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9607 | 9793 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, |
| 9608 | 9794 | &result->value, wanted_type)) |
| ... | ... | @@ -9864,7 +10050,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un |
| 9864 | 10050 | if (undef_allowed == UndefOk) { |
| 9865 | 10051 | return &value->value; |
| 9866 | 10052 | } else { |
| 9867 | ir_add_error(ira, value, buf_sprintf("use of undefined value")); | |
| 10053 | ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior")); | |
| 9868 | 10054 | return nullptr; |
| 9869 | 10055 | } |
| 9870 | 10056 | } |
| ... | ... | @@ -9874,7 +10060,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un |
| 9874 | 10060 | ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 9875 | 10061 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 9876 | 10062 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 9877 | IrExecutable *parent_exec) | |
| 10063 | IrExecutable *parent_exec, AstNode *expected_type_source_node) | |
| 9878 | 10064 | { |
| 9879 | 10065 | if (expected_type != nullptr && type_is_invalid(expected_type)) |
| 9880 | 10066 | return &codegen->invalid_instruction->value; |
| ... | ... | @@ -9910,7 +10096,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod |
| 9910 | 10096 | analyzed_executable->backward_branch_count = backward_branch_count; |
| 9911 | 10097 | analyzed_executable->backward_branch_quota = backward_branch_quota; |
| 9912 | 10098 | analyzed_executable->begin_scope = scope; |
| 9913 | ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node); | |
| 10099 | ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node); | |
| 9914 | 10100 | if (type_is_invalid(result_type)) |
| 9915 | 10101 | return &codegen->invalid_instruction->value; |
| 9916 | 10102 | |
| ... | ... | @@ -10230,49 +10416,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 10230 | 10416 | return result; |
| 10231 | 10417 | } |
| 10232 | 10418 | |
| 10233 | static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, | |
| 10234 | IrInstruction *target, ZigType *wanted_type) | |
| 10235 | { | |
| 10419 | static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *union_type) { | |
| 10420 | assert(union_type->id == ZigTypeIdUnion); | |
| 10421 | ||
| 10236 | 10422 | Error err; |
| 10237 | assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt); | |
| 10423 | if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown))) | |
| 10424 | return ira->codegen->builtin_types.entry_invalid; | |
| 10238 | 10425 | |
| 10239 | ZigType *actual_type = target->value.type; | |
| 10240 | if ((err = ensure_complete_type(ira->codegen, actual_type))) | |
| 10241 | return ira->codegen->invalid_instruction; | |
| 10426 | AstNode *decl_node = union_type->data.unionation.decl_node; | |
| 10427 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { | |
| 10428 | assert(union_type->data.unionation.tag_type != nullptr); | |
| 10429 | return union_type->data.unionation.tag_type; | |
| 10430 | } else { | |
| 10431 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union '%s' has no tag", | |
| 10432 | buf_ptr(&union_type->name))); | |
| 10433 | add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); | |
| 10434 | return ira->codegen->builtin_types.entry_invalid; | |
| 10435 | } | |
| 10436 | } | |
| 10242 | 10437 | |
| 10243 | if (wanted_type != actual_type->data.enumeration.tag_int_type) { | |
| 10244 | ir_add_error(ira, source_instr, | |
| 10245 | buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'", | |
| 10246 | buf_ptr(&wanted_type->name), | |
| 10247 | buf_ptr(&actual_type->data.enumeration.tag_int_type->name))); | |
| 10438 | static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) { | |
| 10439 | Error err; | |
| 10440 | ||
| 10441 | IrInstruction *enum_target; | |
| 10442 | ZigType *enum_type; | |
| 10443 | if (target->value.type->id == ZigTypeIdUnion) { | |
| 10444 | enum_type = ir_resolve_union_tag_type(ira, target, target->value.type); | |
| 10445 | if (type_is_invalid(enum_type)) | |
| 10446 | return ira->codegen->invalid_instruction; | |
| 10447 | enum_target = ir_implicit_cast(ira, target, enum_type); | |
| 10448 | if (type_is_invalid(enum_target->value.type)) | |
| 10449 | return ira->codegen->invalid_instruction; | |
| 10450 | } else if (target->value.type->id == ZigTypeIdEnum) { | |
| 10451 | enum_target = target; | |
| 10452 | enum_type = target->value.type; | |
| 10453 | } else { | |
| 10454 | ir_add_error(ira, target, | |
| 10455 | buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name))); | |
| 10248 | 10456 | return ira->codegen->invalid_instruction; |
| 10249 | 10457 | } |
| 10250 | 10458 | |
| 10251 | assert(actual_type->id == ZigTypeIdEnum); | |
| 10459 | if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown))) | |
| 10460 | return ira->codegen->invalid_instruction; | |
| 10252 | 10461 | |
| 10253 | if (instr_is_comptime(target)) { | |
| 10254 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | |
| 10462 | ZigType *tag_type = enum_type->data.enumeration.tag_int_type; | |
| 10463 | assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); | |
| 10464 | ||
| 10465 | if (instr_is_comptime(enum_target)) { | |
| 10466 | ConstExprValue *val = ir_resolve_const(ira, enum_target, UndefBad); | |
| 10255 | 10467 | if (!val) |
| 10256 | 10468 | return ira->codegen->invalid_instruction; |
| 10257 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10258 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); | |
| 10469 | IrInstruction *result = ir_const(ira, source_instr, tag_type); | |
| 10470 | init_const_bigint(&result->value, tag_type, &val->data.x_enum_tag); | |
| 10259 | 10471 | return result; |
| 10260 | 10472 | } |
| 10261 | 10473 | |
| 10262 | 10474 | // If there is only one possible tag, then we know at comptime what it is. |
| 10263 | if (actual_type->data.enumeration.layout == ContainerLayoutAuto && | |
| 10264 | actual_type->data.enumeration.src_field_count == 1) | |
| 10475 | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && | |
| 10476 | enum_type->data.enumeration.src_field_count == 1) | |
| 10265 | 10477 | { |
| 10266 | assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int); | |
| 10267 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10268 | init_const_bigint(&result->value, wanted_type, | |
| 10269 | &actual_type->data.enumeration.fields[0].value); | |
| 10478 | assert(tag_type == ira->codegen->builtin_types.entry_num_lit_int); | |
| 10479 | IrInstruction *result = ir_const(ira, source_instr, tag_type); | |
| 10480 | init_const_bigint(&result->value, tag_type, | |
| 10481 | &enum_type->data.enumeration.fields[0].value); | |
| 10270 | 10482 | return result; |
| 10271 | 10483 | } |
| 10272 | 10484 | |
| 10273 | 10485 | IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, |
| 10274 | source_instr->source_node, target); | |
| 10275 | result->value.type = wanted_type; | |
| 10486 | source_instr->source_node, enum_target); | |
| 10487 | result->value.type = tag_type; | |
| 10276 | 10488 | return result; |
| 10277 | 10489 | } |
| 10278 | 10490 | |
| ... | ... | @@ -10770,17 +10982,37 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10770 | 10982 | report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg); |
| 10771 | 10983 | break; |
| 10772 | 10984 | } |
| 10985 | case ConstCastResultIdBadAllowsZero: { | |
| 10986 | ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type; | |
| 10987 | ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type; | |
| 10988 | bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type); | |
| 10989 | bool actual_allows_zero = ptr_allows_addr_zero(actual_type); | |
| 10990 | if (actual_allows_zero && !wanted_allows_zero) { | |
| 10991 | add_error_note(ira->codegen, parent_msg, source_node, | |
| 10992 | buf_sprintf("'%s' could have null values which are illegal in type '%s'", | |
| 10993 | buf_ptr(&actual_type->name), | |
| 10994 | buf_ptr(&wanted_type->name))); | |
| 10995 | } else { | |
| 10996 | add_error_note(ira->codegen, parent_msg, source_node, | |
| 10997 | buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'", | |
| 10998 | buf_ptr(&wanted_type->name), | |
| 10999 | buf_ptr(&actual_type->name))); | |
| 11000 | } | |
| 11001 | break; | |
| 11002 | } | |
| 11003 | case ConstCastResultIdFnIsGeneric: | |
| 11004 | add_error_note(ira->codegen, parent_msg, source_node, | |
| 11005 | buf_sprintf("only one of the functions is generic")); | |
| 11006 | break; | |
| 10773 | 11007 | case ConstCastResultIdFnAlign: // TODO |
| 10774 | 11008 | case ConstCastResultIdFnCC: // TODO |
| 10775 | 11009 | case ConstCastResultIdFnVarArgs: // TODO |
| 10776 | case ConstCastResultIdFnIsGeneric: // TODO | |
| 10777 | 11010 | case ConstCastResultIdFnReturnType: // TODO |
| 10778 | 11011 | case ConstCastResultIdFnArgCount: // TODO |
| 10779 | 11012 | case ConstCastResultIdFnGenericArgCount: // TODO |
| 10780 | 11013 | case ConstCastResultIdFnArgNoAlias: // TODO |
| 10781 | 11014 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO |
| 10782 | 11015 | case ConstCastResultIdAsyncAllocatorType: // TODO |
| 10783 | case ConstCastResultIdNullWrapPtr: // TODO | |
| 10784 | 11016 | break; |
| 10785 | 11017 | } |
| 10786 | 11018 | } |
| ... | ... | @@ -10811,6 +11043,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * |
| 10811 | 11043 | return ir_build_vector_to_array(ira, source_instr, vector, array_type); |
| 10812 | 11044 | } |
| 10813 | 11045 | |
| 11046 | static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr, | |
| 11047 | IrInstruction *integer, ZigType *dest_type) | |
| 11048 | { | |
| 11049 | IrInstruction *unsigned_integer; | |
| 11050 | if (instr_is_comptime(integer)) { | |
| 11051 | unsigned_integer = integer; | |
| 11052 | } else { | |
| 11053 | assert(integer->value.type->id == ZigTypeIdInt); | |
| 11054 | ||
| 11055 | if (integer->value.type->data.integral.bit_count > | |
| 11056 | ira->codegen->builtin_types.entry_usize->data.integral.bit_count) | |
| 11057 | { | |
| 11058 | ir_add_error(ira, source_instr, | |
| 11059 | buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'", | |
| 11060 | buf_ptr(&integer->value.type->name), | |
| 11061 | buf_ptr(&dest_type->name))); | |
| 11062 | return ira->codegen->invalid_instruction; | |
| 11063 | } | |
| 11064 | ||
| 11065 | if (integer->value.type->data.integral.is_signed) { | |
| 11066 | ZigType *unsigned_int_type = get_int_type(ira->codegen, false, | |
| 11067 | integer->value.type->data.integral.bit_count); | |
| 11068 | unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type); | |
| 11069 | if (type_is_invalid(unsigned_integer->value.type)) | |
| 11070 | return ira->codegen->invalid_instruction; | |
| 11071 | } else { | |
| 11072 | unsigned_integer = integer; | |
| 11073 | } | |
| 11074 | } | |
| 11075 | ||
| 11076 | return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type); | |
| 11077 | } | |
| 11078 | ||
| 10814 | 11079 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 10815 | 11080 | ZigType *wanted_type, IrInstruction *value) |
| 10816 | 11081 | { |
| ... | ... | @@ -11182,7 +11447,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11182 | 11447 | actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes && |
| 11183 | 11448 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) |
| 11184 | 11449 | { |
| 11185 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr); | |
| 11450 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); | |
| 11186 | 11451 | } |
| 11187 | 11452 | } |
| 11188 | 11453 | |
| ... | ... | @@ -11217,6 +11482,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11217 | 11482 | return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type); |
| 11218 | 11483 | } |
| 11219 | 11484 | |
| 11485 | // casting between C pointers and normal pointers | |
| 11486 | if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer && | |
| 11487 | (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) && | |
| 11488 | types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | |
| 11489 | actual_type->data.pointer.child_type, source_node, | |
| 11490 | !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) | |
| 11491 | { | |
| 11492 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); | |
| 11493 | } | |
| 11494 | ||
| 11495 | // cast from integer to C pointer | |
| 11496 | if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC && | |
| 11497 | (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt)) | |
| 11498 | { | |
| 11499 | return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type); | |
| 11500 | } | |
| 11501 | ||
| 11220 | 11502 | // cast from undefined to anything |
| 11221 | 11503 | if (actual_type->id == ZigTypeIdUndefined) { |
| 11222 | 11504 | return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); |
| ... | ... | @@ -11286,13 +11568,14 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 11286 | 11568 | IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr); |
| 11287 | 11569 | return ref_inst->value; |
| 11288 | 11570 | } |
| 11289 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, | |
| 11290 | source_instruction->source_node, ptr); | |
| 11291 | load_ptr_instruction->value.type = child_type; | |
| 11292 | return load_ptr_instruction; | |
| 11571 | IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type); | |
| 11572 | if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { | |
| 11573 | ir_add_alloca(ira, result, child_type); | |
| 11574 | } | |
| 11575 | return result; | |
| 11293 | 11576 | } else { |
| 11294 | 11577 | ir_add_error_node(ira, source_instruction->source_node, |
| 11295 | buf_sprintf("attempt to dereference non pointer type '%s'", | |
| 11578 | buf_sprintf("attempt to dereference non-pointer type '%s'", | |
| 11296 | 11579 | buf_ptr(&type_entry->name))); |
| 11297 | 11580 | return ira->codegen->invalid_instruction; |
| 11298 | 11581 | } |
| ... | ... | @@ -11588,28 +11871,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 11588 | 11871 | } |
| 11589 | 11872 | |
| 11590 | 11873 | static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { |
| 11591 | if (op_id == IrBinOpCmpEq) { | |
| 11592 | return cmp == CmpEQ; | |
| 11593 | } else if (op_id == IrBinOpCmpNotEq) { | |
| 11594 | return cmp != CmpEQ; | |
| 11595 | } else if (op_id == IrBinOpCmpLessThan) { | |
| 11596 | return cmp == CmpLT; | |
| 11597 | } else if (op_id == IrBinOpCmpGreaterThan) { | |
| 11598 | return cmp == CmpGT; | |
| 11599 | } else if (op_id == IrBinOpCmpLessOrEq) { | |
| 11600 | return cmp != CmpGT; | |
| 11601 | } else if (op_id == IrBinOpCmpGreaterOrEq) { | |
| 11602 | return cmp != CmpLT; | |
| 11603 | } else { | |
| 11604 | zig_unreachable(); | |
| 11874 | switch (op_id) { | |
| 11875 | case IrBinOpCmpEq: | |
| 11876 | return cmp == CmpEQ; | |
| 11877 | case IrBinOpCmpNotEq: | |
| 11878 | return cmp != CmpEQ; | |
| 11879 | case IrBinOpCmpLessThan: | |
| 11880 | return cmp == CmpLT; | |
| 11881 | case IrBinOpCmpGreaterThan: | |
| 11882 | return cmp == CmpGT; | |
| 11883 | case IrBinOpCmpLessOrEq: | |
| 11884 | return cmp != CmpGT; | |
| 11885 | case IrBinOpCmpGreaterOrEq: | |
| 11886 | return cmp != CmpLT; | |
| 11887 | default: | |
| 11888 | zig_unreachable(); | |
| 11605 | 11889 | } |
| 11606 | 11890 | } |
| 11607 | 11891 | |
| 11608 | 11892 | static bool optional_value_is_null(ConstExprValue *val) { |
| 11609 | 11893 | assert(val->special == ConstValSpecialStatic); |
| 11610 | 11894 | if (get_codegen_ptr_type(val->type) != nullptr) { |
| 11611 | return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | |
| 11612 | val->data.x_ptr.data.hard_coded_addr.addr == 0; | |
| 11895 | if (val->data.x_ptr.special == ConstPtrSpecialNull) { | |
| 11896 | return true; | |
| 11897 | } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { | |
| 11898 | return val->data.x_ptr.data.hard_coded_addr.addr == 0; | |
| 11899 | } else { | |
| 11900 | return false; | |
| 11901 | } | |
| 11613 | 11902 | } else if (is_opt_err_set(val->type)) { |
| 11614 | 11903 | return val->data.x_err_set == nullptr; |
| 11615 | 11904 | } else { |
| ... | ... | @@ -11773,7 +12062,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11773 | 12062 | case ZigTypeIdBool: |
| 11774 | 12063 | case ZigTypeIdMetaType: |
| 11775 | 12064 | case ZigTypeIdVoid: |
| 11776 | case ZigTypeIdPointer: | |
| 11777 | 12065 | case ZigTypeIdErrorSet: |
| 11778 | 12066 | case ZigTypeIdFn: |
| 11779 | 12067 | case ZigTypeIdOpaque: |
| ... | ... | @@ -11785,6 +12073,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11785 | 12073 | operator_allowed = is_equality_cmp; |
| 11786 | 12074 | break; |
| 11787 | 12075 | |
| 12076 | case ZigTypeIdPointer: | |
| 12077 | operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC); | |
| 12078 | break; | |
| 12079 | ||
| 11788 | 12080 | case ZigTypeIdUnreachable: |
| 11789 | 12081 | case ZigTypeIdArray: |
| 11790 | 12082 | case ZigTypeIdStruct: |
| ... | ... | @@ -11832,15 +12124,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11832 | 12124 | if (op2_val == nullptr) |
| 11833 | 12125 | return ira->codegen->invalid_instruction; |
| 11834 | 12126 | |
| 11835 | bool answer; | |
| 11836 | 12127 | if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) { |
| 11837 | 12128 | Cmp cmp_result = float_cmp(op1_val, op2_val); |
| 11838 | answer = resolve_cmp_op_id(op_id, cmp_result); | |
| 12129 | bool answer = resolve_cmp_op_id(op_id, cmp_result); | |
| 12130 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | |
| 11839 | 12131 | } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) { |
| 11840 | 12132 | Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11841 | answer = resolve_cmp_op_id(op_id, cmp_result); | |
| 12133 | bool answer = resolve_cmp_op_id(op_id, cmp_result); | |
| 12134 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | |
| 12135 | } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { | |
| 12136 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | |
| 12137 | op1_val->data.x_ptr.special == ConstPtrSpecialNull) && | |
| 12138 | (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | |
| 12139 | op2_val->data.x_ptr.special == ConstPtrSpecialNull)) | |
| 12140 | { | |
| 12141 | uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ? | |
| 12142 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; | |
| 12143 | uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ? | |
| 12144 | 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr; | |
| 12145 | Cmp cmp_result; | |
| 12146 | if (op1_addr > op2_addr) { | |
| 12147 | cmp_result = CmpGT; | |
| 12148 | } else if (op1_addr < op2_addr) { | |
| 12149 | cmp_result = CmpLT; | |
| 12150 | } else { | |
| 12151 | cmp_result = CmpEQ; | |
| 12152 | } | |
| 12153 | bool answer = resolve_cmp_op_id(op_id, cmp_result); | |
| 12154 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | |
| 12155 | } | |
| 11842 | 12156 | } else { |
| 11843 | 12157 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); |
| 12158 | bool answer; | |
| 11844 | 12159 | if (op_id == IrBinOpCmpEq) { |
| 11845 | 12160 | answer = are_equal; |
| 11846 | 12161 | } else if (op_id == IrBinOpCmpNotEq) { |
| ... | ... | @@ -11848,9 +12163,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11848 | 12163 | } else { |
| 11849 | 12164 | zig_unreachable(); |
| 11850 | 12165 | } |
| 12166 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | |
| 11851 | 12167 | } |
| 11852 | ||
| 11853 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | |
| 11854 | 12168 | } |
| 11855 | 12169 | |
| 11856 | 12170 | // some comparisons with unsigned numbers can be evaluated |
| ... | ... | @@ -12245,7 +12559,29 @@ static bool ok_float_op(IrBinOp op) { |
| 12245 | 12559 | zig_unreachable(); |
| 12246 | 12560 | } |
| 12247 | 12561 | |
| 12562 | static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { | |
| 12563 | if (lhs_type->id != ZigTypeIdPointer) | |
| 12564 | return false; | |
| 12565 | switch (op) { | |
| 12566 | case IrBinOpAdd: | |
| 12567 | case IrBinOpSub: | |
| 12568 | break; | |
| 12569 | default: | |
| 12570 | return false; | |
| 12571 | } | |
| 12572 | switch (lhs_type->data.pointer.ptr_len) { | |
| 12573 | case PtrLenSingle: | |
| 12574 | return false; | |
| 12575 | case PtrLenUnknown: | |
| 12576 | case PtrLenC: | |
| 12577 | break; | |
| 12578 | } | |
| 12579 | return true; | |
| 12580 | } | |
| 12581 | ||
| 12248 | 12582 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 12583 | Error err; | |
| 12584 | ||
| 12249 | 12585 | IrInstruction *op1 = instruction->op1->child; |
| 12250 | 12586 | if (type_is_invalid(op1->value.type)) |
| 12251 | 12587 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -12257,23 +12593,54 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 12257 | 12593 | IrBinOp op_id = instruction->op_id; |
| 12258 | 12594 | |
| 12259 | 12595 | // look for pointer math |
| 12260 | if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown && | |
| 12261 | (op_id == IrBinOpAdd || op_id == IrBinOpSub)) | |
| 12262 | { | |
| 12596 | if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) { | |
| 12263 | 12597 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); |
| 12264 | if (casted_op2 == ira->codegen->invalid_instruction) | |
| 12598 | if (type_is_invalid(casted_op2->value.type)) | |
| 12265 | 12599 | return ira->codegen->invalid_instruction; |
| 12266 | 12600 | |
| 12267 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | |
| 12268 | instruction->base.source_node, op_id, op1, casted_op2, true); | |
| 12269 | result->value.type = op1->value.type; | |
| 12270 | return result; | |
| 12271 | } | |
| 12272 | ||
| 12273 | IrInstruction *instructions[] = {op1, op2}; | |
| 12274 | ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2); | |
| 12275 | if (type_is_invalid(resolved_type)) | |
| 12276 | return ira->codegen->invalid_instruction; | |
| 12601 | if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) { | |
| 12602 | IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type); | |
| 12603 | result->value.special = ConstValSpecialUndef; | |
| 12604 | return result; | |
| 12605 | } | |
| 12606 | if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic && | |
| 12607 | (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | |
| 12608 | op1->value.data.x_ptr.special == ConstPtrSpecialNull)) | |
| 12609 | { | |
| 12610 | uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ? | |
| 12611 | 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr; | |
| 12612 | uint64_t elem_offset; | |
| 12613 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) | |
| 12614 | return ira->codegen->invalid_instruction; | |
| 12615 | ZigType *elem_type = op1->value.type->data.pointer.child_type; | |
| 12616 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) | |
| 12617 | return ira->codegen->invalid_instruction; | |
| 12618 | uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset; | |
| 12619 | uint64_t new_addr; | |
| 12620 | if (op_id == IrBinOpAdd) { | |
| 12621 | new_addr = start_addr + byte_offset; | |
| 12622 | } else if (op_id == IrBinOpSub) { | |
| 12623 | new_addr = start_addr - byte_offset; | |
| 12624 | } else { | |
| 12625 | zig_unreachable(); | |
| 12626 | } | |
| 12627 | IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type); | |
| 12628 | result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | |
| 12629 | result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar; | |
| 12630 | result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr; | |
| 12631 | return result; | |
| 12632 | } | |
| 12633 | ||
| 12634 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | |
| 12635 | instruction->base.source_node, op_id, op1, casted_op2, true); | |
| 12636 | result->value.type = op1->value.type; | |
| 12637 | return result; | |
| 12638 | } | |
| 12639 | ||
| 12640 | IrInstruction *instructions[] = {op1, op2}; | |
| 12641 | ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2); | |
| 12642 | if (type_is_invalid(resolved_type)) | |
| 12643 | return ira->codegen->invalid_instruction; | |
| 12277 | 12644 | |
| 12278 | 12645 | bool is_int = resolved_type->id == ZigTypeIdInt || resolved_type->id == ZigTypeIdComptimeInt; |
| 12279 | 12646 | bool is_float = resolved_type->id == ZigTypeIdFloat || resolved_type->id == ZigTypeIdComptimeFloat; |
| ... | ... | @@ -12878,6 +13245,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, |
| 12878 | 13245 | return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value); |
| 12879 | 13246 | } |
| 12880 | 13247 | |
| 13248 | static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) { | |
| 13249 | switch (id) { | |
| 13250 | case GlobalLinkageIdStrong: | |
| 13251 | return VarLinkageExportStrong; | |
| 13252 | case GlobalLinkageIdWeak: | |
| 13253 | return VarLinkageExportWeak; | |
| 13254 | case GlobalLinkageIdLinkOnce: | |
| 13255 | return VarLinkageExportLinkOnce; | |
| 13256 | case GlobalLinkageIdInternal: | |
| 13257 | return VarLinkageInternal; | |
| 13258 | } | |
| 13259 | zig_unreachable(); | |
| 13260 | } | |
| 13261 | ||
| 12881 | 13262 | static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { |
| 12882 | 13263 | IrInstruction *name = instruction->name->child; |
| 12883 | 13264 | Buf *symbol_name = ir_resolve_str(ira, name); |
| ... | ... | @@ -12898,14 +13279,24 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12898 | 13279 | } |
| 12899 | 13280 | } |
| 12900 | 13281 | |
| 12901 | auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, instruction->base.source_node); | |
| 13282 | // TODO: This function needs to be audited. | |
| 13283 | // It's not clear how all the different types are supposed to be handled. | |
| 13284 | // Need comprehensive tests for exporting one thing in one file and declaring an extern var | |
| 13285 | // in another file. | |
| 13286 | TldFn *tld_fn = allocate<TldFn>(1); | |
| 13287 | tld_fn->base.id = TldIdFn; | |
| 13288 | tld_fn->base.source_node = instruction->base.source_node; | |
| 13289 | ||
| 13290 | auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, &tld_fn->base); | |
| 12902 | 13291 | if (entry) { |
| 12903 | AstNode *other_export_node = entry->value; | |
| 13292 | AstNode *other_export_node = entry->value->source_node; | |
| 12904 | 13293 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, |
| 12905 | 13294 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name))); |
| 12906 | 13295 | add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); |
| 13296 | return ira->codegen->invalid_instruction; | |
| 12907 | 13297 | } |
| 12908 | 13298 | |
| 13299 | bool want_var_export = false; | |
| 12909 | 13300 | switch (target->value.type->id) { |
| 12910 | 13301 | case ZigTypeIdInvalid: |
| 12911 | 13302 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -12913,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12913 | 13304 | case ZigTypeIdFn: { |
| 12914 | 13305 | assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction); |
| 12915 | 13306 | ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry; |
| 13307 | tld_fn->fn_entry = fn_entry; | |
| 12916 | 13308 | CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; |
| 12917 | 13309 | switch (cc) { |
| 12918 | 13310 | case CallingConventionUnspecified: { |
| ... | ... | @@ -12941,6 +13333,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12941 | 13333 | ErrorMsg *msg = ir_add_error(ira, target, |
| 12942 | 13334 | buf_sprintf("exported struct value must be declared extern")); |
| 12943 | 13335 | add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here")); |
| 13336 | } else { | |
| 13337 | want_var_export = true; | |
| 12944 | 13338 | } |
| 12945 | 13339 | break; |
| 12946 | 13340 | case ZigTypeIdUnion: |
| ... | ... | @@ -12948,6 +13342,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12948 | 13342 | ErrorMsg *msg = ir_add_error(ira, target, |
| 12949 | 13343 | buf_sprintf("exported union value must be declared extern")); |
| 12950 | 13344 | add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here")); |
| 13345 | } else { | |
| 13346 | want_var_export = true; | |
| 12951 | 13347 | } |
| 12952 | 13348 | break; |
| 12953 | 13349 | case ZigTypeIdEnum: |
| ... | ... | @@ -12955,6 +13351,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12955 | 13351 | ErrorMsg *msg = ir_add_error(ira, target, |
| 12956 | 13352 | buf_sprintf("exported enum value must be declared extern")); |
| 12957 | 13353 | add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here")); |
| 13354 | } else { | |
| 13355 | want_var_export = true; | |
| 12958 | 13356 | } |
| 12959 | 13357 | break; |
| 12960 | 13358 | case ZigTypeIdMetaType: { |
| ... | ... | @@ -13044,6 +13442,16 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 13044 | 13442 | break; |
| 13045 | 13443 | } |
| 13046 | 13444 | |
| 13445 | // TODO audit the various ways to use @export | |
| 13446 | if (want_var_export && target->id == IrInstructionIdLoadPtrGen) { | |
| 13447 | IrInstructionLoadPtrGen *load_ptr = reinterpret_cast<IrInstructionLoadPtrGen *>(target); | |
| 13448 | if (load_ptr->ptr->id == IrInstructionIdVarPtr) { | |
| 13449 | IrInstructionVarPtr *var_ptr = reinterpret_cast<IrInstructionVarPtr *>(load_ptr->ptr); | |
| 13450 | ZigVar *var = var_ptr->var; | |
| 13451 | var->linkage = global_linkage_to_var_linkage(global_linkage_id); | |
| 13452 | } | |
| 13453 | } | |
| 13454 | ||
| 13047 | 13455 | return ir_const_void(ira, &instruction->base); |
| 13048 | 13456 | } |
| 13049 | 13457 | |
| ... | ... | @@ -13331,9 +13739,16 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 13331 | 13739 | if (var->var_type == nullptr || type_is_invalid(var->var_type)) |
| 13332 | 13740 | return ira->codegen->invalid_instruction; |
| 13333 | 13741 | |
| 13742 | ConstExprValue *mem_slot = nullptr; | |
| 13743 | ||
| 13334 | 13744 | bool comptime_var_mem = ir_get_var_is_comptime(var); |
| 13745 | bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal; | |
| 13746 | bool is_const = var->src_is_const; | |
| 13747 | bool is_volatile = false; | |
| 13748 | ||
| 13749 | if (linkage_makes_it_runtime) | |
| 13750 | goto no_mem_slot; | |
| 13335 | 13751 | |
| 13336 | ConstExprValue *mem_slot = nullptr; | |
| 13337 | 13752 | if (var->const_value->special == ConstValSpecialStatic) { |
| 13338 | 13753 | mem_slot = var->const_value; |
| 13339 | 13754 | } else { |
| ... | ... | @@ -13347,8 +13762,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 13347 | 13762 | } |
| 13348 | 13763 | } |
| 13349 | 13764 | |
| 13350 | bool is_const = var->src_is_const; | |
| 13351 | bool is_volatile = false; | |
| 13352 | 13765 | if (mem_slot != nullptr) { |
| 13353 | 13766 | switch (mem_slot->special) { |
| 13354 | 13767 | case ConstValSpecialRuntime: |
| ... | ... | @@ -13387,26 +13800,32 @@ no_mem_slot: |
| 13387 | 13800 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 13388 | 13801 | IrInstruction *ptr, IrInstruction *uncasted_value) |
| 13389 | 13802 | { |
| 13390 | if (ptr->value.type->id != ZigTypeIdPointer) { | |
| 13391 | ir_add_error(ira, ptr, | |
| 13392 | buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); | |
| 13393 | return ira->codegen->invalid_instruction; | |
| 13394 | } | |
| 13803 | assert(ptr->value.type->id == ZigTypeIdPointer); | |
| 13395 | 13804 | |
| 13396 | 13805 | if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { |
| 13397 | 13806 | return ir_const_void(ira, source_instr); |
| 13398 | 13807 | } |
| 13399 | 13808 | |
| 13809 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | |
| 13810 | ||
| 13400 | 13811 | if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) { |
| 13401 | 13812 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 13402 | 13813 | return ira->codegen->invalid_instruction; |
| 13403 | 13814 | } |
| 13404 | 13815 | |
| 13405 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | |
| 13406 | 13816 | IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); |
| 13407 | 13817 | if (value == ira->codegen->invalid_instruction) |
| 13408 | 13818 | return ira->codegen->invalid_instruction; |
| 13409 | 13819 | |
| 13820 | switch (type_has_one_possible_value(ira->codegen, child_type)) { | |
| 13821 | case OnePossibleValueInvalid: | |
| 13822 | return ira->codegen->invalid_instruction; | |
| 13823 | case OnePossibleValueYes: | |
| 13824 | return ir_const_void(ira, source_instr); | |
| 13825 | case OnePossibleValueNo: | |
| 13826 | break; | |
| 13827 | } | |
| 13828 | ||
| 13410 | 13829 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 13411 | 13830 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { |
| 13412 | 13831 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| ... | ... | @@ -13427,15 +13846,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 13427 | 13846 | bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar; |
| 13428 | 13847 | copy_const_val(dest_val, &value->value, same_global_refs); |
| 13429 | 13848 | if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { |
| 13430 | switch (type_has_one_possible_value(ira->codegen, child_type)) { | |
| 13431 | case OnePossibleValueInvalid: | |
| 13432 | return ira->codegen->invalid_instruction; | |
| 13433 | case OnePossibleValueNo: | |
| 13434 | ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr; | |
| 13435 | break; | |
| 13436 | case OnePossibleValueYes: | |
| 13437 | break; | |
| 13438 | } | |
| 13849 | ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr; | |
| 13439 | 13850 | } |
| 13440 | 13851 | return ir_const_void(ira, source_instr); |
| 13441 | 13852 | } |
| ... | ... | @@ -13630,7 +14041,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13630 | 14041 | AstNode *body_node = fn_entry->body_node; |
| 13631 | 14042 | result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, |
| 13632 | 14043 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, |
| 13633 | nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); | |
| 14044 | nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node); | |
| 13634 | 14045 | |
| 13635 | 14046 | if (inferred_err_set_type != nullptr) { |
| 13636 | 14047 | inferred_err_set_type->data.error_set.infer_fn = nullptr; |
| ... | ... | @@ -13826,7 +14237,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13826 | 14237 | ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, |
| 13827 | 14238 | fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), |
| 13828 | 14239 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, |
| 13829 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec); | |
| 14240 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr); | |
| 13830 | 14241 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 13831 | 14242 | impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); |
| 13832 | 14243 | const_instruction->base.value = *align_result; |
| ... | ... | @@ -14108,12 +14519,11 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 14108 | 14519 | size_t src_size = type_size(codegen, pointee->type); |
| 14109 | 14520 | size_t dst_size = type_size(codegen, out_val->type); |
| 14110 | 14521 | |
| 14111 | if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) { | |
| 14112 | copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | |
| 14113 | return ErrorNone; | |
| 14114 | } | |
| 14115 | ||
| 14116 | 14522 | if (dst_size <= src_size) { |
| 14523 | if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) { | |
| 14524 | copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | |
| 14525 | return ErrorNone; | |
| 14526 | } | |
| 14117 | 14527 | Buf buf = BUF_INIT; |
| 14118 | 14528 | buf_resize(&buf, src_size); |
| 14119 | 14529 | buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee); |
| ... | ... | @@ -14129,12 +14539,12 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 14129 | 14539 | if (dst_size == 0) |
| 14130 | 14540 | return ErrorNone; |
| 14131 | 14541 | opt_ir_add_error_node(ira, codegen, source_node, |
| 14132 | buf_sprintf("attempt to read %zu bytes from null pointer", | |
| 14542 | buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from null pointer", | |
| 14133 | 14543 | dst_size)); |
| 14134 | 14544 | return ErrorSemanticAnalyzeFail; |
| 14135 | 14545 | case ConstPtrSpecialRef: { |
| 14136 | 14546 | opt_ir_add_error_node(ira, codegen, source_node, |
| 14137 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", | |
| 14547 | buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from pointer to %s which is %" ZIG_PRI_usize " bytes", | |
| 14138 | 14548 | dst_size, buf_ptr(&pointee->type->name), src_size)); |
| 14139 | 14549 | return ErrorSemanticAnalyzeFail; |
| 14140 | 14550 | } |
| ... | ... | @@ -14148,7 +14558,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 14148 | 14558 | src_size = elem_size * (array_val->type->data.array.len - elem_index); |
| 14149 | 14559 | if (dst_size > src_size) { |
| 14150 | 14560 | opt_ir_add_error_node(ira, codegen, source_node, |
| 14151 | buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes", | |
| 14561 | buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes", | |
| 14152 | 14562 | dst_size, buf_ptr(&array_val->type->name), elem_index, src_size)); |
| 14153 | 14563 | return ErrorSemanticAnalyzeFail; |
| 14154 | 14564 | } |
| ... | ... | @@ -14220,6 +14630,41 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_ |
| 14220 | 14630 | zig_unreachable(); |
| 14221 | 14631 | } |
| 14222 | 14632 | |
| 14633 | static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type, | |
| 14634 | ConstExprValue *operand_val, ConstExprValue *scalar_out_val, bool is_wrap_op) | |
| 14635 | { | |
| 14636 | bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat); | |
| 14637 | ||
| 14638 | bool ok_type = ((scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) || | |
| 14639 | scalar_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op)); | |
| 14640 | ||
| 14641 | if (!ok_type) { | |
| 14642 | const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'"; | |
| 14643 | return ir_add_error(ira, source_instr, buf_sprintf(fmt, buf_ptr(&scalar_type->name))); | |
| 14644 | } | |
| 14645 | ||
| 14646 | if (is_float) { | |
| 14647 | float_negate(scalar_out_val, operand_val); | |
| 14648 | } else if (is_wrap_op) { | |
| 14649 | bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint, | |
| 14650 | scalar_type->data.integral.bit_count); | |
| 14651 | } else { | |
| 14652 | bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint); | |
| 14653 | } | |
| 14654 | ||
| 14655 | scalar_out_val->type = scalar_type; | |
| 14656 | scalar_out_val->special = ConstValSpecialStatic; | |
| 14657 | ||
| 14658 | if (is_wrap_op || is_float || scalar_type->id == ZigTypeIdComptimeInt) { | |
| 14659 | return nullptr; | |
| 14660 | } | |
| 14661 | ||
| 14662 | if (!bigint_fits_in_bits(&scalar_out_val->data.x_bigint, scalar_type->data.integral.bit_count, true)) { | |
| 14663 | return ir_add_error(ira, source_instr, buf_sprintf("negation caused overflow")); | |
| 14664 | } | |
| 14665 | return nullptr; | |
| 14666 | } | |
| 14667 | ||
| 14223 | 14668 | static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) { |
| 14224 | 14669 | IrInstruction *value = instruction->value->child; |
| 14225 | 14670 | ZigType *expr_type = value->value.type; |
| ... | ... | @@ -14228,47 +14673,50 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins |
| 14228 | 14673 | |
| 14229 | 14674 | bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap); |
| 14230 | 14675 | |
| 14231 | bool is_float = (expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat); | |
| 14676 | ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type; | |
| 14232 | 14677 | |
| 14233 | if ((expr_type->id == ZigTypeIdInt && expr_type->data.integral.is_signed) || | |
| 14234 | expr_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op)) | |
| 14235 | { | |
| 14236 | if (instr_is_comptime(value)) { | |
| 14237 | ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad); | |
| 14238 | if (!target_const_val) | |
| 14239 | return ira->codegen->invalid_instruction; | |
| 14678 | if (instr_is_comptime(value)) { | |
| 14679 | ConstExprValue *operand_val = ir_resolve_const(ira, value, UndefBad); | |
| 14680 | if (!operand_val) | |
| 14681 | return ira->codegen->invalid_instruction; | |
| 14240 | 14682 | |
| 14241 | IrInstruction *result = ir_const(ira, &instruction->base, expr_type); | |
| 14242 | ConstExprValue *out_val = &result->value; | |
| 14243 | if (is_float) { | |
| 14244 | float_negate(out_val, target_const_val); | |
| 14245 | } else if (is_wrap_op) { | |
| 14246 | bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint, | |
| 14247 | expr_type->data.integral.bit_count); | |
| 14248 | } else { | |
| 14249 | bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint); | |
| 14250 | } | |
| 14251 | if (is_wrap_op || is_float || expr_type->id == ZigTypeIdComptimeInt) { | |
| 14252 | return result; | |
| 14683 | IrInstruction *result_instruction = ir_const(ira, &instruction->base, expr_type); | |
| 14684 | ConstExprValue *out_val = &result_instruction->value; | |
| 14685 | if (expr_type->id == ZigTypeIdVector) { | |
| 14686 | expand_undef_array(ira->codegen, operand_val); | |
| 14687 | out_val->special = ConstValSpecialUndef; | |
| 14688 | expand_undef_array(ira->codegen, out_val); | |
| 14689 | size_t len = expr_type->data.vector.len; | |
| 14690 | for (size_t i = 0; i < len; i += 1) { | |
| 14691 | ConstExprValue *scalar_operand_val = &operand_val->data.x_array.data.s_none.elements[i]; | |
| 14692 | ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i]; | |
| 14693 | assert(scalar_operand_val->type == scalar_type); | |
| 14694 | assert(scalar_out_val->type == scalar_type); | |
| 14695 | ErrorMsg *msg = ir_eval_negation_scalar(ira, &instruction->base, scalar_type, | |
| 14696 | scalar_operand_val, scalar_out_val, is_wrap_op); | |
| 14697 | if (msg != nullptr) { | |
| 14698 | add_error_note(ira->codegen, msg, instruction->base.source_node, | |
| 14699 | buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); | |
| 14700 | return ira->codegen->invalid_instruction; | |
| 14701 | } | |
| 14253 | 14702 | } |
| 14254 | ||
| 14255 | if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) { | |
| 14256 | ir_add_error(ira, &instruction->base, buf_sprintf("negation caused overflow")); | |
| 14703 | out_val->type = expr_type; | |
| 14704 | out_val->special = ConstValSpecialStatic; | |
| 14705 | } else { | |
| 14706 | if (ir_eval_negation_scalar(ira, &instruction->base, scalar_type, operand_val, out_val, | |
| 14707 | is_wrap_op) != nullptr) | |
| 14708 | { | |
| 14257 | 14709 | return ira->codegen->invalid_instruction; |
| 14258 | 14710 | } |
| 14259 | return result; | |
| 14260 | 14711 | } |
| 14261 | ||
| 14262 | IrInstruction *result = ir_build_un_op(&ira->new_irb, | |
| 14263 | instruction->base.scope, instruction->base.source_node, | |
| 14264 | instruction->op_id, value); | |
| 14265 | result->value.type = expr_type; | |
| 14266 | return result; | |
| 14712 | return result_instruction; | |
| 14267 | 14713 | } |
| 14268 | 14714 | |
| 14269 | const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'"; | |
| 14270 | ir_add_error(ira, &instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name))); | |
| 14271 | return ira->codegen->invalid_instruction; | |
| 14715 | IrInstruction *result = ir_build_un_op(&ira->new_irb, | |
| 14716 | instruction->base.scope, instruction->base.source_node, | |
| 14717 | instruction->op_id, value); | |
| 14718 | result->value.type = expr_type; | |
| 14719 | return result; | |
| 14272 | 14720 | } |
| 14273 | 14721 | |
| 14274 | 14722 | static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) { |
| ... | ... | @@ -14321,11 +14769,18 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction |
| 14321 | 14769 | buf_ptr(&ptr_type->name))); |
| 14322 | 14770 | return ira->codegen->invalid_instruction; |
| 14323 | 14771 | } |
| 14324 | // this dereference is always an rvalue because in the IR gen we identify lvalue and emit | |
| 14325 | // one of the ptr instructions | |
| 14772 | ||
| 14326 | 14773 | IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr); |
| 14327 | 14774 | if (result == ira->codegen->invalid_instruction) |
| 14328 | 14775 | return ira->codegen->invalid_instruction; |
| 14776 | ||
| 14777 | // If the result needs to be an lvalue, type check it | |
| 14778 | if (instruction->lval == LValPtr && result->value.type->id != ZigTypeIdPointer) { | |
| 14779 | ir_add_error(ira, &instruction->base, | |
| 14780 | buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&result->value.type->name))); | |
| 14781 | return ira->codegen->invalid_instruction; | |
| 14782 | } | |
| 14783 | ||
| 14329 | 14784 | return result; |
| 14330 | 14785 | } |
| 14331 | 14786 | case IrUnOpOptional: |
| ... | ... | @@ -14958,6 +15413,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 14958 | 15413 | if (bare_type->id == ZigTypeIdStruct) { |
| 14959 | 15414 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| 14960 | 15415 | if (field) { |
| 15416 | switch (type_has_one_possible_value(ira->codegen, field->type_entry)) { | |
| 15417 | case OnePossibleValueInvalid: | |
| 15418 | return ira->codegen->invalid_instruction; | |
| 15419 | case OnePossibleValueYes: { | |
| 15420 | IrInstruction *elem = ir_const(ira, source_instr, field->type_entry); | |
| 15421 | return ir_get_ref(ira, source_instr, elem, false, false); | |
| 15422 | } | |
| 15423 | case OnePossibleValueNo: | |
| 15424 | break; | |
| 15425 | } | |
| 14961 | 15426 | bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked); |
| 14962 | 15427 | uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); |
| 14963 | 15428 | uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host; |
| ... | ... | @@ -15065,6 +15530,14 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 15065 | 15530 | } |
| 15066 | 15531 | |
| 15067 | 15532 | static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) { |
| 15533 | if (buf_eql_str(lib_name, "c") && ira->codegen->libc_link_lib == nullptr && | |
| 15534 | !ira->codegen->reported_bad_link_libc_error) | |
| 15535 | { | |
| 15536 | ir_add_error_node(ira, source_node, | |
| 15537 | buf_sprintf("dependency on library c must be explicitly specified in the build command")); | |
| 15538 | ira->codegen->reported_bad_link_libc_error = true; | |
| 15539 | } | |
| 15540 | ||
| 15068 | 15541 | LinkLib *link_lib = add_link_lib(ira->codegen, lib_name); |
| 15069 | 15542 | for (size_t i = 0; i < link_lib->symbols.length; i += 1) { |
| 15070 | 15543 | Buf *existing_symbol_name = link_lib->symbols.at(i); |
| ... | ... | @@ -15151,12 +15624,6 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc |
| 15151 | 15624 | if (type_is_invalid(container_ptr->value.type)) |
| 15152 | 15625 | return ira->codegen->invalid_instruction; |
| 15153 | 15626 | |
| 15154 | if (container_ptr->value.type->id != ZigTypeIdPointer) { | |
| 15155 | ir_add_error_node(ira, field_ptr_instruction->base.source_node, | |
| 15156 | buf_sprintf("attempt to dereference non-pointer type '%s'", | |
| 15157 | buf_ptr(&container_ptr->value.type->name))); | |
| 15158 | return ira->codegen->invalid_instruction; | |
| 15159 | } | |
| 15160 | 15627 | ZigType *container_type = container_ptr->value.type->data.pointer.child_type; |
| 15161 | 15628 | |
| 15162 | 15629 | Buf *field_name = field_ptr_instruction->field_name_buffer; |
| ... | ... | @@ -15572,6 +16039,8 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio |
| 15572 | 16039 | static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| 15573 | 16040 | IrInstructionToPtrType *to_ptr_type_instruction) |
| 15574 | 16041 | { |
| 16042 | Error err; | |
| 16043 | ||
| 15575 | 16044 | IrInstruction *value = to_ptr_type_instruction->value->child; |
| 15576 | 16045 | ZigType *type_entry = value->value.type; |
| 15577 | 16046 | if (type_is_invalid(type_entry)) |
| ... | ... | @@ -15587,7 +16056,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| 15587 | 16056 | ptr_type = get_pointer_to_type(ira->codegen, |
| 15588 | 16057 | type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const); |
| 15589 | 16058 | } else if (is_slice(type_entry)) { |
| 15590 | ptr_type = adjust_ptr_len(ira->codegen, type_entry->data.structure.fields[0].type_entry, PtrLenSingle); | |
| 16059 | ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry; | |
| 16060 | ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle); | |
| 16061 | // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type. | |
| 16062 | if (slice_ptr_type->data.pointer.explicit_alignment != 0) { | |
| 16063 | ZigType *elem_type = slice_ptr_type->data.pointer.child_type; | |
| 16064 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown))) | |
| 16065 | return ira->codegen->invalid_instruction; | |
| 16066 | uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type); | |
| 16067 | uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment); | |
| 16068 | ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align); | |
| 16069 | } | |
| 15591 | 16070 | } else if (type_entry->id == ZigTypeIdArgTuple) { |
| 15592 | 16071 | ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad); |
| 15593 | 16072 | if (!arg_tuple_val) |
| ... | ... | @@ -16355,18 +16834,13 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16355 | 16834 | return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type); |
| 16356 | 16835 | } |
| 16357 | 16836 | |
| 16358 | if (target_value_ptr->value.type->id != ZigTypeIdPointer) { | |
| 16359 | ir_add_error(ira, target_value_ptr, buf_sprintf("invalid deref on switch target")); | |
| 16360 | return ira->codegen->invalid_instruction; | |
| 16361 | } | |
| 16362 | ||
| 16363 | 16837 | ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type; |
| 16364 | 16838 | ConstExprValue *pointee_val = nullptr; |
| 16365 | 16839 | if (instr_is_comptime(target_value_ptr)) { |
| 16366 | 16840 | pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node); |
| 16367 | 16841 | if (pointee_val == nullptr) |
| 16368 | 16842 | return ira->codegen->invalid_instruction; |
| 16369 | ||
| 16843 | ||
| 16370 | 16844 | if (pointee_val->special == ConstValSpecialRuntime) |
| 16371 | 16845 | pointee_val = nullptr; |
| 16372 | 16846 | } |
| ... | ... | @@ -16953,9 +17427,13 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr |
| 16953 | 17427 | } |
| 16954 | 17428 | fprintf(stderr, "\n"); |
| 16955 | 17429 | |
| 16956 | // Here we bypass higher level functions such as ir_add_error because we do not want | |
| 16957 | // invalidate_exec to be called. | |
| 16958 | add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement")); | |
| 17430 | auto *expr = &instruction->base.source_node->data.fn_call_expr; | |
| 17431 | if (!expr->seen) { | |
| 17432 | // Here we bypass higher level functions such as ir_add_error because we do not want | |
| 17433 | // invalidate_exec to be called. | |
| 17434 | add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement")); | |
| 17435 | } | |
| 17436 | expr->seen = true; | |
| 16959 | 17437 | |
| 16960 | 17438 | return ir_const_void(ira, &instruction->base); |
| 16961 | 17439 | } |
| ... | ... | @@ -17116,7 +17594,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 17116 | 17594 | static TypeStructField *validate_byte_offset(IrAnalyze *ira, |
| 17117 | 17595 | IrInstruction *type_value, |
| 17118 | 17596 | IrInstruction *field_name_value, |
| 17119 | size_t *byte_offset) | |
| 17597 | size_t *byte_offset) | |
| 17120 | 17598 | { |
| 17121 | 17599 | ZigType *container_type = ir_resolve_type(ira, type_value); |
| 17122 | 17600 | if (type_is_invalid(container_type)) |
| ... | ... | @@ -17290,7 +17768,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17290 | 17768 | |
| 17291 | 17769 | // Loop through the definitions and generate info. |
| 17292 | 17770 | decl_it = decls_scope->decl_table.entry_iterator(); |
| 17293 | curr_entry = nullptr; | |
| 17771 | curr_entry = nullptr; | |
| 17294 | 17772 | int definition_index = 0; |
| 17295 | 17773 | while ((curr_entry = decl_it.next()) != nullptr) { |
| 17296 | 17774 | // Skip comptime blocks and test functions. |
| ... | ... | @@ -17469,6 +17947,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17469 | 17947 | return ErrorNone; |
| 17470 | 17948 | } |
| 17471 | 17949 | |
| 17950 | static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { | |
| 17951 | switch (ptr_len) { | |
| 17952 | case PtrLenSingle: | |
| 17953 | return 0; | |
| 17954 | case PtrLenUnknown: | |
| 17955 | return 1; | |
| 17956 | case PtrLenC: | |
| 17957 | return 3; | |
| 17958 | } | |
| 17959 | zig_unreachable(); | |
| 17960 | } | |
| 17961 | ||
| 17472 | 17962 | static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { |
| 17473 | 17963 | Error err; |
| 17474 | 17964 | ZigType *attrs_type; |
| ... | ... | @@ -17478,7 +17968,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty |
| 17478 | 17968 | size_enum_index = 2; |
| 17479 | 17969 | } else if (ptr_type_entry->id == ZigTypeIdPointer) { |
| 17480 | 17970 | attrs_type = ptr_type_entry; |
| 17481 | size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1; | |
| 17971 | size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len); | |
| 17482 | 17972 | } else { |
| 17483 | 17973 | zig_unreachable(); |
| 17484 | 17974 | } |
| ... | ... | @@ -18172,12 +18662,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, |
| 18172 | 18662 | static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, |
| 18173 | 18663 | IrInstructionSetEvalBranchQuota *instruction) |
| 18174 | 18664 | { |
| 18175 | if (ira->new_irb.exec->parent_exec != nullptr && !ira->new_irb.exec->is_generic_instantiation) { | |
| 18176 | ir_add_error(ira, &instruction->base, | |
| 18177 | buf_sprintf("@setEvalBranchQuota must be called from the top of the comptime stack")); | |
| 18178 | return ira->codegen->invalid_instruction; | |
| 18179 | } | |
| 18180 | ||
| 18181 | 18665 | uint64_t new_quota; |
| 18182 | 18666 | if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota)) |
| 18183 | 18667 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -18204,12 +18688,6 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc |
| 18204 | 18688 | } |
| 18205 | 18689 | |
| 18206 | 18690 | static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) { |
| 18207 | if (ira->codegen->enable_cache) { | |
| 18208 | ir_add_error(ira, &instruction->base, | |
| 18209 | buf_sprintf("TODO @cImport is incompatible with --cache on. The cache system currently is unable to detect subsequent changes in .h files.")); | |
| 18210 | return ira->codegen->invalid_instruction; | |
| 18211 | } | |
| 18212 | ||
| 18213 | 18691 | AstNode *node = instruction->base.source_node; |
| 18214 | 18692 | assert(node->type == NodeTypeFnCallExpr); |
| 18215 | 18693 | AstNode *block_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -18220,12 +18698,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 18220 | 18698 | ZigType *void_type = ira->codegen->builtin_types.entry_void; |
| 18221 | 18699 | ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, |
| 18222 | 18700 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, |
| 18223 | &cimport_scope->buf, block_node, nullptr, nullptr); | |
| 18701 | &cimport_scope->buf, block_node, nullptr, nullptr, nullptr); | |
| 18224 | 18702 | if (type_is_invalid(cimport_result->type)) |
| 18225 | 18703 | return ira->codegen->invalid_instruction; |
| 18226 | 18704 | |
| 18227 | find_libc_include_path(ira->codegen); | |
| 18228 | ||
| 18229 | 18705 | ImportTableEntry *child_import = allocate<ImportTableEntry>(1); |
| 18230 | 18706 | child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import); |
| 18231 | 18707 | child_import->c_import_node = node; |
| ... | ... | @@ -18247,6 +18723,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 18247 | 18723 | |
| 18248 | 18724 | if (errors.length > 0) { |
| 18249 | 18725 | ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); |
| 18726 | if (ira->codegen->libc_link_lib == nullptr) { | |
| 18727 | add_error_note(ira->codegen, parent_err_msg, node, | |
| 18728 | buf_sprintf("libc headers not available; compilation does not link against libc")); | |
| 18729 | } | |
| 18250 | 18730 | for (size_t i = 0; i < errors.length; i += 1) { |
| 18251 | 18731 | ErrorMsg *err_msg = errors.at(i); |
| 18252 | 18732 | err_msg_add_note(parent_err_msg, err_msg); |
| ... | ... | @@ -18713,7 +19193,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru |
| 18713 | 19193 | } |
| 18714 | 19194 | } |
| 18715 | 19195 | |
| 18716 | return ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true); | |
| 19196 | IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type); | |
| 19197 | ir_add_alloca(ira, result, dest_slice_type); | |
| 19198 | return result; | |
| 18717 | 19199 | } |
| 18718 | 19200 | |
| 18719 | 19201 | static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) { |
| ... | ... | @@ -18740,7 +19222,34 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 18740 | 19222 | alignment, 0, 0); |
| 18741 | 19223 | ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); |
| 18742 | 19224 | |
| 18743 | return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); | |
| 19225 | if (instr_is_comptime(target)) { | |
| 19226 | ConstExprValue *target_val = ir_resolve_const(ira, target, UndefBad); | |
| 19227 | if (target_val == nullptr) | |
| 19228 | return ira->codegen->invalid_instruction; | |
| 19229 | ||
| 19230 | IrInstruction *result = ir_const(ira, &instruction->base, dest_slice_type); | |
| 19231 | result->value.data.x_struct.fields = create_const_vals(2); | |
| 19232 | ||
| 19233 | ConstExprValue *ptr_val = &result->value.data.x_struct.fields[slice_ptr_index]; | |
| 19234 | ConstExprValue *target_ptr_val = &target_val->data.x_struct.fields[slice_ptr_index]; | |
| 19235 | copy_const_val(ptr_val, target_ptr_val, false); | |
| 19236 | ptr_val->type = dest_ptr_type; | |
| 19237 | ||
| 19238 | ConstExprValue *len_val = &result->value.data.x_struct.fields[slice_len_index]; | |
| 19239 | len_val->special = ConstValSpecialStatic; | |
| 19240 | len_val->type = ira->codegen->builtin_types.entry_usize; | |
| 19241 | ConstExprValue *target_len_val = &target_val->data.x_struct.fields[slice_len_index]; | |
| 19242 | ZigType *elem_type = src_ptr_type->data.pointer.child_type; | |
| 19243 | BigInt elem_size_bigint; | |
| 19244 | bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type)); | |
| 19245 | bigint_mul(&len_val->data.x_bigint, &target_len_val->data.x_bigint, &elem_size_bigint); | |
| 19246 | ||
| 19247 | return result; | |
| 19248 | } | |
| 19249 | ||
| 19250 | IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type); | |
| 19251 | ir_add_alloca(ira, result, dest_slice_type); | |
| 19252 | return result; | |
| 18744 | 19253 | } |
| 18745 | 19254 | |
| 18746 | 19255 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { |
| ... | ... | @@ -18952,10 +19461,12 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio |
| 18952 | 19461 | if (type_is_invalid(casted_count->value.type)) |
| 18953 | 19462 | return ira->codegen->invalid_instruction; |
| 18954 | 19463 | |
| 19464 | // TODO test this at comptime with u8 and non-u8 types | |
| 18955 | 19465 | if (casted_dest_ptr->value.special == ConstValSpecialStatic && |
| 18956 | 19466 | casted_byte->value.special == ConstValSpecialStatic && |
| 18957 | 19467 | casted_count->value.special == ConstValSpecialStatic && |
| 18958 | casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) | |
| 19468 | casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr && | |
| 19469 | casted_dest_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) | |
| 18959 | 19470 | { |
| 18960 | 19471 | ConstExprValue *dest_ptr_val = &casted_dest_ptr->value; |
| 18961 | 19472 | |
| ... | ... | @@ -19074,6 +19585,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio |
| 19074 | 19585 | if (type_is_invalid(casted_count->value.type)) |
| 19075 | 19586 | return ira->codegen->invalid_instruction; |
| 19076 | 19587 | |
| 19588 | // TODO test this at comptime with u8 and non-u8 types | |
| 19589 | // TODO test with dest ptr being a global runtime variable | |
| 19077 | 19590 | if (casted_dest_ptr->value.special == ConstValSpecialStatic && |
| 19078 | 19591 | casted_src_ptr->value.special == ConstValSpecialStatic && |
| 19079 | 19592 | casted_count->value.special == ConstValSpecialStatic && |
| ... | ... | @@ -20242,7 +20755,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 20242 | 20755 | } else { |
| 20243 | 20756 | seenFalse += 1; |
| 20244 | 20757 | } |
| 20245 | ||
| 20758 | ||
| 20246 | 20759 | if ((seenTrue > 1) || (seenFalse > 1)) { |
| 20247 | 20760 | ir_add_error(ira, value, buf_sprintf("duplicate switch value")); |
| 20248 | 20761 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -20375,7 +20888,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 20375 | 20888 | } |
| 20376 | 20889 | |
| 20377 | 20890 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| 20378 | ZigType *dest_type, IrInstruction *dest_type_src) | |
| 20891 | ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on) | |
| 20379 | 20892 | { |
| 20380 | 20893 | Error err; |
| 20381 | 20894 | |
| ... | ... | @@ -20385,12 +20898,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 20385 | 20898 | // We have a check for zero bits later so we use get_src_ptr_type to |
| 20386 | 20899 | // validate src_type and dest_type. |
| 20387 | 20900 | |
| 20388 | if (get_src_ptr_type(src_type) == nullptr) { | |
| 20901 | ZigType *src_ptr_type = get_src_ptr_type(src_type); | |
| 20902 | if (src_ptr_type == nullptr) { | |
| 20389 | 20903 | ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); |
| 20390 | 20904 | return ira->codegen->invalid_instruction; |
| 20391 | 20905 | } |
| 20392 | 20906 | |
| 20393 | if (get_src_ptr_type(dest_type) == nullptr) { | |
| 20907 | ZigType *dest_ptr_type = get_src_ptr_type(dest_type); | |
| 20908 | if (dest_ptr_type == nullptr) { | |
| 20394 | 20909 | ir_add_error(ira, dest_type_src, |
| 20395 | 20910 | buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); |
| 20396 | 20911 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -20400,25 +20915,44 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 20400 | 20915 | ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier")); |
| 20401 | 20916 | return ira->codegen->invalid_instruction; |
| 20402 | 20917 | } |
| 20918 | uint32_t src_align_bytes; | |
| 20919 | if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) | |
| 20920 | return ira->codegen->invalid_instruction; | |
| 20921 | ||
| 20922 | uint32_t dest_align_bytes; | |
| 20923 | if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) | |
| 20924 | return ira->codegen->invalid_instruction; | |
| 20403 | 20925 | |
| 20404 | 20926 | if (instr_is_comptime(ptr)) { |
| 20405 | ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); | |
| 20927 | bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type); | |
| 20928 | UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad; | |
| 20929 | ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed); | |
| 20406 | 20930 | if (!val) |
| 20407 | 20931 | return ira->codegen->invalid_instruction; |
| 20408 | 20932 | |
| 20933 | if (val->special == ConstValSpecialStatic) { | |
| 20934 | bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull || | |
| 20935 | (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | |
| 20936 | val->data.x_ptr.data.hard_coded_addr.addr == 0); | |
| 20937 | if (is_addr_zero && !dest_allows_addr_zero) { | |
| 20938 | ir_add_error(ira, source_instr, | |
| 20939 | buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name))); | |
| 20940 | return ira->codegen->invalid_instruction; | |
| 20941 | } | |
| 20942 | } | |
| 20943 | ||
| 20409 | 20944 | IrInstruction *result = ir_const(ira, source_instr, dest_type); |
| 20410 | 20945 | copy_const_val(&result->value, val, false); |
| 20411 | 20946 | result->value.type = dest_type; |
| 20412 | return result; | |
| 20413 | } | |
| 20414 | 20947 | |
| 20415 | uint32_t src_align_bytes; | |
| 20416 | if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) | |
| 20417 | return ira->codegen->invalid_instruction; | |
| 20948 | // Keep the bigger alignment, it can only help- | |
| 20949 | // unless the target is zero bits. | |
| 20950 | if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { | |
| 20951 | result = ir_align_cast(ira, result, src_align_bytes, false); | |
| 20952 | } | |
| 20418 | 20953 | |
| 20419 | uint32_t dest_align_bytes; | |
| 20420 | if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) | |
| 20421 | return ira->codegen->invalid_instruction; | |
| 20954 | return result; | |
| 20955 | } | |
| 20422 | 20956 | |
| 20423 | 20957 | if (dest_align_bytes > src_align_bytes) { |
| 20424 | 20958 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); |
| ... | ... | @@ -20429,7 +20963,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 20429 | 20963 | return ira->codegen->invalid_instruction; |
| 20430 | 20964 | } |
| 20431 | 20965 | |
| 20432 | IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr); | |
| 20966 | IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); | |
| 20433 | 20967 | |
| 20434 | 20968 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { |
| 20435 | 20969 | ErrorMsg *msg = ir_add_error(ira, source_instr, |
| ... | ... | @@ -20466,7 +21000,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct |
| 20466 | 21000 | if (type_is_invalid(src_type)) |
| 20467 | 21001 | return ira->codegen->invalid_instruction; |
| 20468 | 21002 | |
| 20469 | return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value); | |
| 21003 | return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value, | |
| 21004 | instruction->safety_check_on); | |
| 20470 | 21005 | } |
| 20471 | 21006 | |
| 20472 | 21007 | static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) { |
| ... | ... | @@ -20529,7 +21064,79 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20529 | 21064 | case ZigTypeIdVector: |
| 20530 | 21065 | return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len); |
| 20531 | 21066 | case ZigTypeIdStruct: |
| 20532 | zig_panic("TODO buf_write_value_bytes struct type"); | |
| 21067 | switch (val->type->data.structure.layout) { | |
| 21068 | case ContainerLayoutAuto: | |
| 21069 | zig_unreachable(); | |
| 21070 | case ContainerLayoutExtern: { | |
| 21071 | size_t src_field_count = val->type->data.structure.src_field_count; | |
| 21072 | for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { | |
| 21073 | TypeStructField *type_field = &val->type->data.structure.fields[field_i]; | |
| 21074 | if (type_field->gen_index == SIZE_MAX) | |
| 21075 | continue; | |
| 21076 | ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; | |
| 21077 | size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref, | |
| 21078 | type_field->gen_index); | |
| 21079 | buf_write_value_bytes(codegen, buf + offset, field_val); | |
| 21080 | } | |
| 21081 | return; | |
| 21082 | } | |
| 21083 | case ContainerLayoutPacked: { | |
| 21084 | size_t src_field_count = val->type->data.structure.src_field_count; | |
| 21085 | size_t gen_field_count = val->type->data.structure.gen_field_count; | |
| 21086 | size_t gen_i = 0; | |
| 21087 | size_t src_i = 0; | |
| 21088 | size_t offset = 0; | |
| 21089 | bool is_big_endian = codegen->is_big_endian; | |
| 21090 | uint8_t child_buf_prealloc[16]; | |
| 21091 | size_t child_buf_len = 16; | |
| 21092 | uint8_t *child_buf = child_buf_prealloc; | |
| 21093 | while (gen_i < gen_field_count) { | |
| 21094 | LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref, | |
| 21095 | (unsigned)gen_i); | |
| 21096 | size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type); | |
| 21097 | size_t big_int_byte_count = big_int_bit_count / 8; | |
| 21098 | if (big_int_byte_count > child_buf_len) { | |
| 21099 | child_buf = allocate_nonzero<uint8_t>(big_int_byte_count); | |
| 21100 | child_buf_len = big_int_byte_count; | |
| 21101 | } | |
| 21102 | BigInt big_int; | |
| 21103 | bigint_init_unsigned(&big_int, 0); | |
| 21104 | size_t used_bits = 0; | |
| 21105 | while (src_i < src_field_count) { | |
| 21106 | TypeStructField *field = &val->type->data.structure.fields[src_i]; | |
| 21107 | assert(field->gen_index != SIZE_MAX); | |
| 21108 | if (field->gen_index != gen_i) | |
| 21109 | break; | |
| 21110 | uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry); | |
| 21111 | buf_write_value_bytes(codegen, child_buf, &val->data.x_struct.fields[src_i]); | |
| 21112 | BigInt child_val; | |
| 21113 | bigint_read_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian, | |
| 21114 | false); | |
| 21115 | if (is_big_endian) { | |
| 21116 | BigInt shift_amt; | |
| 21117 | bigint_init_unsigned(&shift_amt, packed_bits_size); | |
| 21118 | BigInt shifted; | |
| 21119 | bigint_shl(&shifted, &big_int, &shift_amt); | |
| 21120 | bigint_or(&big_int, &shifted, &child_val); | |
| 21121 | } else { | |
| 21122 | BigInt shift_amt; | |
| 21123 | bigint_init_unsigned(&shift_amt, used_bits); | |
| 21124 | BigInt child_val_shifted; | |
| 21125 | bigint_shl(&child_val_shifted, &child_val, &shift_amt); | |
| 21126 | BigInt tmp; | |
| 21127 | bigint_or(&tmp, &big_int, &child_val_shifted); | |
| 21128 | big_int = tmp; | |
| 21129 | used_bits += packed_bits_size; | |
| 21130 | } | |
| 21131 | src_i += 1; | |
| 21132 | } | |
| 21133 | bigint_write_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian); | |
| 21134 | offset += big_int_byte_count; | |
| 21135 | gen_i += 1; | |
| 21136 | } | |
| 21137 | return; | |
| 21138 | } | |
| 21139 | } | |
| 20533 | 21140 | case ZigTypeIdOptional: |
| 20534 | 21141 | zig_panic("TODO buf_write_value_bytes maybe type"); |
| 20535 | 21142 | case ZigTypeIdErrorUnion: |
| ... | ... | @@ -20656,8 +21263,62 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 20656 | 21263 | } |
| 20657 | 21264 | return ErrorNone; |
| 20658 | 21265 | } |
| 20659 | case ContainerLayoutPacked: | |
| 20660 | zig_panic("TODO buf_read_value_bytes packed struct"); | |
| 21266 | case ContainerLayoutPacked: { | |
| 21267 | size_t src_field_count = val->type->data.structure.src_field_count; | |
| 21268 | val->data.x_struct.fields = create_const_vals(src_field_count); | |
| 21269 | size_t gen_field_count = val->type->data.structure.gen_field_count; | |
| 21270 | size_t gen_i = 0; | |
| 21271 | size_t src_i = 0; | |
| 21272 | size_t offset = 0; | |
| 21273 | bool is_big_endian = codegen->is_big_endian; | |
| 21274 | uint8_t child_buf_prealloc[16]; | |
| 21275 | size_t child_buf_len = 16; | |
| 21276 | uint8_t *child_buf = child_buf_prealloc; | |
| 21277 | while (gen_i < gen_field_count) { | |
| 21278 | LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref, | |
| 21279 | (unsigned)gen_i); | |
| 21280 | size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type); | |
| 21281 | size_t big_int_byte_count = big_int_bit_count / 8; | |
| 21282 | if (big_int_byte_count > child_buf_len) { | |
| 21283 | child_buf = allocate_nonzero<uint8_t>(big_int_byte_count); | |
| 21284 | child_buf_len = big_int_byte_count; | |
| 21285 | } | |
| 21286 | BigInt big_int; | |
| 21287 | bigint_read_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian, false); | |
| 21288 | while (src_i < src_field_count) { | |
| 21289 | TypeStructField *field = &val->type->data.structure.fields[src_i]; | |
| 21290 | assert(field->gen_index != SIZE_MAX); | |
| 21291 | if (field->gen_index != gen_i) | |
| 21292 | break; | |
| 21293 | ConstExprValue *field_val = &val->data.x_struct.fields[src_i]; | |
| 21294 | field_val->special = ConstValSpecialStatic; | |
| 21295 | field_val->type = field->type_entry; | |
| 21296 | uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry); | |
| 21297 | ||
| 21298 | BigInt child_val; | |
| 21299 | if (is_big_endian) { | |
| 21300 | zig_panic("TODO buf_read_value_bytes packed struct big endian"); | |
| 21301 | } else { | |
| 21302 | BigInt packed_bits_size_bi; | |
| 21303 | bigint_init_unsigned(&packed_bits_size_bi, packed_bits_size); | |
| 21304 | bigint_truncate(&child_val, &big_int, packed_bits_size, false); | |
| 21305 | BigInt tmp; | |
| 21306 | bigint_shr(&tmp, &big_int, &packed_bits_size_bi); | |
| 21307 | big_int = tmp; | |
| 21308 | } | |
| 21309 | ||
| 21310 | bigint_write_twos_complement(&child_val, child_buf, big_int_bit_count, is_big_endian); | |
| 21311 | if ((err = buf_read_value_bytes(ira, codegen, source_node, child_buf, field_val))) { | |
| 21312 | return err; | |
| 21313 | } | |
| 21314 | ||
| 21315 | src_i += 1; | |
| 21316 | } | |
| 21317 | offset += big_int_byte_count; | |
| 21318 | gen_i += 1; | |
| 21319 | } | |
| 21320 | return ErrorNone; | |
| 21321 | } | |
| 20661 | 21322 | } |
| 20662 | 21323 | zig_unreachable(); |
| 20663 | 21324 | case ZigTypeIdOptional: |
| ... | ... | @@ -20674,32 +21335,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 20674 | 21335 | zig_unreachable(); |
| 20675 | 21336 | } |
| 20676 | 21337 | |
| 20677 | static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { | |
| 20678 | Error err; | |
| 20679 | IrInstruction *dest_type_value = instruction->dest_type->child; | |
| 20680 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | |
| 20681 | if (type_is_invalid(dest_type)) | |
| 20682 | return ira->codegen->invalid_instruction; | |
| 20683 | ||
| 20684 | IrInstruction *value = instruction->value->child; | |
| 20685 | ZigType *src_type = value->value.type; | |
| 20686 | if (type_is_invalid(src_type)) | |
| 20687 | return ira->codegen->invalid_instruction; | |
| 20688 | ||
| 20689 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) | |
| 20690 | return ira->codegen->invalid_instruction; | |
| 20691 | ||
| 20692 | if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown))) | |
| 20693 | return ira->codegen->invalid_instruction; | |
| 20694 | ||
| 20695 | if (get_codegen_ptr_type(src_type) != nullptr) { | |
| 20696 | ir_add_error(ira, value, | |
| 20697 | buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name))); | |
| 20698 | return ira->codegen->invalid_instruction; | |
| 20699 | } | |
| 20700 | ||
| 20701 | switch (src_type->id) { | |
| 21338 | static bool type_can_bit_cast(ZigType *t) { | |
| 21339 | switch (t->id) { | |
| 20702 | 21340 | case ZigTypeIdInvalid: |
| 21341 | zig_unreachable(); | |
| 20703 | 21342 | case ZigTypeIdMetaType: |
| 20704 | 21343 | case ZigTypeIdOpaque: |
| 20705 | 21344 | case ZigTypeIdBoundFn: |
| ... | ... | @@ -20710,42 +21349,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 20710 | 21349 | case ZigTypeIdComptimeInt: |
| 20711 | 21350 | case ZigTypeIdUndefined: |
| 20712 | 21351 | case ZigTypeIdNull: |
| 20713 | ir_add_error(ira, dest_type_value, | |
| 20714 | buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name))); | |
| 20715 | return ira->codegen->invalid_instruction; | |
| 21352 | case ZigTypeIdPointer: | |
| 21353 | return false; | |
| 20716 | 21354 | default: |
| 20717 | break; | |
| 21355 | // TODO list these types out explicitly, there are probably some other invalid ones here | |
| 21356 | return true; | |
| 20718 | 21357 | } |
| 21358 | } | |
| 20719 | 21359 | |
| 20720 | if (get_codegen_ptr_type(dest_type) != nullptr) { | |
| 20721 | ir_add_error(ira, dest_type_value, | |
| 20722 | buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name))); | |
| 21360 | static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | |
| 21361 | ZigType *dest_type) | |
| 21362 | { | |
| 21363 | Error err; | |
| 21364 | ||
| 21365 | ZigType *src_type = value->value.type; | |
| 21366 | assert(get_codegen_ptr_type(src_type) == nullptr); | |
| 21367 | assert(type_can_bit_cast(src_type)); | |
| 21368 | assert(get_codegen_ptr_type(dest_type) == nullptr); | |
| 21369 | assert(type_can_bit_cast(dest_type)); | |
| 21370 | ||
| 21371 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) | |
| 21372 | return ira->codegen->invalid_instruction; | |
| 21373 | ||
| 21374 | if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown))) | |
| 20723 | 21375 | return ira->codegen->invalid_instruction; |
| 20724 | } | |
| 20725 | 21376 | |
| 20726 | switch (dest_type->id) { | |
| 20727 | case ZigTypeIdInvalid: | |
| 20728 | case ZigTypeIdMetaType: | |
| 20729 | case ZigTypeIdOpaque: | |
| 20730 | case ZigTypeIdBoundFn: | |
| 20731 | case ZigTypeIdArgTuple: | |
| 20732 | case ZigTypeIdNamespace: | |
| 20733 | case ZigTypeIdUnreachable: | |
| 20734 | case ZigTypeIdComptimeFloat: | |
| 20735 | case ZigTypeIdComptimeInt: | |
| 20736 | case ZigTypeIdUndefined: | |
| 20737 | case ZigTypeIdNull: | |
| 20738 | ir_add_error(ira, dest_type_value, | |
| 20739 | buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name))); | |
| 20740 | return ira->codegen->invalid_instruction; | |
| 20741 | default: | |
| 20742 | break; | |
| 20743 | } | |
| 20744 | 21377 | |
| 20745 | 21378 | uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); |
| 20746 | 21379 | uint64_t src_size_bytes = type_size(ira->codegen, src_type); |
| 20747 | 21380 | if (dest_size_bytes != src_size_bytes) { |
| 20748 | ir_add_error(ira, &instruction->base, | |
| 21381 | ir_add_error(ira, source_instr, | |
| 20749 | 21382 | buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64, |
| 20750 | 21383 | buf_ptr(&dest_type->name), dest_size_bytes, |
| 20751 | 21384 | buf_ptr(&src_type->name), src_size_bytes)); |
| ... | ... | @@ -20755,7 +21388,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 20755 | 21388 | uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type); |
| 20756 | 21389 | uint64_t src_size_bits = type_size_bits(ira->codegen, src_type); |
| 20757 | 21390 | if (dest_size_bits != src_size_bits) { |
| 20758 | ir_add_error(ira, &instruction->base, | |
| 21391 | ir_add_error(ira, source_instr, | |
| 20759 | 21392 | buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits", |
| 20760 | 21393 | buf_ptr(&dest_type->name), dest_size_bits, |
| 20761 | 21394 | buf_ptr(&src_type->name), src_size_bits)); |
| ... | ... | @@ -20767,44 +21400,64 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 20767 | 21400 | if (!val) |
| 20768 | 21401 | return ira->codegen->invalid_instruction; |
| 20769 | 21402 | |
| 20770 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | |
| 21403 | IrInstruction *result = ir_const(ira, source_instr, dest_type); | |
| 20771 | 21404 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); |
| 20772 | 21405 | buf_write_value_bytes(ira->codegen, buf, val); |
| 20773 | if ((err = buf_read_value_bytes(ira, ira->codegen, instruction->base.source_node, buf, &result->value))) | |
| 21406 | if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value))) | |
| 20774 | 21407 | return ira->codegen->invalid_instruction; |
| 20775 | 21408 | return result; |
| 20776 | 21409 | } |
| 20777 | 21410 | |
| 20778 | IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope, | |
| 20779 | instruction->base.source_node, nullptr, value); | |
| 20780 | result->value.type = dest_type; | |
| 21411 | IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type); | |
| 21412 | if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) { | |
| 21413 | ir_add_alloca(ira, result, dest_type); | |
| 21414 | } | |
| 20781 | 21415 | return result; |
| 20782 | 21416 | } |
| 20783 | 21417 | |
| 20784 | static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { | |
| 20785 | Error err; | |
| 21418 | static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { | |
| 20786 | 21419 | IrInstruction *dest_type_value = instruction->dest_type->child; |
| 20787 | 21420 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); |
| 20788 | 21421 | if (type_is_invalid(dest_type)) |
| 20789 | 21422 | return ira->codegen->invalid_instruction; |
| 20790 | 21423 | |
| 20791 | // We explicitly check for the size, so we can use get_src_ptr_type | |
| 20792 | if (get_src_ptr_type(dest_type) == nullptr) { | |
| 20793 | ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); | |
| 21424 | IrInstruction *value = instruction->value->child; | |
| 21425 | ZigType *src_type = value->value.type; | |
| 21426 | if (type_is_invalid(src_type)) | |
| 21427 | return ira->codegen->invalid_instruction; | |
| 21428 | ||
| 21429 | if (get_codegen_ptr_type(src_type) != nullptr) { | |
| 21430 | ir_add_error(ira, value, | |
| 21431 | buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name))); | |
| 20794 | 21432 | return ira->codegen->invalid_instruction; |
| 20795 | 21433 | } |
| 20796 | 21434 | |
| 20797 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) | |
| 21435 | if (!type_can_bit_cast(src_type)) { | |
| 21436 | ir_add_error(ira, dest_type_value, | |
| 21437 | buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name))); | |
| 20798 | 21438 | return ira->codegen->invalid_instruction; |
| 20799 | if (!type_has_bits(dest_type)) { | |
| 21439 | } | |
| 21440 | ||
| 21441 | if (get_codegen_ptr_type(dest_type) != nullptr) { | |
| 20800 | 21442 | ir_add_error(ira, dest_type_value, |
| 20801 | buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name))); | |
| 21443 | buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name))); | |
| 20802 | 21444 | return ira->codegen->invalid_instruction; |
| 20803 | 21445 | } |
| 20804 | 21446 | |
| 20805 | IrInstruction *target = instruction->target->child; | |
| 20806 | if (type_is_invalid(target->value.type)) | |
| 21447 | if (!type_can_bit_cast(dest_type)) { | |
| 21448 | ir_add_error(ira, dest_type_value, | |
| 21449 | buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name))); | |
| 20807 | 21450 | return ira->codegen->invalid_instruction; |
| 21451 | } | |
| 21452 | ||
| 21453 | return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type); | |
| 21454 | } | |
| 21455 | ||
| 21456 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | |
| 21457 | ZigType *ptr_type) | |
| 21458 | { | |
| 21459 | assert(get_src_ptr_type(ptr_type) != nullptr); | |
| 21460 | assert(type_has_bits(ptr_type)); | |
| 20808 | 21461 | |
| 20809 | 21462 | IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); |
| 20810 | 21463 | if (type_is_invalid(casted_int->value.type)) |
| ... | ... | @@ -20815,19 +21468,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru |
| 20815 | 21468 | if (!val) |
| 20816 | 21469 | return ira->codegen->invalid_instruction; |
| 20817 | 21470 | |
| 20818 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | |
| 21471 | IrInstruction *result = ir_const(ira, source_instr, ptr_type); | |
| 20819 | 21472 | result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 20820 | 21473 | result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar; |
| 20821 | 21474 | result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint); |
| 20822 | 21475 | return result; |
| 20823 | 21476 | } |
| 20824 | 21477 | |
| 20825 | IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope, | |
| 20826 | instruction->base.source_node, nullptr, casted_int); | |
| 20827 | result->value.type = dest_type; | |
| 21478 | IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope, | |
| 21479 | source_instr->source_node, nullptr, casted_int); | |
| 21480 | result->value.type = ptr_type; | |
| 20828 | 21481 | return result; |
| 20829 | 21482 | } |
| 20830 | 21483 | |
| 21484 | static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { | |
| 21485 | Error err; | |
| 21486 | IrInstruction *dest_type_value = instruction->dest_type->child; | |
| 21487 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | |
| 21488 | if (type_is_invalid(dest_type)) | |
| 21489 | return ira->codegen->invalid_instruction; | |
| 21490 | ||
| 21491 | // We explicitly check for the size, so we can use get_src_ptr_type | |
| 21492 | if (get_src_ptr_type(dest_type) == nullptr) { | |
| 21493 | ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); | |
| 21494 | return ira->codegen->invalid_instruction; | |
| 21495 | } | |
| 21496 | ||
| 21497 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) | |
| 21498 | return ira->codegen->invalid_instruction; | |
| 21499 | if (!type_has_bits(dest_type)) { | |
| 21500 | ir_add_error(ira, dest_type_value, | |
| 21501 | buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name))); | |
| 21502 | return ira->codegen->invalid_instruction; | |
| 21503 | } | |
| 21504 | ||
| 21505 | ||
| 21506 | IrInstruction *target = instruction->target->child; | |
| 21507 | if (type_is_invalid(target->value.type)) | |
| 21508 | return ira->codegen->invalid_instruction; | |
| 21509 | ||
| 21510 | return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type); | |
| 21511 | } | |
| 21512 | ||
| 20831 | 21513 | static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 20832 | 21514 | IrInstructionDeclRef *instruction) |
| 20833 | 21515 | { |
| ... | ... | @@ -20931,6 +21613,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct |
| 20931 | 21613 | } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) { |
| 20932 | 21614 | ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque")); |
| 20933 | 21615 | return ira->codegen->invalid_instruction; |
| 21616 | } else if (instruction->ptr_len == PtrLenC) { | |
| 21617 | if (!type_allowed_in_extern(ira->codegen, child_type)) { | |
| 21618 | ir_add_error(ira, &instruction->base, | |
| 21619 | buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name))); | |
| 21620 | return ira->codegen->invalid_instruction; | |
| 21621 | } else if (child_type->id == ZigTypeIdOpaque) { | |
| 21622 | ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types")); | |
| 21623 | return ira->codegen->invalid_instruction; | |
| 21624 | } | |
| 20934 | 21625 | } |
| 20935 | 21626 | |
| 20936 | 21627 | uint32_t align_bytes; |
| ... | ... | @@ -21068,20 +21759,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct |
| 21068 | 21759 | |
| 21069 | 21760 | return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type); |
| 21070 | 21761 | } else if (enum_type->id == ZigTypeIdUnion) { |
| 21071 | if ((err = ensure_complete_type(ira->codegen, enum_type))) | |
| 21072 | return ira->codegen->invalid_instruction; | |
| 21073 | ||
| 21074 | AstNode *decl_node = enum_type->data.unionation.decl_node; | |
| 21075 | if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) { | |
| 21076 | assert(enum_type->data.unionation.tag_type != nullptr); | |
| 21077 | ||
| 21078 | return ir_const_type(ira, &instruction->base, enum_type->data.unionation.tag_type); | |
| 21079 | } else { | |
| 21080 | ErrorMsg *msg = ir_add_error(ira, target_inst, buf_sprintf("union '%s' has no tag", | |
| 21081 | buf_ptr(&enum_type->name))); | |
| 21082 | add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); | |
| 21762 | ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target, enum_type); | |
| 21763 | if (type_is_invalid(tag_type)) | |
| 21083 | 21764 | return ira->codegen->invalid_instruction; |
| 21084 | } | |
| 21765 | return ir_const_type(ira, &instruction->base, tag_type); | |
| 21085 | 21766 | } else { |
| 21086 | 21767 | ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'", |
| 21087 | 21768 | buf_ptr(&enum_type->name))); |
| ... | ... | @@ -21662,23 +22343,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr |
| 21662 | 22343 | |
| 21663 | 22344 | |
| 21664 | 22345 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { |
| 21665 | Error err; | |
| 21666 | 22346 | IrInstruction *target = instruction->target->child; |
| 21667 | 22347 | if (type_is_invalid(target->value.type)) |
| 21668 | 22348 | return ira->codegen->invalid_instruction; |
| 21669 | 22349 | |
| 21670 | if (target->value.type->id != ZigTypeIdEnum) { | |
| 21671 | ir_add_error(ira, instruction->target, | |
| 21672 | buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name))); | |
| 21673 | return ira->codegen->invalid_instruction; | |
| 21674 | } | |
| 21675 | ||
| 21676 | if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown))) | |
| 21677 | return ira->codegen->invalid_instruction; | |
| 21678 | ||
| 21679 | ZigType *tag_type = target->value.type->data.enumeration.tag_int_type; | |
| 21680 | ||
| 21681 | return ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type); | |
| 22350 | return ir_analyze_enum_to_int(ira, &instruction->base, target); | |
| 21682 | 22351 | } |
| 21683 | 22352 | |
| 21684 | 22353 | static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) { |
| ... | ... | @@ -21750,6 +22419,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21750 | 22419 | case IrInstructionIdArrayToVector: |
| 21751 | 22420 | case IrInstructionIdVectorToArray: |
| 21752 | 22421 | case IrInstructionIdAssertZero: |
| 22422 | case IrInstructionIdResizeSlice: | |
| 22423 | case IrInstructionIdLoadPtrGen: | |
| 22424 | case IrInstructionIdBitCastGen: | |
| 21753 | 22425 | zig_unreachable(); |
| 21754 | 22426 | |
| 21755 | 22427 | case IrInstructionIdReturn: |
| ... | ... | @@ -22149,12 +22821,14 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 22149 | 22821 | case IrInstructionIdCmpxchgGen: |
| 22150 | 22822 | case IrInstructionIdCmpxchgSrc: |
| 22151 | 22823 | case IrInstructionIdAssertZero: |
| 22824 | case IrInstructionIdResizeSlice: | |
| 22152 | 22825 | return true; |
| 22153 | 22826 | |
| 22154 | 22827 | case IrInstructionIdPhi: |
| 22155 | 22828 | case IrInstructionIdUnOp: |
| 22156 | 22829 | case IrInstructionIdBinOp: |
| 22157 | 22830 | case IrInstructionIdLoadPtr: |
| 22831 | case IrInstructionIdLoadPtrGen: | |
| 22158 | 22832 | case IrInstructionIdConst: |
| 22159 | 22833 | case IrInstructionIdCast: |
| 22160 | 22834 | case IrInstructionIdContainerInitList: |
| ... | ... | @@ -22205,6 +22879,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 22205 | 22879 | case IrInstructionIdPtrCastSrc: |
| 22206 | 22880 | case IrInstructionIdPtrCastGen: |
| 22207 | 22881 | case IrInstructionIdBitCast: |
| 22882 | case IrInstructionIdBitCastGen: | |
| 22208 | 22883 | case IrInstructionIdWidenOrShorten: |
| 22209 | 22884 | case IrInstructionIdPtrToInt: |
| 22210 | 22885 | case IrInstructionIdIntToPtr: |
src/ir.hpp+1-1| ... | ... | @@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); |
| 16 | 16 | ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 17 | 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 | IrExecutable *parent_exec); | |
| 19 | IrExecutable *parent_exec, AstNode *expected_type_source_node); | |
| 20 | 20 | |
| 21 | 21 | ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, |
| 22 | 22 | ZigType *expected_type, AstNode *expected_type_source_node); |
src/ir_print.cpp+27-3| ... | ... | @@ -336,6 +336,11 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { |
| 336 | 336 | fprintf(irp->f, ".*"); |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) { | |
| 340 | ir_print_other_instruction(irp, instruction->ptr); | |
| 341 | fprintf(irp->f, ".*"); | |
| 342 | } | |
| 343 | ||
| 339 | 344 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { |
| 340 | 345 | fprintf(irp->f, "*"); |
| 341 | 346 | ir_print_var_instruction(irp, instruction->ptr); |
| ... | ... | @@ -915,14 +920,18 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc |
| 915 | 920 | |
| 916 | 921 | static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { |
| 917 | 922 | fprintf(irp->f, "@bitCast("); |
| 918 | if (instruction->dest_type) { | |
| 919 | ir_print_other_instruction(irp, instruction->dest_type); | |
| 920 | } | |
| 923 | ir_print_other_instruction(irp, instruction->dest_type); | |
| 921 | 924 | fprintf(irp->f, ","); |
| 922 | 925 | ir_print_other_instruction(irp, instruction->value); |
| 923 | 926 | fprintf(irp->f, ")"); |
| 924 | 927 | } |
| 925 | 928 | |
| 929 | static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) { | |
| 930 | fprintf(irp->f, "@bitCast("); | |
| 931 | ir_print_other_instruction(irp, instruction->operand); | |
| 932 | fprintf(irp->f, ")"); | |
| 933 | } | |
| 934 | ||
| 926 | 935 | static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { |
| 927 | 936 | fprintf(irp->f, "WidenOrShorten("); |
| 928 | 937 | ir_print_other_instruction(irp, instruction->target); |
| ... | ... | @@ -990,6 +999,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct |
| 990 | 999 | fprintf(irp->f, ")"); |
| 991 | 1000 | } |
| 992 | 1001 | |
| 1002 | static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) { | |
| 1003 | fprintf(irp->f, "@resizeSlice("); | |
| 1004 | ir_print_other_instruction(irp, instruction->operand); | |
| 1005 | fprintf(irp->f, ")"); | |
| 1006 | } | |
| 1007 | ||
| 993 | 1008 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { |
| 994 | 1009 | fprintf(irp->f, "inttoerr "); |
| 995 | 1010 | ir_print_other_instruction(irp, instruction->target); |
| ... | ... | @@ -1462,6 +1477,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1462 | 1477 | case IrInstructionIdLoadPtr: |
| 1463 | 1478 | ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction); |
| 1464 | 1479 | break; |
| 1480 | case IrInstructionIdLoadPtrGen: | |
| 1481 | ir_print_load_ptr_gen(irp, (IrInstructionLoadPtrGen *)instruction); | |
| 1482 | break; | |
| 1465 | 1483 | case IrInstructionIdStorePtr: |
| 1466 | 1484 | ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction); |
| 1467 | 1485 | break; |
| ... | ... | @@ -1678,6 +1696,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1678 | 1696 | case IrInstructionIdBitCast: |
| 1679 | 1697 | ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); |
| 1680 | 1698 | break; |
| 1699 | case IrInstructionIdBitCastGen: | |
| 1700 | ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction); | |
| 1701 | break; | |
| 1681 | 1702 | case IrInstructionIdWidenOrShorten: |
| 1682 | 1703 | ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction); |
| 1683 | 1704 | break; |
| ... | ... | @@ -1852,6 +1873,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1852 | 1873 | case IrInstructionIdAssertZero: |
| 1853 | 1874 | ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); |
| 1854 | 1875 | break; |
| 1876 | case IrInstructionIdResizeSlice: | |
| 1877 | ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction); | |
| 1878 | break; | |
| 1855 | 1879 | } |
| 1856 | 1880 | fprintf(irp->f, "\n"); |
| 1857 | 1881 | } |
src/libc_installation.cpp created+498| ... | ... | @@ -0,0 +1,498 @@ |
| 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 | #include "libc_installation.hpp" | |
| 9 | #include "os.hpp" | |
| 10 | #include "windows_sdk.h" | |
| 11 | #include "target.hpp" | |
| 12 | ||
| 13 | static const char *zig_libc_keys[] = { | |
| 14 | "include_dir", | |
| 15 | "sys_include_dir", | |
| 16 | "crt_dir", | |
| 17 | "lib_dir", | |
| 18 | "static_lib_dir", | |
| 19 | "msvc_lib_dir", | |
| 20 | "kernel32_lib_dir", | |
| 21 | "dynamic_linker_path", | |
| 22 | }; | |
| 23 | ||
| 24 | static const size_t zig_libc_keys_len = array_length(zig_libc_keys); | |
| 25 | ||
| 26 | static bool zig_libc_match_key(Slice<uint8_t> name, Slice<uint8_t> value, bool *found_keys, | |
| 27 | size_t index, Buf *field_ptr) | |
| 28 | { | |
| 29 | if (!memEql(name, str(zig_libc_keys[index]))) return false; | |
| 30 | buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len); | |
| 31 | found_keys[index] = true; | |
| 32 | return true; | |
| 33 | } | |
| 34 | ||
| 35 | static void zig_libc_init_empty(ZigLibCInstallation *libc) { | |
| 36 | *libc = {}; | |
| 37 | buf_init_from_str(&libc->include_dir, ""); | |
| 38 | buf_init_from_str(&libc->sys_include_dir, ""); | |
| 39 | buf_init_from_str(&libc->crt_dir, ""); | |
| 40 | buf_init_from_str(&libc->lib_dir, ""); | |
| 41 | buf_init_from_str(&libc->static_lib_dir, ""); | |
| 42 | buf_init_from_str(&libc->msvc_lib_dir, ""); | |
| 43 | buf_init_from_str(&libc->kernel32_lib_dir, ""); | |
| 44 | buf_init_from_str(&libc->dynamic_linker_path, ""); | |
| 45 | } | |
| 46 | ||
| 47 | Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) { | |
| 48 | Error err; | |
| 49 | zig_libc_init_empty(libc); | |
| 50 | ||
| 51 | bool found_keys[array_length(zig_libc_keys)] = {}; | |
| 52 | ||
| 53 | Buf *contents = buf_alloc(); | |
| 54 | if ((err = os_fetch_file_path(libc_file, contents, false))) { | |
| 55 | if (err != ErrorFileNotFound && verbose) { | |
| 56 | fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err)); | |
| 57 | } | |
| 58 | return err; | |
| 59 | } | |
| 60 | ||
| 61 | SplitIterator it = memSplit(buf_to_slice(contents), str("\n")); | |
| 62 | for (;;) { | |
| 63 | Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&it); | |
| 64 | if (!opt_line.is_some) | |
| 65 | break; | |
| 66 | ||
| 67 | if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#') | |
| 68 | continue; | |
| 69 | ||
| 70 | SplitIterator line_it = memSplit(opt_line.value, str("=")); | |
| 71 | Slice<uint8_t> name; | |
| 72 | if (!SplitIterator_next(&line_it).unwrap(&name)) { | |
| 73 | if (verbose) { | |
| 74 | fprintf(stderr, "missing equal sign after field name\n"); | |
| 75 | } | |
| 76 | return ErrorSemanticAnalyzeFail; | |
| 77 | } | |
| 78 | Slice<uint8_t> value = SplitIterator_rest(&line_it); | |
| 79 | bool match = false; | |
| 80 | match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir); | |
| 81 | match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir); | |
| 82 | match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir); | |
| 83 | match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->lib_dir); | |
| 84 | match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->static_lib_dir); | |
| 85 | match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->msvc_lib_dir); | |
| 86 | match = match || zig_libc_match_key(name, value, found_keys, 6, &libc->kernel32_lib_dir); | |
| 87 | match = match || zig_libc_match_key(name, value, found_keys, 7, &libc->dynamic_linker_path); | |
| 88 | } | |
| 89 | ||
| 90 | for (size_t i = 0; i < zig_libc_keys_len; i += 1) { | |
| 91 | if (!found_keys[i]) { | |
| 92 | if (verbose) { | |
| 93 | fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]); | |
| 94 | } | |
| 95 | return ErrorSemanticAnalyzeFail; | |
| 96 | } | |
| 97 | } | |
| 98 | ||
| 99 | if (buf_len(&libc->include_dir) == 0) { | |
| 100 | if (verbose) { | |
| 101 | fprintf(stderr, "include_dir may not be empty\n"); | |
| 102 | } | |
| 103 | return ErrorSemanticAnalyzeFail; | |
| 104 | } | |
| 105 | ||
| 106 | if (buf_len(&libc->sys_include_dir) == 0) { | |
| 107 | if (verbose) { | |
| 108 | fprintf(stderr, "sys_include_dir may not be empty\n"); | |
| 109 | } | |
| 110 | return ErrorSemanticAnalyzeFail; | |
| 111 | } | |
| 112 | ||
| 113 | if (buf_len(&libc->crt_dir) == 0) { | |
| 114 | if (!target_is_darwin(target)) { | |
| 115 | if (verbose) { | |
| 116 | fprintf(stderr, "crt_dir may not be empty for %s\n", target_os_name(target->os)); | |
| 117 | } | |
| 118 | return ErrorSemanticAnalyzeFail; | |
| 119 | } | |
| 120 | } | |
| 121 | ||
| 122 | if (buf_len(&libc->lib_dir) == 0) { | |
| 123 | if (!target_is_darwin(target) && target->os != OsWindows) { | |
| 124 | if (verbose) { | |
| 125 | fprintf(stderr, "lib_dir may not be empty for %s\n", target_os_name(target->os)); | |
| 126 | } | |
| 127 | return ErrorSemanticAnalyzeFail; | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | if (buf_len(&libc->static_lib_dir) == 0) { | |
| 132 | if (!target_is_darwin(target) && target->os != OsWindows) { | |
| 133 | if (verbose) { | |
| 134 | fprintf(stderr, "static_lib_dir may not be empty for %s\n", target_os_name(target->os)); | |
| 135 | } | |
| 136 | return ErrorSemanticAnalyzeFail; | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | if (buf_len(&libc->msvc_lib_dir) == 0) { | |
| 141 | if (target->os == OsWindows) { | |
| 142 | if (verbose) { | |
| 143 | fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", target_os_name(target->os)); | |
| 144 | } | |
| 145 | return ErrorSemanticAnalyzeFail; | |
| 146 | } | |
| 147 | } | |
| 148 | ||
| 149 | if (buf_len(&libc->kernel32_lib_dir) == 0) { | |
| 150 | if (target->os == OsWindows) { | |
| 151 | if (verbose) { | |
| 152 | fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", target_os_name(target->os)); | |
| 153 | } | |
| 154 | return ErrorSemanticAnalyzeFail; | |
| 155 | } | |
| 156 | } | |
| 157 | ||
| 158 | if (buf_len(&libc->dynamic_linker_path) == 0) { | |
| 159 | if (!target_is_darwin(target) && target->os != OsWindows) { | |
| 160 | if (verbose) { | |
| 161 | fprintf(stderr, "dynamic_linker_path may not be empty for %s\n", target_os_name(target->os)); | |
| 162 | } | |
| 163 | return ErrorSemanticAnalyzeFail; | |
| 164 | } | |
| 165 | } | |
| 166 | ||
| 167 | return ErrorNone; | |
| 168 | } | |
| 169 | ||
| 170 | #if defined(ZIG_OS_WINDOWS) | |
| 171 | static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { | |
| 172 | Error err; | |
| 173 | if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) { | |
| 174 | if (verbose) { | |
| 175 | fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err)); | |
| 176 | } | |
| 177 | return err; | |
| 178 | } | |
| 179 | return ErrorNone; | |
| 180 | } | |
| 181 | static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, | |
| 182 | bool verbose) | |
| 183 | { | |
| 184 | Error err; | |
| 185 | if ((err = os_get_win32_ucrt_lib_path(sdk, &self->crt_dir, target->arch))) { | |
| 186 | if (verbose) { | |
| 187 | fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err)); | |
| 188 | } | |
| 189 | return err; | |
| 190 | } | |
| 191 | return ErrorNone; | |
| 192 | } | |
| 193 | static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, | |
| 194 | bool verbose) | |
| 195 | { | |
| 196 | Error err; | |
| 197 | if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch))) { | |
| 198 | if (verbose) { | |
| 199 | fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err)); | |
| 200 | } | |
| 201 | return err; | |
| 202 | } | |
| 203 | return ErrorNone; | |
| 204 | } | |
| 205 | static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { | |
| 206 | if (sdk->msvc_lib_dir_ptr == nullptr) { | |
| 207 | if (verbose) { | |
| 208 | fprintf(stderr, "Unable to determine vcruntime.lib path\n"); | |
| 209 | } | |
| 210 | return ErrorFileNotFound; | |
| 211 | } | |
| 212 | buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); | |
| 213 | return ErrorNone; | |
| 214 | } | |
| 215 | static Error zig_libc_find_native_msvc_include_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { | |
| 216 | Error err; | |
| 217 | if (sdk->msvc_lib_dir_ptr == nullptr) { | |
| 218 | if (verbose) { | |
| 219 | fprintf(stderr, "Unable to determine vcruntime.h path\n"); | |
| 220 | } | |
| 221 | return ErrorFileNotFound; | |
| 222 | } | |
| 223 | Buf search_path = BUF_INIT; | |
| 224 | buf_init_from_mem(&search_path, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); | |
| 225 | buf_append_str(&search_path, "\\..\\..\\include"); | |
| 226 | ||
| 227 | Buf *vcruntime_path = buf_sprintf("%s\\vcruntime.h", buf_ptr(&search_path)); | |
| 228 | bool exists; | |
| 229 | if ((err = os_file_exists(vcruntime_path, &exists))) { | |
| 230 | exists = false; | |
| 231 | } | |
| 232 | if (exists) { | |
| 233 | self->sys_include_dir = search_path; | |
| 234 | return ErrorNone; | |
| 235 | } | |
| 236 | ||
| 237 | if (verbose) { | |
| 238 | fprintf(stderr, "Unable to determine vcruntime.h path\n"); | |
| 239 | } | |
| 240 | return ErrorFileNotFound; | |
| 241 | } | |
| 242 | #else | |
| 243 | static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) { | |
| 244 | const char *cc_exe = getenv("CC"); | |
| 245 | cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; | |
| 246 | ZigList<const char *> args = {}; | |
| 247 | args.append("-E"); | |
| 248 | args.append("-Wp,-v"); | |
| 249 | args.append("-xc"); | |
| 250 | args.append("/dev/null"); | |
| 251 | Termination term; | |
| 252 | Buf *out_stderr = buf_alloc(); | |
| 253 | Buf *out_stdout = buf_alloc(); | |
| 254 | Error err; | |
| 255 | if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { | |
| 256 | if (verbose) { | |
| 257 | fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err)); | |
| 258 | } | |
| 259 | return err; | |
| 260 | } | |
| 261 | if (term.how != TerminationIdClean || term.code != 0) { | |
| 262 | if (verbose) { | |
| 263 | fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe); | |
| 264 | } | |
| 265 | return ErrorCCompileErrors; | |
| 266 | } | |
| 267 | char *prev_newline = buf_ptr(out_stderr); | |
| 268 | ZigList<const char *> search_paths = {}; | |
| 269 | for (;;) { | |
| 270 | char *newline = strchr(prev_newline, '\n'); | |
| 271 | if (newline == nullptr) { | |
| 272 | break; | |
| 273 | } | |
| 274 | *newline = 0; | |
| 275 | if (prev_newline[0] == ' ') { | |
| 276 | search_paths.append(prev_newline); | |
| 277 | } | |
| 278 | prev_newline = newline + 1; | |
| 279 | } | |
| 280 | if (search_paths.length == 0) { | |
| 281 | if (verbose) { | |
| 282 | fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe); | |
| 283 | } | |
| 284 | return ErrorCCompileErrors; | |
| 285 | } | |
| 286 | for (size_t i = 0; i < search_paths.length; i += 1) { | |
| 287 | // search in reverse order | |
| 288 | const char *search_path = search_paths.items[search_paths.length - i - 1]; | |
| 289 | // cut off spaces | |
| 290 | while (*search_path == ' ') { | |
| 291 | search_path += 1; | |
| 292 | } | |
| 293 | ||
| 294 | if (buf_len(&self->include_dir) == 0) { | |
| 295 | Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path); | |
| 296 | bool exists; | |
| 297 | if ((err = os_file_exists(stdlib_path, &exists))) { | |
| 298 | exists = false; | |
| 299 | } | |
| 300 | if (exists) { | |
| 301 | buf_init_from_str(&self->include_dir, search_path); | |
| 302 | } | |
| 303 | } | |
| 304 | if (buf_len(&self->sys_include_dir) == 0) { | |
| 305 | Buf *stdlib_path = buf_sprintf("%s/sys/errno.h", search_path); | |
| 306 | bool exists; | |
| 307 | if ((err = os_file_exists(stdlib_path, &exists))) { | |
| 308 | exists = false; | |
| 309 | } | |
| 310 | if (exists) { | |
| 311 | buf_init_from_str(&self->sys_include_dir, search_path); | |
| 312 | } | |
| 313 | } | |
| 314 | if (buf_len(&self->include_dir) != 0 && buf_len(&self->sys_include_dir) != 0) { | |
| 315 | return ErrorNone; | |
| 316 | } | |
| 317 | } | |
| 318 | if (verbose) { | |
| 319 | if (buf_len(&self->include_dir) == 0) { | |
| 320 | fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe); | |
| 321 | } | |
| 322 | if (buf_len(&self->sys_include_dir) == 0) { | |
| 323 | fprintf(stderr, "unable to determine libc include path: sys/errno.h not found in '%s' search paths\n", cc_exe); | |
| 324 | } | |
| 325 | } | |
| 326 | return ErrorFileNotFound; | |
| 327 | } | |
| 328 | #if !defined(ZIG_OS_DARWIN) && !defined(ZIG_OS_FREEBSD) && !defined(ZIG_OS_NETBSD) | |
| 329 | static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) { | |
| 330 | const char *cc_exe = getenv("CC"); | |
| 331 | cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; | |
| 332 | ZigList<const char *> args = {}; | |
| 333 | args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file))); | |
| 334 | Termination term; | |
| 335 | Buf *out_stderr = buf_alloc(); | |
| 336 | Buf *out_stdout = buf_alloc(); | |
| 337 | Error err; | |
| 338 | if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { | |
| 339 | if (verbose) { | |
| 340 | fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err)); | |
| 341 | } | |
| 342 | return err; | |
| 343 | } | |
| 344 | if (term.how != TerminationIdClean || term.code != 0) { | |
| 345 | if (verbose) { | |
| 346 | fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe); | |
| 347 | } | |
| 348 | return ErrorCCompileErrors; | |
| 349 | } | |
| 350 | if (buf_ends_with_str(out_stdout, "\n")) { | |
| 351 | buf_resize(out_stdout, buf_len(out_stdout) - 1); | |
| 352 | } | |
| 353 | if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) { | |
| 354 | return ErrorCCompilerCannotFindFile; | |
| 355 | } | |
| 356 | if (want_dirname) { | |
| 357 | os_path_dirname(out_stdout, out); | |
| 358 | } else { | |
| 359 | buf_init_from_buf(out, out_stdout); | |
| 360 | } | |
| 361 | return ErrorNone; | |
| 362 | } | |
| 363 | static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool verbose) { | |
| 364 | return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose); | |
| 365 | } | |
| 366 | static Error zig_libc_find_native_lib_dir_posix(ZigLibCInstallation *self, bool verbose) { | |
| 367 | return zig_libc_cc_print_file_name("libgcc_s.so", &self->lib_dir, true, verbose); | |
| 368 | } | |
| 369 | ||
| 370 | static Error zig_libc_find_native_static_lib_dir_posix(ZigLibCInstallation *self, bool verbose) { | |
| 371 | return zig_libc_cc_print_file_name("crtbegin.o", &self->static_lib_dir, true, verbose); | |
| 372 | } | |
| 373 | #endif | |
| 374 | ||
| 375 | static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self, bool verbose) { | |
| 376 | #if defined(ZIG_OS_LINUX) | |
| 377 | Error err; | |
| 378 | static const char *dyn_tests[] = { | |
| 379 | "ld-linux-x86-64.so.2", | |
| 380 | "ld-musl-x86_64.so.1", | |
| 381 | }; | |
| 382 | for (size_t i = 0; i < array_length(dyn_tests); i += 1) { | |
| 383 | const char *lib_name = dyn_tests[i]; | |
| 384 | if ((err = zig_libc_cc_print_file_name(lib_name, &self->dynamic_linker_path, false, true))) { | |
| 385 | if (err != ErrorCCompilerCannotFindFile) | |
| 386 | return err; | |
| 387 | continue; | |
| 388 | } | |
| 389 | return ErrorNone; | |
| 390 | } | |
| 391 | #endif | |
| 392 | ZigTarget native_target; | |
| 393 | get_native_target(&native_target); | |
| 394 | const char *dynamic_linker_path = target_dynamic_linker(&native_target); | |
| 395 | if (dynamic_linker_path != nullptr) { | |
| 396 | buf_init_from_str(&self->dynamic_linker_path, dynamic_linker_path); | |
| 397 | } | |
| 398 | return ErrorNone; | |
| 399 | } | |
| 400 | #endif | |
| 401 | ||
| 402 | void zig_libc_render(ZigLibCInstallation *self, FILE *file) { | |
| 403 | fprintf(file, | |
| 404 | "# The directory that contains `stdlib.h`.\n" | |
| 405 | "# On POSIX, include directories be found with: `cc -E -Wp,-v -xc /dev/null`\n" | |
| 406 | "include_dir=%s\n" | |
| 407 | "# The system-specific include directory. May be the same as `include_dir`.\n" | |
| 408 | "# On Windows it's the directory that includes `vcruntime.h`.\n" | |
| 409 | "# On POSIX it's the directory that includes `sys/errno.h`.\n" | |
| 410 | "sys_include_dir=%s\n" | |
| 411 | "\n" | |
| 412 | "# The directory that contains `crt1.o`.\n" | |
| 413 | "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n" | |
| 414 | "# Not needed when targeting MacOS.\n" | |
| 415 | "crt_dir=%s\n" | |
| 416 | "\n" | |
| 417 | "# The directory that contains `libgcc_s.so`.\n" | |
| 418 | "# On POSIX, can be found with `cc -print-file-name=libgcc_s.so`.\n" | |
| 419 | "# Not needed when targeting MacOS or Windows.\n" | |
| 420 | "lib_dir=%s\n" | |
| 421 | "\n" | |
| 422 | "# The directory that contains `crtbegin.o`.\n" | |
| 423 | "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n" | |
| 424 | "# Not needed when targeting MacOS or Windows.\n" | |
| 425 | "static_lib_dir=%s\n" | |
| 426 | "\n" | |
| 427 | "# The directory that contains `vcruntime.lib`.\n" | |
| 428 | "# Only needed when targeting Windows.\n" | |
| 429 | "msvc_lib_dir=%s\n" | |
| 430 | "\n" | |
| 431 | "# The directory that contains `kernel32.lib`.\n" | |
| 432 | "# Only needed when targeting Windows.\n" | |
| 433 | "kernel32_lib_dir=%s\n" | |
| 434 | "\n" | |
| 435 | "# The full path to the dynamic linker, on the target system.\n" | |
| 436 | "# Not needed when targeting MacOS or Windows.\n" | |
| 437 | "dynamic_linker_path=%s\n" | |
| 438 | "\n" | |
| 439 | , | |
| 440 | buf_ptr(&self->include_dir), | |
| 441 | buf_ptr(&self->sys_include_dir), | |
| 442 | buf_ptr(&self->crt_dir), | |
| 443 | buf_ptr(&self->lib_dir), | |
| 444 | buf_ptr(&self->static_lib_dir), | |
| 445 | buf_ptr(&self->msvc_lib_dir), | |
| 446 | buf_ptr(&self->kernel32_lib_dir), | |
| 447 | buf_ptr(&self->dynamic_linker_path) | |
| 448 | ); | |
| 449 | } | |
| 450 | ||
| 451 | Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) { | |
| 452 | Error err; | |
| 453 | zig_libc_init_empty(self); | |
| 454 | #if defined(ZIG_OS_WINDOWS) | |
| 455 | ZigTarget native_target; | |
| 456 | get_native_target(&native_target); | |
| 457 | ZigWindowsSDK *sdk; | |
| 458 | switch (zig_find_windows_sdk(&sdk)) { | |
| 459 | case ZigFindWindowsSdkErrorNone: | |
| 460 | if ((err = zig_libc_find_native_msvc_include_dir(self, sdk, verbose))) | |
| 461 | return err; | |
| 462 | if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose))) | |
| 463 | return err; | |
| 464 | if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose))) | |
| 465 | return err; | |
| 466 | if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose))) | |
| 467 | return err; | |
| 468 | if ((err = zig_libc_find_crt_dir_windows(self, sdk, &native_target, verbose))) | |
| 469 | return err; | |
| 470 | return ErrorNone; | |
| 471 | case ZigFindWindowsSdkErrorOutOfMemory: | |
| 472 | return ErrorNoMem; | |
| 473 | case ZigFindWindowsSdkErrorNotFound: | |
| 474 | return ErrorFileNotFound; | |
| 475 | case ZigFindWindowsSdkErrorPathTooLong: | |
| 476 | return ErrorPathTooLong; | |
| 477 | } | |
| 478 | zig_unreachable(); | |
| 479 | #else | |
| 480 | if ((err = zig_libc_find_native_include_dir_posix(self, verbose))) | |
| 481 | return err; | |
| 482 | #if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | |
| 483 | buf_init_from_str(&self->crt_dir, "/usr/lib"); | |
| 484 | buf_init_from_str(&self->lib_dir, "/usr/lib"); | |
| 485 | buf_init_from_str(&self->static_lib_dir, "/usr/lib"); | |
| 486 | #elif !defined(ZIG_OS_DARWIN) | |
| 487 | if ((err = zig_libc_find_native_crt_dir_posix(self, verbose))) | |
| 488 | return err; | |
| 489 | if ((err = zig_libc_find_native_lib_dir_posix(self, verbose))) | |
| 490 | return err; | |
| 491 | if ((err = zig_libc_find_native_static_lib_dir_posix(self, verbose))) | |
| 492 | return err; | |
| 493 | #endif | |
| 494 | if ((err = zig_libc_find_native_dynamic_linker_posix(self, verbose))) | |
| 495 | return err; | |
| 496 | return ErrorNone; | |
| 497 | #endif | |
| 498 | } |
src/libc_installation.hpp created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 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_LIBC_INSTALLATION_HPP | |
| 9 | #define ZIG_LIBC_INSTALLATION_HPP | |
| 10 | ||
| 11 | #include <stdio.h> | |
| 12 | ||
| 13 | #include "buffer.hpp" | |
| 14 | #include "error.hpp" | |
| 15 | #include "target.hpp" | |
| 16 | ||
| 17 | // Must be synchronized with zig_libc_keys | |
| 18 | struct ZigLibCInstallation { | |
| 19 | Buf include_dir; | |
| 20 | Buf sys_include_dir; | |
| 21 | Buf crt_dir; | |
| 22 | Buf lib_dir; | |
| 23 | Buf static_lib_dir; | |
| 24 | Buf msvc_lib_dir; | |
| 25 | Buf kernel32_lib_dir; | |
| 26 | Buf dynamic_linker_path; | |
| 27 | }; | |
| 28 | ||
| 29 | Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, | |
| 30 | const ZigTarget *target, bool verbose); | |
| 31 | void zig_libc_render(ZigLibCInstallation *self, FILE *file); | |
| 32 | ||
| 33 | Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose); | |
| 34 | ||
| 35 | #endif |
src/link.cpp+75-114| ... | ... | @@ -17,32 +17,33 @@ struct LinkJob { |
| 17 | 17 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table; |
| 18 | 18 | }; |
| 19 | 19 | |
| 20 | static const char *get_libc_file(CodeGen *g, const char *file) { | |
| 20 | static const char *get_libc_crt_file(CodeGen *g, const char *file) { | |
| 21 | assert(g->libc != nullptr); | |
| 21 | 22 | Buf *out_buf = buf_alloc(); |
| 22 | os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf); | |
| 23 | os_path_join(&g->libc->crt_dir, buf_create_from_str(file), out_buf); | |
| 23 | 24 | return buf_ptr(out_buf); |
| 24 | 25 | } |
| 25 | 26 | |
| 26 | 27 | static const char *get_libc_static_file(CodeGen *g, const char *file) { |
| 28 | assert(g->libc != nullptr); | |
| 27 | 29 | Buf *out_buf = buf_alloc(); |
| 28 | os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf); | |
| 30 | os_path_join(&g->libc->static_lib_dir, buf_create_from_str(file), out_buf); | |
| 29 | 31 | return buf_ptr(out_buf); |
| 30 | 32 | } |
| 31 | 33 | |
| 32 | 34 | static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) { |
| 33 | ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; | |
| 34 | ||
| 35 | 35 | // The Mach-O LLD code is not well maintained, and trips an assertion |
| 36 | 36 | // when we link compiler_rt and builtin as libraries rather than objects. |
| 37 | 37 | // Here we workaround this by having compiler_rt and builtin be objects. |
| 38 | 38 | // TODO write our own linker. https://github.com/ziglang/zig/issues/1535 |
| 39 | 39 | OutType child_out_type = OutTypeLib; |
| 40 | if (parent_gen->zig_target.os == OsMacOSX) { | |
| 40 | if (parent_gen->zig_target->os == OsMacOSX) { | |
| 41 | 41 | child_out_type = OutTypeObj; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type, | |
| 45 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir); | |
| 44 | CodeGen *child_gen = codegen_create(full_path, parent_gen->zig_target, child_out_type, | |
| 45 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, | |
| 46 | parent_gen->libc); | |
| 46 | 47 | |
| 47 | 48 | child_gen->out_h_path = nullptr; |
| 48 | 49 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; |
| ... | ... | @@ -55,6 +56,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) |
| 55 | 56 | codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); |
| 56 | 57 | codegen_set_is_static(child_gen, true); |
| 57 | 58 | child_gen->disable_pic = parent_gen->disable_pic; |
| 59 | child_gen->valgrind_support = ValgrindSupportDisabled; | |
| 58 | 60 | |
| 59 | 61 | codegen_set_out_name(child_gen, buf_create_from_str(aname)); |
| 60 | 62 | |
| ... | ... | @@ -94,7 +96,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) { |
| 94 | 96 | } |
| 95 | 97 | |
| 96 | 98 | static const char *get_darwin_arch_string(const ZigTarget *t) { |
| 97 | switch (t->arch.arch) { | |
| 99 | switch (t->arch) { | |
| 98 | 100 | case ZigLLVM_aarch64: |
| 99 | 101 | return "arm64"; |
| 100 | 102 | case ZigLLVM_thumb: |
| ... | ... | @@ -107,13 +109,13 @@ static const char *get_darwin_arch_string(const ZigTarget *t) { |
| 107 | 109 | case ZigLLVM_ppc64le: |
| 108 | 110 | return "ppc64le"; |
| 109 | 111 | default: |
| 110 | return ZigLLVMGetArchTypeName(t->arch.arch); | |
| 112 | return ZigLLVMGetArchTypeName(t->arch); | |
| 111 | 113 | } |
| 112 | 114 | } |
| 113 | 115 | |
| 114 | 116 | |
| 115 | 117 | static const char *getLDMOption(const ZigTarget *t) { |
| 116 | switch (t->arch.arch) { | |
| 118 | switch (t->arch) { | |
| 117 | 119 | case ZigLLVM_x86: |
| 118 | 120 | return "elf_i386"; |
| 119 | 121 | case ZigLLVM_aarch64: |
| ... | ... | @@ -147,7 +149,7 @@ static const char *getLDMOption(const ZigTarget *t) { |
| 147 | 149 | case ZigLLVM_systemz: |
| 148 | 150 | return "elf64_s390"; |
| 149 | 151 | case ZigLLVM_x86_64: |
| 150 | if (t->env_type == ZigLLVM_GNUX32) { | |
| 152 | if (t->abi == ZigLLVM_GNUX32) { | |
| 151 | 153 | return "elf32_x86_64"; |
| 152 | 154 | } |
| 153 | 155 | // Any target elf will use the freebsd osabi if suffixed with "_fbsd". |
| ... | ... | @@ -170,78 +172,27 @@ static void add_rpath(LinkJob *lj, Buf *rpath) { |
| 170 | 172 | lj->rpath_table.put(rpath, true); |
| 171 | 173 | } |
| 172 | 174 | |
| 173 | static Buf *try_dynamic_linker_path(const char *ld_name) { | |
| 174 | const char *cc_exe = getenv("CC"); | |
| 175 | cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; | |
| 176 | ZigList<const char *> args = {}; | |
| 177 | args.append(buf_ptr(buf_sprintf("-print-file-name=%s", ld_name))); | |
| 178 | Termination term; | |
| 179 | Buf *out_stderr = buf_alloc(); | |
| 180 | Buf *out_stdout = buf_alloc(); | |
| 181 | int err; | |
| 182 | if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { | |
| 183 | return nullptr; | |
| 184 | } | |
| 185 | if (term.how != TerminationIdClean || term.code != 0) { | |
| 186 | return nullptr; | |
| 187 | } | |
| 188 | if (buf_ends_with_str(out_stdout, "\n")) { | |
| 189 | buf_resize(out_stdout, buf_len(out_stdout) - 1); | |
| 190 | } | |
| 191 | if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, ld_name)) { | |
| 192 | return nullptr; | |
| 193 | } | |
| 194 | return out_stdout; | |
| 195 | } | |
| 196 | ||
| 197 | static Buf *get_dynamic_linker_path(CodeGen *g) { | |
| 198 | if (g->zig_target.os == OsFreeBSD) { | |
| 199 | return buf_create_from_str("/libexec/ld-elf.so.1"); | |
| 200 | } | |
| 201 | if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) { | |
| 202 | static const char *ld_names[] = { | |
| 203 | "ld-linux-x86-64.so.2", | |
| 204 | "ld-musl-x86_64.so.1", | |
| 205 | }; | |
| 206 | for (size_t i = 0; i < array_length(ld_names); i += 1) { | |
| 207 | const char *ld_name = ld_names[i]; | |
| 208 | Buf *result = try_dynamic_linker_path(ld_name); | |
| 209 | if (result != nullptr) { | |
| 210 | return result; | |
| 211 | } | |
| 212 | } | |
| 213 | } | |
| 214 | return target_dynamic_linker(&g->zig_target); | |
| 215 | } | |
| 216 | ||
| 217 | 175 | static void construct_linker_job_elf(LinkJob *lj) { |
| 218 | 176 | CodeGen *g = lj->codegen; |
| 219 | 177 | |
| 220 | 178 | lj->args.append("-error-limit=0"); |
| 221 | 179 | |
| 222 | if (g->libc_link_lib != nullptr) { | |
| 223 | find_libc_lib_path(g); | |
| 224 | } | |
| 225 | ||
| 226 | 180 | if (g->linker_script) { |
| 227 | 181 | lj->args.append("-T"); |
| 228 | 182 | lj->args.append(g->linker_script); |
| 229 | 183 | } |
| 230 | 184 | |
| 231 | if (g->no_rosegment_workaround) { | |
| 232 | lj->args.append("--no-rosegment"); | |
| 233 | } | |
| 234 | 185 | lj->args.append("--gc-sections"); |
| 235 | 186 | |
| 236 | 187 | lj->args.append("-m"); |
| 237 | lj->args.append(getLDMOption(&g->zig_target)); | |
| 188 | lj->args.append(getLDMOption(g->zig_target)); | |
| 238 | 189 | |
| 239 | 190 | bool is_lib = g->out_type == OutTypeLib; |
| 240 | 191 | bool shared = !g->is_static && is_lib; |
| 241 | 192 | Buf *soname = nullptr; |
| 242 | 193 | if (g->is_static) { |
| 243 | if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb || | |
| 244 | g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb) | |
| 194 | if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb || | |
| 195 | g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb) | |
| 245 | 196 | { |
| 246 | 197 | lj->args.append("-Bstatic"); |
| 247 | 198 | } else { |
| ... | ... | @@ -263,15 +214,18 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 263 | 214 | if (lj->link_in_crt) { |
| 264 | 215 | const char *crt1o; |
| 265 | 216 | const char *crtbegino; |
| 266 | if (g->is_static) { | |
| 217 | if (g->zig_target->os == OsNetBSD) { | |
| 218 | crt1o = "crt0.o"; | |
| 219 | crtbegino = "crtbegin.o"; | |
| 220 | } else if (g->is_static) { | |
| 267 | 221 | crt1o = "crt1.o"; |
| 268 | 222 | crtbegino = "crtbeginT.o"; |
| 269 | 223 | } else { |
| 270 | 224 | crt1o = "Scrt1.o"; |
| 271 | 225 | crtbegino = "crtbegin.o"; |
| 272 | 226 | } |
| 273 | lj->args.append(get_libc_file(g, crt1o)); | |
| 274 | lj->args.append(get_libc_file(g, "crti.o")); | |
| 227 | lj->args.append(get_libc_crt_file(g, crt1o)); | |
| 228 | lj->args.append(get_libc_crt_file(g, "crti.o")); | |
| 275 | 229 | lj->args.append(get_libc_static_file(g, crtbegino)); |
| 276 | 230 | } |
| 277 | 231 | |
| ... | ... | @@ -307,23 +261,24 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 307 | 261 | } |
| 308 | 262 | |
| 309 | 263 | if (g->libc_link_lib != nullptr) { |
| 264 | assert(g->libc != nullptr); | |
| 310 | 265 | lj->args.append("-L"); |
| 311 | lj->args.append(buf_ptr(g->libc_lib_dir)); | |
| 266 | lj->args.append(buf_ptr(&g->libc->crt_dir)); | |
| 267 | ||
| 268 | if (!buf_eql_buf(&g->libc->crt_dir, &g->libc->lib_dir)) { | |
| 269 | lj->args.append("-L"); | |
| 270 | lj->args.append(buf_ptr(&g->libc->lib_dir)); | |
| 271 | } | |
| 312 | 272 | |
| 313 | 273 | lj->args.append("-L"); |
| 314 | lj->args.append(buf_ptr(g->libc_static_lib_dir)); | |
| 315 | } | |
| 274 | lj->args.append(buf_ptr(&g->libc->static_lib_dir)); | |
| 316 | 275 | |
| 317 | if (!g->is_static) { | |
| 318 | if (g->dynamic_linker != nullptr) { | |
| 319 | assert(buf_len(g->dynamic_linker) != 0); | |
| 320 | lj->args.append("-dynamic-linker"); | |
| 321 | lj->args.append(buf_ptr(g->dynamic_linker)); | |
| 322 | } else { | |
| 323 | Buf *resolved_dynamic_linker = get_dynamic_linker_path(g); | |
| 276 | if (!g->is_static) { | |
| 277 | assert(buf_len(&g->libc->dynamic_linker_path) != 0); | |
| 324 | 278 | lj->args.append("-dynamic-linker"); |
| 325 | lj->args.append(buf_ptr(resolved_dynamic_linker)); | |
| 279 | lj->args.append(buf_ptr(&g->libc->dynamic_linker_path)); | |
| 326 | 280 | } |
| 281 | ||
| 327 | 282 | } |
| 328 | 283 | |
| 329 | 284 | if (shared) { |
| ... | ... | @@ -390,14 +345,14 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 390 | 345 | // crt end |
| 391 | 346 | if (lj->link_in_crt) { |
| 392 | 347 | lj->args.append(get_libc_static_file(g, "crtend.o")); |
| 393 | lj->args.append(get_libc_file(g, "crtn.o")); | |
| 348 | lj->args.append(get_libc_crt_file(g, "crtn.o")); | |
| 394 | 349 | } |
| 395 | 350 | |
| 396 | if (!g->is_native_target) { | |
| 351 | if (!g->zig_target->is_native) { | |
| 397 | 352 | lj->args.append("--allow-shlib-undefined"); |
| 398 | 353 | } |
| 399 | 354 | |
| 400 | if (g->zig_target.os == OsZen) { | |
| 355 | if (g->zig_target->os == OsZen) { | |
| 401 | 356 | lj->args.append("-e"); |
| 402 | 357 | lj->args.append("_start"); |
| 403 | 358 | |
| ... | ... | @@ -420,16 +375,16 @@ static void construct_linker_job_wasm(LinkJob *lj) { |
| 420 | 375 | } |
| 421 | 376 | |
| 422 | 377 | //static bool is_target_cyg_mingw(const ZigTarget *target) { |
| 423 | // return (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_Cygnus) || | |
| 424 | // (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_GNU); | |
| 378 | // return (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_Cygnus) || | |
| 379 | // (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_GNU); | |
| 425 | 380 | //} |
| 426 | 381 | |
| 427 | 382 | static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) { |
| 428 | if (g->zig_target.arch.arch == ZigLLVM_x86) { | |
| 383 | if (g->zig_target->arch == ZigLLVM_x86) { | |
| 429 | 384 | list->append("-MACHINE:X86"); |
| 430 | } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) { | |
| 385 | } else if (g->zig_target->arch == ZigLLVM_x86_64) { | |
| 431 | 386 | list->append("-MACHINE:X64"); |
| 432 | } else if (g->zig_target.arch.arch == ZigLLVM_arm) { | |
| 387 | } else if (g->zig_target->arch == ZigLLVM_arm) { | |
| 433 | 388 | list->append("-MACHINE:ARM"); |
| 434 | 389 | } |
| 435 | 390 | } |
| ... | ... | @@ -515,7 +470,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) { |
| 515 | 470 | // lj->args.append("-Bdynamic"); |
| 516 | 471 | // if (dll || shared) { |
| 517 | 472 | // lj->args.append("-e"); |
| 518 | // if (g->zig_target.arch.arch == ZigLLVM_x86) { | |
| 473 | // if (g->zig_target.arch == ZigLLVM_x86) { | |
| 519 | 474 | // lj->args.append("_DllMainCRTStartup@12"); |
| 520 | 475 | // } else { |
| 521 | 476 | // lj->args.append("DllMainCRTStartup"); |
| ... | ... | @@ -541,7 +496,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) { |
| 541 | 496 | //lj->args.append("-lmingw32"); |
| 542 | 497 | |
| 543 | 498 | //lj->args.append("-lgcc"); |
| 544 | //bool is_android = (g->zig_target.env_type == ZigLLVM_Android); | |
| 499 | //bool is_android = (g->zig_target.abi == ZigLLVM_Android); | |
| 545 | 500 | //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target); |
| 546 | 501 | //if (!g->is_static && !is_android) { |
| 547 | 502 | // if (!is_cyg_ming) { |
| ... | ... | @@ -588,10 +543,6 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 588 | 543 | |
| 589 | 544 | lj->args.append("/ERRORLIMIT:0"); |
| 590 | 545 | |
| 591 | if (g->libc_link_lib != nullptr) { | |
| 592 | find_libc_lib_path(g); | |
| 593 | } | |
| 594 | ||
| 595 | 546 | lj->args.append("/NOLOGO"); |
| 596 | 547 | |
| 597 | 548 | if (!g->strip_debug_symbols) { |
| ... | ... | @@ -608,6 +559,11 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 608 | 559 | bool is_library = g->out_type == OutTypeLib; |
| 609 | 560 | switch (g->subsystem) { |
| 610 | 561 | case TargetSubsystemAuto: |
| 562 | if (g->zig_target->os == OsUefi) { | |
| 563 | add_uefi_link_args(lj); | |
| 564 | } else { | |
| 565 | add_nt_link_args(lj, is_library); | |
| 566 | } | |
| 611 | 567 | break; |
| 612 | 568 | case TargetSubsystemConsole: |
| 613 | 569 | lj->args.append("/SUBSYSTEM:console"); |
| ... | ... | @@ -646,13 +602,11 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 646 | 602 | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); |
| 647 | 603 | |
| 648 | 604 | if (g->libc_link_lib != nullptr) { |
| 649 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); | |
| 650 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); | |
| 605 | assert(g->libc != nullptr); | |
| 651 | 606 | |
| 652 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); | |
| 653 | if (g->libc_static_lib_dir != nullptr) { | |
| 654 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); | |
| 655 | } | |
| 607 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); | |
| 608 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); | |
| 609 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir)))); | |
| 656 | 610 | } |
| 657 | 611 | |
| 658 | 612 | if (is_library && !g->is_static) { |
| ... | ... | @@ -687,7 +641,7 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 687 | 641 | continue; |
| 688 | 642 | } |
| 689 | 643 | if (link_lib->provided_explicitly) { |
| 690 | if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) { | |
| 644 | if (lj->codegen->zig_target->abi == ZigLLVM_GNU) { | |
| 691 | 645 | Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); |
| 692 | 646 | lj->args.append(buf_ptr(arg)); |
| 693 | 647 | } |
| ... | ... | @@ -717,7 +671,8 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 717 | 671 | gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path)))); |
| 718 | 672 | gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path)))); |
| 719 | 673 | Buf diag = BUF_INIT; |
| 720 | if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) { | |
| 674 | ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target); | |
| 675 | if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) { | |
| 721 | 676 | fprintf(stderr, "%s\n", buf_ptr(&diag)); |
| 722 | 677 | exit(1); |
| 723 | 678 | } |
| ... | ... | @@ -786,7 +741,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { |
| 786 | 741 | platform->kind = MacOS; |
| 787 | 742 | } else if (g->mios_version_min) { |
| 788 | 743 | platform->kind = IPhoneOS; |
| 789 | } else if (g->zig_target.os == OsMacOSX) { | |
| 744 | } else if (g->zig_target->os == OsMacOSX) { | |
| 790 | 745 | platform->kind = MacOS; |
| 791 | 746 | g->mmacosx_version_min = buf_create_from_str("10.10"); |
| 792 | 747 | } else { |
| ... | ... | @@ -813,8 +768,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { |
| 813 | 768 | } |
| 814 | 769 | |
| 815 | 770 | if (platform->kind == IPhoneOS && |
| 816 | (g->zig_target.arch.arch == ZigLLVM_x86 || | |
| 817 | g->zig_target.arch.arch == ZigLLVM_x86_64)) | |
| 771 | (g->zig_target->arch == ZigLLVM_x86 || | |
| 772 | g->zig_target->arch == ZigLLVM_x86_64)) | |
| 818 | 773 | { |
| 819 | 774 | platform->kind = IPhoneOSSimulator; |
| 820 | 775 | } |
| ... | ... | @@ -878,7 +833,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 878 | 833 | } |
| 879 | 834 | |
| 880 | 835 | lj->args.append("-arch"); |
| 881 | lj->args.append(get_darwin_arch_string(&g->zig_target)); | |
| 836 | lj->args.append(get_darwin_arch_string(g->zig_target)); | |
| 882 | 837 | |
| 883 | 838 | DarwinPlatform platform; |
| 884 | 839 | get_darwin_platform(lj, &platform); |
| ... | ... | @@ -893,7 +848,11 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 893 | 848 | lj->args.append("-ios_simulator_version_min"); |
| 894 | 849 | break; |
| 895 | 850 | } |
| 896 | lj->args.append(buf_ptr(buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro))); | |
| 851 | Buf *version_string = buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro); | |
| 852 | lj->args.append(buf_ptr(version_string)); | |
| 853 | ||
| 854 | lj->args.append("-sdk_version"); | |
| 855 | lj->args.append(buf_ptr(version_string)); | |
| 897 | 856 | |
| 898 | 857 | |
| 899 | 858 | if (g->out_type == OutTypeExe) { |
| ... | ... | @@ -914,7 +873,9 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 914 | 873 | add_rpath(lj, &g->output_file_path); |
| 915 | 874 | |
| 916 | 875 | if (shared) { |
| 917 | lj->args.append("-headerpad_max_install_names"); | |
| 876 | if (g->system_linker_hack) { | |
| 877 | lj->args.append("-headerpad_max_install_names"); | |
| 878 | } | |
| 918 | 879 | } else if (g->is_static) { |
| 919 | 880 | lj->args.append("-lcrt0.o"); |
| 920 | 881 | } else { |
| ... | ... | @@ -929,7 +890,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 929 | 890 | } |
| 930 | 891 | break; |
| 931 | 892 | case IPhoneOS: |
| 932 | if (g->zig_target.arch.arch == ZigLLVM_aarch64) { | |
| 893 | if (g->zig_target->arch == ZigLLVM_aarch64) { | |
| 933 | 894 | // iOS does not need any crt1 files for arm64 |
| 934 | 895 | } else if (darwin_version_lt(&platform, 3, 1)) { |
| 935 | 896 | lj->args.append("-lcrt1.o"); |
| ... | ... | @@ -959,7 +920,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 959 | 920 | lj->args.append(buf_ptr(compiler_rt_o_path)); |
| 960 | 921 | } |
| 961 | 922 | |
| 962 | if (g->is_native_target) { | |
| 923 | if (g->zig_target->is_native) { | |
| 963 | 924 | for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) { |
| 964 | 925 | LinkLib *link_lib = g->link_libs_list.at(lib_i); |
| 965 | 926 | if (buf_eql_str(link_lib->name, "c")) { |
| ... | ... | @@ -1000,7 +961,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 1000 | 961 | } |
| 1001 | 962 | |
| 1002 | 963 | static void construct_linker_job(LinkJob *lj) { |
| 1003 | switch (lj->codegen->zig_target.oformat) { | |
| 964 | switch (target_object_format(lj->codegen->zig_target)) { | |
| 1004 | 965 | case ZigLLVM_UnknownObjectFormat: |
| 1005 | 966 | zig_unreachable(); |
| 1006 | 967 | |
| ... | ... | @@ -1040,7 +1001,7 @@ void codegen_link(CodeGen *g) { |
| 1040 | 1001 | for (size_t i = 0; i < g->link_objects.length; i += 1) { |
| 1041 | 1002 | file_names.append((const char *)buf_ptr(g->link_objects.at(i))); |
| 1042 | 1003 | } |
| 1043 | ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os); | |
| 1004 | ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os); | |
| 1044 | 1005 | codegen_add_time_event(g, "LLVM Link"); |
| 1045 | 1006 | if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) { |
| 1046 | 1007 | fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path)); |
| ... | ... | @@ -1065,7 +1026,7 @@ void codegen_link(CodeGen *g) { |
| 1065 | 1026 | Buf diag = BUF_INIT; |
| 1066 | 1027 | |
| 1067 | 1028 | codegen_add_time_event(g, "LLVM Link"); |
| 1068 | if (g->system_linker_hack && g->zig_target.os == OsMacOSX) { | |
| 1029 | if (g->system_linker_hack && g->zig_target->os == OsMacOSX) { | |
| 1069 | 1030 | Termination term; |
| 1070 | 1031 | ZigList<const char *> args = {}; |
| 1071 | 1032 | for (size_t i = 1; i < lj.args.length; i += 1) { |
| ... | ... | @@ -1075,7 +1036,7 @@ void codegen_link(CodeGen *g) { |
| 1075 | 1036 | if (term.how != TerminationIdClean || term.code != 0) { |
| 1076 | 1037 | exit(1); |
| 1077 | 1038 | } |
| 1078 | } else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) { | |
| 1039 | } else if (!zig_lld_link(target_object_format(g->zig_target), lj.args.items, lj.args.length, &diag)) { | |
| 1079 | 1040 | fprintf(stderr, "%s\n", buf_ptr(&diag)); |
| 1080 | 1041 | exit(1); |
| 1081 | 1042 | } |
src/main.cpp+231-114| ... | ... | @@ -13,16 +13,17 @@ |
| 13 | 13 | #include "error.hpp" |
| 14 | 14 | #include "os.hpp" |
| 15 | 15 | #include "target.hpp" |
| 16 | #include "libc_installation.hpp" | |
| 16 | 17 | |
| 17 | 18 | #include <stdio.h> |
| 18 | 19 | |
| 19 | 20 | static int print_error_usage(const char *arg0) { |
| 20 | fprintf(stderr, "See `%s help` for detailed usage information\n", arg0); | |
| 21 | fprintf(stderr, "See `%s --help` for detailed usage information\n", arg0); | |
| 21 | 22 | return EXIT_FAILURE; |
| 22 | 23 | } |
| 23 | 24 | |
| 24 | static int print_full_usage(const char *arg0) { | |
| 25 | fprintf(stdout, | |
| 25 | static int print_full_usage(const char *arg0, FILE *file, int return_code) { | |
| 26 | fprintf(file, | |
| 26 | 27 | "Usage: %s [command] [options]\n" |
| 27 | 28 | "\n" |
| 28 | 29 | "Commands:\n" |
| ... | ... | @@ -31,10 +32,12 @@ static int print_full_usage(const char *arg0) { |
| 31 | 32 | " build-lib [source] create library from source or object files\n" |
| 32 | 33 | " build-obj [source] create object from source or assembly\n" |
| 33 | 34 | " builtin show the source code of that @import(\"builtin\")\n" |
| 34 | " help show this usage information\n" | |
| 35 | " cc C compiler\n" | |
| 36 | " fmt parse files and render in canonical zig format\n" | |
| 35 | 37 | " id print the base64-encoded compiler id\n" |
| 36 | 38 | " init-exe initialize a `zig build` application in the cwd\n" |
| 37 | 39 | " init-lib initialize a `zig build` library in the cwd\n" |
| 40 | " libc [paths_file] Display native libc paths file or validate one\n" | |
| 38 | 41 | " run [source] create executable and run immediately\n" |
| 39 | 42 | " translate-c [source] convert c code to zig code\n" |
| 40 | 43 | " targets list available compilation targets\n" |
| ... | ... | @@ -44,16 +47,20 @@ static int print_full_usage(const char *arg0) { |
| 44 | 47 | "\n" |
| 45 | 48 | "Compile Options:\n" |
| 46 | 49 | " --assembly [source] add assembly file to build\n" |
| 50 | " --c-source [options] [file] compile C source code\n" | |
| 47 | 51 | " --cache-dir [path] override the cache directory\n" |
| 48 | 52 | " --cache [auto|off|on] build in global cache, print out paths to stdout\n" |
| 49 | 53 | " --color [auto|off|on] enable or disable colored error messages\n" |
| 50 | 54 | " --disable-pic disable Position Independent Code for libraries\n" |
| 55 | " --disable-valgrind omit valgrind client requests in debug builds\n" | |
| 56 | " --enable-valgrind include valgrind client requests release builds\n" | |
| 51 | 57 | " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" |
| 52 | 58 | " -ftime-report print timing diagnostics\n" |
| 53 | " --libc-include-dir [path] directory where libc stdlib.h resides\n" | |
| 59 | " --libc [file] Provide a file which specifies libc paths\n" | |
| 54 | 60 | " --name [name] override output name\n" |
| 55 | 61 | " --output [file] override destination path\n" |
| 56 | 62 | " --output-h [file] generate header file\n" |
| 63 | " --output-lib [file] override import library path\n" | |
| 57 | 64 | " --pkg-begin [name] [path] make pkg available to import and push current pkg\n" |
| 58 | 65 | " --pkg-end pop current pkg\n" |
| 59 | 66 | " --release-fast build with optimizations on and safety off\n" |
| ... | ... | @@ -62,15 +69,14 @@ static int print_full_usage(const char *arg0) { |
| 62 | 69 | " --single-threaded source may assume it is only used single-threaded\n" |
| 63 | 70 | " --static output will be statically linked\n" |
| 64 | 71 | " --strip exclude debug symbols\n" |
| 65 | " --target-arch [name] specify target architecture\n" | |
| 66 | " --target-environ [name] specify target environment\n" | |
| 67 | " --target-os [name] specify target operating system\n" | |
| 72 | " -target [name] <arch><sub>-<os>-<abi> see the targets command\n" | |
| 68 | 73 | " --verbose-tokenize enable compiler debug output for tokenization\n" |
| 69 | 74 | " --verbose-ast enable compiler debug output for AST parsing\n" |
| 70 | 75 | " --verbose-link enable compiler debug output for linking\n" |
| 71 | 76 | " --verbose-ir enable compiler debug output for Zig IR\n" |
| 72 | 77 | " --verbose-llvm-ir enable compiler debug output for LLVM IR\n" |
| 73 | 78 | " --verbose-cimport enable compiler debug output for C imports\n" |
| 79 | " --verbose-cc enable compiler debug output for C compilation\n" | |
| 74 | 80 | " -dirafter [dir] same as -isystem but do it last\n" |
| 75 | 81 | " -isystem [dir] add additional search path for other .h files\n" |
| 76 | 82 | " -mllvm [arg] forward an arg to LLVM's option processing\n" |
| ... | ... | @@ -79,10 +85,6 @@ static int print_full_usage(const char *arg0) { |
| 79 | 85 | "Link Options:\n" |
| 80 | 86 | " --dynamic-linker [path] set the path to ld.so\n" |
| 81 | 87 | " --each-lib-rpath add rpath for each used dynamic library\n" |
| 82 | " --libc-lib-dir [path] directory where libc crt1.o resides\n" | |
| 83 | " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n" | |
| 84 | " --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides\n" | |
| 85 | " --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides\n" | |
| 86 | 88 | " --library [lib] link against lib\n" |
| 87 | 89 | " --forbid-library [lib] make it an error to link against lib\n" |
| 88 | 90 | " --library-path [dir] add a directory to the library search path\n" |
| ... | ... | @@ -91,7 +93,6 @@ static int print_full_usage(const char *arg0) { |
| 91 | 93 | " -L[dir] alias for --library-path\n" |
| 92 | 94 | " -rdynamic add all symbols to the dynamic symbol table\n" |
| 93 | 95 | " -rpath [path] add directory to the runtime library search path\n" |
| 94 | " --no-rosegment compromise security to workaround valgrind bug\n" | |
| 95 | 96 | " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n" |
| 96 | 97 | " -framework [name] (darwin) link against framework\n" |
| 97 | 98 | " -mios-version-min [ver] (darwin) set iOS deployment target\n" |
| ... | ... | @@ -106,7 +107,27 @@ static int print_full_usage(const char *arg0) { |
| 106 | 107 | " --test-cmd [arg] specify test execution command one arg at a time\n" |
| 107 | 108 | " --test-cmd-bin appends test binary path to test cmd args\n" |
| 108 | 109 | , arg0); |
| 109 | return EXIT_SUCCESS; | |
| 110 | return return_code; | |
| 111 | } | |
| 112 | ||
| 113 | static int print_libc_usage(const char *arg0, FILE *file, int return_code) { | |
| 114 | fprintf(file, | |
| 115 | "Usage: %s libc\n" | |
| 116 | "\n" | |
| 117 | "Detect the native libc installation and print the resulting paths to stdout.\n" | |
| 118 | "You can save this into a file and then edit the paths to create a cross\n" | |
| 119 | "compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n" | |
| 120 | "\n" | |
| 121 | "When compiling natively and no `--libc` argument provided, Zig automatically\n" | |
| 122 | "creates zig-cache/native_libc.txt so that it does not have to detect libc\n" | |
| 123 | "on every invocation. You can remove this file to have Zig re-detect the\n" | |
| 124 | "native libc.\n" | |
| 125 | "\n\n" | |
| 126 | "Usage: %s libc [file]\n" | |
| 127 | "\n" | |
| 128 | "Parse a libc installation text file and validate it.\n" | |
| 129 | , arg0, arg0); | |
| 130 | return return_code; | |
| 110 | 131 | } |
| 111 | 132 | |
| 112 | 133 | static const char *ZIG_ZEN = "\n" |
| ... | ... | @@ -122,6 +143,14 @@ static const char *ZIG_ZEN = "\n" |
| 122 | 143 | " * Minimize energy spent on coding style.\n" |
| 123 | 144 | " * Together we serve end users.\n"; |
| 124 | 145 | |
| 146 | static bool arch_available_in_llvm(ZigLLVM_ArchType arch) { | |
| 147 | LLVMTargetRef target_ref; | |
| 148 | char *err_msg = nullptr; | |
| 149 | char triple_string[128]; | |
| 150 | sprintf(triple_string, "%s-unknown-unknown-unknown", ZigLLVMGetArchTypeName(arch)); | |
| 151 | return !LLVMGetTargetFromTriple(triple_string, &target_ref, &err_msg); | |
| 152 | } | |
| 153 | ||
| 125 | 154 | static int print_target_list(FILE *f) { |
| 126 | 155 | ZigTarget native; |
| 127 | 156 | get_native_target(&native); |
| ... | ... | @@ -129,28 +158,36 @@ static int print_target_list(FILE *f) { |
| 129 | 158 | fprintf(f, "Architectures:\n"); |
| 130 | 159 | size_t arch_count = target_arch_count(); |
| 131 | 160 | for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) { |
| 132 | const ArchType *arch = get_target_arch(arch_i); | |
| 133 | char arch_name[50]; | |
| 134 | get_arch_name(arch_name, arch); | |
| 135 | const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ? | |
| 136 | " (native)" : ""; | |
| 137 | fprintf(f, " %s%s\n", arch_name, native_str); | |
| 161 | ZigLLVM_ArchType arch = target_arch_enum(arch_i); | |
| 162 | if (!arch_available_in_llvm(arch)) | |
| 163 | continue; | |
| 164 | const char *arch_name = target_arch_name(arch); | |
| 165 | SubArchList sub_arch_list = target_subarch_list(arch); | |
| 166 | size_t sub_count = target_subarch_count(sub_arch_list); | |
| 167 | const char *arch_native_str = (native.arch == arch) ? " (native)" : ""; | |
| 168 | fprintf(stderr, " %s%s\n", arch_name, arch_native_str); | |
| 169 | for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) { | |
| 170 | ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); | |
| 171 | const char *sub_name = target_subarch_name(sub); | |
| 172 | const char *sub_native_str = (native.arch == arch && native.sub_arch == sub) ? " (native)" : ""; | |
| 173 | fprintf(f, " %s%s\n", sub_name, sub_native_str); | |
| 174 | } | |
| 138 | 175 | } |
| 139 | 176 | |
| 140 | 177 | fprintf(f, "\nOperating Systems:\n"); |
| 141 | 178 | size_t os_count = target_os_count(); |
| 142 | 179 | for (size_t i = 0; i < os_count; i += 1) { |
| 143 | Os os_type = get_target_os(i); | |
| 180 | Os os_type = target_os_enum(i); | |
| 144 | 181 | const char *native_str = (native.os == os_type) ? " (native)" : ""; |
| 145 | fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str); | |
| 182 | fprintf(f, " %s%s\n", target_os_name(os_type), native_str); | |
| 146 | 183 | } |
| 147 | 184 | |
| 148 | fprintf(f, "\nEnvironments:\n"); | |
| 149 | size_t environ_count = target_environ_count(); | |
| 150 | for (size_t i = 0; i < environ_count; i += 1) { | |
| 151 | ZigLLVM_EnvironmentType environ_type = get_target_environ(i); | |
| 152 | const char *native_str = (native.env_type == environ_type) ? " (native)" : ""; | |
| 153 | fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str); | |
| 185 | fprintf(f, "\nC ABIs:\n"); | |
| 186 | size_t abi_count = target_abi_count(); | |
| 187 | for (size_t i = 0; i < abi_count; i += 1) { | |
| 188 | ZigLLVM_EnvironmentType abi = target_abi_enum(i); | |
| 189 | const char *native_str = (native.abi == abi) ? " (native)" : ""; | |
| 190 | fprintf(f, " %s%s\n", target_abi_name(abi), native_str); | |
| 154 | 191 | } |
| 155 | 192 | |
| 156 | 193 | return EXIT_SUCCESS; |
| ... | ... | @@ -160,13 +197,13 @@ enum Cmd { |
| 160 | 197 | CmdNone, |
| 161 | 198 | CmdBuild, |
| 162 | 199 | CmdBuiltin, |
| 163 | CmdHelp, | |
| 164 | 200 | CmdRun, |
| 165 | 201 | CmdTargets, |
| 166 | 202 | CmdTest, |
| 167 | 203 | CmdTranslateC, |
| 168 | 204 | CmdVersion, |
| 169 | 205 | CmdZen, |
| 206 | CmdLibC, | |
| 170 | 207 | }; |
| 171 | 208 | |
| 172 | 209 | static const char *default_zig_cache_name = "zig-cache"; |
| ... | ... | @@ -219,6 +256,8 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) { |
| 219 | 256 | zig_unreachable(); |
| 220 | 257 | } |
| 221 | 258 | |
| 259 | extern "C" int ZigClang_main(int argc, char **argv); | |
| 260 | ||
| 222 | 261 | int main(int argc, char **argv) { |
| 223 | 262 | char *arg0 = argv[0]; |
| 224 | 263 | Error err; |
| ... | ... | @@ -236,6 +275,12 @@ int main(int argc, char **argv) { |
| 236 | 275 | return 0; |
| 237 | 276 | } |
| 238 | 277 | |
| 278 | if (argc >= 2 && (strcmp(argv[1], "cc") == 0 || | |
| 279 | strcmp(argv[1], "-cc1") == 0 || strcmp(argv[1], "-cc1as") == 0)) | |
| 280 | { | |
| 281 | return ZigClang_main(argc, argv); | |
| 282 | } | |
| 283 | ||
| 239 | 284 | // Must be before all os.hpp function calls. |
| 240 | 285 | os_init(); |
| 241 | 286 | |
| ... | ... | @@ -345,6 +390,7 @@ int main(int argc, char **argv) { |
| 345 | 390 | const char *in_file = nullptr; |
| 346 | 391 | const char *out_file = nullptr; |
| 347 | 392 | const char *out_file_h = nullptr; |
| 393 | const char *out_file_lib = nullptr; | |
| 348 | 394 | bool strip = false; |
| 349 | 395 | bool is_static = false; |
| 350 | 396 | OutType out_type = OutTypeUnknown; |
| ... | ... | @@ -355,23 +401,17 @@ int main(int argc, char **argv) { |
| 355 | 401 | bool verbose_ir = false; |
| 356 | 402 | bool verbose_llvm_ir = false; |
| 357 | 403 | bool verbose_cimport = false; |
| 404 | bool verbose_cc = false; | |
| 358 | 405 | ErrColor color = ErrColorAuto; |
| 359 | 406 | CacheOpt enable_cache = CacheOptAuto; |
| 360 | const char *libc_lib_dir = nullptr; | |
| 361 | const char *libc_static_lib_dir = nullptr; | |
| 362 | const char *libc_include_dir = nullptr; | |
| 363 | const char *msvc_lib_dir = nullptr; | |
| 364 | const char *kernel32_lib_dir = nullptr; | |
| 365 | const char *dynamic_linker = nullptr; | |
| 407 | const char *libc_txt = nullptr; | |
| 366 | 408 | ZigList<const char *> clang_argv = {0}; |
| 367 | 409 | ZigList<const char *> llvm_argv = {0}; |
| 368 | 410 | ZigList<const char *> lib_dirs = {0}; |
| 369 | 411 | ZigList<const char *> link_libs = {0}; |
| 370 | 412 | ZigList<const char *> forbidden_link_libs = {0}; |
| 371 | 413 | ZigList<const char *> frameworks = {0}; |
| 372 | const char *target_arch = nullptr; | |
| 373 | const char *target_os = nullptr; | |
| 374 | const char *target_environ = nullptr; | |
| 414 | const char *target_string = nullptr; | |
| 375 | 415 | bool rdynamic = false; |
| 376 | 416 | const char *mmacosx_version_min = nullptr; |
| 377 | 417 | const char *mios_version_min = nullptr; |
| ... | ... | @@ -379,6 +419,7 @@ int main(int argc, char **argv) { |
| 379 | 419 | ZigList<const char *> rpath_list = {0}; |
| 380 | 420 | bool each_lib_rpath = false; |
| 381 | 421 | ZigList<const char *> objects = {0}; |
| 422 | ZigList<CFile *> c_source_files = {0}; | |
| 382 | 423 | ZigList<const char *> asm_files = {0}; |
| 383 | 424 | const char *test_filter = nullptr; |
| 384 | 425 | const char *test_name_prefix = nullptr; |
| ... | ... | @@ -392,11 +433,11 @@ int main(int argc, char **argv) { |
| 392 | 433 | BuildMode build_mode = BuildModeDebug; |
| 393 | 434 | ZigList<const char *> test_exec_args = {0}; |
| 394 | 435 | int runtime_args_start = -1; |
| 395 | bool no_rosegment_workaround = false; | |
| 396 | 436 | bool system_linker_hack = false; |
| 397 | 437 | TargetSubsystem subsystem = TargetSubsystemAuto; |
| 398 | 438 | bool is_single_threaded = false; |
| 399 | 439 | Buf *override_std_dir = nullptr; |
| 440 | ValgrindSupport valgrind_support = ValgrindSupportAuto; | |
| 400 | 441 | |
| 401 | 442 | if (argc >= 2 && strcmp(argv[1], "build") == 0) { |
| 402 | 443 | Buf zig_exe_path_buf = BUF_INIT; |
| ... | ... | @@ -432,8 +473,11 @@ int main(int argc, char **argv) { |
| 432 | 473 | Buf *build_runner_path = buf_alloc(); |
| 433 | 474 | os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path); |
| 434 | 475 | |
| 435 | CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), | |
| 436 | override_std_dir); | |
| 476 | ZigTarget target; | |
| 477 | get_native_target(&target); | |
| 478 | CodeGen *g = codegen_create(build_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), | |
| 479 | override_std_dir, nullptr); | |
| 480 | g->valgrind_support = valgrind_support; | |
| 437 | 481 | g->enable_time_report = timing_info; |
| 438 | 482 | buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name); |
| 439 | 483 | codegen_set_out_name(g, buf_create_from_str("build")); |
| ... | ... | @@ -484,6 +528,7 @@ int main(int argc, char **argv) { |
| 484 | 528 | " --verbose-ir Enable compiler debug output for Zig IR\n" |
| 485 | 529 | " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n" |
| 486 | 530 | " --verbose-cimport Enable compiler debug output for C imports\n" |
| 531 | " --verbose-cc Enable compiler debug output for C compilation\n" | |
| 487 | 532 | "\n" |
| 488 | 533 | , zig_exe_path); |
| 489 | 534 | return EXIT_SUCCESS; |
| ... | ... | @@ -493,7 +538,7 @@ int main(int argc, char **argv) { |
| 493 | 538 | "No 'build.zig' file found.\n" |
| 494 | 539 | "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n" |
| 495 | 540 | "or build an executable directly with `zig build-exe $FILENAME.zig`.\n" |
| 496 | "See: `zig build --help` or `zig help` for more options.\n" | |
| 541 | "See: `zig build --help` or `zig --help` for more options.\n" | |
| 497 | 542 | ); |
| 498 | 543 | return EXIT_FAILURE; |
| 499 | 544 | } |
| ... | ... | @@ -515,6 +560,37 @@ int main(int argc, char **argv) { |
| 515 | 560 | fprintf(stderr, "\n"); |
| 516 | 561 | } |
| 517 | 562 | return (term.how == TerminationIdClean) ? term.code : -1; |
| 563 | } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) { | |
| 564 | init_all_targets(); | |
| 565 | ZigTarget target; | |
| 566 | get_native_target(&target); | |
| 567 | Buf *fmt_runner_path = buf_alloc(); | |
| 568 | os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path); | |
| 569 | CodeGen *g = codegen_create(fmt_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), | |
| 570 | nullptr, nullptr); | |
| 571 | buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name); | |
| 572 | g->valgrind_support = valgrind_support; | |
| 573 | g->is_single_threaded = true; | |
| 574 | codegen_set_out_name(g, buf_create_from_str("fmt")); | |
| 575 | g->enable_cache = true; | |
| 576 | ||
| 577 | codegen_build_and_link(g); | |
| 578 | ||
| 579 | // TODO standardize os.cpp so that the args are supposed to have the exe | |
| 580 | ZigList<const char*> args_with_exe = {0}; | |
| 581 | ZigList<const char*> args_without_exe = {0}; | |
| 582 | const char *exec_path = buf_ptr(&g->output_file_path); | |
| 583 | args_with_exe.append(exec_path); | |
| 584 | for (int i = 2; i < argc; i += 1) { | |
| 585 | args_with_exe.append(argv[i]); | |
| 586 | args_without_exe.append(argv[i]); | |
| 587 | } | |
| 588 | args_with_exe.append(nullptr); | |
| 589 | os_execv(exec_path, args_with_exe.items); | |
| 590 | ||
| 591 | Termination term; | |
| 592 | os_spawn_process(exec_path, args_without_exe, &term); | |
| 593 | return term.code; | |
| 518 | 594 | } |
| 519 | 595 | |
| 520 | 596 | for (int i = 1; i < argc; i += 1) { |
| ... | ... | @@ -527,6 +603,12 @@ int main(int argc, char **argv) { |
| 527 | 603 | build_mode = BuildModeSafeRelease; |
| 528 | 604 | } else if (strcmp(arg, "--release-small") == 0) { |
| 529 | 605 | build_mode = BuildModeSmallRelease; |
| 606 | } else if (strcmp(arg, "--help") == 0) { | |
| 607 | if (cmd == CmdLibC) { | |
| 608 | return print_libc_usage(arg0, stdout, EXIT_SUCCESS); | |
| 609 | } else { | |
| 610 | return print_full_usage(arg0, stdout, EXIT_SUCCESS); | |
| 611 | } | |
| 530 | 612 | } else if (strcmp(arg, "--strip") == 0) { |
| 531 | 613 | strip = true; |
| 532 | 614 | } else if (strcmp(arg, "--static") == 0) { |
| ... | ... | @@ -543,16 +625,20 @@ int main(int argc, char **argv) { |
| 543 | 625 | verbose_llvm_ir = true; |
| 544 | 626 | } else if (strcmp(arg, "--verbose-cimport") == 0) { |
| 545 | 627 | verbose_cimport = true; |
| 628 | } else if (strcmp(arg, "--verbose-cc") == 0) { | |
| 629 | verbose_cc = true; | |
| 546 | 630 | } else if (strcmp(arg, "-rdynamic") == 0) { |
| 547 | 631 | rdynamic = true; |
| 548 | } else if (strcmp(arg, "--no-rosegment") == 0) { | |
| 549 | no_rosegment_workaround = true; | |
| 550 | 632 | } else if (strcmp(arg, "--each-lib-rpath") == 0) { |
| 551 | 633 | each_lib_rpath = true; |
| 552 | 634 | } else if (strcmp(arg, "-ftime-report") == 0) { |
| 553 | 635 | timing_info = true; |
| 554 | 636 | } else if (strcmp(arg, "--disable-pic") == 0) { |
| 555 | 637 | disable_pic = true; |
| 638 | } else if (strcmp(arg, "--enable-valgrind") == 0) { | |
| 639 | valgrind_support = ValgrindSupportEnabled; | |
| 640 | } else if (strcmp(arg, "--disable-valgrind") == 0) { | |
| 641 | valgrind_support = ValgrindSupportDisabled; | |
| 556 | 642 | } else if (strcmp(arg, "--system-linker-hack") == 0) { |
| 557 | 643 | system_linker_hack = true; |
| 558 | 644 | } else if (strcmp(arg, "--single-threaded") == 0) { |
| ... | ... | @@ -590,6 +676,8 @@ int main(int argc, char **argv) { |
| 590 | 676 | out_file = argv[i]; |
| 591 | 677 | } else if (strcmp(arg, "--output-h") == 0) { |
| 592 | 678 | out_file_h = argv[i]; |
| 679 | } else if (strcmp(arg, "--output-lib") == 0) { | |
| 680 | out_file_lib = argv[i]; | |
| 593 | 681 | } else if (strcmp(arg, "--color") == 0) { |
| 594 | 682 | if (strcmp(argv[i], "auto") == 0) { |
| 595 | 683 | color = ErrColorAuto; |
| ... | ... | @@ -625,18 +713,8 @@ int main(int argc, char **argv) { |
| 625 | 713 | } |
| 626 | 714 | } else if (strcmp(arg, "--name") == 0) { |
| 627 | 715 | out_name = argv[i]; |
| 628 | } else if (strcmp(arg, "--libc-lib-dir") == 0) { | |
| 629 | libc_lib_dir = argv[i]; | |
| 630 | } else if (strcmp(arg, "--libc-static-lib-dir") == 0) { | |
| 631 | libc_static_lib_dir = argv[i]; | |
| 632 | } else if (strcmp(arg, "--libc-include-dir") == 0) { | |
| 633 | libc_include_dir = argv[i]; | |
| 634 | } else if (strcmp(arg, "--msvc-lib-dir") == 0) { | |
| 635 | msvc_lib_dir = argv[i]; | |
| 636 | } else if (strcmp(arg, "--kernel32-lib-dir") == 0) { | |
| 637 | kernel32_lib_dir = argv[i]; | |
| 638 | } else if (strcmp(arg, "--dynamic-linker") == 0) { | |
| 639 | dynamic_linker = argv[i]; | |
| 716 | } else if (strcmp(arg, "--libc") == 0) { | |
| 717 | libc_txt = argv[i]; | |
| 640 | 718 | } else if (strcmp(arg, "-isystem") == 0) { |
| 641 | 719 | clang_argv.append("-isystem"); |
| 642 | 720 | clang_argv.append(argv[i]); |
| ... | ... | @@ -658,16 +736,25 @@ int main(int argc, char **argv) { |
| 658 | 736 | forbidden_link_libs.append(argv[i]); |
| 659 | 737 | } else if (strcmp(arg, "--object") == 0) { |
| 660 | 738 | objects.append(argv[i]); |
| 739 | } else if (strcmp(arg, "--c-source") == 0) { | |
| 740 | CFile *c_file = allocate<CFile>(1); | |
| 741 | for (;;) { | |
| 742 | if (argv[i][0] == '-') { | |
| 743 | c_file->args.append(argv[i]); | |
| 744 | i += 1; | |
| 745 | continue; | |
| 746 | } else { | |
| 747 | c_file->source_path = argv[i]; | |
| 748 | c_source_files.append(c_file); | |
| 749 | break; | |
| 750 | } | |
| 751 | } | |
| 661 | 752 | } else if (strcmp(arg, "--assembly") == 0) { |
| 662 | 753 | asm_files.append(argv[i]); |
| 663 | 754 | } else if (strcmp(arg, "--cache-dir") == 0) { |
| 664 | 755 | cache_dir = argv[i]; |
| 665 | } else if (strcmp(arg, "--target-arch") == 0) { | |
| 666 | target_arch = argv[i]; | |
| 667 | } else if (strcmp(arg, "--target-os") == 0) { | |
| 668 | target_os = argv[i]; | |
| 669 | } else if (strcmp(arg, "--target-environ") == 0) { | |
| 670 | target_environ = argv[i]; | |
| 756 | } else if (strcmp(arg, "-target") == 0) { | |
| 757 | target_string = argv[i]; | |
| 671 | 758 | } else if (strcmp(arg, "-mmacosx-version-min") == 0) { |
| 672 | 759 | mmacosx_version_min = argv[i]; |
| 673 | 760 | } else if (strcmp(arg, "-mios-version-min") == 0) { |
| ... | ... | @@ -736,8 +823,6 @@ int main(int argc, char **argv) { |
| 736 | 823 | } else if (strcmp(arg, "build-lib") == 0) { |
| 737 | 824 | cmd = CmdBuild; |
| 738 | 825 | out_type = OutTypeLib; |
| 739 | } else if (strcmp(arg, "help") == 0) { | |
| 740 | cmd = CmdHelp; | |
| 741 | 826 | } else if (strcmp(arg, "run") == 0) { |
| 742 | 827 | cmd = CmdRun; |
| 743 | 828 | out_type = OutTypeExe; |
| ... | ... | @@ -745,6 +830,8 @@ int main(int argc, char **argv) { |
| 745 | 830 | cmd = CmdVersion; |
| 746 | 831 | } else if (strcmp(arg, "zen") == 0) { |
| 747 | 832 | cmd = CmdZen; |
| 833 | } else if (strcmp(arg, "libc") == 0) { | |
| 834 | cmd = CmdLibC; | |
| 748 | 835 | } else if (strcmp(arg, "translate-c") == 0) { |
| 749 | 836 | cmd = CmdTranslateC; |
| 750 | 837 | } else if (strcmp(arg, "test") == 0) { |
| ... | ... | @@ -764,6 +851,7 @@ int main(int argc, char **argv) { |
| 764 | 851 | case CmdRun: |
| 765 | 852 | case CmdTranslateC: |
| 766 | 853 | case CmdTest: |
| 854 | case CmdLibC: | |
| 767 | 855 | if (!in_file) { |
| 768 | 856 | in_file = arg; |
| 769 | 857 | if (cmd == CmdRun) { |
| ... | ... | @@ -776,7 +864,6 @@ int main(int argc, char **argv) { |
| 776 | 864 | } |
| 777 | 865 | break; |
| 778 | 866 | case CmdBuiltin: |
| 779 | case CmdHelp: | |
| 780 | 867 | case CmdVersion: |
| 781 | 868 | case CmdZen: |
| 782 | 869 | case CmdTargets: |
| ... | ... | @@ -795,36 +882,34 @@ int main(int argc, char **argv) { |
| 795 | 882 | |
| 796 | 883 | init_all_targets(); |
| 797 | 884 | |
| 798 | ZigTarget alloc_target; | |
| 799 | ZigTarget *target; | |
| 800 | if (!target_arch && !target_os && !target_environ) { | |
| 801 | target = nullptr; | |
| 885 | ZigTarget target; | |
| 886 | if (target_string == nullptr) { | |
| 887 | get_native_target(&target); | |
| 802 | 888 | } else { |
| 803 | target = &alloc_target; | |
| 804 | get_unknown_target(target); | |
| 805 | if (target_arch) { | |
| 806 | if (parse_target_arch(target_arch, &target->arch)) { | |
| 807 | fprintf(stderr, "invalid --target-arch argument\n"); | |
| 808 | return print_error_usage(arg0); | |
| 809 | } | |
| 810 | } | |
| 811 | if (target_os) { | |
| 812 | if (parse_target_os(target_os, &target->os)) { | |
| 813 | fprintf(stderr, "invalid --target-os argument\n"); | |
| 814 | return print_error_usage(arg0); | |
| 815 | } | |
| 816 | } | |
| 817 | if (target_environ) { | |
| 818 | if (parse_target_environ(target_environ, &target->env_type)) { | |
| 819 | fprintf(stderr, "invalid --target-environ argument\n"); | |
| 820 | return print_error_usage(arg0); | |
| 821 | } | |
| 889 | if ((err = target_parse_triple(&target, target_string))) { | |
| 890 | fprintf(stderr, "invalid target: %s\n", err_str(err)); | |
| 891 | return print_error_usage(arg0); | |
| 822 | 892 | } |
| 823 | 893 | } |
| 824 | 894 | |
| 825 | 895 | switch (cmd) { |
| 896 | case CmdLibC: { | |
| 897 | if (in_file) { | |
| 898 | ZigLibCInstallation libc; | |
| 899 | if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true))) | |
| 900 | return EXIT_FAILURE; | |
| 901 | return EXIT_SUCCESS; | |
| 902 | } | |
| 903 | ZigLibCInstallation libc; | |
| 904 | if ((err = zig_libc_find_native(&libc, true))) | |
| 905 | return EXIT_FAILURE; | |
| 906 | zig_libc_render(&libc, stdout); | |
| 907 | return EXIT_SUCCESS; | |
| 908 | } | |
| 826 | 909 | case CmdBuiltin: { |
| 827 | CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir); | |
| 910 | CodeGen *g = codegen_create(nullptr, &target, out_type, build_mode, get_zig_lib_dir(), override_std_dir, | |
| 911 | nullptr); | |
| 912 | g->valgrind_support = valgrind_support; | |
| 828 | 913 | g->is_single_threaded = is_single_threaded; |
| 829 | 914 | Buf *builtin_source = codegen_generate_builtin_source(g); |
| 830 | 915 | if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { |
| ... | ... | @@ -838,15 +923,43 @@ int main(int argc, char **argv) { |
| 838 | 923 | case CmdTranslateC: |
| 839 | 924 | case CmdTest: |
| 840 | 925 | { |
| 841 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) { | |
| 842 | fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n"); | |
| 926 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 && | |
| 927 | c_source_files.length == 0) | |
| 928 | { | |
| 929 | fprintf(stderr, | |
| 930 | "Expected at least one of these things:\n" | |
| 931 | " * Zig root source file argument\n" | |
| 932 | " * --object argument\n" | |
| 933 | " * --assembly argument\n" | |
| 934 | " * --c-source argument\n"); | |
| 843 | 935 | return print_error_usage(arg0); |
| 844 | 936 | } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) { |
| 845 | 937 | fprintf(stderr, "Expected source file argument.\n"); |
| 846 | 938 | return print_error_usage(arg0); |
| 847 | } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) { | |
| 848 | fprintf(stderr, "When building an object file, --object arguments are invalid.\n"); | |
| 849 | return print_error_usage(arg0); | |
| 939 | } else if (cmd == CmdBuild && out_type == OutTypeObj) { | |
| 940 | if (objects.length != 0) { | |
| 941 | fprintf(stderr, | |
| 942 | "When building an object file, --object arguments are invalid.\n" | |
| 943 | "Consider building a static library instead.\n"); | |
| 944 | return print_error_usage(arg0); | |
| 945 | } | |
| 946 | size_t zig_root_src_count = in_file ? 1 : 0; | |
| 947 | if (zig_root_src_count + c_source_files.length > 1) { | |
| 948 | fprintf(stderr, | |
| 949 | "When building an object file, only one of these allowed:\n" | |
| 950 | " * Zig root source file argument\n" | |
| 951 | " * --c-source argument\n" | |
| 952 | "Consider building a static library instead.\n"); | |
| 953 | return print_error_usage(arg0); | |
| 954 | } | |
| 955 | if (c_source_files.length != 0 && asm_files.length != 0) { | |
| 956 | fprintf(stderr, | |
| 957 | "When building an object file, only one of these allowed:\n" | |
| 958 | " * --assembly argument\n" | |
| 959 | " * --c-source argument\n" | |
| 960 | "Consider building a static library instead.\n"); | |
| 961 | return print_error_usage(arg0); | |
| 962 | } | |
| 850 | 963 | } |
| 851 | 964 | |
| 852 | 965 | assert(cmd != CmdBuild || out_type != OutTypeUnknown); |
| ... | ... | @@ -873,6 +986,13 @@ int main(int argc, char **argv) { |
| 873 | 986 | } |
| 874 | 987 | } |
| 875 | 988 | |
| 989 | if (need_name && buf_out_name == nullptr && c_source_files.length == 1) { | |
| 990 | Buf basename = BUF_INIT; | |
| 991 | os_path_split(buf_create_from_str(c_source_files.at(0)->source_path), nullptr, &basename); | |
| 992 | buf_out_name = buf_alloc(); | |
| 993 | os_path_extname(&basename, buf_out_name, nullptr); | |
| 994 | } | |
| 995 | ||
| 876 | 996 | if (need_name && buf_out_name == nullptr) { |
| 877 | 997 | fprintf(stderr, "--name [name] not provided and unable to infer\n\n"); |
| 878 | 998 | return print_error_usage(arg0); |
| ... | ... | @@ -883,8 +1003,17 @@ int main(int argc, char **argv) { |
| 883 | 1003 | if (cmd == CmdRun && buf_out_name == nullptr) { |
| 884 | 1004 | buf_out_name = buf_create_from_str("run"); |
| 885 | 1005 | } |
| 886 | CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(), | |
| 887 | override_std_dir); | |
| 1006 | ZigLibCInstallation *libc = nullptr; | |
| 1007 | if (libc_txt != nullptr) { | |
| 1008 | libc = allocate<ZigLibCInstallation>(1); | |
| 1009 | if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) { | |
| 1010 | fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err)); | |
| 1011 | return EXIT_FAILURE; | |
| 1012 | } | |
| 1013 | } | |
| 1014 | CodeGen *g = codegen_create(zig_root_source_file, &target, out_type, build_mode, get_zig_lib_dir(), | |
| 1015 | override_std_dir, libc); | |
| 1016 | g->valgrind_support = valgrind_support; | |
| 888 | 1017 | g->subsystem = subsystem; |
| 889 | 1018 | |
| 890 | 1019 | if (disable_pic) { |
| ... | ... | @@ -909,24 +1038,13 @@ int main(int argc, char **argv) { |
| 909 | 1038 | codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length); |
| 910 | 1039 | codegen_set_strip(g, strip); |
| 911 | 1040 | codegen_set_is_static(g, is_static); |
| 912 | if (libc_lib_dir) | |
| 913 | codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir)); | |
| 914 | if (libc_static_lib_dir) | |
| 915 | codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir)); | |
| 916 | if (libc_include_dir) | |
| 917 | codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir)); | |
| 918 | if (msvc_lib_dir) | |
| 919 | codegen_set_msvc_lib_dir(g, buf_create_from_str(msvc_lib_dir)); | |
| 920 | if (kernel32_lib_dir) | |
| 921 | codegen_set_kernel32_lib_dir(g, buf_create_from_str(kernel32_lib_dir)); | |
| 922 | if (dynamic_linker) | |
| 923 | codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); | |
| 924 | 1041 | g->verbose_tokenize = verbose_tokenize; |
| 925 | 1042 | g->verbose_ast = verbose_ast; |
| 926 | 1043 | g->verbose_link = verbose_link; |
| 927 | 1044 | g->verbose_ir = verbose_ir; |
| 928 | 1045 | g->verbose_llvm_ir = verbose_llvm_ir; |
| 929 | 1046 | g->verbose_cimport = verbose_cimport; |
| 1047 | g->verbose_cc = verbose_cc; | |
| 930 | 1048 | codegen_set_errmsg_color(g, color); |
| 931 | 1049 | g->system_linker_hack = system_linker_hack; |
| 932 | 1050 | |
| ... | ... | @@ -949,7 +1067,6 @@ int main(int argc, char **argv) { |
| 949 | 1067 | } |
| 950 | 1068 | |
| 951 | 1069 | codegen_set_rdynamic(g, rdynamic); |
| 952 | g->no_rosegment_workaround = no_rosegment_workaround; | |
| 953 | 1070 | if (mmacosx_version_min && mios_version_min) { |
| 954 | 1071 | fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n"); |
| 955 | 1072 | return EXIT_FAILURE; |
| ... | ... | @@ -975,11 +1092,14 @@ int main(int argc, char **argv) { |
| 975 | 1092 | codegen_set_output_path(g, buf_create_from_str(out_file)); |
| 976 | 1093 | if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib)) |
| 977 | 1094 | codegen_set_output_h_path(g, buf_create_from_str(out_file_h)); |
| 1095 | if (out_file_lib != nullptr && out_type == OutTypeLib && !is_static) | |
| 1096 | codegen_set_output_lib_path(g, buf_create_from_str(out_file_lib)); | |
| 978 | 1097 | |
| 979 | 1098 | |
| 980 | 1099 | add_package(g, cur_pkg, g->root_package); |
| 981 | 1100 | |
| 982 | 1101 | if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) { |
| 1102 | g->c_source_files = c_source_files; | |
| 983 | 1103 | for (size_t i = 0; i < objects.length; i += 1) { |
| 984 | 1104 | codegen_add_object(g, buf_create_from_str(objects.at(i))); |
| 985 | 1105 | } |
| ... | ... | @@ -1052,7 +1172,7 @@ int main(int argc, char **argv) { |
| 1052 | 1172 | } |
| 1053 | 1173 | } |
| 1054 | 1174 | |
| 1055 | if (!target_can_exec(&native, target)) { | |
| 1175 | if (!target_can_exec(&native, &target)) { | |
| 1056 | 1176 | fprintf(stderr, "Created %s but skipping execution because it is non-native.\n", |
| 1057 | 1177 | buf_ptr(test_exe_path)); |
| 1058 | 1178 | return 0; |
| ... | ... | @@ -1079,8 +1199,6 @@ int main(int argc, char **argv) { |
| 1079 | 1199 | zig_unreachable(); |
| 1080 | 1200 | } |
| 1081 | 1201 | } |
| 1082 | case CmdHelp: | |
| 1083 | return print_full_usage(arg0); | |
| 1084 | 1202 | case CmdVersion: |
| 1085 | 1203 | printf("%s\n", ZIG_VERSION_STRING); |
| 1086 | 1204 | return EXIT_SUCCESS; |
| ... | ... | @@ -1090,7 +1208,6 @@ int main(int argc, char **argv) { |
| 1090 | 1208 | case CmdTargets: |
| 1091 | 1209 | return print_target_list(stdout); |
| 1092 | 1210 | case CmdNone: |
| 1093 | fprintf(stderr, "Zig programming language\n"); | |
| 1094 | return print_error_usage(arg0); | |
| 1211 | return print_full_usage(arg0, stderr, EXIT_FAILURE); | |
| 1095 | 1212 | } |
| 1096 | 1213 | } |
src/os.cpp+34-13| ... | ... | @@ -50,11 +50,11 @@ typedef SSIZE_T ssize_t; |
| 50 | 50 | |
| 51 | 51 | #endif |
| 52 | 52 | |
| 53 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) | |
| 53 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | |
| 54 | 54 | #include <link.h> |
| 55 | 55 | #endif |
| 56 | 56 | |
| 57 | #if defined(ZIG_OS_FREEBSD) | |
| 57 | #if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | |
| 58 | 58 | #include <sys/sysctl.h> |
| 59 | 59 | #endif |
| 60 | 60 | |
| ... | ... | @@ -78,7 +78,7 @@ static clock_serv_t cclock; |
| 78 | 78 | #if defined(__APPLE__) && !defined(environ) |
| 79 | 79 | #include <crt_externs.h> |
| 80 | 80 | #define environ (*_NSGetEnviron()) |
| 81 | #elif defined(ZIG_OS_FREEBSD) | |
| 81 | #elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | |
| 82 | 82 | extern char **environ; |
| 83 | 83 | #endif |
| 84 | 84 | |
| ... | ... | @@ -1099,7 +1099,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { |
| 1099 | 1099 | case EINTR: |
| 1100 | 1100 | return ErrorInterrupted; |
| 1101 | 1101 | case EINVAL: |
| 1102 | zig_unreachable(); | |
| 1102 | return ErrorInvalidFilename; | |
| 1103 | 1103 | case ENFILE: |
| 1104 | 1104 | case ENOMEM: |
| 1105 | 1105 | return ErrorSystemResources; |
| ... | ... | @@ -1232,6 +1232,18 @@ static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_p |
| 1232 | 1232 | } |
| 1233 | 1233 | #endif |
| 1234 | 1234 | |
| 1235 | Buf *os_tmp_filename(Buf *prefix, Buf *suffix) { | |
| 1236 | Buf *result = buf_create_from_buf(prefix); | |
| 1237 | ||
| 1238 | const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; | |
| 1239 | assert(array_length(base64) == 64 + 1); | |
| 1240 | for (size_t i = 0; i < 12; i += 1) { | |
| 1241 | buf_append_char(result, base64[rand() % 64]); | |
| 1242 | } | |
| 1243 | buf_append_buf(result, suffix); | |
| 1244 | return result; | |
| 1245 | } | |
| 1246 | ||
| 1235 | 1247 | #if defined(ZIG_OS_WINDOWS) |
| 1236 | 1248 | static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) { |
| 1237 | 1249 | char tmp_dir[MAX_PATH + 1]; |
| ... | ... | @@ -1458,6 +1470,15 @@ Error os_self_exe_path(Buf *out_path) { |
| 1458 | 1470 | } |
| 1459 | 1471 | buf_resize(out_path, cb - 1); |
| 1460 | 1472 | return ErrorNone; |
| 1473 | #elif defined(ZIG_OS_NETBSD) | |
| 1474 | buf_resize(out_path, PATH_MAX); | |
| 1475 | int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; | |
| 1476 | size_t cb = PATH_MAX; | |
| 1477 | if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { | |
| 1478 | return ErrorUnexpected; | |
| 1479 | } | |
| 1480 | buf_resize(out_path, cb - 1); | |
| 1481 | return ErrorNone; | |
| 1461 | 1482 | #endif |
| 1462 | 1483 | return ErrorFileNotFound; |
| 1463 | 1484 | } |
| ... | ... | @@ -1541,7 +1562,7 @@ void os_stderr_set_color(TermColor color) { |
| 1541 | 1562 | #endif |
| 1542 | 1563 | } |
| 1543 | 1564 | |
| 1544 | int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { | |
| 1565 | Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { | |
| 1545 | 1566 | #if defined(ZIG_OS_WINDOWS) |
| 1546 | 1567 | buf_resize(output_buf, 0); |
| 1547 | 1568 | buf_appendf(output_buf, "%s\\Lib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr); |
| ... | ... | @@ -1562,7 +1583,7 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch |
| 1562 | 1583 | buf_init_from_buf(tmp_buf, output_buf); |
| 1563 | 1584 | buf_append_str(tmp_buf, "ucrt.lib"); |
| 1564 | 1585 | if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { |
| 1565 | return 0; | |
| 1586 | return ErrorNone; | |
| 1566 | 1587 | } |
| 1567 | 1588 | else { |
| 1568 | 1589 | buf_resize(output_buf, 0); |
| ... | ... | @@ -1573,12 +1594,12 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch |
| 1573 | 1594 | #endif |
| 1574 | 1595 | } |
| 1575 | 1596 | |
| 1576 | int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { | |
| 1597 | Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { | |
| 1577 | 1598 | #if defined(ZIG_OS_WINDOWS) |
| 1578 | 1599 | buf_resize(output_buf, 0); |
| 1579 | 1600 | buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr); |
| 1580 | 1601 | if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) { |
| 1581 | return 0; | |
| 1602 | return ErrorNone; | |
| 1582 | 1603 | } |
| 1583 | 1604 | else { |
| 1584 | 1605 | buf_resize(output_buf, 0); |
| ... | ... | @@ -1589,7 +1610,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { |
| 1589 | 1610 | #endif |
| 1590 | 1611 | } |
| 1591 | 1612 | |
| 1592 | int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { | |
| 1613 | Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { | |
| 1593 | 1614 | #if defined(ZIG_OS_WINDOWS) |
| 1594 | 1615 | { |
| 1595 | 1616 | buf_resize(output_buf, 0); |
| ... | ... | @@ -1611,7 +1632,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy |
| 1611 | 1632 | buf_init_from_buf(tmp_buf, output_buf); |
| 1612 | 1633 | buf_append_str(tmp_buf, "kernel32.lib"); |
| 1613 | 1634 | if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { |
| 1614 | return 0; | |
| 1635 | return ErrorNone; | |
| 1615 | 1636 | } |
| 1616 | 1637 | } |
| 1617 | 1638 | { |
| ... | ... | @@ -1634,7 +1655,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy |
| 1634 | 1655 | buf_init_from_buf(tmp_buf, output_buf); |
| 1635 | 1656 | buf_append_str(tmp_buf, "kernel32.lib"); |
| 1636 | 1657 | if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { |
| 1637 | return 0; | |
| 1658 | return ErrorNone; | |
| 1638 | 1659 | } |
| 1639 | 1660 | } |
| 1640 | 1661 | return ErrorFileNotFound; |
| ... | ... | @@ -1776,7 +1797,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { |
| 1776 | 1797 | } |
| 1777 | 1798 | |
| 1778 | 1799 | |
| 1779 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) | |
| 1800 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | |
| 1780 | 1801 | static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) { |
| 1781 | 1802 | ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data); |
| 1782 | 1803 | if (info->dlpi_name[0] == '/') { |
| ... | ... | @@ -1787,7 +1808,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, |
| 1787 | 1808 | #endif |
| 1788 | 1809 | |
| 1789 | 1810 | Error os_self_exe_shared_libs(ZigList<Buf *> &paths) { |
| 1790 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) | |
| 1811 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) | |
| 1791 | 1812 | paths.resize(0); |
| 1792 | 1813 | dl_iterate_phdr(self_exe_shared_libs_callback, &paths); |
| 1793 | 1814 | return ErrorNone; |
src/os.hpp+6-3| ... | ... | @@ -25,6 +25,8 @@ |
| 25 | 25 | #define ZIG_OS_LINUX |
| 26 | 26 | #elif defined(__FreeBSD__) |
| 27 | 27 | #define ZIG_OS_FREEBSD |
| 28 | #elif defined(__NetBSD__) | |
| 29 | #define ZIG_OS_NETBSD | |
| 28 | 30 | #else |
| 29 | 31 | #define ZIG_OS_UNKNOWN |
| 30 | 32 | #endif |
| ... | ... | @@ -119,6 +121,7 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd); |
| 119 | 121 | bool os_stderr_tty(void); |
| 120 | 122 | void os_stderr_set_color(TermColor color); |
| 121 | 123 | |
| 124 | Buf *os_tmp_filename(Buf *prefix, Buf *suffix); | |
| 122 | 125 | Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path); |
| 123 | 126 | Error os_delete_file(Buf *path); |
| 124 | 127 | |
| ... | ... | @@ -133,9 +136,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path); |
| 133 | 136 | |
| 134 | 137 | Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname); |
| 135 | 138 | |
| 136 | int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf); | |
| 137 | int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); | |
| 138 | int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); | |
| 139 | Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf); | |
| 140 | Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); | |
| 141 | Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); | |
| 139 | 142 | |
| 140 | 143 | Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths); |
| 141 | 144 |
src/parser.cpp+11-1| ... | ... | @@ -2739,6 +2739,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) { |
| 2739 | 2739 | |
| 2740 | 2740 | AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async); |
| 2741 | 2741 | res->data.fn_call_expr.is_async = true; |
| 2742 | res->data.fn_call_expr.seen = false; | |
| 2742 | 2743 | if (eat_token_if(pc, TokenIdCmpLessThan) != nullptr) { |
| 2743 | 2744 | AstNode *prefix_expr = ast_expect(pc, ast_parse_prefix_expr); |
| 2744 | 2745 | expect_token(pc, TokenIdCmpGreaterThan); |
| ... | ... | @@ -2759,6 +2760,7 @@ static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { |
| 2759 | 2760 | |
| 2760 | 2761 | AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren); |
| 2761 | 2762 | res->data.fn_call_expr.params = params; |
| 2763 | res->data.fn_call_expr.seen = false; | |
| 2762 | 2764 | return res; |
| 2763 | 2765 | } |
| 2764 | 2766 | |
| ... | ... | @@ -2778,7 +2780,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) { |
| 2778 | 2780 | // PtrTypeStart |
| 2779 | 2781 | // <- ASTERISK |
| 2780 | 2782 | // / ASTERISK2 |
| 2781 | // / LBRACKET ASTERISK RBRACKET | |
| 2783 | // / PTRUNKNOWN | |
| 2784 | // / PTRC | |
| 2782 | 2785 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2783 | 2786 | Token *asterisk = eat_token_if(pc, TokenIdStar); |
| 2784 | 2787 | if (asterisk != nullptr) { |
| ... | ... | @@ -2804,6 +2807,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2804 | 2807 | return res; |
| 2805 | 2808 | } |
| 2806 | 2809 | |
| 2810 | Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket); | |
| 2811 | if (cptr != nullptr) { | |
| 2812 | AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr); | |
| 2813 | res->data.pointer_type.star_token = cptr; | |
| 2814 | return res; | |
| 2815 | } | |
| 2816 | ||
| 2807 | 2817 | return nullptr; |
| 2808 | 2818 | } |
| 2809 | 2819 |
src/target.cpp+599-344| ... | ... | @@ -9,127 +9,116 @@ |
| 9 | 9 | #include "error.hpp" |
| 10 | 10 | #include "target.hpp" |
| 11 | 11 | #include "util.hpp" |
| 12 | #include "os.hpp" | |
| 12 | 13 | |
| 13 | 14 | #include <stdio.h> |
| 14 | 15 | |
| 15 | static const ArchType arch_list[] = { | |
| 16 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_5a}, | |
| 17 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_4a}, | |
| 18 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_3a}, | |
| 19 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_2a}, | |
| 20 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a}, | |
| 21 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8}, | |
| 22 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8r}, | |
| 23 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_baseline}, | |
| 24 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_mainline}, | |
| 25 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7}, | |
| 26 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7em}, | |
| 27 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7m}, | |
| 28 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7s}, | |
| 29 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7k}, | |
| 30 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7ve}, | |
| 31 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6}, | |
| 32 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6m}, | |
| 33 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6k}, | |
| 34 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6t2}, | |
| 35 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5}, | |
| 36 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5te}, | |
| 37 | {ZigLLVM_arm, ZigLLVM_ARMSubArch_v4t}, | |
| 38 | ||
| 39 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_5a}, | |
| 40 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_4a}, | |
| 41 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_3a}, | |
| 42 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_2a}, | |
| 43 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_1a}, | |
| 44 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8}, | |
| 45 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8r}, | |
| 46 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_baseline}, | |
| 47 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_mainline}, | |
| 48 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7}, | |
| 49 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7em}, | |
| 50 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7m}, | |
| 51 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7s}, | |
| 52 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7k}, | |
| 53 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7ve}, | |
| 54 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6}, | |
| 55 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6m}, | |
| 56 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6k}, | |
| 57 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6t2}, | |
| 58 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5}, | |
| 59 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5te}, | |
| 60 | {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v4t}, | |
| 61 | ||
| 62 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_5a}, | |
| 63 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_4a}, | |
| 64 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_3a}, | |
| 65 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_2a}, | |
| 66 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_1a}, | |
| 67 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8}, | |
| 68 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8r}, | |
| 69 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_baseline}, | |
| 70 | {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_mainline}, | |
| 71 | ||
| 72 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_5a}, | |
| 73 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_4a}, | |
| 74 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_3a}, | |
| 75 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_2a}, | |
| 76 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_1a}, | |
| 77 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8}, | |
| 78 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8r}, | |
| 79 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_baseline}, | |
| 80 | {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_mainline}, | |
| 81 | ||
| 82 | {ZigLLVM_arc, ZigLLVM_NoSubArch}, | |
| 83 | {ZigLLVM_avr, ZigLLVM_NoSubArch}, | |
| 84 | {ZigLLVM_bpfel, ZigLLVM_NoSubArch}, | |
| 85 | {ZigLLVM_bpfeb, ZigLLVM_NoSubArch}, | |
| 86 | {ZigLLVM_hexagon, ZigLLVM_NoSubArch}, | |
| 87 | ||
| 88 | {ZigLLVM_mips, ZigLLVM_MipsSubArch_r6}, | |
| 89 | {ZigLLVM_mipsel, ZigLLVM_MipsSubArch_r6}, | |
| 90 | {ZigLLVM_mips64, ZigLLVM_MipsSubArch_r6}, | |
| 91 | {ZigLLVM_mips64el, ZigLLVM_MipsSubArch_r6}, | |
| 92 | ||
| 93 | {ZigLLVM_msp430, ZigLLVM_NoSubArch}, | |
| 94 | {ZigLLVM_ppc, ZigLLVM_NoSubArch}, | |
| 95 | {ZigLLVM_ppc64, ZigLLVM_NoSubArch}, | |
| 96 | {ZigLLVM_ppc64le, ZigLLVM_NoSubArch}, | |
| 97 | {ZigLLVM_r600, ZigLLVM_NoSubArch}, | |
| 98 | {ZigLLVM_amdgcn, ZigLLVM_NoSubArch}, | |
| 99 | {ZigLLVM_riscv32, ZigLLVM_NoSubArch}, | |
| 100 | {ZigLLVM_riscv64, ZigLLVM_NoSubArch}, | |
| 101 | {ZigLLVM_sparc, ZigLLVM_NoSubArch}, | |
| 102 | {ZigLLVM_sparcv9, ZigLLVM_NoSubArch}, | |
| 103 | {ZigLLVM_sparcel, ZigLLVM_NoSubArch}, | |
| 104 | {ZigLLVM_systemz, ZigLLVM_NoSubArch}, | |
| 105 | {ZigLLVM_tce, ZigLLVM_NoSubArch}, | |
| 106 | {ZigLLVM_tcele, ZigLLVM_NoSubArch}, | |
| 107 | {ZigLLVM_thumb, ZigLLVM_NoSubArch}, | |
| 108 | {ZigLLVM_thumbeb, ZigLLVM_NoSubArch}, | |
| 109 | {ZigLLVM_x86, ZigLLVM_NoSubArch}, | |
| 110 | {ZigLLVM_x86_64, ZigLLVM_NoSubArch}, | |
| 111 | {ZigLLVM_xcore, ZigLLVM_NoSubArch}, | |
| 112 | {ZigLLVM_nvptx, ZigLLVM_NoSubArch}, | |
| 113 | {ZigLLVM_nvptx64, ZigLLVM_NoSubArch}, | |
| 114 | {ZigLLVM_le32, ZigLLVM_NoSubArch}, | |
| 115 | {ZigLLVM_le64, ZigLLVM_NoSubArch}, | |
| 116 | {ZigLLVM_amdil, ZigLLVM_NoSubArch}, | |
| 117 | {ZigLLVM_amdil64, ZigLLVM_NoSubArch}, | |
| 118 | {ZigLLVM_hsail, ZigLLVM_NoSubArch}, | |
| 119 | {ZigLLVM_hsail64, ZigLLVM_NoSubArch}, | |
| 120 | {ZigLLVM_spir, ZigLLVM_NoSubArch}, | |
| 121 | {ZigLLVM_spir64, ZigLLVM_NoSubArch}, | |
| 122 | ||
| 123 | {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v3}, | |
| 124 | {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v4}, | |
| 125 | {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v5}, | |
| 126 | ||
| 127 | {ZigLLVM_shave, ZigLLVM_NoSubArch}, | |
| 128 | {ZigLLVM_lanai, ZigLLVM_NoSubArch}, | |
| 129 | {ZigLLVM_wasm32, ZigLLVM_NoSubArch}, | |
| 130 | {ZigLLVM_wasm64, ZigLLVM_NoSubArch}, | |
| 131 | {ZigLLVM_renderscript32, ZigLLVM_NoSubArch}, | |
| 132 | {ZigLLVM_renderscript64, ZigLLVM_NoSubArch}, | |
| 16 | static const SubArchList subarch_list_list[] = { | |
| 17 | SubArchListNone, | |
| 18 | SubArchListArm32, | |
| 19 | SubArchListArm64, | |
| 20 | SubArchListKalimba, | |
| 21 | SubArchListMips, | |
| 22 | }; | |
| 23 | ||
| 24 | static const ZigLLVM_SubArchType subarch_list_arm32[] = { | |
| 25 | ZigLLVM_ARMSubArch_v8_5a, | |
| 26 | ZigLLVM_ARMSubArch_v8_4a, | |
| 27 | ZigLLVM_ARMSubArch_v8_3a, | |
| 28 | ZigLLVM_ARMSubArch_v8_2a, | |
| 29 | ZigLLVM_ARMSubArch_v8_1a, | |
| 30 | ZigLLVM_ARMSubArch_v8, | |
| 31 | ZigLLVM_ARMSubArch_v8r, | |
| 32 | ZigLLVM_ARMSubArch_v8m_baseline, | |
| 33 | ZigLLVM_ARMSubArch_v8m_mainline, | |
| 34 | ZigLLVM_ARMSubArch_v7, | |
| 35 | ZigLLVM_ARMSubArch_v7em, | |
| 36 | ZigLLVM_ARMSubArch_v7m, | |
| 37 | ZigLLVM_ARMSubArch_v7s, | |
| 38 | ZigLLVM_ARMSubArch_v7k, | |
| 39 | ZigLLVM_ARMSubArch_v7ve, | |
| 40 | ZigLLVM_ARMSubArch_v6, | |
| 41 | ZigLLVM_ARMSubArch_v6m, | |
| 42 | ZigLLVM_ARMSubArch_v6k, | |
| 43 | ZigLLVM_ARMSubArch_v6t2, | |
| 44 | ZigLLVM_ARMSubArch_v5, | |
| 45 | ZigLLVM_ARMSubArch_v5te, | |
| 46 | ZigLLVM_ARMSubArch_v4t, | |
| 47 | ||
| 48 | }; | |
| 49 | ||
| 50 | static const ZigLLVM_SubArchType subarch_list_arm64[] = { | |
| 51 | ZigLLVM_ARMSubArch_v8_5a, | |
| 52 | ZigLLVM_ARMSubArch_v8_4a, | |
| 53 | ZigLLVM_ARMSubArch_v8_3a, | |
| 54 | ZigLLVM_ARMSubArch_v8_2a, | |
| 55 | ZigLLVM_ARMSubArch_v8_1a, | |
| 56 | ZigLLVM_ARMSubArch_v8, | |
| 57 | ZigLLVM_ARMSubArch_v8r, | |
| 58 | ZigLLVM_ARMSubArch_v8m_baseline, | |
| 59 | ZigLLVM_ARMSubArch_v8m_mainline, | |
| 60 | }; | |
| 61 | ||
| 62 | static const ZigLLVM_SubArchType subarch_list_kalimba[] = { | |
| 63 | ZigLLVM_KalimbaSubArch_v5, | |
| 64 | ZigLLVM_KalimbaSubArch_v4, | |
| 65 | ZigLLVM_KalimbaSubArch_v3, | |
| 66 | }; | |
| 67 | ||
| 68 | static const ZigLLVM_SubArchType subarch_list_mips[] = { | |
| 69 | ZigLLVM_MipsSubArch_r6, | |
| 70 | }; | |
| 71 | ||
| 72 | static const ZigLLVM_ArchType arch_list[] = { | |
| 73 | ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale | |
| 74 | ZigLLVM_armeb, // ARM (big endian): armeb | |
| 75 | ZigLLVM_aarch64, // AArch64 (little endian): aarch64 | |
| 76 | ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be | |
| 77 | ZigLLVM_arc, // ARC: Synopsys ARC | |
| 78 | ZigLLVM_avr, // AVR: Atmel AVR microcontroller | |
| 79 | ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) | |
| 80 | ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) | |
| 81 | ZigLLVM_hexagon, // Hexagon: hexagon | |
| 82 | ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6 | |
| 83 | ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el | |
| 84 | ZigLLVM_mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 | |
| 85 | ZigLLVM_mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el | |
| 86 | ZigLLVM_msp430, // MSP430: msp430 | |
| 87 | ZigLLVM_ppc, // PPC: powerpc | |
| 88 | ZigLLVM_ppc64, // PPC64: powerpc64, ppu | |
| 89 | ZigLLVM_ppc64le, // PPC64LE: powerpc64le | |
| 90 | ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX | |
| 91 | ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs | |
| 92 | ZigLLVM_riscv32, // RISC-V (32-bit): riscv32 | |
| 93 | ZigLLVM_riscv64, // RISC-V (64-bit): riscv64 | |
| 94 | ZigLLVM_sparc, // Sparc: sparc | |
| 95 | ZigLLVM_sparcv9, // Sparcv9: Sparcv9 | |
| 96 | ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant | |
| 97 | ZigLLVM_systemz, // SystemZ: s390x | |
| 98 | ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce | |
| 99 | ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele | |
| 100 | ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.* | |
| 101 | ZigLLVM_thumbeb, // Thumb (big endian): thumbeb | |
| 102 | ZigLLVM_x86, // X86: i[3-9]86 | |
| 103 | ZigLLVM_x86_64, // X86-64: amd64, x86_64 | |
| 104 | ZigLLVM_xcore, // XCore: xcore | |
| 105 | ZigLLVM_nvptx, // NVPTX: 32-bit | |
| 106 | ZigLLVM_nvptx64, // NVPTX: 64-bit | |
| 107 | ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl) | |
| 108 | ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl) | |
| 109 | ZigLLVM_amdil, // AMDIL | |
| 110 | ZigLLVM_amdil64, // AMDIL with 64-bit pointers | |
| 111 | ZigLLVM_hsail, // AMD HSAIL | |
| 112 | ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers | |
| 113 | ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version | |
| 114 | ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version | |
| 115 | ZigLLVM_kalimba, // Kalimba: generic kalimba | |
| 116 | ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors | |
| 117 | ZigLLVM_lanai, // Lanai: Lanai 32-bit | |
| 118 | ZigLLVM_wasm32, // WebAssembly with 32-bit pointers | |
| 119 | ZigLLVM_wasm64, // WebAssembly with 64-bit pointers | |
| 120 | ZigLLVM_renderscript32, // 32-bit RenderScript | |
| 121 | ZigLLVM_renderscript64, // 64-bit RenderScript | |
| 133 | 122 | }; |
| 134 | 123 | |
| 135 | 124 | static const ZigLLVM_VendorType vendor_list[] = { |
| ... | ... | @@ -190,7 +179,7 @@ static const Os os_list[] = { |
| 190 | 179 | }; |
| 191 | 180 | |
| 192 | 181 | // Coordinate with zig_llvm.h |
| 193 | static const ZigLLVM_EnvironmentType environ_list[] = { | |
| 182 | static const ZigLLVM_EnvironmentType abi_list[] = { | |
| 194 | 183 | ZigLLVM_UnknownEnvironment, |
| 195 | 184 | |
| 196 | 185 | ZigLLVM_GNU, |
| ... | ... | @@ -225,11 +214,12 @@ size_t target_oformat_count(void) { |
| 225 | 214 | return array_length(oformat_list); |
| 226 | 215 | } |
| 227 | 216 | |
| 228 | const ZigLLVM_ObjectFormatType get_target_oformat(size_t index) { | |
| 217 | ZigLLVM_ObjectFormatType target_oformat_enum(size_t index) { | |
| 218 | assert(index < array_length(oformat_list)); | |
| 229 | 219 | return oformat_list[index]; |
| 230 | 220 | } |
| 231 | 221 | |
| 232 | const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat) { | |
| 222 | const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) { | |
| 233 | 223 | switch (oformat) { |
| 234 | 224 | case ZigLLVM_UnknownObjectFormat: return "unknown"; |
| 235 | 225 | case ZigLLVM_COFF: return "coff"; |
| ... | ... | @@ -244,22 +234,25 @@ size_t target_arch_count(void) { |
| 244 | 234 | return array_length(arch_list); |
| 245 | 235 | } |
| 246 | 236 | |
| 247 | const ArchType *get_target_arch(size_t index) { | |
| 248 | return &arch_list[index]; | |
| 237 | ZigLLVM_ArchType target_arch_enum(size_t index) { | |
| 238 | assert(index < array_length(arch_list)); | |
| 239 | return arch_list[index]; | |
| 249 | 240 | } |
| 250 | 241 | |
| 251 | 242 | size_t target_vendor_count(void) { |
| 252 | 243 | return array_length(vendor_list); |
| 253 | 244 | } |
| 254 | 245 | |
| 255 | ZigLLVM_VendorType get_target_vendor(size_t index) { | |
| 246 | ZigLLVM_VendorType target_vendor_enum(size_t index) { | |
| 247 | assert(index < array_length(vendor_list)); | |
| 256 | 248 | return vendor_list[index]; |
| 257 | 249 | } |
| 258 | 250 | |
| 259 | 251 | size_t target_os_count(void) { |
| 260 | 252 | return array_length(os_list); |
| 261 | 253 | } |
| 262 | Os get_target_os(size_t index) { | |
| 254 | Os target_os_enum(size_t index) { | |
| 255 | assert(index < array_length(os_list)); | |
| 263 | 256 | return os_list[index]; |
| 264 | 257 | } |
| 265 | 258 | |
| ... | ... | @@ -414,7 +407,7 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) { |
| 414 | 407 | zig_unreachable(); |
| 415 | 408 | } |
| 416 | 409 | |
| 417 | const char *get_target_os_name(Os os_type) { | |
| 410 | const char *target_os_name(Os os_type) { | |
| 418 | 411 | switch (os_type) { |
| 419 | 412 | case OsFreestanding: |
| 420 | 413 | return "freestanding"; |
| ... | ... | @@ -460,78 +453,257 @@ const char *get_target_os_name(Os os_type) { |
| 460 | 453 | zig_unreachable(); |
| 461 | 454 | } |
| 462 | 455 | |
| 463 | size_t target_environ_count(void) { | |
| 464 | return array_length(environ_list); | |
| 456 | size_t target_abi_count(void) { | |
| 457 | return array_length(abi_list); | |
| 458 | } | |
| 459 | ZigLLVM_EnvironmentType target_abi_enum(size_t index) { | |
| 460 | assert(index < array_length(abi_list)); | |
| 461 | return abi_list[index]; | |
| 465 | 462 | } |
| 466 | ZigLLVM_EnvironmentType get_target_environ(size_t index) { | |
| 467 | return environ_list[index]; | |
| 463 | const char *target_abi_name(ZigLLVM_EnvironmentType abi) { | |
| 464 | if (abi == ZigLLVM_UnknownEnvironment) | |
| 465 | return "none"; | |
| 466 | return ZigLLVMGetEnvironmentTypeName(abi); | |
| 468 | 467 | } |
| 469 | 468 | |
| 470 | 469 | void get_native_target(ZigTarget *target) { |
| 471 | 470 | ZigLLVM_OSType os_type; |
| 471 | ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os | |
| 472 | 472 | ZigLLVMGetNativeTarget( |
| 473 | &target->arch.arch, | |
| 474 | &target->arch.sub_arch, | |
| 473 | &target->arch, | |
| 474 | &target->sub_arch, | |
| 475 | 475 | &target->vendor, |
| 476 | 476 | &os_type, |
| 477 | &target->env_type, | |
| 478 | &target->oformat); | |
| 477 | &target->abi, | |
| 478 | &oformat); | |
| 479 | 479 | target->os = get_zig_os_type(os_type); |
| 480 | target->is_native = true; | |
| 481 | if (target->abi == ZigLLVM_UnknownEnvironment) { | |
| 482 | target->abi = target_default_abi(target->arch, target->os); | |
| 483 | } | |
| 480 | 484 | } |
| 481 | 485 | |
| 482 | void get_unknown_target(ZigTarget *target) { | |
| 483 | target->arch.arch = ZigLLVM_UnknownArch; | |
| 484 | target->arch.sub_arch = ZigLLVM_NoSubArch; | |
| 485 | target->vendor = ZigLLVM_UnknownVendor; | |
| 486 | target->os = OsFreestanding; | |
| 487 | target->env_type = ZigLLVM_UnknownEnvironment; | |
| 488 | target->oformat = ZigLLVM_UnknownObjectFormat; | |
| 486 | Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub, | |
| 487 | const char *archsub_ptr, size_t archsub_len) | |
| 488 | { | |
| 489 | for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) { | |
| 490 | ZigLLVM_ArchType arch = arch_list[arch_i]; | |
| 491 | SubArchList sub_arch_list = target_subarch_list(arch); | |
| 492 | size_t subarch_count = target_subarch_count(sub_arch_list); | |
| 493 | if (subarch_count == 0) { | |
| 494 | if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) { | |
| 495 | *out_arch = arch; | |
| 496 | *out_sub = ZigLLVM_NoSubArch; | |
| 497 | return ErrorNone; | |
| 498 | } | |
| 499 | continue; | |
| 500 | } | |
| 501 | for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) { | |
| 502 | ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); | |
| 503 | char arch_name[64]; | |
| 504 | int n = sprintf(arch_name, "%s%s", target_arch_name(arch), target_subarch_name(sub)); | |
| 505 | if (mem_eql_mem(arch_name, n, archsub_ptr, archsub_len)) { | |
| 506 | *out_arch = arch; | |
| 507 | *out_sub = sub; | |
| 508 | return ErrorNone; | |
| 509 | } | |
| 510 | } | |
| 511 | } | |
| 512 | return ErrorUnknownArchitecture; | |
| 489 | 513 | } |
| 490 | 514 | |
| 491 | static void get_arch_name_raw(char *out_str, ZigLLVM_ArchType arch, ZigLLVM_SubArchType sub_arch) { | |
| 492 | const char *sub_str = (sub_arch == ZigLLVM_NoSubArch) ? "" : ZigLLVMGetSubArchTypeName(sub_arch); | |
| 493 | sprintf(out_str, "%s%s", ZigLLVMGetArchTypeName(arch), sub_str); | |
| 494 | } | |
| 515 | SubArchList target_subarch_list(ZigLLVM_ArchType arch) { | |
| 516 | switch (arch) { | |
| 517 | case ZigLLVM_UnknownArch: | |
| 518 | zig_unreachable(); | |
| 519 | case ZigLLVM_arm: | |
| 520 | case ZigLLVM_armeb: | |
| 521 | case ZigLLVM_thumb: | |
| 522 | case ZigLLVM_thumbeb: | |
| 523 | return SubArchListArm32; | |
| 524 | ||
| 525 | case ZigLLVM_aarch64: | |
| 526 | case ZigLLVM_aarch64_be: | |
| 527 | return SubArchListArm64; | |
| 495 | 528 | |
| 496 | void get_arch_name(char *out_str, const ArchType *arch) { | |
| 497 | return get_arch_name_raw(out_str, arch->arch, arch->sub_arch); | |
| 529 | case ZigLLVM_kalimba: | |
| 530 | return SubArchListKalimba; | |
| 531 | ||
| 532 | case ZigLLVM_arc: | |
| 533 | case ZigLLVM_avr: | |
| 534 | case ZigLLVM_bpfel: | |
| 535 | case ZigLLVM_bpfeb: | |
| 536 | case ZigLLVM_hexagon: | |
| 537 | case ZigLLVM_mips: | |
| 538 | case ZigLLVM_mipsel: | |
| 539 | case ZigLLVM_mips64: | |
| 540 | case ZigLLVM_mips64el: | |
| 541 | case ZigLLVM_msp430: | |
| 542 | case ZigLLVM_ppc: | |
| 543 | case ZigLLVM_ppc64: | |
| 544 | case ZigLLVM_ppc64le: | |
| 545 | case ZigLLVM_r600: | |
| 546 | case ZigLLVM_amdgcn: | |
| 547 | case ZigLLVM_riscv32: | |
| 548 | case ZigLLVM_riscv64: | |
| 549 | case ZigLLVM_sparc: | |
| 550 | case ZigLLVM_sparcv9: | |
| 551 | case ZigLLVM_sparcel: | |
| 552 | case ZigLLVM_systemz: | |
| 553 | case ZigLLVM_tce: | |
| 554 | case ZigLLVM_tcele: | |
| 555 | case ZigLLVM_x86: | |
| 556 | case ZigLLVM_x86_64: | |
| 557 | case ZigLLVM_xcore: | |
| 558 | case ZigLLVM_nvptx: | |
| 559 | case ZigLLVM_nvptx64: | |
| 560 | case ZigLLVM_le32: | |
| 561 | case ZigLLVM_le64: | |
| 562 | case ZigLLVM_amdil: | |
| 563 | case ZigLLVM_amdil64: | |
| 564 | case ZigLLVM_hsail: | |
| 565 | case ZigLLVM_hsail64: | |
| 566 | case ZigLLVM_spir: | |
| 567 | case ZigLLVM_spir64: | |
| 568 | case ZigLLVM_shave: | |
| 569 | case ZigLLVM_lanai: | |
| 570 | case ZigLLVM_wasm32: | |
| 571 | case ZigLLVM_wasm64: | |
| 572 | case ZigLLVM_renderscript32: | |
| 573 | case ZigLLVM_renderscript64: | |
| 574 | return SubArchListNone; | |
| 575 | } | |
| 576 | zig_unreachable(); | |
| 498 | 577 | } |
| 499 | 578 | |
| 500 | int parse_target_arch(const char *str, ArchType *out_arch) { | |
| 501 | for (size_t i = 0; i < array_length(arch_list); i += 1) { | |
| 502 | const ArchType *arch = &arch_list[i]; | |
| 503 | char arch_name[50]; | |
| 504 | get_arch_name_raw(arch_name, arch->arch, arch->sub_arch); | |
| 505 | if (strcmp(arch_name, str) == 0) { | |
| 506 | *out_arch = *arch; | |
| 579 | size_t target_subarch_count(SubArchList sub_arch_list) { | |
| 580 | switch (sub_arch_list) { | |
| 581 | case SubArchListNone: | |
| 507 | 582 | return 0; |
| 508 | } | |
| 583 | case SubArchListArm32: | |
| 584 | return array_length(subarch_list_arm32); | |
| 585 | case SubArchListArm64: | |
| 586 | return array_length(subarch_list_arm64); | |
| 587 | case SubArchListKalimba: | |
| 588 | return array_length(subarch_list_kalimba); | |
| 589 | case SubArchListMips: | |
| 590 | return array_length(subarch_list_mips); | |
| 591 | } | |
| 592 | zig_unreachable(); | |
| 593 | } | |
| 594 | ||
| 595 | ZigLLVM_SubArchType target_subarch_enum(SubArchList sub_arch_list, size_t i) { | |
| 596 | switch (sub_arch_list) { | |
| 597 | case SubArchListNone: | |
| 598 | zig_unreachable(); | |
| 599 | case SubArchListArm32: | |
| 600 | assert(i < array_length(subarch_list_arm32)); | |
| 601 | return subarch_list_arm32[i]; | |
| 602 | case SubArchListArm64: | |
| 603 | assert(i < array_length(subarch_list_arm64)); | |
| 604 | return subarch_list_arm64[i]; | |
| 605 | case SubArchListKalimba: | |
| 606 | assert(i < array_length(subarch_list_kalimba)); | |
| 607 | return subarch_list_kalimba[i]; | |
| 608 | case SubArchListMips: | |
| 609 | assert(i < array_length(subarch_list_mips)); | |
| 610 | return subarch_list_mips[i]; | |
| 509 | 611 | } |
| 510 | return ErrorFileNotFound; | |
| 612 | zig_unreachable(); | |
| 613 | } | |
| 614 | ||
| 615 | const char *target_subarch_name(ZigLLVM_SubArchType subarch) { | |
| 616 | return ZigLLVMGetSubArchTypeName(subarch); | |
| 617 | } | |
| 618 | ||
| 619 | size_t target_subarch_list_count(void) { | |
| 620 | return array_length(subarch_list_list); | |
| 621 | } | |
| 622 | ||
| 623 | SubArchList target_subarch_list_enum(size_t index) { | |
| 624 | assert(index < array_length(subarch_list_list)); | |
| 625 | return subarch_list_list[index]; | |
| 626 | } | |
| 627 | ||
| 628 | const char *target_subarch_list_name(SubArchList sub_arch_list) { | |
| 629 | switch (sub_arch_list) { | |
| 630 | case SubArchListNone: | |
| 631 | return "None"; | |
| 632 | case SubArchListArm32: | |
| 633 | return "Arm32"; | |
| 634 | case SubArchListArm64: | |
| 635 | return "Arm64"; | |
| 636 | case SubArchListKalimba: | |
| 637 | return "Kalimba"; | |
| 638 | case SubArchListMips: | |
| 639 | return "Mips"; | |
| 640 | } | |
| 641 | zig_unreachable(); | |
| 511 | 642 | } |
| 512 | 643 | |
| 513 | int parse_target_os(const char *str, Os *out_os) { | |
| 644 | Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) { | |
| 514 | 645 | for (size_t i = 0; i < array_length(os_list); i += 1) { |
| 515 | 646 | Os os = os_list[i]; |
| 516 | const char *os_name = get_target_os_name(os); | |
| 517 | if (strcmp(os_name, str) == 0) { | |
| 647 | const char *os_name = target_os_name(os); | |
| 648 | if (mem_eql_str(os_ptr, os_len, os_name)) { | |
| 518 | 649 | *out_os = os; |
| 519 | return 0; | |
| 650 | return ErrorNone; | |
| 520 | 651 | } |
| 521 | 652 | } |
| 522 | return ErrorFileNotFound; | |
| 653 | return ErrorUnknownOperatingSystem; | |
| 523 | 654 | } |
| 524 | 655 | |
| 525 | int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *out_environ) { | |
| 526 | for (size_t i = 0; i < array_length(environ_list); i += 1) { | |
| 527 | ZigLLVM_EnvironmentType env_type = environ_list[i]; | |
| 528 | const char *environ_name = ZigLLVMGetEnvironmentTypeName(env_type); | |
| 529 | if (strcmp(environ_name, str) == 0) { | |
| 530 | *out_environ = env_type; | |
| 531 | return 0; | |
| 656 | Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, size_t abi_len) { | |
| 657 | for (size_t i = 0; i < array_length(abi_list); i += 1) { | |
| 658 | ZigLLVM_EnvironmentType abi = abi_list[i]; | |
| 659 | const char *abi_name = target_abi_name(abi); | |
| 660 | if (mem_eql_str(abi_ptr, abi_len, abi_name)) { | |
| 661 | *out_abi = abi; | |
| 662 | return ErrorNone; | |
| 663 | } | |
| 664 | } | |
| 665 | return ErrorUnknownABI; | |
| 666 | } | |
| 667 | ||
| 668 | Error target_parse_triple(ZigTarget *target, const char *triple) { | |
| 669 | Error err; | |
| 670 | SplitIterator it = memSplit(str(triple), str("-")); | |
| 671 | ||
| 672 | Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it); | |
| 673 | Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it); | |
| 674 | Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it); | |
| 675 | ||
| 676 | if (!opt_archsub.is_some) | |
| 677 | return ErrorMissingArchitecture; | |
| 678 | ||
| 679 | if (!opt_os.is_some) | |
| 680 | return ErrorMissingOperatingSystem; | |
| 681 | ||
| 682 | if ((err = target_parse_archsub(&target->arch, &target->sub_arch, | |
| 683 | (char*)opt_archsub.value.ptr, opt_archsub.value.len))) | |
| 684 | { | |
| 685 | return err; | |
| 686 | } | |
| 687 | ||
| 688 | if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { | |
| 689 | return err; | |
| 690 | } | |
| 691 | ||
| 692 | if (opt_abi.is_some) { | |
| 693 | if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { | |
| 694 | return err; | |
| 532 | 695 | } |
| 696 | } else { | |
| 697 | target->abi = target_default_abi(target->arch, target->os); | |
| 533 | 698 | } |
| 534 | return ErrorFileNotFound; | |
| 699 | ||
| 700 | target->vendor = ZigLLVM_UnknownVendor; | |
| 701 | target->is_native = false; | |
| 702 | return ErrorNone; | |
| 703 | } | |
| 704 | ||
| 705 | const char *target_arch_name(ZigLLVM_ArchType arch) { | |
| 706 | return ZigLLVMGetArchTypeName(arch); | |
| 535 | 707 | } |
| 536 | 708 | |
| 537 | 709 | void init_all_targets(void) { |
| ... | ... | @@ -543,121 +715,39 @@ void init_all_targets(void) { |
| 543 | 715 | } |
| 544 | 716 | |
| 545 | 717 | void get_target_triple(Buf *triple, const ZigTarget *target) { |
| 546 | char arch_name[50]; | |
| 547 | get_arch_name(arch_name, &target->arch); | |
| 548 | ||
| 549 | 718 | buf_resize(triple, 0); |
| 550 | ||
| 551 | // LLVM WebAssembly output support requires the target to be activated at | |
| 552 | // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly. | |
| 553 | // | |
| 554 | // LLVM determines the output format based on the environment suffix, | |
| 555 | // defaulting to an object based on the architecture. The default format in | |
| 556 | // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to | |
| 557 | // explicitly set this ourself in order for it to work. | |
| 558 | // | |
| 559 | // This is fixed in LLVM 7 and you will be able to get wasm output by | |
| 560 | // using the target triple `wasm32-unknown-unknown-unknown`. | |
| 561 | if (!strncmp(arch_name, "wasm", 4)) { | |
| 562 | buf_appendf(triple, "%s-%s-%s-wasm", arch_name, | |
| 563 | ZigLLVMGetVendorTypeName(target->vendor), | |
| 564 | ZigLLVMGetOSTypeName(get_llvm_os_type(target->os))); | |
| 565 | } else { | |
| 566 | buf_appendf(triple, "%s-%s-%s-%s", arch_name, | |
| 567 | ZigLLVMGetVendorTypeName(target->vendor), | |
| 568 | ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), | |
| 569 | ZigLLVMGetEnvironmentTypeName(target->env_type)); | |
| 570 | } | |
| 719 | buf_appendf(triple, "%s%s-%s-%s-%s", | |
| 720 | ZigLLVMGetArchTypeName(target->arch), | |
| 721 | ZigLLVMGetSubArchTypeName(target->sub_arch), | |
| 722 | ZigLLVMGetVendorTypeName(target->vendor), | |
| 723 | ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), | |
| 724 | ZigLLVMGetEnvironmentTypeName(target->abi)); | |
| 571 | 725 | } |
| 572 | 726 | |
| 573 | static bool is_os_darwin(ZigTarget *target) { | |
| 727 | bool target_is_darwin(const ZigTarget *target) { | |
| 574 | 728 | switch (target->os) { |
| 575 | 729 | case OsMacOSX: |
| 576 | 730 | case OsIOS: |
| 731 | case OsWatchOS: | |
| 732 | case OsTvOS: | |
| 577 | 733 | return true; |
| 578 | 734 | default: |
| 579 | 735 | return false; |
| 580 | 736 | } |
| 581 | 737 | } |
| 582 | 738 | |
| 583 | void resolve_target_object_format(ZigTarget *target) { | |
| 584 | if (target->oformat != ZigLLVM_UnknownObjectFormat) { | |
| 585 | return; | |
| 739 | ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) { | |
| 740 | if (target->os == OsUefi || target->os == OsWindows) { | |
| 741 | return ZigLLVM_COFF; | |
| 742 | } else if (target_is_darwin(target)) { | |
| 743 | return ZigLLVM_MachO; | |
| 586 | 744 | } |
| 587 | ||
| 588 | switch (target->arch.arch) { | |
| 589 | case ZigLLVM_UnknownArch: | |
| 590 | case ZigLLVM_aarch64: | |
| 591 | case ZigLLVM_arm: | |
| 592 | case ZigLLVM_thumb: | |
| 593 | case ZigLLVM_x86: | |
| 594 | case ZigLLVM_x86_64: | |
| 595 | if (is_os_darwin(target)) { | |
| 596 | target->oformat = ZigLLVM_MachO; | |
| 597 | } else if (target->os == OsWindows) { | |
| 598 | target->oformat = ZigLLVM_COFF; | |
| 599 | } else { | |
| 600 | target->oformat = ZigLLVM_ELF; | |
| 601 | } | |
| 602 | return; | |
| 603 | ||
| 604 | case ZigLLVM_aarch64_be: | |
| 605 | case ZigLLVM_amdgcn: | |
| 606 | case ZigLLVM_amdil: | |
| 607 | case ZigLLVM_amdil64: | |
| 608 | case ZigLLVM_armeb: | |
| 609 | case ZigLLVM_arc: | |
| 610 | case ZigLLVM_avr: | |
| 611 | case ZigLLVM_bpfeb: | |
| 612 | case ZigLLVM_bpfel: | |
| 613 | case ZigLLVM_hexagon: | |
| 614 | case ZigLLVM_lanai: | |
| 615 | case ZigLLVM_hsail: | |
| 616 | case ZigLLVM_hsail64: | |
| 617 | case ZigLLVM_kalimba: | |
| 618 | case ZigLLVM_le32: | |
| 619 | case ZigLLVM_le64: | |
| 620 | case ZigLLVM_mips: | |
| 621 | case ZigLLVM_mips64: | |
| 622 | case ZigLLVM_mips64el: | |
| 623 | case ZigLLVM_mipsel: | |
| 624 | case ZigLLVM_msp430: | |
| 625 | case ZigLLVM_nvptx: | |
| 626 | case ZigLLVM_nvptx64: | |
| 627 | case ZigLLVM_ppc64le: | |
| 628 | case ZigLLVM_r600: | |
| 629 | case ZigLLVM_renderscript32: | |
| 630 | case ZigLLVM_renderscript64: | |
| 631 | case ZigLLVM_riscv32: | |
| 632 | case ZigLLVM_riscv64: | |
| 633 | case ZigLLVM_shave: | |
| 634 | case ZigLLVM_sparc: | |
| 635 | case ZigLLVM_sparcel: | |
| 636 | case ZigLLVM_sparcv9: | |
| 637 | case ZigLLVM_spir: | |
| 638 | case ZigLLVM_spir64: | |
| 639 | case ZigLLVM_systemz: | |
| 640 | case ZigLLVM_tce: | |
| 641 | case ZigLLVM_tcele: | |
| 642 | case ZigLLVM_thumbeb: | |
| 643 | case ZigLLVM_xcore: | |
| 644 | target->oformat= ZigLLVM_ELF; | |
| 645 | return; | |
| 646 | ||
| 647 | case ZigLLVM_wasm32: | |
| 648 | case ZigLLVM_wasm64: | |
| 649 | target->oformat = ZigLLVM_Wasm; | |
| 650 | return; | |
| 651 | ||
| 652 | case ZigLLVM_ppc: | |
| 653 | case ZigLLVM_ppc64: | |
| 654 | if (is_os_darwin(target)) { | |
| 655 | target->oformat = ZigLLVM_MachO; | |
| 656 | } else { | |
| 657 | target->oformat= ZigLLVM_ELF; | |
| 658 | } | |
| 659 | return; | |
| 745 | if (target->arch == ZigLLVM_wasm32 || | |
| 746 | target->arch == ZigLLVM_wasm64) | |
| 747 | { | |
| 748 | return ZigLLVM_Wasm; | |
| 660 | 749 | } |
| 750 | return ZigLLVM_ELF; | |
| 661 | 751 | } |
| 662 | 752 | |
| 663 | 753 | // See lib/Support/Triple.cpp in LLVM for the source of this data. |
| ... | ... | @@ -728,7 +818,7 @@ static int get_arch_pointer_bit_width(ZigLLVM_ArchType arch) { |
| 728 | 818 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 729 | 819 | switch (target->os) { |
| 730 | 820 | case OsFreestanding: |
| 731 | switch (target->arch.arch) { | |
| 821 | switch (target->arch) { | |
| 732 | 822 | case ZigLLVM_msp430: |
| 733 | 823 | switch (id) { |
| 734 | 824 | case CIntTypeShort: |
| ... | ... | @@ -756,7 +846,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 756 | 846 | return 32; |
| 757 | 847 | case CIntTypeLong: |
| 758 | 848 | case CIntTypeULong: |
| 759 | return get_arch_pointer_bit_width(target->arch.arch); | |
| 849 | return get_arch_pointer_bit_width(target->arch); | |
| 760 | 850 | case CIntTypeLongLong: |
| 761 | 851 | case CIntTypeULongLong: |
| 762 | 852 | return 64; |
| ... | ... | @@ -768,6 +858,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 768 | 858 | case OsMacOSX: |
| 769 | 859 | case OsZen: |
| 770 | 860 | case OsFreeBSD: |
| 861 | 	case OsNetBSD: | |
| 771 | 862 | case OsOpenBSD: |
| 772 | 863 | switch (id) { |
| 773 | 864 | case CIntTypeShort: |
| ... | ... | @@ -778,7 +869,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 778 | 869 | return 32; |
| 779 | 870 | case CIntTypeLong: |
| 780 | 871 | case CIntTypeULong: |
| 781 | return get_arch_pointer_bit_width(target->arch.arch); | |
| 872 | return get_arch_pointer_bit_width(target->arch); | |
| 782 | 873 | case CIntTypeLongLong: |
| 783 | 874 | case CIntTypeULongLong: |
| 784 | 875 | return 64; |
| ... | ... | @@ -808,7 +899,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 808 | 899 | case OsIOS: |
| 809 | 900 | case OsKFreeBSD: |
| 810 | 901 | case OsLv2: |
| 811 | case OsNetBSD: | |
| 812 | 902 | case OsSolaris: |
| 813 | 903 | case OsHaiku: |
| 814 | 904 | case OsMinix: |
| ... | ... | @@ -835,23 +925,27 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 835 | 925 | zig_unreachable(); |
| 836 | 926 | } |
| 837 | 927 | |
| 838 | const char *target_o_file_ext(ZigTarget *target) { | |
| 839 | if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) { | |
| 928 | bool target_allows_addr_zero(const ZigTarget *target) { | |
| 929 | return target->os == OsFreestanding; | |
| 930 | } | |
| 931 | ||
| 932 | const char *target_o_file_ext(const ZigTarget *target) { | |
| 933 | if (target->abi == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) { | |
| 840 | 934 | return ".obj"; |
| 841 | 935 | } else { |
| 842 | 936 | return ".o"; |
| 843 | 937 | } |
| 844 | 938 | } |
| 845 | 939 | |
| 846 | const char *target_asm_file_ext(ZigTarget *target) { | |
| 940 | const char *target_asm_file_ext(const ZigTarget *target) { | |
| 847 | 941 | return ".s"; |
| 848 | 942 | } |
| 849 | 943 | |
| 850 | const char *target_llvm_ir_file_ext(ZigTarget *target) { | |
| 944 | const char *target_llvm_ir_file_ext(const ZigTarget *target) { | |
| 851 | 945 | return ".ll"; |
| 852 | 946 | } |
| 853 | 947 | |
| 854 | const char *target_exe_file_ext(ZigTarget *target) { | |
| 948 | const char *target_exe_file_ext(const ZigTarget *target) { | |
| 855 | 949 | if (target->os == OsWindows) { |
| 856 | 950 | return ".exe"; |
| 857 | 951 | } else if (target->os == OsUefi) { |
| ... | ... | @@ -861,7 +955,9 @@ const char *target_exe_file_ext(ZigTarget *target) { |
| 861 | 955 | } |
| 862 | 956 | } |
| 863 | 957 | |
| 864 | const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) { | |
| 958 | const char *target_lib_file_ext(const ZigTarget *target, bool is_static, | |
| 959 | size_t version_major, size_t version_minor, size_t version_patch) | |
| 960 | { | |
| 865 | 961 | if (target->os == OsWindows || target->os == OsUefi) { |
| 866 | 962 | if (is_static) { |
| 867 | 963 | return ".lib"; |
| ... | ... | @@ -872,7 +968,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio |
| 872 | 968 | if (is_static) { |
| 873 | 969 | return ".a"; |
| 874 | 970 | } else { |
| 875 | return buf_ptr(buf_sprintf(".so.%zu", version_major)); | |
| 971 | return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize, version_major)); | |
| 876 | 972 | } |
| 877 | 973 | } |
| 878 | 974 | } |
| ... | ... | @@ -883,8 +979,8 @@ enum FloatAbi { |
| 883 | 979 | FloatAbiSoftFp, |
| 884 | 980 | }; |
| 885 | 981 | |
| 886 | static FloatAbi get_float_abi(ZigTarget *target) { | |
| 887 | const ZigLLVM_EnvironmentType env = target->env_type; | |
| 982 | static FloatAbi get_float_abi(const ZigTarget *target) { | |
| 983 | const ZigLLVM_EnvironmentType env = target->abi; | |
| 888 | 984 | if (env == ZigLLVM_GNUEABIHF || |
| 889 | 985 | env == ZigLLVM_EABIHF || |
| 890 | 986 | env == ZigLLVM_MuslEABIHF) |
| ... | ... | @@ -899,64 +995,153 @@ static bool is_64_bit(ZigLLVM_ArchType arch) { |
| 899 | 995 | return get_arch_pointer_bit_width(arch) == 64; |
| 900 | 996 | } |
| 901 | 997 | |
| 902 | Buf *target_dynamic_linker(ZigTarget *target) { | |
| 903 | const ZigLLVM_ArchType arch = target->arch.arch; | |
| 904 | const ZigLLVM_EnvironmentType env = target->env_type; | |
| 998 | const char *target_dynamic_linker(const ZigTarget *target) { | |
| 999 | switch (target->os) { | |
| 1000 | case OsFreeBSD: | |
| 1001 | return "/libexec/ld-elf.so.1"; | |
| 1002 | case OsNetBSD: | |
| 1003 | return "/libexec/ld.elf_so"; | |
| 1004 | case OsLinux: { | |
| 1005 | const ZigLLVM_EnvironmentType abi = target->abi; | |
| 1006 | if (abi == ZigLLVM_Android) { | |
| 1007 | if (is_64_bit(target->arch)) { | |
| 1008 | return "/system/bin/linker64"; | |
| 1009 | } else { | |
| 1010 | return "/system/bin/linker"; | |
| 1011 | } | |
| 1012 | } | |
| 905 | 1013 | |
| 906 | if (env == ZigLLVM_Android) { | |
| 907 | if (is_64_bit(arch)) { | |
| 908 | return buf_create_from_str("/system/bin/linker64"); | |
| 909 | } else { | |
| 910 | return buf_create_from_str("/system/bin/linker"); | |
| 911 | } | |
| 912 | } else if (arch == ZigLLVM_x86 || | |
| 913 | arch == ZigLLVM_sparc || | |
| 914 | arch == ZigLLVM_sparcel) | |
| 915 | { | |
| 916 | return buf_create_from_str("/lib/ld-linux.so.2"); | |
| 917 | } else if (arch == ZigLLVM_aarch64) { | |
| 918 | return buf_create_from_str("/lib/ld-linux-aarch64.so.1"); | |
| 919 | } else if (arch == ZigLLVM_aarch64_be) { | |
| 920 | return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1"); | |
| 921 | } else if (arch == ZigLLVM_arm || arch == ZigLLVM_thumb) { | |
| 922 | if (get_float_abi(target) == FloatAbiHard) { | |
| 923 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); | |
| 924 | } else { | |
| 925 | return buf_create_from_str("/lib/ld-linux.so.3"); | |
| 926 | } | |
| 927 | } else if (arch == ZigLLVM_armeb || arch == ZigLLVM_thumbeb) { | |
| 928 | if (get_float_abi(target) == FloatAbiHard) { | |
| 929 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); | |
| 930 | } else { | |
| 931 | return buf_create_from_str("/lib/ld-linux.so.3"); | |
| 1014 | switch (target->arch) { | |
| 1015 | case ZigLLVM_UnknownArch: | |
| 1016 | zig_unreachable(); | |
| 1017 | case ZigLLVM_x86: | |
| 1018 | case ZigLLVM_sparc: | |
| 1019 | case ZigLLVM_sparcel: | |
| 1020 | return "/lib/ld-linux.so.2"; | |
| 1021 | ||
| 1022 | case ZigLLVM_aarch64: | |
| 1023 | return "/lib/ld-linux-aarch64.so.1"; | |
| 1024 | ||
| 1025 | case ZigLLVM_aarch64_be: | |
| 1026 | return "/lib/ld-linux-aarch64_be.so.1"; | |
| 1027 | ||
| 1028 | case ZigLLVM_arm: | |
| 1029 | case ZigLLVM_thumb: | |
| 1030 | if (get_float_abi(target) == FloatAbiHard) { | |
| 1031 | return "/lib/ld-linux-armhf.so.3"; | |
| 1032 | } else { | |
| 1033 | return "/lib/ld-linux.so.3"; | |
| 1034 | } | |
| 1035 | ||
| 1036 | case ZigLLVM_armeb: | |
| 1037 | case ZigLLVM_thumbeb: | |
| 1038 | if (get_float_abi(target) == FloatAbiHard) { | |
| 1039 | return "/lib/ld-linux-armhf.so.3"; | |
| 1040 | } else { | |
| 1041 | return "/lib/ld-linux.so.3"; | |
| 1042 | } | |
| 1043 | ||
| 1044 | case ZigLLVM_mips: | |
| 1045 | case ZigLLVM_mipsel: | |
| 1046 | case ZigLLVM_mips64: | |
| 1047 | case ZigLLVM_mips64el: | |
| 1048 | zig_panic("TODO implement target_dynamic_linker for mips"); | |
| 1049 | ||
| 1050 | case ZigLLVM_ppc: | |
| 1051 | return "/lib/ld.so.1"; | |
| 1052 | ||
| 1053 | case ZigLLVM_ppc64: | |
| 1054 | return "/lib64/ld64.so.2"; | |
| 1055 | ||
| 1056 | case ZigLLVM_ppc64le: | |
| 1057 | return "/lib64/ld64.so.2"; | |
| 1058 | ||
| 1059 | case ZigLLVM_systemz: | |
| 1060 | return "/lib64/ld64.so.1"; | |
| 1061 | ||
| 1062 | case ZigLLVM_sparcv9: | |
| 1063 | return "/lib64/ld-linux.so.2"; | |
| 1064 | ||
| 1065 | case ZigLLVM_x86_64: | |
| 1066 | if (abi == ZigLLVM_GNUX32) { | |
| 1067 | return "/libx32/ld-linux-x32.so.2"; | |
| 1068 | } | |
| 1069 | if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) { | |
| 1070 | return "/lib/ld-musl-x86_64.so.1"; | |
| 1071 | } | |
| 1072 | return "/lib64/ld-linux-x86-64.so.2"; | |
| 1073 | ||
| 1074 | case ZigLLVM_wasm32: | |
| 1075 | case ZigLLVM_wasm64: | |
| 1076 | return nullptr; | |
| 1077 | ||
| 1078 | case ZigLLVM_arc: | |
| 1079 | case ZigLLVM_avr: | |
| 1080 | case ZigLLVM_bpfel: | |
| 1081 | case ZigLLVM_bpfeb: | |
| 1082 | case ZigLLVM_hexagon: | |
| 1083 | case ZigLLVM_msp430: | |
| 1084 | case ZigLLVM_r600: | |
| 1085 | case ZigLLVM_amdgcn: | |
| 1086 | case ZigLLVM_riscv32: | |
| 1087 | case ZigLLVM_riscv64: | |
| 1088 | case ZigLLVM_tce: | |
| 1089 | case ZigLLVM_tcele: | |
| 1090 | case ZigLLVM_xcore: | |
| 1091 | case ZigLLVM_nvptx: | |
| 1092 | case ZigLLVM_nvptx64: | |
| 1093 | case ZigLLVM_le32: | |
| 1094 | case ZigLLVM_le64: | |
| 1095 | case ZigLLVM_amdil: | |
| 1096 | case ZigLLVM_amdil64: | |
| 1097 | case ZigLLVM_hsail: | |
| 1098 | case ZigLLVM_hsail64: | |
| 1099 | case ZigLLVM_spir: | |
| 1100 | case ZigLLVM_spir64: | |
| 1101 | case ZigLLVM_kalimba: | |
| 1102 | case ZigLLVM_shave: | |
| 1103 | case ZigLLVM_lanai: | |
| 1104 | case ZigLLVM_renderscript32: | |
| 1105 | case ZigLLVM_renderscript64: | |
| 1106 | zig_panic("TODO implement target_dynamic_linker for this arch"); | |
| 1107 | } | |
| 1108 | zig_unreachable(); | |
| 932 | 1109 | } |
| 933 | } else if (arch == ZigLLVM_mips || arch == ZigLLVM_mipsel || | |
| 934 | arch == ZigLLVM_mips64 || arch == ZigLLVM_mips64el) | |
| 935 | { | |
| 936 | // when you want to solve this TODO, grep clang codebase for | |
| 937 | // getLinuxDynamicLinker | |
| 938 | zig_panic("TODO figure out MIPS dynamic linker name"); | |
| 939 | } else if (arch == ZigLLVM_ppc) { | |
| 940 | return buf_create_from_str("/lib/ld.so.1"); | |
| 941 | } else if (arch == ZigLLVM_ppc64) { | |
| 942 | return buf_create_from_str("/lib64/ld64.so.2"); | |
| 943 | } else if (arch == ZigLLVM_ppc64le) { | |
| 944 | return buf_create_from_str("/lib64/ld64.so.2"); | |
| 945 | } else if (arch == ZigLLVM_systemz) { | |
| 946 | return buf_create_from_str("/lib64/ld64.so.1"); | |
| 947 | } else if (arch == ZigLLVM_sparcv9) { | |
| 948 | return buf_create_from_str("/lib64/ld-linux.so.2"); | |
| 949 | } else if (arch == ZigLLVM_x86_64 && | |
| 950 | env == ZigLLVM_GNUX32) | |
| 951 | { | |
| 952 | return buf_create_from_str("/libx32/ld-linux-x32.so.2"); | |
| 953 | } else if (arch == ZigLLVM_x86_64 && | |
| 954 | (env == ZigLLVM_Musl || env == ZigLLVM_MuslEABI || env == ZigLLVM_MuslEABIHF)) | |
| 955 | { | |
| 956 | return buf_create_from_str("/lib/ld-musl-x86_64.so.1"); | |
| 957 | } else { | |
| 958 | return buf_create_from_str("/lib64/ld-linux-x86-64.so.2"); | |
| 1110 | case OsFreestanding: | |
| 1111 | case OsIOS: | |
| 1112 | case OsTvOS: | |
| 1113 | case OsWatchOS: | |
| 1114 | case OsMacOSX: | |
| 1115 | return nullptr; | |
| 1116 | ||
| 1117 | case OsAnanas: | |
| 1118 | case OsCloudABI: | |
| 1119 | case OsDragonFly: | |
| 1120 | case OsFuchsia: | |
| 1121 | case OsKFreeBSD: | |
| 1122 | case OsLv2: | |
| 1123 | case OsOpenBSD: | |
| 1124 | case OsSolaris: | |
| 1125 | case OsWindows: | |
| 1126 | case OsHaiku: | |
| 1127 | case OsMinix: | |
| 1128 | case OsRTEMS: | |
| 1129 | case OsNaCl: | |
| 1130 | case OsCNK: | |
| 1131 | case OsAIX: | |
| 1132 | case OsCUDA: | |
| 1133 | case OsNVCL: | |
| 1134 | case OsAMDHSA: | |
| 1135 | case OsPS4: | |
| 1136 | case OsELFIAMCU: | |
| 1137 | case OsMesa3D: | |
| 1138 | case OsContiki: | |
| 1139 | case OsAMDPAL: | |
| 1140 | case OsZen: | |
| 1141 | case OsUefi: | |
| 1142 | zig_panic("TODO implement target_dynamic_linker for this OS"); | |
| 959 | 1143 | } |
| 1144 | zig_unreachable(); | |
| 960 | 1145 | } |
| 961 | 1146 | |
| 962 | 1147 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) { |
| ... | ... | @@ -967,15 +1152,15 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target |
| 967 | 1152 | return true; |
| 968 | 1153 | } |
| 969 | 1154 | |
| 970 | if (guest_target->os == host_target->os && guest_target->arch.arch == host_target->arch.arch && | |
| 971 | guest_target->arch.sub_arch == host_target->arch.sub_arch) | |
| 1155 | if (guest_target->os == host_target->os && guest_target->arch == host_target->arch && | |
| 1156 | guest_target->sub_arch == host_target->sub_arch) | |
| 972 | 1157 | { |
| 973 | 1158 | // OS, arch, and sub-arch match |
| 974 | 1159 | return true; |
| 975 | 1160 | } |
| 976 | 1161 | |
| 977 | 1162 | if (guest_target->os == OsWindows && host_target->os == OsWindows && |
| 978 | host_target->arch.arch == ZigLLVM_x86_64 && guest_target->arch.arch == ZigLLVM_x86) | |
| 1163 | host_target->arch == ZigLLVM_x86_64 && guest_target->arch == ZigLLVM_x86) | |
| 979 | 1164 | { |
| 980 | 1165 | // 64-bit windows can run 32-bit programs |
| 981 | 1166 | return true; |
| ... | ... | @@ -984,8 +1169,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target |
| 984 | 1169 | return false; |
| 985 | 1170 | } |
| 986 | 1171 | |
| 987 | const char *arch_stack_pointer_register_name(const ArchType *arch) { | |
| 988 | switch (arch->arch) { | |
| 1172 | const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { | |
| 1173 | switch (arch) { | |
| 989 | 1174 | case ZigLLVM_UnknownArch: |
| 990 | 1175 | zig_unreachable(); |
| 991 | 1176 | case ZigLLVM_x86: |
| ... | ... | @@ -1047,7 +1232,7 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) { |
| 1047 | 1232 | } |
| 1048 | 1233 | |
| 1049 | 1234 | bool target_is_arm(const ZigTarget *target) { |
| 1050 | switch (target->arch.arch) { | |
| 1235 | switch (target->arch) { | |
| 1051 | 1236 | case ZigLLVM_UnknownArch: |
| 1052 | 1237 | zig_unreachable(); |
| 1053 | 1238 | case ZigLLVM_aarch64: |
| ... | ... | @@ -1105,3 +1290,73 @@ bool target_is_arm(const ZigTarget *target) { |
| 1105 | 1290 | } |
| 1106 | 1291 | zig_unreachable(); |
| 1107 | 1292 | } |
| 1293 | ||
| 1294 | // Valgrind supports more, but Zig does not support them yet. | |
| 1295 | bool target_has_valgrind_support(const ZigTarget *target) { | |
| 1296 | switch (target->arch) { | |
| 1297 | case ZigLLVM_UnknownArch: | |
| 1298 | zig_unreachable(); | |
| 1299 | case ZigLLVM_x86_64: | |
| 1300 | return (target->os == OsLinux || target_is_darwin(target) || target->os == OsSolaris || | |
| 1301 | (target->os == OsWindows && target->abi != ZigLLVM_MSVC)); | |
| 1302 | default: | |
| 1303 | return false; | |
| 1304 | } | |
| 1305 | zig_unreachable(); | |
| 1306 | } | |
| 1307 | ||
| 1308 | bool target_requires_libc(const ZigTarget *target) { | |
| 1309 | // On Darwin, we always link libSystem which contains libc. | |
| 1310 | // Similarly on FreeBSD and NetBSD we always link system libc | |
| 1311 | // since this is the stable syscall interface. | |
| 1312 | return (target_is_darwin(target) || target->os == OsFreeBSD || target->os == OsNetBSD); | |
| 1313 | } | |
| 1314 | ||
| 1315 | bool target_supports_fpic(const ZigTarget *target) { | |
| 1316 | // This is not whether the target supports Position Independent Code, but whether the -fPIC | |
| 1317 | // C compiler argument is valid. | |
| 1318 | return target->os != OsWindows; | |
| 1319 | } | |
| 1320 | ||
| 1321 | ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { | |
| 1322 | switch (os) { | |
| 1323 | case OsFreestanding: | |
| 1324 | case OsAnanas: | |
| 1325 | case OsCloudABI: | |
| 1326 | case OsDragonFly: | |
| 1327 | case OsLv2: | |
| 1328 | case OsSolaris: | |
| 1329 | case OsHaiku: | |
| 1330 | case OsMinix: | |
| 1331 | case OsRTEMS: | |
| 1332 | case OsNaCl: | |
| 1333 | case OsCNK: | |
| 1334 | case OsAIX: | |
| 1335 | case OsCUDA: | |
| 1336 | case OsNVCL: | |
| 1337 | case OsAMDHSA: | |
| 1338 | case OsPS4: | |
| 1339 | case OsELFIAMCU: | |
| 1340 | case OsMesa3D: | |
| 1341 | case OsContiki: | |
| 1342 | case OsAMDPAL: | |
| 1343 | case OsZen: | |
| 1344 | return ZigLLVM_EABI; | |
| 1345 | case OsOpenBSD: | |
| 1346 | case OsMacOSX: | |
| 1347 | case OsFreeBSD: | |
| 1348 | case OsIOS: | |
| 1349 | case OsTvOS: | |
| 1350 | case OsWatchOS: | |
| 1351 | case OsFuchsia: | |
| 1352 | case OsKFreeBSD: | |
| 1353 | case OsNetBSD: | |
| 1354 | return ZigLLVM_GNU; | |
| 1355 | case OsWindows: | |
| 1356 | case OsUefi: | |
| 1357 | return ZigLLVM_MSVC; | |
| 1358 | case OsLinux: | |
| 1359 | return ZigLLVM_Musl; | |
| 1360 | } | |
| 1361 | zig_unreachable(); | |
| 1362 | } |
src/target.hpp+54-31| ... | ... | @@ -12,11 +12,6 @@ |
| 12 | 12 | |
| 13 | 13 | struct Buf; |
| 14 | 14 | |
| 15 | struct ArchType { | |
| 16 | ZigLLVM_ArchType arch; | |
| 17 | ZigLLVM_SubArchType sub_arch; | |
| 18 | }; | |
| 19 | ||
| 20 | 15 | // Synchronize with target.cpp::os_list |
| 21 | 16 | enum Os { |
| 22 | 17 | OsFreestanding, |
| ... | ... | @@ -57,6 +52,15 @@ enum Os { |
| 57 | 52 | OsUefi, |
| 58 | 53 | }; |
| 59 | 54 | |
| 55 | // Synchronize with target.cpp::subarch_list_list | |
| 56 | enum SubArchList { | |
| 57 | SubArchListNone, | |
| 58 | SubArchListArm32, | |
| 59 | SubArchListArm64, | |
| 60 | SubArchListKalimba, | |
| 61 | SubArchListMips, | |
| 62 | }; | |
| 63 | ||
| 60 | 64 | enum TargetSubsystem { |
| 61 | 65 | TargetSubsystemAuto, // Zig should infer the subsystem |
| 62 | 66 | TargetSubsystemConsole, |
| ... | ... | @@ -70,11 +74,12 @@ enum TargetSubsystem { |
| 70 | 74 | }; |
| 71 | 75 | |
| 72 | 76 | struct ZigTarget { |
| 73 | ArchType arch; | |
| 77 | ZigLLVM_ArchType arch; | |
| 78 | ZigLLVM_SubArchType sub_arch; | |
| 74 | 79 | ZigLLVM_VendorType vendor; |
| 75 | 80 | Os os; |
| 76 | ZigLLVM_EnvironmentType env_type; | |
| 77 | ZigLLVM_ObjectFormatType oformat; | |
| 81 | ZigLLVM_EnvironmentType abi; | |
| 82 | bool is_native; | |
| 78 | 83 | }; |
| 79 | 84 | |
| 80 | 85 | enum CIntType { |
| ... | ... | @@ -90,53 +95,71 @@ enum CIntType { |
| 90 | 95 | CIntTypeCount, |
| 91 | 96 | }; |
| 92 | 97 | |
| 98 | Error target_parse_triple(ZigTarget *target, const char *triple); | |
| 99 | Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub, | |
| 100 | const char *archsub_ptr, size_t archsub_len); | |
| 101 | Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); | |
| 102 | Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len); | |
| 103 | ||
| 93 | 104 | size_t target_arch_count(void); |
| 94 | const ArchType *get_target_arch(size_t index); | |
| 95 | void get_arch_name(char *out_str, const ArchType *arch); | |
| 105 | ZigLLVM_ArchType target_arch_enum(size_t index); | |
| 106 | const char *target_arch_name(ZigLLVM_ArchType arch); | |
| 107 | ||
| 108 | SubArchList target_subarch_list(ZigLLVM_ArchType arch); | |
| 109 | size_t target_subarch_count(SubArchList sub_arch_list); | |
| 110 | ZigLLVM_SubArchType target_subarch_enum(SubArchList subarch_list, size_t index); | |
| 111 | const char *target_subarch_name(ZigLLVM_SubArchType subarch); | |
| 96 | 112 | |
| 97 | const char *arch_stack_pointer_register_name(const ArchType *arch); | |
| 113 | size_t target_subarch_list_count(void); | |
| 114 | SubArchList target_subarch_list_enum(size_t index); | |
| 115 | const char *target_subarch_list_name(SubArchList sub_arch_list); | |
| 116 | ||
| 117 | const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch); | |
| 98 | 118 | |
| 99 | 119 | size_t target_vendor_count(void); |
| 100 | ZigLLVM_VendorType get_target_vendor(size_t index); | |
| 120 | ZigLLVM_VendorType target_vendor_enum(size_t index); | |
| 101 | 121 | |
| 102 | 122 | size_t target_os_count(void); |
| 103 | Os get_target_os(size_t index); | |
| 104 | const char *get_target_os_name(Os os_type); | |
| 123 | Os target_os_enum(size_t index); | |
| 124 | const char *target_os_name(Os os_type); | |
| 105 | 125 | |
| 106 | size_t target_environ_count(void); | |
| 107 | ZigLLVM_EnvironmentType get_target_environ(size_t index); | |
| 126 | size_t target_abi_count(void); | |
| 127 | ZigLLVM_EnvironmentType target_abi_enum(size_t index); | |
| 128 | const char *target_abi_name(ZigLLVM_EnvironmentType abi); | |
| 129 | ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os); | |
| 108 | 130 | |
| 109 | 131 | |
| 110 | 132 | size_t target_oformat_count(void); |
| 111 | const ZigLLVM_ObjectFormatType get_target_oformat(size_t index); | |
| 112 | const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat); | |
| 133 | ZigLLVM_ObjectFormatType target_oformat_enum(size_t index); | |
| 134 | const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat); | |
| 135 | ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target); | |
| 113 | 136 | |
| 114 | 137 | void get_native_target(ZigTarget *target); |
| 115 | void get_unknown_target(ZigTarget *target); | |
| 116 | ||
| 117 | int parse_target_arch(const char *str, ArchType *arch); | |
| 118 | int parse_target_os(const char *str, Os *os); | |
| 119 | int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *env_type); | |
| 138 | void get_target_triple(Buf *triple, const ZigTarget *target); | |
| 120 | 139 | |
| 121 | 140 | void init_all_targets(void); |
| 122 | 141 | |
| 123 | void get_target_triple(Buf *triple, const ZigTarget *target); | |
| 124 | ||
| 125 | 142 | void resolve_target_object_format(ZigTarget *target); |
| 126 | 143 | |
| 127 | 144 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id); |
| 128 | 145 | |
| 129 | const char *target_o_file_ext(ZigTarget *target); | |
| 130 | const char *target_asm_file_ext(ZigTarget *target); | |
| 131 | const char *target_llvm_ir_file_ext(ZigTarget *target); | |
| 132 | const char *target_exe_file_ext(ZigTarget *target); | |
| 133 | const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch); | |
| 146 | const char *target_o_file_ext(const ZigTarget *target); | |
| 147 | const char *target_asm_file_ext(const ZigTarget *target); | |
| 148 | const char *target_llvm_ir_file_ext(const ZigTarget *target); | |
| 149 | const char *target_exe_file_ext(const ZigTarget *target); | |
| 150 | const char *target_lib_file_ext(const ZigTarget *target, bool is_static, | |
| 151 | size_t version_major, size_t version_minor, size_t version_patch); | |
| 134 | 152 | |
| 135 | Buf *target_dynamic_linker(ZigTarget *target); | |
| 153 | const char *target_dynamic_linker(const ZigTarget *target); | |
| 136 | 154 | |
| 137 | 155 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); |
| 138 | 156 | ZigLLVM_OSType get_llvm_os_type(Os os_type); |
| 139 | 157 | |
| 140 | 158 | bool target_is_arm(const ZigTarget *target); |
| 159 | bool target_allows_addr_zero(const ZigTarget *target); | |
| 160 | bool target_has_valgrind_support(const ZigTarget *target); | |
| 161 | bool target_is_darwin(const ZigTarget *target); | |
| 162 | bool target_requires_libc(const ZigTarget *target); | |
| 163 | bool target_supports_fpic(const ZigTarget *target); | |
| 141 | 164 | |
| 142 | 165 | #endif |
src/tokenizer.cpp+18-1| ... | ... | @@ -221,6 +221,7 @@ enum TokenizeState { |
| 221 | 221 | TokenizeStateError, |
| 222 | 222 | TokenizeStateLBracket, |
| 223 | 223 | TokenizeStateLBracketStar, |
| 224 | TokenizeStateLBracketStarC, | |
| 224 | 225 | }; |
| 225 | 226 | |
| 226 | 227 | |
| ... | ... | @@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 846 | 847 | switch (c) { |
| 847 | 848 | case '*': |
| 848 | 849 | t.state = TokenizeStateLBracketStar; |
| 849 | set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket); | |
| 850 | 850 | break; |
| 851 | 851 | default: |
| 852 | 852 | // reinterpret as just an lbracket |
| ... | ... | @@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 857 | 857 | } |
| 858 | 858 | break; |
| 859 | 859 | case TokenizeStateLBracketStar: |
| 860 | switch (c) { | |
| 861 | case 'c': | |
| 862 | t.state = TokenizeStateLBracketStarC; | |
| 863 | set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket); | |
| 864 | break; | |
| 865 | case ']': | |
| 866 | set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket); | |
| 867 | end_token(&t); | |
| 868 | t.state = TokenizeStateStart; | |
| 869 | break; | |
| 870 | default: | |
| 871 | invalid_char_error(&t, c); | |
| 872 | } | |
| 873 | break; | |
| 874 | case TokenizeStateLBracketStarC: | |
| 860 | 875 | switch (c) { |
| 861 | 876 | case ']': |
| 862 | 877 | end_token(&t); |
| ... | ... | @@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1491 | 1506 | case TokenizeStateLineStringContinue: |
| 1492 | 1507 | case TokenizeStateLineStringContinueC: |
| 1493 | 1508 | case TokenizeStateLBracketStar: |
| 1509 | case TokenizeStateLBracketStarC: | |
| 1494 | 1510 | tokenize_error(&t, "unexpected EOF"); |
| 1495 | 1511 | break; |
| 1496 | 1512 | case TokenizeStateLineComment: |
| ... | ... | @@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) { |
| 1528 | 1544 | case TokenIdBitShiftRightEq: return ">>="; |
| 1529 | 1545 | case TokenIdBitXorEq: return "^="; |
| 1530 | 1546 | case TokenIdBracketStarBracket: return "[*]"; |
| 1547 | case TokenIdBracketStarCBracket: return "[*c]"; | |
| 1531 | 1548 | case TokenIdCharLiteral: return "CharLiteral"; |
| 1532 | 1549 | case TokenIdCmpEq: return "=="; |
| 1533 | 1550 | case TokenIdCmpGreaterOrEq: return ">="; |
src/tokenizer.hpp+1| ... | ... | @@ -29,6 +29,7 @@ enum TokenId { |
| 29 | 29 | TokenIdBitShiftRightEq, |
| 30 | 30 | TokenIdBitXorEq, |
| 31 | 31 | TokenIdBracketStarBracket, |
| 32 | TokenIdBracketStarCBracket, | |
| 32 | 33 | TokenIdCharLiteral, |
| 33 | 34 | TokenIdCmpEq, |
| 34 | 35 | TokenIdCmpGreaterOrEq, |
src/translate_c.cpp+945-1697| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | * This file is part of zig, which is MIT licensed. |
| 5 | 5 | * See http://opensource.org/licenses/MIT |
| 6 | 6 | */ |
| 7 | ||
| 8 | 7 | #include "all_types.hpp" |
| 9 | 8 | #include "analyze.hpp" |
| 10 | 9 | #include "c_tokenizer.hpp" |
| ... | ... | @@ -13,7 +12,7 @@ |
| 13 | 12 | #include "os.hpp" |
| 14 | 13 | #include "translate_c.hpp" |
| 15 | 14 | #include "parser.hpp" |
| 16 | ||
| 15 | #include "zig_clang.h" | |
| 17 | 16 | |
| 18 | 17 | #if __GNUC__ >= 8 |
| 19 | 18 | #pragma GCC diagnostic push |
| ... | ... | @@ -30,8 +29,6 @@ |
| 30 | 29 | |
| 31 | 30 | #include <string.h> |
| 32 | 31 | |
| 33 | using namespace clang; | |
| 34 | ||
| 35 | 32 | struct Alias { |
| 36 | 33 | Buf *new_name; |
| 37 | 34 | Buf *canon_name; |
| ... | ... | @@ -87,13 +84,13 @@ struct Context { |
| 87 | 84 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; |
| 88 | 85 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; |
| 89 | 86 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; |
| 90 | SourceManager *source_manager; | |
| 87 | ZigClangSourceManager *source_manager; | |
| 91 | 88 | ZigList<Alias> aliases; |
| 92 | 89 | AstNode *source_node; |
| 93 | 90 | bool warnings_on; |
| 94 | 91 | |
| 95 | 92 | CodeGen *codegen; |
| 96 | ASTContext *ctx; | |
| 93 | ZigClangASTContext *ctx; | |
| 97 | 94 | |
| 98 | 95 | TransScopeRoot *global_scope; |
| 99 | 96 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; |
| ... | ... | @@ -117,22 +114,38 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren |
| 117 | 114 | |
| 118 | 115 | static TransScopeBlock *trans_scope_block_find(TransScope *scope); |
| 119 | 116 | |
| 120 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); | |
| 121 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); | |
| 122 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); | |
| 117 | static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl); | |
| 118 | static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl); | |
| 119 | static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl); | |
| 123 | 120 | |
| 124 | static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | |
| 121 | static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt, | |
| 125 | 122 | ResultUsed result_used, TransLRValue lrval, |
| 126 | 123 | AstNode **out_node, TransScope **out_child_scope, |
| 127 | 124 | TransScope **out_node_scope); |
| 128 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); | |
| 129 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | |
| 130 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | |
| 131 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | |
| 132 | static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc); | |
| 125 | static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node); | |
| 126 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); | |
| 127 | static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc); | |
| 128 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); | |
| 129 | static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc); | |
| 130 | ||
| 131 | static ZigClangSourceLocation bitcast(clang::SourceLocation src) { | |
| 132 | ZigClangSourceLocation dest; | |
| 133 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangSourceLocation)); | |
| 134 | return dest; | |
| 135 | } | |
| 136 | static ZigClangQualType bitcast(clang::QualType src) { | |
| 137 | ZigClangQualType dest; | |
| 138 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); | |
| 139 | return dest; | |
| 140 | } | |
| 141 | static clang::QualType bitcast(ZigClangQualType src) { | |
| 142 | clang::QualType dest; | |
| 143 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); | |
| 144 | return dest; | |
| 145 | } | |
| 133 | 146 | |
| 134 | 147 | ATTRIBUTE_PRINTF(3, 4) |
| 135 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | |
| 148 | static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) { | |
| 136 | 149 | if (!c->warnings_on) { |
| 137 | 150 | return; |
| 138 | 151 | } |
| ... | ... | @@ -142,16 +155,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma |
| 142 | 155 | Buf *msg = buf_vprintf(format, ap); |
| 143 | 156 | va_end(ap); |
| 144 | 157 | |
| 145 | StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl)); | |
| 146 | const char *filename_bytes = (const char *)filename.bytes_begin(); | |
| 158 | ZigClangSourceLocation sl = bitcast(clang_sl); | |
| 159 | const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager, | |
| 160 | ZigClangSourceManager_getSpellingLoc(c->source_manager, sl)); | |
| 147 | 161 | Buf *path; |
| 148 | 162 | if (filename_bytes) { |
| 149 | 163 | path = buf_create_from_str(filename_bytes); |
| 150 | 164 | } else { |
| 151 | 165 | path = buf_sprintf("(no file)"); |
| 152 | 166 | } |
| 153 | unsigned line = c->source_manager->getSpellingLineNumber(sl); | |
| 154 | unsigned column = c->source_manager->getSpellingColumnNumber(sl); | |
| 167 | unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl); | |
| 168 | unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl); | |
| 155 | 169 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); |
| 156 | 170 | } |
| 157 | 171 | |
| ... | ... | @@ -292,11 +306,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod |
| 292 | 306 | node); |
| 293 | 307 | } |
| 294 | 308 | |
| 309 | static TokenId ptr_len_to_token_id(PtrLen ptr_len) { | |
| 310 | switch (ptr_len) { | |
| 311 | case PtrLenSingle: | |
| 312 | return TokenIdStar; | |
| 313 | case PtrLenUnknown: | |
| 314 | return TokenIdBracketStarBracket; | |
| 315 | case PtrLenC: | |
| 316 | return TokenIdBracketStarCBracket; | |
| 317 | } | |
| 318 | zig_unreachable(); | |
| 319 | } | |
| 320 | ||
| 295 | 321 | static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) { |
| 296 | 322 | AstNode *node = trans_create_node(c, NodeTypePointerType); |
| 297 | 323 | node->data.pointer_type.star_token = allocate<ZigToken>(1); |
| 298 | node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket; | |
| 299 | node->data.pointer_type.is_const = is_const; | |
| 324 | node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len); | |
| 300 | 325 | node->data.pointer_type.is_const = is_const; |
| 301 | 326 | node->data.pointer_type.is_volatile = is_volatile; |
| 302 | 327 | node->data.pointer_type.op_expr = child_node; |
| ... | ... | @@ -461,15 +486,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) { |
| 461 | 486 | return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size()); |
| 462 | 487 | } |
| 463 | 488 | |
| 464 | static const char *decl_name(const Decl *decl) { | |
| 465 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | |
| 489 | static const char *decl_name(const clang::Decl *decl) { | |
| 490 | const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl); | |
| 466 | 491 | return (const char *)named_decl->getName().bytes_begin(); |
| 467 | 492 | } |
| 468 | 493 | |
| 469 | 494 | static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { |
| 470 | 495 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 471 | 496 | node->data.int_literal.bigint = allocate<BigInt>(1); |
| 472 | bool is_negative = aps_int.isNegative(); | |
| 497 | bool is_negative = aps_int.isSigned() && aps_int.isNegative(); | |
| 473 | 498 | if (!is_negative) { |
| 474 | 499 | bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false); |
| 475 | 500 | return node; |
| ... | ... | @@ -480,41 +505,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 480 | 505 | |
| 481 | 506 | } |
| 482 | 507 | |
| 483 | static const Type *qual_type_canon(QualType qt) { | |
| 508 | static const clang::Type *qual_type_canon(clang::QualType qt) { | |
| 484 | 509 | return qt.getCanonicalType().getTypePtr(); |
| 485 | 510 | } |
| 486 | 511 | |
| 487 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { | |
| 512 | static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) { | |
| 488 | 513 | // String literals in C are `char *` but they should really be `const char *`. |
| 489 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | |
| 490 | const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr); | |
| 491 | if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) { | |
| 492 | const Expr *sub_expr = cast_expr->getSubExpr(); | |
| 493 | if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) { | |
| 494 | QualType array_qt = sub_expr->getType(); | |
| 495 | const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr()); | |
| 496 | QualType pointee_qt = array_type->getElementType(); | |
| 514 | if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { | |
| 515 | const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr); | |
| 516 | if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) { | |
| 517 | const clang::Expr *sub_expr = cast_expr->getSubExpr(); | |
| 518 | if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) { | |
| 519 | clang::QualType array_qt = sub_expr->getType(); | |
| 520 | const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr()); | |
| 521 | clang::QualType pointee_qt = array_type->getElementType(); | |
| 497 | 522 | pointee_qt.addConst(); |
| 498 | return c->ctx->getPointerType(pointee_qt); | |
| 523 | return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt))); | |
| 499 | 524 | } |
| 500 | 525 | } |
| 501 | 526 | } |
| 502 | 527 | return expr->getType(); |
| 503 | 528 | } |
| 504 | 529 | |
| 505 | static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) { | |
| 506 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | |
| 507 | const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr); | |
| 530 | static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) { | |
| 531 | if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { | |
| 532 | const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr); | |
| 508 | 533 | return get_expr_qual_type(c, cast_expr->getSubExpr()); |
| 509 | 534 | } |
| 510 | 535 | return expr->getType(); |
| 511 | 536 | } |
| 512 | 537 | |
| 513 | static AstNode *get_expr_type(Context *c, const Expr *expr) { | |
| 538 | static AstNode *get_expr_type(Context *c, const clang::Expr *expr) { | |
| 514 | 539 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc()); |
| 515 | 540 | } |
| 516 | 541 | |
| 517 | static bool qual_types_equal(QualType t1, QualType t2) { | |
| 542 | static bool qual_types_equal(clang::QualType t1, clang::QualType t2) { | |
| 518 | 543 | if (t1.isConstQualified() != t2.isConstQualified()) { |
| 519 | 544 | return false; |
| 520 | 545 | } |
| ... | ... | @@ -531,37 +556,37 @@ static bool is_c_void_type(AstNode *node) { |
| 531 | 556 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 532 | 557 | } |
| 533 | 558 | |
| 534 | static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) { | |
| 535 | QualType t1 = get_expr_qual_type(c, expr1); | |
| 536 | QualType t2 = get_expr_qual_type(c, expr2); | |
| 559 | static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) { | |
| 560 | clang::QualType t1 = get_expr_qual_type(c, expr1); | |
| 561 | clang::QualType t2 = get_expr_qual_type(c, expr2); | |
| 537 | 562 | |
| 538 | 563 | return qual_types_equal(t1, t2); |
| 539 | 564 | } |
| 540 | 565 | |
| 541 | static bool qual_type_is_ptr(QualType qt) { | |
| 542 | const Type *ty = qual_type_canon(qt); | |
| 543 | return ty->getTypeClass() == Type::Pointer; | |
| 566 | static bool qual_type_is_ptr(clang::QualType qt) { | |
| 567 | const clang::Type *ty = qual_type_canon(qt); | |
| 568 | return ty->getTypeClass() == clang::Type::Pointer; | |
| 544 | 569 | } |
| 545 | 570 | |
| 546 | static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) { | |
| 547 | const Type *ty = qual_type_canon(qt); | |
| 571 | static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) { | |
| 572 | const clang::Type *ty = qual_type_canon(qt); | |
| 548 | 573 | *is_ptr = false; |
| 549 | 574 | |
| 550 | if (ty->getTypeClass() == Type::Pointer) { | |
| 575 | if (ty->getTypeClass() == clang::Type::Pointer) { | |
| 551 | 576 | *is_ptr = true; |
| 552 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | |
| 553 | QualType child_qt = pointer_ty->getPointeeType(); | |
| 577 | const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty); | |
| 578 | clang::QualType child_qt = pointer_ty->getPointeeType(); | |
| 554 | 579 | ty = child_qt.getTypePtr(); |
| 555 | 580 | } |
| 556 | 581 | |
| 557 | if (ty->getTypeClass() == Type::FunctionProto) { | |
| 558 | return static_cast<const FunctionProtoType*>(ty); | |
| 582 | if (ty->getTypeClass() == clang::Type::FunctionProto) { | |
| 583 | return static_cast<const clang::FunctionProtoType*>(ty); | |
| 559 | 584 | } |
| 560 | 585 | |
| 561 | 586 | return nullptr; |
| 562 | 587 | } |
| 563 | 588 | |
| 564 | static bool qual_type_is_fn_ptr(QualType qt) { | |
| 589 | static bool qual_type_is_fn_ptr(clang::QualType qt) { | |
| 565 | 590 | bool is_ptr; |
| 566 | 591 | if (qual_type_get_fn_proto(qt, &is_ptr)) { |
| 567 | 592 | return is_ptr; |
| ... | ... | @@ -570,30 +595,30 @@ static bool qual_type_is_fn_ptr(QualType qt) { |
| 570 | 595 | return false; |
| 571 | 596 | } |
| 572 | 597 | |
| 573 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { | |
| 574 | const Type *ty = qt.getTypePtr(); | |
| 598 | static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) { | |
| 599 | const clang::Type *ty = qt.getTypePtr(); | |
| 575 | 600 | switch (ty->getTypeClass()) { |
| 576 | case Type::Builtin: | |
| 601 | case clang::Type::Builtin: | |
| 577 | 602 | { |
| 578 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | |
| 603 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 579 | 604 | switch (builtin_ty->getKind()) { |
| 580 | case BuiltinType::Char_U: | |
| 581 | case BuiltinType::UChar: | |
| 582 | case BuiltinType::Char_S: | |
| 583 | case BuiltinType::SChar: | |
| 605 | case clang::BuiltinType::Char_U: | |
| 606 | case clang::BuiltinType::UChar: | |
| 607 | case clang::BuiltinType::Char_S: | |
| 608 | case clang::BuiltinType::SChar: | |
| 584 | 609 | return 8; |
| 585 | case BuiltinType::UInt128: | |
| 586 | case BuiltinType::Int128: | |
| 610 | case clang::BuiltinType::UInt128: | |
| 611 | case clang::BuiltinType::Int128: | |
| 587 | 612 | return 128; |
| 588 | 613 | default: |
| 589 | 614 | return 0; |
| 590 | 615 | } |
| 591 | 616 | zig_unreachable(); |
| 592 | 617 | } |
| 593 | case Type::Typedef: | |
| 618 | case clang::Type::Typedef: | |
| 594 | 619 | { |
| 595 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | |
| 596 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 620 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); | |
| 621 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 597 | 622 | const char *type_name = decl_name(typedef_decl); |
| 598 | 623 | if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) { |
| 599 | 624 | return 8; |
| ... | ... | @@ -614,8 +639,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So |
| 614 | 639 | } |
| 615 | 640 | |
| 616 | 641 | |
| 617 | static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, | |
| 618 | const SourceLocation &source_loc) | |
| 642 | static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt, | |
| 643 | const clang::SourceLocation &source_loc) | |
| 619 | 644 | { |
| 620 | 645 | uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc); |
| 621 | 646 | if (int_bit_width != 0) { |
| ... | ... | @@ -633,7 +658,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| 633 | 658 | // FieldAccess |
| 634 | 659 | // FnCall (.builtin = true) |
| 635 | 660 | // Symbol "import" |
| 636 | // StringLiteral "std" | |
| 661 | // clang::StringLiteral "std" | |
| 637 | 662 | // Symbol "math" |
| 638 | 663 | // Symbol "Log2Int" |
| 639 | 664 | // zig_type_node |
| ... | ... | @@ -647,21 +672,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| 647 | 672 | return log2int_fn_call; |
| 648 | 673 | } |
| 649 | 674 | |
| 650 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | |
| 651 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | |
| 652 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | |
| 653 | if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) { | |
| 675 | static bool qual_type_child_is_fn_proto(const clang::QualType &qt) { | |
| 676 | if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) { | |
| 677 | const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr()); | |
| 678 | if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) { | |
| 654 | 679 | return true; |
| 655 | 680 | } |
| 656 | } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) { | |
| 657 | const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr()); | |
| 681 | } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) { | |
| 682 | const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr()); | |
| 658 | 683 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); |
| 659 | 684 | } |
| 660 | 685 | return false; |
| 661 | 686 | } |
| 662 | 687 | |
| 663 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type, | |
| 664 | QualType src_type, AstNode *expr) | |
| 688 | static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type, | |
| 689 | clang::QualType src_type, AstNode *expr) | |
| 665 | 690 | { |
| 666 | 691 | if (qual_types_equal(dest_type, src_type)) { |
| 667 | 692 | return expr; |
| ... | ... | @@ -678,72 +703,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, |
| 678 | 703 | return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); |
| 679 | 704 | } |
| 680 | 705 | |
| 681 | static bool c_is_signed_integer(Context *c, QualType qt) { | |
| 682 | const Type *c_type = qual_type_canon(qt); | |
| 683 | if (c_type->getTypeClass() != Type::Builtin) | |
| 706 | static bool c_is_signed_integer(Context *c, clang::QualType qt) { | |
| 707 | const clang::Type *c_type = qual_type_canon(qt); | |
| 708 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 684 | 709 | return false; |
| 685 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | |
| 710 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 686 | 711 | switch (builtin_ty->getKind()) { |
| 687 | case BuiltinType::SChar: | |
| 688 | case BuiltinType::Short: | |
| 689 | case BuiltinType::Int: | |
| 690 | case BuiltinType::Long: | |
| 691 | case BuiltinType::LongLong: | |
| 692 | case BuiltinType::Int128: | |
| 693 | case BuiltinType::WChar_S: | |
| 712 | case clang::BuiltinType::SChar: | |
| 713 | case clang::BuiltinType::Short: | |
| 714 | case clang::BuiltinType::Int: | |
| 715 | case clang::BuiltinType::Long: | |
| 716 | case clang::BuiltinType::LongLong: | |
| 717 | case clang::BuiltinType::Int128: | |
| 718 | case clang::BuiltinType::WChar_S: | |
| 694 | 719 | return true; |
| 695 | 720 | default: |
| 696 | 721 | return false; |
| 697 | 722 | } |
| 698 | 723 | } |
| 699 | 724 | |
| 700 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | |
| 701 | const Type *c_type = qual_type_canon(qt); | |
| 702 | if (c_type->getTypeClass() != Type::Builtin) | |
| 725 | static bool c_is_unsigned_integer(Context *c, clang::QualType qt) { | |
| 726 | const clang::Type *c_type = qual_type_canon(qt); | |
| 727 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 703 | 728 | return false; |
| 704 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | |
| 729 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 705 | 730 | switch (builtin_ty->getKind()) { |
| 706 | case BuiltinType::Char_U: | |
| 707 | case BuiltinType::UChar: | |
| 708 | case BuiltinType::Char_S: | |
| 709 | case BuiltinType::UShort: | |
| 710 | case BuiltinType::UInt: | |
| 711 | case BuiltinType::ULong: | |
| 712 | case BuiltinType::ULongLong: | |
| 713 | case BuiltinType::UInt128: | |
| 714 | case BuiltinType::WChar_U: | |
| 731 | case clang::BuiltinType::Char_U: | |
| 732 | case clang::BuiltinType::UChar: | |
| 733 | case clang::BuiltinType::Char_S: | |
| 734 | case clang::BuiltinType::UShort: | |
| 735 | case clang::BuiltinType::UInt: | |
| 736 | case clang::BuiltinType::ULong: | |
| 737 | case clang::BuiltinType::ULongLong: | |
| 738 | case clang::BuiltinType::UInt128: | |
| 739 | case clang::BuiltinType::WChar_U: | |
| 715 | 740 | return true; |
| 716 | 741 | default: |
| 717 | 742 | return false; |
| 718 | 743 | } |
| 719 | 744 | } |
| 720 | 745 | |
| 721 | static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) { | |
| 722 | const Type *c_type = qual_type_canon(qt); | |
| 723 | if (c_type->getTypeClass() != Type::Builtin) | |
| 746 | static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) { | |
| 747 | const clang::Type *c_type = qual_type_canon(qt); | |
| 748 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 724 | 749 | return false; |
| 725 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | |
| 750 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 726 | 751 | return builtin_ty->getKind() == kind; |
| 727 | 752 | } |
| 728 | 753 | |
| 729 | static bool c_is_float(Context *c, QualType qt) { | |
| 730 | const Type *c_type = qt.getTypePtr(); | |
| 731 | if (c_type->getTypeClass() != Type::Builtin) | |
| 754 | static bool c_is_float(Context *c, clang::QualType qt) { | |
| 755 | const clang::Type *c_type = qt.getTypePtr(); | |
| 756 | if (c_type->getTypeClass() != clang::Type::Builtin) | |
| 732 | 757 | return false; |
| 733 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | |
| 758 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); | |
| 734 | 759 | switch (builtin_ty->getKind()) { |
| 735 | case BuiltinType::Half: | |
| 736 | case BuiltinType::Float: | |
| 737 | case BuiltinType::Double: | |
| 738 | case BuiltinType::Float128: | |
| 739 | case BuiltinType::LongDouble: | |
| 760 | case clang::BuiltinType::Half: | |
| 761 | case clang::BuiltinType::Float: | |
| 762 | case clang::BuiltinType::Double: | |
| 763 | case clang::BuiltinType::Float128: | |
| 764 | case clang::BuiltinType::LongDouble: | |
| 740 | 765 | return true; |
| 741 | 766 | default: |
| 742 | 767 | return false; |
| 743 | 768 | } |
| 744 | 769 | } |
| 745 | 770 | |
| 746 | static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { | |
| 771 | static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) { | |
| 747 | 772 | if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) { |
| 748 | 773 | // float and signed integer overflow is undefined behavior. |
| 749 | 774 | return false; |
| ... | ... | @@ -753,23 +778,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { |
| 753 | 778 | } |
| 754 | 779 | } |
| 755 | 780 | |
| 756 | static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) { | |
| 781 | static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { | |
| 757 | 782 | switch (ty->getTypeClass()) { |
| 758 | case Type::Builtin: { | |
| 759 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | |
| 760 | return builtin_ty->getKind() == BuiltinType::Void; | |
| 783 | case clang::Type::Builtin: { | |
| 784 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 785 | return builtin_ty->getKind() == clang::BuiltinType::Void; | |
| 761 | 786 | } |
| 762 | case Type::Record: { | |
| 763 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | |
| 787 | case clang::Type::Record: { | |
| 788 | const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty); | |
| 764 | 789 | return record_ty->getDecl()->getDefinition() == nullptr; |
| 765 | 790 | } |
| 766 | case Type::Elaborated: { | |
| 767 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | |
| 791 | case clang::Type::Elaborated: { | |
| 792 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); | |
| 768 | 793 | return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc); |
| 769 | 794 | } |
| 770 | case Type::Typedef: { | |
| 771 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | |
| 772 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 795 | case clang::Type::Typedef: { | |
| 796 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); | |
| 797 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 773 | 798 | return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc); |
| 774 | 799 | } |
| 775 | 800 | default: |
| ... | ... | @@ -777,136 +802,136 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou |
| 777 | 802 | } |
| 778 | 803 | } |
| 779 | 804 | |
| 780 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { | |
| 805 | static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { | |
| 781 | 806 | switch (ty->getTypeClass()) { |
| 782 | case Type::Builtin: | |
| 807 | case clang::Type::Builtin: | |
| 783 | 808 | { |
| 784 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | |
| 809 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 785 | 810 | switch (builtin_ty->getKind()) { |
| 786 | case BuiltinType::Void: | |
| 811 | case clang::BuiltinType::Void: | |
| 787 | 812 | return trans_create_node_symbol_str(c, "c_void"); |
| 788 | case BuiltinType::Bool: | |
| 813 | case clang::BuiltinType::Bool: | |
| 789 | 814 | return trans_create_node_symbol_str(c, "bool"); |
| 790 | case BuiltinType::Char_U: | |
| 791 | case BuiltinType::UChar: | |
| 792 | case BuiltinType::Char_S: | |
| 793 | case BuiltinType::Char8: | |
| 815 | case clang::BuiltinType::Char_U: | |
| 816 | case clang::BuiltinType::UChar: | |
| 817 | case clang::BuiltinType::Char_S: | |
| 818 | case clang::BuiltinType::Char8: | |
| 794 | 819 | return trans_create_node_symbol_str(c, "u8"); |
| 795 | case BuiltinType::SChar: | |
| 820 | case clang::BuiltinType::SChar: | |
| 796 | 821 | return trans_create_node_symbol_str(c, "i8"); |
| 797 | case BuiltinType::UShort: | |
| 822 | case clang::BuiltinType::UShort: | |
| 798 | 823 | return trans_create_node_symbol_str(c, "c_ushort"); |
| 799 | case BuiltinType::UInt: | |
| 824 | case clang::BuiltinType::UInt: | |
| 800 | 825 | return trans_create_node_symbol_str(c, "c_uint"); |
| 801 | case BuiltinType::ULong: | |
| 826 | case clang::BuiltinType::ULong: | |
| 802 | 827 | return trans_create_node_symbol_str(c, "c_ulong"); |
| 803 | case BuiltinType::ULongLong: | |
| 828 | case clang::BuiltinType::ULongLong: | |
| 804 | 829 | return trans_create_node_symbol_str(c, "c_ulonglong"); |
| 805 | case BuiltinType::Short: | |
| 830 | case clang::BuiltinType::Short: | |
| 806 | 831 | return trans_create_node_symbol_str(c, "c_short"); |
| 807 | case BuiltinType::Int: | |
| 832 | case clang::BuiltinType::Int: | |
| 808 | 833 | return trans_create_node_symbol_str(c, "c_int"); |
| 809 | case BuiltinType::Long: | |
| 834 | case clang::BuiltinType::Long: | |
| 810 | 835 | return trans_create_node_symbol_str(c, "c_long"); |
| 811 | case BuiltinType::LongLong: | |
| 836 | case clang::BuiltinType::LongLong: | |
| 812 | 837 | return trans_create_node_symbol_str(c, "c_longlong"); |
| 813 | case BuiltinType::UInt128: | |
| 838 | case clang::BuiltinType::UInt128: | |
| 814 | 839 | return trans_create_node_symbol_str(c, "u128"); |
| 815 | case BuiltinType::Int128: | |
| 840 | case clang::BuiltinType::Int128: | |
| 816 | 841 | return trans_create_node_symbol_str(c, "i128"); |
| 817 | case BuiltinType::Float: | |
| 842 | case clang::BuiltinType::Float: | |
| 818 | 843 | return trans_create_node_symbol_str(c, "f32"); |
| 819 | case BuiltinType::Double: | |
| 844 | case clang::BuiltinType::Double: | |
| 820 | 845 | return trans_create_node_symbol_str(c, "f64"); |
| 821 | case BuiltinType::Float128: | |
| 846 | case clang::BuiltinType::Float128: | |
| 822 | 847 | return trans_create_node_symbol_str(c, "f128"); |
| 823 | case BuiltinType::Float16: | |
| 848 | case clang::BuiltinType::Float16: | |
| 824 | 849 | return trans_create_node_symbol_str(c, "f16"); |
| 825 | case BuiltinType::LongDouble: | |
| 850 | case clang::BuiltinType::LongDouble: | |
| 826 | 851 | return trans_create_node_symbol_str(c, "c_longdouble"); |
| 827 | case BuiltinType::WChar_U: | |
| 828 | case BuiltinType::Char16: | |
| 829 | case BuiltinType::Char32: | |
| 830 | case BuiltinType::WChar_S: | |
| 831 | case BuiltinType::Half: | |
| 832 | case BuiltinType::NullPtr: | |
| 833 | case BuiltinType::ObjCId: | |
| 834 | case BuiltinType::ObjCClass: | |
| 835 | case BuiltinType::ObjCSel: | |
| 836 | case BuiltinType::OMPArraySection: | |
| 837 | case BuiltinType::Dependent: | |
| 838 | case BuiltinType::Overload: | |
| 839 | case BuiltinType::BoundMember: | |
| 840 | case BuiltinType::PseudoObject: | |
| 841 | case BuiltinType::UnknownAny: | |
| 842 | case BuiltinType::BuiltinFn: | |
| 843 | case BuiltinType::ARCUnbridgedCast: | |
| 844 | case BuiltinType::ShortAccum: | |
| 845 | case BuiltinType::Accum: | |
| 846 | case BuiltinType::LongAccum: | |
| 847 | case BuiltinType::UShortAccum: | |
| 848 | case BuiltinType::UAccum: | |
| 849 | case BuiltinType::ULongAccum: | |
| 850 | ||
| 851 | case BuiltinType::OCLImage1dRO: | |
| 852 | case BuiltinType::OCLImage1dArrayRO: | |
| 853 | case BuiltinType::OCLImage1dBufferRO: | |
| 854 | case BuiltinType::OCLImage2dRO: | |
| 855 | case BuiltinType::OCLImage2dArrayRO: | |
| 856 | case BuiltinType::OCLImage2dDepthRO: | |
| 857 | case BuiltinType::OCLImage2dArrayDepthRO: | |
| 858 | case BuiltinType::OCLImage2dMSAARO: | |
| 859 | case BuiltinType::OCLImage2dArrayMSAARO: | |
| 860 | case BuiltinType::OCLImage2dMSAADepthRO: | |
| 861 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | |
| 862 | case BuiltinType::OCLImage3dRO: | |
| 863 | case BuiltinType::OCLImage1dWO: | |
| 864 | case BuiltinType::OCLImage1dArrayWO: | |
| 865 | case BuiltinType::OCLImage1dBufferWO: | |
| 866 | case BuiltinType::OCLImage2dWO: | |
| 867 | case BuiltinType::OCLImage2dArrayWO: | |
| 868 | case BuiltinType::OCLImage2dDepthWO: | |
| 869 | case BuiltinType::OCLImage2dArrayDepthWO: | |
| 870 | case BuiltinType::OCLImage2dMSAAWO: | |
| 871 | case BuiltinType::OCLImage2dArrayMSAAWO: | |
| 872 | case BuiltinType::OCLImage2dMSAADepthWO: | |
| 873 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | |
| 874 | case BuiltinType::OCLImage3dWO: | |
| 875 | case BuiltinType::OCLImage1dRW: | |
| 876 | case BuiltinType::OCLImage1dArrayRW: | |
| 877 | case BuiltinType::OCLImage1dBufferRW: | |
| 878 | case BuiltinType::OCLImage2dRW: | |
| 879 | case BuiltinType::OCLImage2dArrayRW: | |
| 880 | case BuiltinType::OCLImage2dDepthRW: | |
| 881 | case BuiltinType::OCLImage2dArrayDepthRW: | |
| 882 | case BuiltinType::OCLImage2dMSAARW: | |
| 883 | case BuiltinType::OCLImage2dArrayMSAARW: | |
| 884 | case BuiltinType::OCLImage2dMSAADepthRW: | |
| 885 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | |
| 886 | case BuiltinType::OCLImage3dRW: | |
| 887 | case BuiltinType::OCLSampler: | |
| 888 | case BuiltinType::OCLEvent: | |
| 889 | case BuiltinType::OCLClkEvent: | |
| 890 | case BuiltinType::OCLQueue: | |
| 891 | case BuiltinType::OCLReserveID: | |
| 892 | case BuiltinType::ShortFract: | |
| 893 | case BuiltinType::Fract: | |
| 894 | case BuiltinType::LongFract: | |
| 895 | case BuiltinType::UShortFract: | |
| 896 | case BuiltinType::UFract: | |
| 897 | case BuiltinType::ULongFract: | |
| 898 | case BuiltinType::SatShortAccum: | |
| 899 | case BuiltinType::SatAccum: | |
| 900 | case BuiltinType::SatLongAccum: | |
| 901 | case BuiltinType::SatUShortAccum: | |
| 902 | case BuiltinType::SatUAccum: | |
| 903 | case BuiltinType::SatULongAccum: | |
| 904 | case BuiltinType::SatShortFract: | |
| 905 | case BuiltinType::SatFract: | |
| 906 | case BuiltinType::SatLongFract: | |
| 907 | case BuiltinType::SatUShortFract: | |
| 908 | case BuiltinType::SatUFract: | |
| 909 | case BuiltinType::SatULongFract: | |
| 852 | case clang::BuiltinType::WChar_U: | |
| 853 | case clang::BuiltinType::Char16: | |
| 854 | case clang::BuiltinType::Char32: | |
| 855 | case clang::BuiltinType::WChar_S: | |
| 856 | case clang::BuiltinType::Half: | |
| 857 | case clang::BuiltinType::NullPtr: | |
| 858 | case clang::BuiltinType::ObjCId: | |
| 859 | case clang::BuiltinType::ObjCClass: | |
| 860 | case clang::BuiltinType::ObjCSel: | |
| 861 | case clang::BuiltinType::OMPArraySection: | |
| 862 | case clang::BuiltinType::Dependent: | |
| 863 | case clang::BuiltinType::Overload: | |
| 864 | case clang::BuiltinType::BoundMember: | |
| 865 | case clang::BuiltinType::PseudoObject: | |
| 866 | case clang::BuiltinType::UnknownAny: | |
| 867 | case clang::BuiltinType::BuiltinFn: | |
| 868 | case clang::BuiltinType::ARCUnbridgedCast: | |
| 869 | case clang::BuiltinType::ShortAccum: | |
| 870 | case clang::BuiltinType::Accum: | |
| 871 | case clang::BuiltinType::LongAccum: | |
| 872 | case clang::BuiltinType::UShortAccum: | |
| 873 | case clang::BuiltinType::UAccum: | |
| 874 | case clang::BuiltinType::ULongAccum: | |
| 875 | ||
| 876 | case clang::BuiltinType::OCLImage1dRO: | |
| 877 | case clang::BuiltinType::OCLImage1dArrayRO: | |
| 878 | case clang::BuiltinType::OCLImage1dBufferRO: | |
| 879 | case clang::BuiltinType::OCLImage2dRO: | |
| 880 | case clang::BuiltinType::OCLImage2dArrayRO: | |
| 881 | case clang::BuiltinType::OCLImage2dDepthRO: | |
| 882 | case clang::BuiltinType::OCLImage2dArrayDepthRO: | |
| 883 | case clang::BuiltinType::OCLImage2dMSAARO: | |
| 884 | case clang::BuiltinType::OCLImage2dArrayMSAARO: | |
| 885 | case clang::BuiltinType::OCLImage2dMSAADepthRO: | |
| 886 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRO: | |
| 887 | case clang::BuiltinType::OCLImage3dRO: | |
| 888 | case clang::BuiltinType::OCLImage1dWO: | |
| 889 | case clang::BuiltinType::OCLImage1dArrayWO: | |
| 890 | case clang::BuiltinType::OCLImage1dBufferWO: | |
| 891 | case clang::BuiltinType::OCLImage2dWO: | |
| 892 | case clang::BuiltinType::OCLImage2dArrayWO: | |
| 893 | case clang::BuiltinType::OCLImage2dDepthWO: | |
| 894 | case clang::BuiltinType::OCLImage2dArrayDepthWO: | |
| 895 | case clang::BuiltinType::OCLImage2dMSAAWO: | |
| 896 | case clang::BuiltinType::OCLImage2dArrayMSAAWO: | |
| 897 | case clang::BuiltinType::OCLImage2dMSAADepthWO: | |
| 898 | case clang::BuiltinType::OCLImage2dArrayMSAADepthWO: | |
| 899 | case clang::BuiltinType::OCLImage3dWO: | |
| 900 | case clang::BuiltinType::OCLImage1dRW: | |
| 901 | case clang::BuiltinType::OCLImage1dArrayRW: | |
| 902 | case clang::BuiltinType::OCLImage1dBufferRW: | |
| 903 | case clang::BuiltinType::OCLImage2dRW: | |
| 904 | case clang::BuiltinType::OCLImage2dArrayRW: | |
| 905 | case clang::BuiltinType::OCLImage2dDepthRW: | |
| 906 | case clang::BuiltinType::OCLImage2dArrayDepthRW: | |
| 907 | case clang::BuiltinType::OCLImage2dMSAARW: | |
| 908 | case clang::BuiltinType::OCLImage2dArrayMSAARW: | |
| 909 | case clang::BuiltinType::OCLImage2dMSAADepthRW: | |
| 910 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRW: | |
| 911 | case clang::BuiltinType::OCLImage3dRW: | |
| 912 | case clang::BuiltinType::OCLSampler: | |
| 913 | case clang::BuiltinType::OCLEvent: | |
| 914 | case clang::BuiltinType::OCLClkEvent: | |
| 915 | case clang::BuiltinType::OCLQueue: | |
| 916 | case clang::BuiltinType::OCLReserveID: | |
| 917 | case clang::BuiltinType::ShortFract: | |
| 918 | case clang::BuiltinType::Fract: | |
| 919 | case clang::BuiltinType::LongFract: | |
| 920 | case clang::BuiltinType::UShortFract: | |
| 921 | case clang::BuiltinType::UFract: | |
| 922 | case clang::BuiltinType::ULongFract: | |
| 923 | case clang::BuiltinType::SatShortAccum: | |
| 924 | case clang::BuiltinType::SatAccum: | |
| 925 | case clang::BuiltinType::SatLongAccum: | |
| 926 | case clang::BuiltinType::SatUShortAccum: | |
| 927 | case clang::BuiltinType::SatUAccum: | |
| 928 | case clang::BuiltinType::SatULongAccum: | |
| 929 | case clang::BuiltinType::SatShortFract: | |
| 930 | case clang::BuiltinType::SatFract: | |
| 931 | case clang::BuiltinType::SatLongFract: | |
| 932 | case clang::BuiltinType::SatUShortFract: | |
| 933 | case clang::BuiltinType::SatUFract: | |
| 934 | case clang::BuiltinType::SatULongFract: | |
| 910 | 935 | case BuiltinType::OCLIntelSubgroupAVCMcePayload: |
| 911 | 936 | case BuiltinType::OCLIntelSubgroupAVCImePayload: |
| 912 | 937 | case BuiltinType::OCLIntelSubgroupAVCRefPayload: |
| ... | ... | @@ -924,10 +949,10 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 924 | 949 | } |
| 925 | 950 | break; |
| 926 | 951 | } |
| 927 | case Type::Pointer: | |
| 952 | case clang::Type::Pointer: | |
| 928 | 953 | { |
| 929 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | |
| 930 | QualType child_qt = pointer_ty->getPointeeType(); | |
| 954 | const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty); | |
| 955 | clang::QualType child_qt = pointer_ty->getPointeeType(); | |
| 931 | 956 | AstNode *child_node = trans_qual_type(c, child_qt, source_loc); |
| 932 | 957 | if (child_node == nullptr) { |
| 933 | 958 | emit_warning(c, source_loc, "pointer to unsupported type"); |
| ... | ... | @@ -938,90 +963,94 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 938 | 963 | return trans_create_node_prefix_op(c, PrefixOpOptional, child_node); |
| 939 | 964 | } |
| 940 | 965 | |
| 941 | PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown; | |
| 942 | ||
| 943 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 944 | child_qt.isVolatileQualified(), child_node, ptr_len); | |
| 945 | return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node); | |
| 966 | if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) { | |
| 967 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 968 | child_qt.isVolatileQualified(), child_node, PtrLenSingle); | |
| 969 | return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node); | |
| 970 | } else { | |
| 971 | return trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 972 | child_qt.isVolatileQualified(), child_node, PtrLenC); | |
| 973 | } | |
| 946 | 974 | } |
| 947 | case Type::Typedef: | |
| 975 | case clang::Type::Typedef: | |
| 948 | 976 | { |
| 949 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | |
| 950 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 977 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); | |
| 978 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 951 | 979 | return resolve_typedef_decl(c, typedef_decl); |
| 952 | 980 | } |
| 953 | case Type::Elaborated: | |
| 981 | case clang::Type::Elaborated: | |
| 954 | 982 | { |
| 955 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | |
| 983 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); | |
| 956 | 984 | switch (elaborated_ty->getKeyword()) { |
| 957 | case ETK_Struct: | |
| 958 | case ETK_Enum: | |
| 959 | case ETK_Union: | |
| 985 | case clang::ETK_Struct: | |
| 986 | case clang::ETK_Enum: | |
| 987 | case clang::ETK_Union: | |
| 960 | 988 | return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc); |
| 961 | case ETK_Interface: | |
| 962 | case ETK_Class: | |
| 963 | case ETK_Typename: | |
| 964 | case ETK_None: | |
| 989 | case clang::ETK_Interface: | |
| 990 | case clang::ETK_Class: | |
| 991 | case clang::ETK_Typename: | |
| 992 | case clang::ETK_None: | |
| 965 | 993 | emit_warning(c, source_loc, "unsupported elaborated type"); |
| 966 | 994 | return nullptr; |
| 967 | 995 | } |
| 968 | 996 | } |
| 969 | case Type::FunctionProto: | |
| 997 | case clang::Type::FunctionProto: | |
| 998 | case clang::Type::FunctionNoProto: | |
| 970 | 999 | { |
| 971 | const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty); | |
| 1000 | const clang::FunctionType *fn_ty = static_cast<const clang::FunctionType*>(ty); | |
| 972 | 1001 | |
| 973 | 1002 | AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); |
| 974 | switch (fn_proto_ty->getCallConv()) { | |
| 975 | case CC_C: // __attribute__((cdecl)) | |
| 1003 | switch (fn_ty->getCallConv()) { | |
| 1004 | case clang::CC_C: // __attribute__((cdecl)) | |
| 976 | 1005 | proto_node->data.fn_proto.cc = CallingConventionC; |
| 977 | 1006 | proto_node->data.fn_proto.is_extern = true; |
| 978 | 1007 | break; |
| 979 | case CC_X86StdCall: // __attribute__((stdcall)) | |
| 1008 | case clang::CC_X86StdCall: // __attribute__((stdcall)) | |
| 980 | 1009 | proto_node->data.fn_proto.cc = CallingConventionStdcall; |
| 981 | 1010 | break; |
| 982 | case CC_X86FastCall: // __attribute__((fastcall)) | |
| 1011 | case clang::CC_X86FastCall: // __attribute__((fastcall)) | |
| 983 | 1012 | emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); |
| 984 | 1013 | return nullptr; |
| 985 | case CC_X86ThisCall: // __attribute__((thiscall)) | |
| 1014 | case clang::CC_X86ThisCall: // __attribute__((thiscall)) | |
| 986 | 1015 | emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); |
| 987 | 1016 | return nullptr; |
| 988 | case CC_X86VectorCall: // __attribute__((vectorcall)) | |
| 1017 | case clang::CC_X86VectorCall: // __attribute__((vectorcall)) | |
| 989 | 1018 | emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); |
| 990 | 1019 | return nullptr; |
| 991 | case CC_X86Pascal: // __attribute__((pascal)) | |
| 1020 | case clang::CC_X86Pascal: // __attribute__((pascal)) | |
| 992 | 1021 | emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); |
| 993 | 1022 | return nullptr; |
| 994 | case CC_Win64: // __attribute__((ms_abi)) | |
| 1023 | case clang::CC_Win64: // __attribute__((ms_abi)) | |
| 995 | 1024 | emit_warning(c, source_loc, "unsupported calling convention: win64"); |
| 996 | 1025 | return nullptr; |
| 997 | case CC_X86_64SysV: // __attribute__((sysv_abi)) | |
| 1026 | case clang::CC_X86_64SysV: // __attribute__((sysv_abi)) | |
| 998 | 1027 | emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); |
| 999 | 1028 | return nullptr; |
| 1000 | case CC_X86RegCall: | |
| 1029 | case clang::CC_X86RegCall: | |
| 1001 | 1030 | emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); |
| 1002 | 1031 | return nullptr; |
| 1003 | case CC_AAPCS: // __attribute__((pcs("aapcs"))) | |
| 1032 | case clang::CC_AAPCS: // __attribute__((pcs("aapcs"))) | |
| 1004 | 1033 | emit_warning(c, source_loc, "unsupported calling convention: aapcs"); |
| 1005 | 1034 | return nullptr; |
| 1006 | case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | |
| 1035 | case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | |
| 1007 | 1036 | emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); |
| 1008 | 1037 | return nullptr; |
| 1009 | case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | |
| 1038 | case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | |
| 1010 | 1039 | emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); |
| 1011 | 1040 | return nullptr; |
| 1012 | case CC_SpirFunction: // default for OpenCL functions on SPIR target | |
| 1041 | case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target | |
| 1013 | 1042 | emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); |
| 1014 | 1043 | return nullptr; |
| 1015 | case CC_OpenCLKernel: | |
| 1044 | case clang::CC_OpenCLKernel: | |
| 1016 | 1045 | emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); |
| 1017 | 1046 | return nullptr; |
| 1018 | case CC_Swift: | |
| 1047 | case clang::CC_Swift: | |
| 1019 | 1048 | emit_warning(c, source_loc, "unsupported calling convention: Swift"); |
| 1020 | 1049 | return nullptr; |
| 1021 | case CC_PreserveMost: | |
| 1050 | case clang::CC_PreserveMost: | |
| 1022 | 1051 | emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); |
| 1023 | 1052 | return nullptr; |
| 1024 | case CC_PreserveAll: | |
| 1053 | case clang::CC_PreserveAll: | |
| 1025 | 1054 | emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); |
| 1026 | 1055 | return nullptr; |
| 1027 | 1056 | case CC_AArch64VectorCall: |
| ... | ... | @@ -1029,20 +1058,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1029 | 1058 | return nullptr; |
| 1030 | 1059 | } |
| 1031 | 1060 | |
| 1032 | proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic(); | |
| 1033 | size_t param_count = fn_proto_ty->getNumParams(); | |
| 1034 | ||
| 1035 | if (fn_proto_ty->getNoReturnAttr()) { | |
| 1061 | if (fn_ty->getNoReturnAttr()) { | |
| 1036 | 1062 | proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn"); |
| 1037 | 1063 | } else { |
| 1038 | proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(), | |
| 1064 | proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_ty->getReturnType(), | |
| 1039 | 1065 | source_loc); |
| 1040 | 1066 | if (proto_node->data.fn_proto.return_type == nullptr) { |
| 1041 | 1067 | emit_warning(c, source_loc, "unsupported function proto return type"); |
| 1042 | 1068 | return nullptr; |
| 1043 | 1069 | } |
| 1044 | 1070 | // convert c_void to actual void (only for return type) |
| 1045 | // we do want to look at the AstNode instead of QualType, because | |
| 1071 | // we do want to look at the AstNode instead of clang::QualType, because | |
| 1046 | 1072 | // if they do something like: |
| 1047 | 1073 | // typedef Foo void; |
| 1048 | 1074 | // void foo(void) -> Foo; |
| ... | ... | @@ -1058,8 +1084,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1058 | 1084 | proto_node->data.fn_proto.name = buf_create_from_str(fn_name); |
| 1059 | 1085 | } |
| 1060 | 1086 | |
| 1087 | if (ty->getTypeClass() == clang::Type::FunctionNoProto) { | |
| 1088 | return proto_node; | |
| 1089 | } | |
| 1090 | ||
| 1091 | const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty); | |
| 1092 | ||
| 1093 | proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic(); | |
| 1094 | size_t param_count = fn_proto_ty->getNumParams(); | |
| 1095 | ||
| 1061 | 1096 | for (size_t i = 0; i < param_count; i += 1) { |
| 1062 | QualType qt = fn_proto_ty->getParamType(i); | |
| 1097 | clang::QualType qt = fn_proto_ty->getParamType(i); | |
| 1063 | 1098 | AstNode *param_type_node = trans_qual_type(c, qt, source_loc); |
| 1064 | 1099 | |
| 1065 | 1100 | if (param_type_node == nullptr) { |
| ... | ... | @@ -1082,19 +1117,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1082 | 1117 | |
| 1083 | 1118 | return proto_node; |
| 1084 | 1119 | } |
| 1085 | case Type::Record: | |
| 1120 | case clang::Type::Record: | |
| 1086 | 1121 | { |
| 1087 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | |
| 1122 | const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty); | |
| 1088 | 1123 | return resolve_record_decl(c, record_ty->getDecl()); |
| 1089 | 1124 | } |
| 1090 | case Type::Enum: | |
| 1125 | case clang::Type::Enum: | |
| 1091 | 1126 | { |
| 1092 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | |
| 1127 | const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty); | |
| 1093 | 1128 | return resolve_enum_decl(c, enum_ty->getDecl()); |
| 1094 | 1129 | } |
| 1095 | case Type::ConstantArray: | |
| 1130 | case clang::Type::ConstantArray: | |
| 1096 | 1131 | { |
| 1097 | const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty); | |
| 1132 | const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty); | |
| 1098 | 1133 | AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); |
| 1099 | 1134 | if (child_type_node == nullptr) { |
| 1100 | 1135 | emit_warning(c, source_loc, "unresolved array element type"); |
| ... | ... | @@ -1104,84 +1139,83 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1104 | 1139 | AstNode *size_node = trans_create_node_unsigned(c, size); |
| 1105 | 1140 | return trans_create_node_array_type(c, size_node, child_type_node); |
| 1106 | 1141 | } |
| 1107 | case Type::Paren: | |
| 1142 | case clang::Type::Paren: | |
| 1108 | 1143 | { |
| 1109 | const ParenType *paren_ty = static_cast<const ParenType *>(ty); | |
| 1144 | const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty); | |
| 1110 | 1145 | return trans_qual_type(c, paren_ty->getInnerType(), source_loc); |
| 1111 | 1146 | } |
| 1112 | case Type::Decayed: | |
| 1147 | case clang::Type::Decayed: | |
| 1113 | 1148 | { |
| 1114 | const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty); | |
| 1149 | const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty); | |
| 1115 | 1150 | return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); |
| 1116 | 1151 | } |
| 1117 | case Type::Attributed: | |
| 1152 | case clang::Type::Attributed: | |
| 1118 | 1153 | { |
| 1119 | const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty); | |
| 1154 | const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty); | |
| 1120 | 1155 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); |
| 1121 | 1156 | } |
| 1122 | case Type::IncompleteArray: | |
| 1157 | case clang::Type::IncompleteArray: | |
| 1123 | 1158 | { |
| 1124 | const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty); | |
| 1125 | QualType child_qt = incomplete_array_ty->getElementType(); | |
| 1159 | const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty); | |
| 1160 | clang::QualType child_qt = incomplete_array_ty->getElementType(); | |
| 1126 | 1161 | AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc); |
| 1127 | 1162 | if (child_type_node == nullptr) { |
| 1128 | 1163 | emit_warning(c, source_loc, "unresolved array element type"); |
| 1129 | 1164 | return nullptr; |
| 1130 | 1165 | } |
| 1131 | 1166 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), |
| 1132 | child_qt.isVolatileQualified(), child_type_node, PtrLenUnknown); | |
| 1167 | child_qt.isVolatileQualified(), child_type_node, PtrLenC); | |
| 1133 | 1168 | return pointer_node; |
| 1134 | 1169 | } |
| 1135 | case Type::BlockPointer: | |
| 1136 | case Type::LValueReference: | |
| 1137 | case Type::RValueReference: | |
| 1138 | case Type::MemberPointer: | |
| 1139 | case Type::VariableArray: | |
| 1140 | case Type::DependentSizedArray: | |
| 1141 | case Type::DependentSizedExtVector: | |
| 1142 | case Type::Vector: | |
| 1143 | case Type::ExtVector: | |
| 1144 | case Type::FunctionNoProto: | |
| 1145 | case Type::UnresolvedUsing: | |
| 1146 | case Type::Adjusted: | |
| 1147 | case Type::TypeOfExpr: | |
| 1148 | case Type::TypeOf: | |
| 1149 | case Type::Decltype: | |
| 1150 | case Type::UnaryTransform: | |
| 1151 | case Type::TemplateTypeParm: | |
| 1152 | case Type::SubstTemplateTypeParm: | |
| 1153 | case Type::SubstTemplateTypeParmPack: | |
| 1154 | case Type::TemplateSpecialization: | |
| 1155 | case Type::Auto: | |
| 1156 | case Type::InjectedClassName: | |
| 1157 | case Type::DependentName: | |
| 1158 | case Type::DependentTemplateSpecialization: | |
| 1159 | case Type::PackExpansion: | |
| 1160 | case Type::ObjCObject: | |
| 1161 | case Type::ObjCInterface: | |
| 1162 | case Type::Complex: | |
| 1163 | case Type::ObjCObjectPointer: | |
| 1164 | case Type::Atomic: | |
| 1165 | case Type::Pipe: | |
| 1166 | case Type::ObjCTypeParam: | |
| 1167 | case Type::DeducedTemplateSpecialization: | |
| 1168 | case Type::DependentAddressSpace: | |
| 1169 | case Type::DependentVector: | |
| 1170 | case clang::Type::BlockPointer: | |
| 1171 | case clang::Type::LValueReference: | |
| 1172 | case clang::Type::RValueReference: | |
| 1173 | case clang::Type::MemberPointer: | |
| 1174 | case clang::Type::VariableArray: | |
| 1175 | case clang::Type::DependentSizedArray: | |
| 1176 | case clang::Type::DependentSizedExtVector: | |
| 1177 | case clang::Type::Vector: | |
| 1178 | case clang::Type::ExtVector: | |
| 1179 | case clang::Type::UnresolvedUsing: | |
| 1180 | case clang::Type::Adjusted: | |
| 1181 | case clang::Type::TypeOfExpr: | |
| 1182 | case clang::Type::TypeOf: | |
| 1183 | case clang::Type::Decltype: | |
| 1184 | case clang::Type::UnaryTransform: | |
| 1185 | case clang::Type::TemplateTypeParm: | |
| 1186 | case clang::Type::SubstTemplateTypeParm: | |
| 1187 | case clang::Type::SubstTemplateTypeParmPack: | |
| 1188 | case clang::Type::TemplateSpecialization: | |
| 1189 | case clang::Type::Auto: | |
| 1190 | case clang::Type::InjectedClassName: | |
| 1191 | case clang::Type::DependentName: | |
| 1192 | case clang::Type::DependentTemplateSpecialization: | |
| 1193 | case clang::Type::PackExpansion: | |
| 1194 | case clang::Type::ObjCObject: | |
| 1195 | case clang::Type::ObjCInterface: | |
| 1196 | case clang::Type::Complex: | |
| 1197 | case clang::Type::ObjCObjectPointer: | |
| 1198 | case clang::Type::Atomic: | |
| 1199 | case clang::Type::Pipe: | |
| 1200 | case clang::Type::ObjCTypeParam: | |
| 1201 | case clang::Type::DeducedTemplateSpecialization: | |
| 1202 | case clang::Type::DependentAddressSpace: | |
| 1203 | case clang::Type::DependentVector: | |
| 1170 | 1204 | emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); |
| 1171 | 1205 | return nullptr; |
| 1172 | 1206 | } |
| 1173 | 1207 | zig_unreachable(); |
| 1174 | 1208 | } |
| 1175 | 1209 | |
| 1176 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) { | |
| 1210 | static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) { | |
| 1177 | 1211 | return trans_type(c, qt.getTypePtr(), source_loc); |
| 1178 | 1212 | } |
| 1179 | 1213 | |
| 1180 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt, | |
| 1214 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, | |
| 1181 | 1215 | AstNode *block_node, TransScope **out_node_scope) |
| 1182 | 1216 | { |
| 1183 | 1217 | assert(block_node->type == NodeTypeBlock); |
| 1184 | for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | |
| 1218 | for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | |
| 1185 | 1219 | AstNode *child_node; |
| 1186 | 1220 | scope = trans_stmt(c, scope, *it, &child_node); |
| 1187 | 1221 | if (scope == nullptr) |
| ... | ... | @@ -1195,7 +1229,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo |
| 1195 | 1229 | return ErrorNone; |
| 1196 | 1230 | } |
| 1197 | 1231 | |
| 1198 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt, | |
| 1232 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, | |
| 1199 | 1233 | TransScope **out_node_scope) |
| 1200 | 1234 | { |
| 1201 | 1235 | TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope); |
| ... | ... | @@ -1204,8 +1238,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun |
| 1204 | 1238 | return child_scope_block->node; |
| 1205 | 1239 | } |
| 1206 | 1240 | |
| 1207 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) { | |
| 1208 | const Expr *value_expr = stmt->getRetValue(); | |
| 1241 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) { | |
| 1242 | const clang::Expr *value_expr = stmt->getRetValue(); | |
| 1209 | 1243 | if (value_expr == nullptr) { |
| 1210 | 1244 | return trans_create_node(c, NodeTypeReturnExpr); |
| 1211 | 1245 | } else { |
| ... | ... | @@ -1217,18 +1251,18 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm |
| 1217 | 1251 | } |
| 1218 | 1252 | } |
| 1219 | 1253 | |
| 1220 | static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) { | |
| 1254 | static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) { | |
| 1221 | 1255 | Expr::EvalResult result; |
| 1222 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { | |
| 1256 | if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) { | |
| 1223 | 1257 | emit_warning(c, stmt->getBeginLoc(), "invalid integer literal"); |
| 1224 | 1258 | return nullptr; |
| 1225 | 1259 | } |
| 1226 | 1260 | return trans_create_node_apint(c, result.Val.getInt()); |
| 1227 | 1261 | } |
| 1228 | 1262 | |
| 1229 | static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) { | |
| 1263 | static AstNode *trans_constant_expr(Context *c, const clang::ConstantExpr *expr) { | |
| 1230 | 1264 | Expr::EvalResult result; |
| 1231 | if (!expr->EvaluateAsConstantExpr(result, Expr::EvaluateForCodeGen, *c->ctx)) { | |
| 1265 | if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, *c->ctx)) { | |
| 1232 | 1266 | emit_warning(c, expr->getBeginLoc(), "invalid constant expression"); |
| 1233 | 1267 | return nullptr; |
| 1234 | 1268 | } |
| ... | ... | @@ -1236,13 +1270,13 @@ static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) { |
| 1236 | 1270 | } |
| 1237 | 1271 | |
| 1238 | 1272 | static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| 1239 | const ConditionalOperator *stmt) | |
| 1273 | const clang::ConditionalOperator *stmt) | |
| 1240 | 1274 | { |
| 1241 | 1275 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 1242 | 1276 | |
| 1243 | Expr *cond_expr = stmt->getCond(); | |
| 1244 | Expr *true_expr = stmt->getTrueExpr(); | |
| 1245 | Expr *false_expr = stmt->getFalseExpr(); | |
| 1277 | clang::Expr *cond_expr = stmt->getCond(); | |
| 1278 | clang::Expr *true_expr = stmt->getTrueExpr(); | |
| 1279 | clang::Expr *false_expr = stmt->getFalseExpr(); | |
| 1246 | 1280 | |
| 1247 | 1281 | node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue); |
| 1248 | 1282 | if (node->data.if_bool_expr.condition == nullptr) |
| ... | ... | @@ -1259,7 +1293,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T |
| 1259 | 1293 | return maybe_suppress_result(c, result_used, node); |
| 1260 | 1294 | } |
| 1261 | 1295 | |
| 1262 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { | |
| 1296 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) { | |
| 1263 | 1297 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1264 | 1298 | node->data.bin_op_expr.bin_op = bin_op; |
| 1265 | 1299 | |
| ... | ... | @@ -1274,7 +1308,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi |
| 1274 | 1308 | return node; |
| 1275 | 1309 | } |
| 1276 | 1310 | |
| 1277 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { | |
| 1311 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) { | |
| 1278 | 1312 | assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr); |
| 1279 | 1313 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1280 | 1314 | node->data.bin_op_expr.bin_op = bin_op; |
| ... | ... | @@ -1290,7 +1324,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh |
| 1290 | 1324 | return node; |
| 1291 | 1325 | } |
| 1292 | 1326 | |
| 1293 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) { | |
| 1327 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) { | |
| 1294 | 1328 | if (result_used == ResultUsedNo) { |
| 1295 | 1329 | // common case |
| 1296 | 1330 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| ... | ... | @@ -1341,10 +1375,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco |
| 1341 | 1375 | } |
| 1342 | 1376 | } |
| 1343 | 1377 | |
| 1344 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type, | |
| 1345 | Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) | |
| 1378 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type, | |
| 1379 | clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr) | |
| 1346 | 1380 | { |
| 1347 | const SourceLocation &rhs_location = rhs_expr->getBeginLoc(); | |
| 1381 | const clang::SourceLocation &rhs_location = rhs_expr->getBeginLoc(); | |
| 1348 | 1382 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); |
| 1349 | 1383 | // lhs >> u5(rh) |
| 1350 | 1384 | |
| ... | ... | @@ -1358,22 +1392,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re |
| 1358 | 1392 | return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); |
| 1359 | 1393 | } |
| 1360 | 1394 | |
| 1361 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) { | |
| 1395 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) { | |
| 1362 | 1396 | switch (stmt->getOpcode()) { |
| 1363 | case BO_PtrMemD: | |
| 1397 | case clang::BO_PtrMemD: | |
| 1364 | 1398 | emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD"); |
| 1365 | 1399 | return nullptr; |
| 1366 | case BO_PtrMemI: | |
| 1400 | case clang::BO_PtrMemI: | |
| 1367 | 1401 | emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI"); |
| 1368 | 1402 | return nullptr; |
| 1369 | case BO_Cmp: | |
| 1403 | case clang::BO_Cmp: | |
| 1370 | 1404 | emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp"); |
| 1371 | 1405 | return nullptr; |
| 1372 | case BO_Mul: | |
| 1406 | case clang::BO_Mul: | |
| 1373 | 1407 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1374 | 1408 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| 1375 | 1409 | stmt->getRHS()); |
| 1376 | case BO_Div: | |
| 1410 | case clang::BO_Div: | |
| 1377 | 1411 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1378 | 1412 | // unsigned/float division uses the operator |
| 1379 | 1413 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| ... | ... | @@ -1388,7 +1422,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1388 | 1422 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1389 | 1423 | return fn_call; |
| 1390 | 1424 | } |
| 1391 | case BO_Rem: | |
| 1425 | case clang::BO_Rem: | |
| 1392 | 1426 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1393 | 1427 | // unsigned/float division uses the operator |
| 1394 | 1428 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| ... | ... | @@ -1403,43 +1437,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1403 | 1437 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1404 | 1438 | return fn_call; |
| 1405 | 1439 | } |
| 1406 | case BO_Add: | |
| 1440 | case clang::BO_Add: | |
| 1407 | 1441 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1408 | 1442 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| 1409 | 1443 | stmt->getRHS()); |
| 1410 | case BO_Sub: | |
| 1444 | case clang::BO_Sub: | |
| 1411 | 1445 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1412 | 1446 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| 1413 | 1447 | stmt->getRHS()); |
| 1414 | case BO_Shl: | |
| 1448 | case clang::BO_Shl: | |
| 1415 | 1449 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); |
| 1416 | case BO_Shr: | |
| 1450 | case clang::BO_Shr: | |
| 1417 | 1451 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); |
| 1418 | case BO_LT: | |
| 1452 | case clang::BO_LT: | |
| 1419 | 1453 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); |
| 1420 | case BO_GT: | |
| 1454 | case clang::BO_GT: | |
| 1421 | 1455 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); |
| 1422 | case BO_LE: | |
| 1456 | case clang::BO_LE: | |
| 1423 | 1457 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); |
| 1424 | case BO_GE: | |
| 1458 | case clang::BO_GE: | |
| 1425 | 1459 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 1426 | case BO_EQ: | |
| 1460 | case clang::BO_EQ: | |
| 1427 | 1461 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 1428 | case BO_NE: | |
| 1462 | case clang::BO_NE: | |
| 1429 | 1463 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 1430 | case BO_And: | |
| 1464 | case clang::BO_And: | |
| 1431 | 1465 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 1432 | case BO_Xor: | |
| 1466 | case clang::BO_Xor: | |
| 1433 | 1467 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 1434 | case BO_Or: | |
| 1468 | case clang::BO_Or: | |
| 1435 | 1469 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 1436 | case BO_LAnd: | |
| 1470 | case clang::BO_LAnd: | |
| 1437 | 1471 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 1438 | case BO_LOr: | |
| 1472 | case clang::BO_LOr: | |
| 1439 | 1473 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1440 | case BO_Assign: | |
| 1474 | case clang::BO_Assign: | |
| 1441 | 1475 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); |
| 1442 | case BO_Comma: | |
| 1476 | case clang::BO_Comma: | |
| 1443 | 1477 | { |
| 1444 | 1478 | TransScopeBlock *scope_block = trans_scope_block_create(c, scope); |
| 1445 | 1479 | Buf *label_name = buf_create_from_str("x"); |
| ... | ... | @@ -1456,16 +1490,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1456 | 1490 | scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs))); |
| 1457 | 1491 | return scope_block->node; |
| 1458 | 1492 | } |
| 1459 | case BO_MulAssign: | |
| 1460 | case BO_DivAssign: | |
| 1461 | case BO_RemAssign: | |
| 1462 | case BO_AddAssign: | |
| 1463 | case BO_SubAssign: | |
| 1464 | case BO_ShlAssign: | |
| 1465 | case BO_ShrAssign: | |
| 1466 | case BO_AndAssign: | |
| 1467 | case BO_XorAssign: | |
| 1468 | case BO_OrAssign: | |
| 1493 | case clang::BO_MulAssign: | |
| 1494 | case clang::BO_DivAssign: | |
| 1495 | case clang::BO_RemAssign: | |
| 1496 | case clang::BO_AddAssign: | |
| 1497 | case clang::BO_SubAssign: | |
| 1498 | case clang::BO_ShlAssign: | |
| 1499 | case clang::BO_ShrAssign: | |
| 1500 | case clang::BO_AndAssign: | |
| 1501 | case clang::BO_XorAssign: | |
| 1502 | case clang::BO_OrAssign: | |
| 1469 | 1503 | zig_unreachable(); |
| 1470 | 1504 | } |
| 1471 | 1505 | |
| ... | ... | @@ -1473,9 +1507,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1473 | 1507 | } |
| 1474 | 1508 | |
| 1475 | 1509 | static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, |
| 1476 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) | |
| 1510 | const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) | |
| 1477 | 1511 | { |
| 1478 | const SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc(); | |
| 1512 | const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc(); | |
| 1479 | 1513 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1480 | 1514 | |
| 1481 | 1515 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| ... | ... | @@ -1555,7 +1589,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1555 | 1589 | } |
| 1556 | 1590 | |
| 1557 | 1591 | static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope, |
| 1558 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) | |
| 1592 | const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) | |
| 1559 | 1593 | { |
| 1560 | 1594 | if (result_used == ResultUsedNo) { |
| 1561 | 1595 | // simple common case, where the C and Zig are identical: |
| ... | ... | @@ -1615,76 +1649,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1615 | 1649 | |
| 1616 | 1650 | |
| 1617 | 1651 | static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| 1618 | const CompoundAssignOperator *stmt) | |
| 1652 | const clang::CompoundAssignOperator *stmt) | |
| 1619 | 1653 | { |
| 1620 | 1654 | switch (stmt->getOpcode()) { |
| 1621 | case BO_MulAssign: | |
| 1655 | case clang::BO_MulAssign: | |
| 1622 | 1656 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1623 | 1657 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1624 | 1658 | else |
| 1625 | 1659 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1626 | case BO_DivAssign: | |
| 1660 | case clang::BO_DivAssign: | |
| 1627 | 1661 | emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign"); |
| 1628 | 1662 | return nullptr; |
| 1629 | case BO_RemAssign: | |
| 1663 | case clang::BO_RemAssign: | |
| 1630 | 1664 | emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign"); |
| 1631 | 1665 | return nullptr; |
| 1632 | case BO_Cmp: | |
| 1666 | case clang::BO_Cmp: | |
| 1633 | 1667 | emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp"); |
| 1634 | 1668 | return nullptr; |
| 1635 | case BO_AddAssign: | |
| 1669 | case clang::BO_AddAssign: | |
| 1636 | 1670 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1637 | 1671 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1638 | 1672 | else |
| 1639 | 1673 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1640 | case BO_SubAssign: | |
| 1674 | case clang::BO_SubAssign: | |
| 1641 | 1675 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1642 | 1676 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1643 | 1677 | else |
| 1644 | 1678 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub); |
| 1645 | case BO_ShlAssign: | |
| 1679 | case clang::BO_ShlAssign: | |
| 1646 | 1680 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); |
| 1647 | case BO_ShrAssign: | |
| 1681 | case clang::BO_ShrAssign: | |
| 1648 | 1682 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); |
| 1649 | case BO_AndAssign: | |
| 1683 | case clang::BO_AndAssign: | |
| 1650 | 1684 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); |
| 1651 | case BO_XorAssign: | |
| 1685 | case clang::BO_XorAssign: | |
| 1652 | 1686 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); |
| 1653 | case BO_OrAssign: | |
| 1687 | case clang::BO_OrAssign: | |
| 1654 | 1688 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1655 | case BO_PtrMemD: | |
| 1656 | case BO_PtrMemI: | |
| 1657 | case BO_Assign: | |
| 1658 | case BO_Mul: | |
| 1659 | case BO_Div: | |
| 1660 | case BO_Rem: | |
| 1661 | case BO_Add: | |
| 1662 | case BO_Sub: | |
| 1663 | case BO_Shl: | |
| 1664 | case BO_Shr: | |
| 1665 | case BO_LT: | |
| 1666 | case BO_GT: | |
| 1667 | case BO_LE: | |
| 1668 | case BO_GE: | |
| 1669 | case BO_EQ: | |
| 1670 | case BO_NE: | |
| 1671 | case BO_And: | |
| 1672 | case BO_Xor: | |
| 1673 | case BO_Or: | |
| 1674 | case BO_LAnd: | |
| 1675 | case BO_LOr: | |
| 1676 | case BO_Comma: | |
| 1689 | case clang::BO_PtrMemD: | |
| 1690 | case clang::BO_PtrMemI: | |
| 1691 | case clang::BO_Assign: | |
| 1692 | case clang::BO_Mul: | |
| 1693 | case clang::BO_Div: | |
| 1694 | case clang::BO_Rem: | |
| 1695 | case clang::BO_Add: | |
| 1696 | case clang::BO_Sub: | |
| 1697 | case clang::BO_Shl: | |
| 1698 | case clang::BO_Shr: | |
| 1699 | case clang::BO_LT: | |
| 1700 | case clang::BO_GT: | |
| 1701 | case clang::BO_LE: | |
| 1702 | case clang::BO_GE: | |
| 1703 | case clang::BO_EQ: | |
| 1704 | case clang::BO_NE: | |
| 1705 | case clang::BO_And: | |
| 1706 | case clang::BO_Xor: | |
| 1707 | case clang::BO_Or: | |
| 1708 | case clang::BO_LAnd: | |
| 1709 | case clang::BO_LOr: | |
| 1710 | case clang::BO_Comma: | |
| 1677 | 1711 | zig_unreachable(); |
| 1678 | 1712 | } |
| 1679 | 1713 | |
| 1680 | 1714 | zig_unreachable(); |
| 1681 | 1715 | } |
| 1682 | 1716 | |
| 1683 | static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) { | |
| 1717 | static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) { | |
| 1684 | 1718 | switch (stmt->getCastKind()) { |
| 1685 | case CK_LValueToRValue: | |
| 1719 | case clang::CK_LValueToRValue: | |
| 1686 | 1720 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1687 | case CK_IntegralCast: | |
| 1721 | case clang::CK_IntegralCast: | |
| 1688 | 1722 | { |
| 1689 | 1723 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1690 | 1724 | if (target_node == nullptr) |
| ... | ... | @@ -1692,15 +1726,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1692 | 1726 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), |
| 1693 | 1727 | stmt->getSubExpr()->getType(), target_node); |
| 1694 | 1728 | } |
| 1695 | case CK_FunctionToPointerDecay: | |
| 1696 | case CK_ArrayToPointerDecay: | |
| 1729 | case clang::CK_FunctionToPointerDecay: | |
| 1730 | case clang::CK_ArrayToPointerDecay: | |
| 1697 | 1731 | { |
| 1698 | 1732 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1699 | 1733 | if (target_node == nullptr) |
| 1700 | 1734 | return nullptr; |
| 1701 | 1735 | return target_node; |
| 1702 | 1736 | } |
| 1703 | case CK_BitCast: | |
| 1737 | case clang::CK_BitCast: | |
| 1704 | 1738 | { |
| 1705 | 1739 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1706 | 1740 | if (target_node == nullptr) |
| ... | ... | @@ -1717,172 +1751,55 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1717 | 1751 | node->data.fn_call_expr.params.append(target_node); |
| 1718 | 1752 | return node; |
| 1719 | 1753 | } |
| 1720 | case CK_NullToPointer: | |
| 1721 | return trans_create_node(c, NodeTypeNullLiteral); | |
| 1722 | case CK_Dependent: | |
| 1754 | case clang::CK_NullToPointer: | |
| 1755 | return trans_create_node_unsigned(c, 0); | |
| 1756 | case clang::CK_NoOp: | |
| 1757 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | |
| 1758 | case clang::CK_Dependent: | |
| 1723 | 1759 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent"); |
| 1724 | 1760 | return nullptr; |
| 1725 | case CK_LValueBitCast: | |
| 1761 | case clang::CK_LValueBitCast: | |
| 1726 | 1762 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast"); |
| 1727 | 1763 | return nullptr; |
| 1728 | case CK_NoOp: | |
| 1729 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | |
| 1730 | case CK_BaseToDerived: | |
| 1764 | case clang::CK_BaseToDerived: | |
| 1731 | 1765 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived"); |
| 1732 | 1766 | return nullptr; |
| 1733 | case CK_DerivedToBase: | |
| 1767 | case clang::CK_DerivedToBase: | |
| 1734 | 1768 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase"); |
| 1735 | 1769 | return nullptr; |
| 1736 | case CK_UncheckedDerivedToBase: | |
| 1770 | case clang::CK_UncheckedDerivedToBase: | |
| 1737 | 1771 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase"); |
| 1738 | 1772 | return nullptr; |
| 1739 | case CK_Dynamic: | |
| 1773 | case clang::CK_Dynamic: | |
| 1740 | 1774 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic"); |
| 1741 | 1775 | return nullptr; |
| 1742 | case CK_ToUnion: | |
| 1776 | case clang::CK_ToUnion: | |
| 1743 | 1777 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion"); |
| 1744 | 1778 | return nullptr; |
| 1745 | case CK_NullToMemberPointer: | |
| 1779 | case clang::CK_NullToMemberPointer: | |
| 1746 | 1780 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer"); |
| 1747 | 1781 | return nullptr; |
| 1748 | case CK_BaseToDerivedMemberPointer: | |
| 1782 | case clang::CK_BaseToDerivedMemberPointer: | |
| 1749 | 1783 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer"); |
| 1750 | 1784 | return nullptr; |
| 1751 | case CK_DerivedToBaseMemberPointer: | |
| 1785 | case clang::CK_DerivedToBaseMemberPointer: | |
| 1752 | 1786 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer"); |
| 1753 | 1787 | return nullptr; |
| 1754 | case CK_MemberPointerToBoolean: | |
| 1788 | case clang::CK_MemberPointerToBoolean: | |
| 1755 | 1789 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean"); |
| 1756 | 1790 | return nullptr; |
| 1757 | case CK_ReinterpretMemberPointer: | |
| 1791 | case clang::CK_ReinterpretMemberPointer: | |
| 1758 | 1792 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer"); |
| 1759 | 1793 | return nullptr; |
| 1760 | case CK_UserDefinedConversion: | |
| 1794 | case clang::CK_UserDefinedConversion: | |
| 1761 | 1795 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion"); |
| 1762 | 1796 | return nullptr; |
| 1763 | case CK_ConstructorConversion: | |
| 1764 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ConstructorConversion"); | |
| 1765 | return nullptr; | |
| 1766 | case CK_IntegralToPointer: | |
| 1767 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralToPointer"); | |
| 1768 | return nullptr; | |
| 1769 | case CK_PointerToIntegral: | |
| 1770 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_PointerToIntegral"); | |
| 1771 | return nullptr; | |
| 1772 | case CK_PointerToBoolean: | |
| 1773 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_PointerToBoolean"); | |
| 1774 | return nullptr; | |
| 1775 | case CK_ToVoid: | |
| 1776 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToVoid"); | |
| 1777 | return nullptr; | |
| 1778 | case CK_VectorSplat: | |
| 1779 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_VectorSplat"); | |
| 1780 | return nullptr; | |
| 1781 | case CK_IntegralToBoolean: | |
| 1782 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralToBoolean"); | |
| 1783 | return nullptr; | |
| 1784 | case CK_IntegralToFloating: | |
| 1785 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralToFloating"); | |
| 1786 | return nullptr; | |
| 1787 | case CK_FloatingToIntegral: | |
| 1788 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingToIntegral"); | |
| 1789 | return nullptr; | |
| 1790 | case CK_FloatingToBoolean: | |
| 1791 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingToBoolean"); | |
| 1792 | return nullptr; | |
| 1793 | case CK_BooleanToSignedIntegral: | |
| 1794 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BooleanToSignedIntegral"); | |
| 1795 | return nullptr; | |
| 1796 | case CK_FloatingCast: | |
| 1797 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingCast"); | |
| 1798 | return nullptr; | |
| 1799 | case CK_CPointerToObjCPointerCast: | |
| 1800 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_CPointerToObjCPointerCast"); | |
| 1801 | return nullptr; | |
| 1802 | case CK_BlockPointerToObjCPointerCast: | |
| 1803 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast"); | |
| 1804 | return nullptr; | |
| 1805 | case CK_AnyPointerToBlockPointerCast: | |
| 1806 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast"); | |
| 1807 | return nullptr; | |
| 1808 | case CK_ObjCObjectLValueCast: | |
| 1809 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ObjCObjectLValueCast"); | |
| 1810 | return nullptr; | |
| 1811 | case CK_FloatingRealToComplex: | |
| 1812 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingRealToComplex"); | |
| 1813 | return nullptr; | |
| 1814 | case CK_FloatingComplexToReal: | |
| 1815 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexToReal"); | |
| 1816 | return nullptr; | |
| 1817 | case CK_FloatingComplexToBoolean: | |
| 1818 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexToBoolean"); | |
| 1819 | return nullptr; | |
| 1820 | case CK_FloatingComplexCast: | |
| 1821 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexCast"); | |
| 1822 | return nullptr; | |
| 1823 | case CK_FloatingComplexToIntegralComplex: | |
| 1824 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex"); | |
| 1825 | return nullptr; | |
| 1826 | case CK_IntegralRealToComplex: | |
| 1827 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralRealToComplex"); | |
| 1828 | return nullptr; | |
| 1829 | case CK_IntegralComplexToReal: | |
| 1830 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexToReal"); | |
| 1831 | return nullptr; | |
| 1832 | case CK_IntegralComplexToBoolean: | |
| 1833 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexToBoolean"); | |
| 1834 | return nullptr; | |
| 1835 | case CK_IntegralComplexCast: | |
| 1836 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexCast"); | |
| 1837 | return nullptr; | |
| 1838 | case CK_IntegralComplexToFloatingComplex: | |
| 1839 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex"); | |
| 1840 | return nullptr; | |
| 1841 | case CK_ARCProduceObject: | |
| 1842 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCProduceObject"); | |
| 1843 | return nullptr; | |
| 1844 | case CK_ARCConsumeObject: | |
| 1845 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCConsumeObject"); | |
| 1846 | return nullptr; | |
| 1847 | case CK_ARCReclaimReturnedObject: | |
| 1848 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCReclaimReturnedObject"); | |
| 1849 | return nullptr; | |
| 1850 | case CK_ARCExtendBlockObject: | |
| 1851 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCExtendBlockObject"); | |
| 1852 | return nullptr; | |
| 1853 | case CK_AtomicToNonAtomic: | |
| 1854 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_AtomicToNonAtomic"); | |
| 1855 | return nullptr; | |
| 1856 | case CK_NonAtomicToAtomic: | |
| 1857 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NonAtomicToAtomic"); | |
| 1858 | return nullptr; | |
| 1859 | case CK_CopyAndAutoreleaseBlockObject: | |
| 1860 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject"); | |
| 1861 | return nullptr; | |
| 1862 | case CK_BuiltinFnToFnPtr: | |
| 1863 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BuiltinFnToFnPtr"); | |
| 1864 | return nullptr; | |
| 1865 | case CK_AddressSpaceConversion: | |
| 1866 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_AddressSpaceConversion"); | |
| 1867 | return nullptr; | |
| 1868 | case CK_IntToOCLSampler: | |
| 1869 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntToOCLSampler"); | |
| 1870 | return nullptr; | |
| 1871 | case CK_FixedPointCast: | |
| 1872 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FixedPointCast"); | |
| 1873 | return nullptr; | |
| 1874 | case CK_FixedPointToBoolean: | |
| 1875 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FixedPointToBoolean"); | |
| 1876 | return nullptr; | |
| 1877 | case CK_ZeroToOCLOpaqueType: | |
| 1878 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ZeroToOCLOpaqueType"); | |
| 1879 | return nullptr; | |
| 1880 | 1797 | } |
| 1881 | 1798 | zig_unreachable(); |
| 1882 | 1799 | } |
| 1883 | 1800 | |
| 1884 | static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) { | |
| 1885 | const ValueDecl *value_decl = stmt->getDecl(); | |
| 1801 | static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) { | |
| 1802 | const clang::ValueDecl *value_decl = stmt->getDecl(); | |
| 1886 | 1803 | Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1887 | 1804 | Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name); |
| 1888 | 1805 | if (lrval == TransLValue) { |
| ... | ... | @@ -1892,9 +1809,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef |
| 1892 | 1809 | } |
| 1893 | 1810 | |
| 1894 | 1811 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 1895 | const UnaryOperator *stmt, BinOpType assign_op) | |
| 1812 | const clang::UnaryOperator *stmt, BinOpType assign_op) | |
| 1896 | 1813 | { |
| 1897 | Expr *op_expr = stmt->getSubExpr(); | |
| 1814 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 1898 | 1815 | |
| 1899 | 1816 | if (result_used == ResultUsedNo) { |
| 1900 | 1817 | // common case |
| ... | ... | @@ -1948,9 +1865,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr |
| 1948 | 1865 | } |
| 1949 | 1866 | |
| 1950 | 1867 | static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 1951 | const UnaryOperator *stmt, BinOpType assign_op) | |
| 1868 | const clang::UnaryOperator *stmt, BinOpType assign_op) | |
| 1952 | 1869 | { |
| 1953 | Expr *op_expr = stmt->getSubExpr(); | |
| 1870 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 1954 | 1871 | |
| 1955 | 1872 | if (result_used == ResultUsedNo) { |
| 1956 | 1873 | // common case |
| ... | ... | @@ -1997,36 +1914,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra |
| 1997 | 1914 | return child_scope->node; |
| 1998 | 1915 | } |
| 1999 | 1916 | |
| 2000 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) { | |
| 1917 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) { | |
| 2001 | 1918 | switch (stmt->getOpcode()) { |
| 2002 | case UO_PostInc: | |
| 1919 | case clang::UO_PostInc: | |
| 2003 | 1920 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 2004 | 1921 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 2005 | 1922 | else |
| 2006 | 1923 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 2007 | case UO_PostDec: | |
| 1924 | case clang::UO_PostDec: | |
| 2008 | 1925 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 2009 | 1926 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 2010 | 1927 | else |
| 2011 | 1928 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 2012 | case UO_PreInc: | |
| 1929 | case clang::UO_PreInc: | |
| 2013 | 1930 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 2014 | 1931 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 2015 | 1932 | else |
| 2016 | 1933 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 2017 | case UO_PreDec: | |
| 1934 | case clang::UO_PreDec: | |
| 2018 | 1935 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 2019 | 1936 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 2020 | 1937 | else |
| 2021 | 1938 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 2022 | case UO_AddrOf: | |
| 1939 | case clang::UO_AddrOf: | |
| 2023 | 1940 | { |
| 2024 | 1941 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); |
| 2025 | 1942 | if (value_node == nullptr) |
| 2026 | 1943 | return value_node; |
| 2027 | 1944 | return trans_create_node_addr_of(c, value_node); |
| 2028 | 1945 | } |
| 2029 | case UO_Deref: | |
| 1946 | case clang::UO_Deref: | |
| 2030 | 1947 | { |
| 2031 | 1948 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); |
| 2032 | 1949 | if (value_node == nullptr) |
| ... | ... | @@ -2037,12 +1954,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2037 | 1954 | AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node); |
| 2038 | 1955 | return trans_create_node_ptr_deref(c, unwrapped); |
| 2039 | 1956 | } |
| 2040 | case UO_Plus: | |
| 1957 | case clang::UO_Plus: | |
| 2041 | 1958 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus"); |
| 2042 | 1959 | return nullptr; |
| 2043 | case UO_Minus: | |
| 1960 | case clang::UO_Minus: | |
| 2044 | 1961 | { |
| 2045 | Expr *op_expr = stmt->getSubExpr(); | |
| 1962 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 2046 | 1963 | if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) { |
| 2047 | 1964 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 2048 | 1965 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| ... | ... | @@ -2068,41 +1985,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2068 | 1985 | return nullptr; |
| 2069 | 1986 | } |
| 2070 | 1987 | } |
| 2071 | case UO_Not: | |
| 1988 | case clang::UO_Not: | |
| 2072 | 1989 | { |
| 2073 | Expr *op_expr = stmt->getSubExpr(); | |
| 1990 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 2074 | 1991 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 2075 | 1992 | if (sub_node == nullptr) |
| 2076 | 1993 | return nullptr; |
| 2077 | 1994 | |
| 2078 | 1995 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); |
| 2079 | 1996 | } |
| 2080 | case UO_LNot: | |
| 1997 | case clang::UO_LNot: | |
| 2081 | 1998 | { |
| 2082 | Expr *op_expr = stmt->getSubExpr(); | |
| 1999 | clang::Expr *op_expr = stmt->getSubExpr(); | |
| 2083 | 2000 | AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 2084 | 2001 | if (sub_node == nullptr) |
| 2085 | 2002 | return nullptr; |
| 2086 | 2003 | |
| 2087 | 2004 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node); |
| 2088 | 2005 | } |
| 2089 | case UO_Real: | |
| 2006 | case clang::UO_Real: | |
| 2090 | 2007 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real"); |
| 2091 | 2008 | return nullptr; |
| 2092 | case UO_Imag: | |
| 2009 | case clang::UO_Imag: | |
| 2093 | 2010 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag"); |
| 2094 | 2011 | return nullptr; |
| 2095 | case UO_Extension: | |
| 2012 | case clang::UO_Extension: | |
| 2096 | 2013 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Extension"); |
| 2097 | 2014 | return nullptr; |
| 2098 | case UO_Coawait: | |
| 2015 | case clang::UO_Coawait: | |
| 2099 | 2016 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait"); |
| 2100 | 2017 | return nullptr; |
| 2101 | 2018 | } |
| 2102 | 2019 | zig_unreachable(); |
| 2103 | 2020 | } |
| 2104 | 2021 | |
| 2105 | static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt, | |
| 2022 | static int trans_local_declaration(Context *c, TransScope *scope, const clang::DeclStmt *stmt, | |
| 2106 | 2023 | AstNode **out_node, TransScope **out_scope) |
| 2107 | 2024 | { |
| 2108 | 2025 | // declarations are added via the scope |
| ... | ... | @@ -2112,11 +2029,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2112 | 2029 | assert(scope_block != nullptr); |
| 2113 | 2030 | |
| 2114 | 2031 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { |
| 2115 | Decl *decl = *iter; | |
| 2032 | clang::Decl *decl = *iter; | |
| 2116 | 2033 | switch (decl->getKind()) { |
| 2117 | case Decl::Var: { | |
| 2118 | VarDecl *var_decl = (VarDecl *)decl; | |
| 2119 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | |
| 2034 | case clang::Decl::Var: { | |
| 2035 | clang::VarDecl *var_decl = (clang::VarDecl *)decl; | |
| 2036 | clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | |
| 2120 | 2037 | AstNode *init_node = nullptr; |
| 2121 | 2038 | if (var_decl->hasInit()) { |
| 2122 | 2039 | init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue); |
| ... | ... | @@ -2141,225 +2058,9 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2141 | 2058 | scope_block->node->data.block.statements.append(node); |
| 2142 | 2059 | continue; |
| 2143 | 2060 | } |
| 2144 | case Decl::AccessSpec: | |
| 2061 | case clang::Decl::AccessSpec: | |
| 2145 | 2062 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec"); |
| 2146 | 2063 | return ErrorUnexpected; |
| 2147 | case Decl::Block: | |
| 2148 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Block"); | |
| 2149 | return ErrorUnexpected; | |
| 2150 | case Decl::Captured: | |
| 2151 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Captured"); | |
| 2152 | return ErrorUnexpected; | |
| 2153 | case Decl::ClassScopeFunctionSpecialization: | |
| 2154 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassScopeFunctionSpecialization"); | |
| 2155 | return ErrorUnexpected; | |
| 2156 | case Decl::Empty: | |
| 2157 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Empty"); | |
| 2158 | return ErrorUnexpected; | |
| 2159 | case Decl::Export: | |
| 2160 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Export"); | |
| 2161 | return ErrorUnexpected; | |
| 2162 | case Decl::ExternCContext: | |
| 2163 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ExternCContext"); | |
| 2164 | return ErrorUnexpected; | |
| 2165 | case Decl::FileScopeAsm: | |
| 2166 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind FileScopeAsm"); | |
| 2167 | return ErrorUnexpected; | |
| 2168 | case Decl::Friend: | |
| 2169 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Friend"); | |
| 2170 | return ErrorUnexpected; | |
| 2171 | case Decl::FriendTemplate: | |
| 2172 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind FriendTemplate"); | |
| 2173 | return ErrorUnexpected; | |
| 2174 | case Decl::Import: | |
| 2175 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Import"); | |
| 2176 | return ErrorUnexpected; | |
| 2177 | case Decl::LinkageSpec: | |
| 2178 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind LinkageSpec"); | |
| 2179 | return ErrorUnexpected; | |
| 2180 | case Decl::Label: | |
| 2181 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Label"); | |
| 2182 | return ErrorUnexpected; | |
| 2183 | case Decl::Namespace: | |
| 2184 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Namespace"); | |
| 2185 | return ErrorUnexpected; | |
| 2186 | case Decl::NamespaceAlias: | |
| 2187 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind NamespaceAlias"); | |
| 2188 | return ErrorUnexpected; | |
| 2189 | case Decl::ObjCCompatibleAlias: | |
| 2190 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCCompatibleAlias"); | |
| 2191 | return ErrorUnexpected; | |
| 2192 | case Decl::ObjCCategory: | |
| 2193 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCCategory"); | |
| 2194 | return ErrorUnexpected; | |
| 2195 | case Decl::ObjCCategoryImpl: | |
| 2196 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCCategoryImpl"); | |
| 2197 | return ErrorUnexpected; | |
| 2198 | case Decl::ObjCImplementation: | |
| 2199 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCImplementation"); | |
| 2200 | return ErrorUnexpected; | |
| 2201 | case Decl::ObjCInterface: | |
| 2202 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCInterface"); | |
| 2203 | return ErrorUnexpected; | |
| 2204 | case Decl::ObjCProtocol: | |
| 2205 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCProtocol"); | |
| 2206 | return ErrorUnexpected; | |
| 2207 | case Decl::ObjCMethod: | |
| 2208 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCMethod"); | |
| 2209 | return ErrorUnexpected; | |
| 2210 | case Decl::ObjCProperty: | |
| 2211 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCProperty"); | |
| 2212 | return ErrorUnexpected; | |
| 2213 | case Decl::BuiltinTemplate: | |
| 2214 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind BuiltinTemplate"); | |
| 2215 | return ErrorUnexpected; | |
| 2216 | case Decl::ClassTemplate: | |
| 2217 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassTemplate"); | |
| 2218 | return ErrorUnexpected; | |
| 2219 | case Decl::FunctionTemplate: | |
| 2220 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind FunctionTemplate"); | |
| 2221 | return ErrorUnexpected; | |
| 2222 | case Decl::TypeAliasTemplate: | |
| 2223 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TypeAliasTemplate"); | |
| 2224 | return ErrorUnexpected; | |
| 2225 | case Decl::VarTemplate: | |
| 2226 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind VarTemplate"); | |
| 2227 | return ErrorUnexpected; | |
| 2228 | case Decl::TemplateTemplateParm: | |
| 2229 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TemplateTemplateParm"); | |
| 2230 | return ErrorUnexpected; | |
| 2231 | case Decl::Enum: | |
| 2232 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Enum"); | |
| 2233 | return ErrorUnexpected; | |
| 2234 | case Decl::Record: | |
| 2235 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Record"); | |
| 2236 | return ErrorUnexpected; | |
| 2237 | case Decl::CXXRecord: | |
| 2238 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXRecord"); | |
| 2239 | return ErrorUnexpected; | |
| 2240 | case Decl::ClassTemplateSpecialization: | |
| 2241 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassTemplateSpecialization"); | |
| 2242 | return ErrorUnexpected; | |
| 2243 | case Decl::ClassTemplatePartialSpecialization: | |
| 2244 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassTemplatePartialSpecialization"); | |
| 2245 | return ErrorUnexpected; | |
| 2246 | case Decl::TemplateTypeParm: | |
| 2247 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TemplateTypeParm"); | |
| 2248 | return ErrorUnexpected; | |
| 2249 | case Decl::ObjCTypeParam: | |
| 2250 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCTypeParam"); | |
| 2251 | return ErrorUnexpected; | |
| 2252 | case Decl::TypeAlias: | |
| 2253 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TypeAlias"); | |
| 2254 | return ErrorUnexpected; | |
| 2255 | case Decl::Typedef: | |
| 2256 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Typedef"); | |
| 2257 | return ErrorUnexpected; | |
| 2258 | case Decl::UnresolvedUsingTypename: | |
| 2259 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UnresolvedUsingTypename"); | |
| 2260 | return ErrorUnexpected; | |
| 2261 | case Decl::Using: | |
| 2262 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Using"); | |
| 2263 | return ErrorUnexpected; | |
| 2264 | case Decl::UsingDirective: | |
| 2265 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UsingDirective"); | |
| 2266 | return ErrorUnexpected; | |
| 2267 | case Decl::UsingPack: | |
| 2268 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UsingPack"); | |
| 2269 | return ErrorUnexpected; | |
| 2270 | case Decl::UsingShadow: | |
| 2271 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UsingShadow"); | |
| 2272 | return ErrorUnexpected; | |
| 2273 | case Decl::ConstructorUsingShadow: | |
| 2274 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ConstructorUsingShadow"); | |
| 2275 | return ErrorUnexpected; | |
| 2276 | case Decl::Binding: | |
| 2277 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Binding"); | |
| 2278 | return ErrorUnexpected; | |
| 2279 | case Decl::Field: | |
| 2280 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Field"); | |
| 2281 | return ErrorUnexpected; | |
| 2282 | case Decl::ObjCAtDefsField: | |
| 2283 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCAtDefsField"); | |
| 2284 | return ErrorUnexpected; | |
| 2285 | case Decl::ObjCIvar: | |
| 2286 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCIvar"); | |
| 2287 | return ErrorUnexpected; | |
| 2288 | case Decl::Function: | |
| 2289 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Function"); | |
| 2290 | return ErrorUnexpected; | |
| 2291 | case Decl::CXXDeductionGuide: | |
| 2292 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXDeductionGuide"); | |
| 2293 | return ErrorUnexpected; | |
| 2294 | case Decl::CXXMethod: | |
| 2295 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXMethod"); | |
| 2296 | return ErrorUnexpected; | |
| 2297 | case Decl::CXXConstructor: | |
| 2298 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXConstructor"); | |
| 2299 | return ErrorUnexpected; | |
| 2300 | case Decl::CXXConversion: | |
| 2301 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXConversion"); | |
| 2302 | return ErrorUnexpected; | |
| 2303 | case Decl::CXXDestructor: | |
| 2304 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXDestructor"); | |
| 2305 | return ErrorUnexpected; | |
| 2306 | case Decl::MSProperty: | |
| 2307 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind MSProperty"); | |
| 2308 | return ErrorUnexpected; | |
| 2309 | case Decl::NonTypeTemplateParm: | |
| 2310 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind NonTypeTemplateParm"); | |
| 2311 | return ErrorUnexpected; | |
| 2312 | case Decl::Decomposition: | |
| 2313 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Decomposition"); | |
| 2314 | return ErrorUnexpected; | |
| 2315 | case Decl::ImplicitParam: | |
| 2316 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ImplicitParam"); | |
| 2317 | return ErrorUnexpected; | |
| 2318 | case Decl::OMPCapturedExpr: | |
| 2319 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPCapturedExpr"); | |
| 2320 | return ErrorUnexpected; | |
| 2321 | case Decl::ParmVar: | |
| 2322 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ParmVar"); | |
| 2323 | return ErrorUnexpected; | |
| 2324 | case Decl::VarTemplateSpecialization: | |
| 2325 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind VarTemplateSpecialization"); | |
| 2326 | return ErrorUnexpected; | |
| 2327 | case Decl::VarTemplatePartialSpecialization: | |
| 2328 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind VarTemplatePartialSpecialization"); | |
| 2329 | return ErrorUnexpected; | |
| 2330 | case Decl::EnumConstant: | |
| 2331 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind EnumConstant"); | |
| 2332 | return ErrorUnexpected; | |
| 2333 | case Decl::IndirectField: | |
| 2334 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind IndirectField"); | |
| 2335 | return ErrorUnexpected; | |
| 2336 | case Decl::OMPDeclareReduction: | |
| 2337 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPDeclareReduction"); | |
| 2338 | return ErrorUnexpected; | |
| 2339 | case Decl::UnresolvedUsingValue: | |
| 2340 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UnresolvedUsingValue"); | |
| 2341 | return ErrorUnexpected; | |
| 2342 | case Decl::OMPThreadPrivate: | |
| 2343 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPThreadPrivate"); | |
| 2344 | return ErrorUnexpected; | |
| 2345 | case Decl::ObjCPropertyImpl: | |
| 2346 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCPropertyImpl"); | |
| 2347 | return ErrorUnexpected; | |
| 2348 | case Decl::PragmaComment: | |
| 2349 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind PragmaComment"); | |
| 2350 | return ErrorUnexpected; | |
| 2351 | case Decl::PragmaDetectMismatch: | |
| 2352 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind PragmaDetectMismatch"); | |
| 2353 | return ErrorUnexpected; | |
| 2354 | case Decl::StaticAssert: | |
| 2355 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind StaticAssert"); | |
| 2356 | return ErrorUnexpected; | |
| 2357 | case Decl::TranslationUnit: | |
| 2358 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TranslationUnit"); | |
| 2359 | return ErrorUnexpected; | |
| 2360 | case Decl::OMPRequires: | |
| 2361 | emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPRequires"); | |
| 2362 | return ErrorUnexpected; | |
| 2363 | 2064 | } |
| 2364 | 2065 | zig_unreachable(); |
| 2365 | 2066 | } |
| ... | ... | @@ -2384,7 +2085,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) |
| 2384 | 2085 | return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast); |
| 2385 | 2086 | } |
| 2386 | 2087 | |
| 2387 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) { | |
| 2088 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) { | |
| 2388 | 2089 | AstNode *res = trans_expr(c, result_used, scope, expr, lrval); |
| 2389 | 2090 | if (res == nullptr) |
| 2390 | 2091 | return nullptr; |
| ... | ... | @@ -2421,143 +2122,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2421 | 2122 | } |
| 2422 | 2123 | |
| 2423 | 2124 | |
| 2424 | const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr(); | |
| 2125 | const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr(); | |
| 2425 | 2126 | auto classs = ty->getTypeClass(); |
| 2426 | 2127 | switch (classs) { |
| 2427 | case Type::Builtin: | |
| 2128 | case clang::Type::Builtin: | |
| 2428 | 2129 | { |
| 2429 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | |
| 2130 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); | |
| 2430 | 2131 | switch (builtin_ty->getKind()) { |
| 2431 | case BuiltinType::Bool: | |
| 2432 | case BuiltinType::Char_U: | |
| 2433 | case BuiltinType::UChar: | |
| 2434 | case BuiltinType::Char_S: | |
| 2435 | case BuiltinType::SChar: | |
| 2436 | case BuiltinType::UShort: | |
| 2437 | case BuiltinType::UInt: | |
| 2438 | case BuiltinType::ULong: | |
| 2439 | case BuiltinType::ULongLong: | |
| 2440 | case BuiltinType::Short: | |
| 2441 | case BuiltinType::Int: | |
| 2442 | case BuiltinType::Long: | |
| 2443 | case BuiltinType::LongLong: | |
| 2444 | case BuiltinType::UInt128: | |
| 2445 | case BuiltinType::Int128: | |
| 2446 | case BuiltinType::Float: | |
| 2447 | case BuiltinType::Double: | |
| 2448 | case BuiltinType::Float128: | |
| 2449 | case BuiltinType::LongDouble: | |
| 2450 | case BuiltinType::WChar_U: | |
| 2451 | case BuiltinType::Char8: | |
| 2452 | case BuiltinType::Char16: | |
| 2453 | case BuiltinType::Char32: | |
| 2454 | case BuiltinType::WChar_S: | |
| 2455 | case BuiltinType::Float16: | |
| 2132 | case clang::BuiltinType::Bool: | |
| 2133 | case clang::BuiltinType::Char_U: | |
| 2134 | case clang::BuiltinType::UChar: | |
| 2135 | case clang::BuiltinType::Char_S: | |
| 2136 | case clang::BuiltinType::SChar: | |
| 2137 | case clang::BuiltinType::UShort: | |
| 2138 | case clang::BuiltinType::UInt: | |
| 2139 | case clang::BuiltinType::ULong: | |
| 2140 | case clang::BuiltinType::ULongLong: | |
| 2141 | case clang::BuiltinType::Short: | |
| 2142 | case clang::BuiltinType::Int: | |
| 2143 | case clang::BuiltinType::Long: | |
| 2144 | case clang::BuiltinType::LongLong: | |
| 2145 | case clang::BuiltinType::UInt128: | |
| 2146 | case clang::BuiltinType::Int128: | |
| 2147 | case clang::BuiltinType::Float: | |
| 2148 | case clang::BuiltinType::Double: | |
| 2149 | case clang::BuiltinType::Float128: | |
| 2150 | case clang::BuiltinType::LongDouble: | |
| 2151 | case clang::BuiltinType::WChar_U: | |
| 2152 | case clang::BuiltinType::Char8: | |
| 2153 | case clang::BuiltinType::Char16: | |
| 2154 | case clang::BuiltinType::Char32: | |
| 2155 | case clang::BuiltinType::WChar_S: | |
| 2156 | case clang::BuiltinType::Float16: | |
| 2456 | 2157 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); |
| 2457 | case BuiltinType::NullPtr: | |
| 2458 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | |
| 2459 | ||
| 2460 | case BuiltinType::Void: | |
| 2461 | case BuiltinType::Half: | |
| 2462 | case BuiltinType::ObjCId: | |
| 2463 | case BuiltinType::ObjCClass: | |
| 2464 | case BuiltinType::ObjCSel: | |
| 2465 | case BuiltinType::OMPArraySection: | |
| 2466 | case BuiltinType::Dependent: | |
| 2467 | case BuiltinType::Overload: | |
| 2468 | case BuiltinType::BoundMember: | |
| 2469 | case BuiltinType::PseudoObject: | |
| 2470 | case BuiltinType::UnknownAny: | |
| 2471 | case BuiltinType::BuiltinFn: | |
| 2472 | case BuiltinType::ARCUnbridgedCast: | |
| 2473 | case BuiltinType::OCLImage1dRO: | |
| 2474 | case BuiltinType::OCLImage1dArrayRO: | |
| 2475 | case BuiltinType::OCLImage1dBufferRO: | |
| 2476 | case BuiltinType::OCLImage2dRO: | |
| 2477 | case BuiltinType::OCLImage2dArrayRO: | |
| 2478 | case BuiltinType::OCLImage2dDepthRO: | |
| 2479 | case BuiltinType::OCLImage2dArrayDepthRO: | |
| 2480 | case BuiltinType::OCLImage2dMSAARO: | |
| 2481 | case BuiltinType::OCLImage2dArrayMSAARO: | |
| 2482 | case BuiltinType::OCLImage2dMSAADepthRO: | |
| 2483 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | |
| 2484 | case BuiltinType::OCLImage3dRO: | |
| 2485 | case BuiltinType::OCLImage1dWO: | |
| 2486 | case BuiltinType::OCLImage1dArrayWO: | |
| 2487 | case BuiltinType::OCLImage1dBufferWO: | |
| 2488 | case BuiltinType::OCLImage2dWO: | |
| 2489 | case BuiltinType::OCLImage2dArrayWO: | |
| 2490 | case BuiltinType::OCLImage2dDepthWO: | |
| 2491 | case BuiltinType::OCLImage2dArrayDepthWO: | |
| 2492 | case BuiltinType::OCLImage2dMSAAWO: | |
| 2493 | case BuiltinType::OCLImage2dArrayMSAAWO: | |
| 2494 | case BuiltinType::OCLImage2dMSAADepthWO: | |
| 2495 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | |
| 2496 | case BuiltinType::OCLImage3dWO: | |
| 2497 | case BuiltinType::OCLImage1dRW: | |
| 2498 | case BuiltinType::OCLImage1dArrayRW: | |
| 2499 | case BuiltinType::OCLImage1dBufferRW: | |
| 2500 | case BuiltinType::OCLImage2dRW: | |
| 2501 | case BuiltinType::OCLImage2dArrayRW: | |
| 2502 | case BuiltinType::OCLImage2dDepthRW: | |
| 2503 | case BuiltinType::OCLImage2dArrayDepthRW: | |
| 2504 | case BuiltinType::OCLImage2dMSAARW: | |
| 2505 | case BuiltinType::OCLImage2dArrayMSAARW: | |
| 2506 | case BuiltinType::OCLImage2dMSAADepthRW: | |
| 2507 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | |
| 2508 | case BuiltinType::OCLImage3dRW: | |
| 2509 | case BuiltinType::OCLSampler: | |
| 2510 | case BuiltinType::OCLEvent: | |
| 2511 | case BuiltinType::OCLClkEvent: | |
| 2512 | case BuiltinType::OCLQueue: | |
| 2513 | case BuiltinType::OCLReserveID: | |
| 2514 | case BuiltinType::ShortAccum: | |
| 2515 | case BuiltinType::Accum: | |
| 2516 | case BuiltinType::LongAccum: | |
| 2517 | case BuiltinType::UShortAccum: | |
| 2518 | case BuiltinType::UAccum: | |
| 2519 | case BuiltinType::ULongAccum: | |
| 2520 | case BuiltinType::ShortFract: | |
| 2521 | case BuiltinType::Fract: | |
| 2522 | case BuiltinType::LongFract: | |
| 2523 | case BuiltinType::UShortFract: | |
| 2524 | case BuiltinType::UFract: | |
| 2525 | case BuiltinType::ULongFract: | |
| 2526 | case BuiltinType::SatShortAccum: | |
| 2527 | case BuiltinType::SatAccum: | |
| 2528 | case BuiltinType::SatLongAccum: | |
| 2529 | case BuiltinType::SatUShortAccum: | |
| 2530 | case BuiltinType::SatUAccum: | |
| 2531 | case BuiltinType::SatULongAccum: | |
| 2532 | case BuiltinType::SatShortFract: | |
| 2533 | case BuiltinType::SatFract: | |
| 2534 | case BuiltinType::SatLongFract: | |
| 2535 | case BuiltinType::SatUShortFract: | |
| 2536 | case BuiltinType::SatUFract: | |
| 2537 | case BuiltinType::SatULongFract: | |
| 2538 | case BuiltinType::OCLIntelSubgroupAVCMcePayload: | |
| 2539 | case BuiltinType::OCLIntelSubgroupAVCImePayload: | |
| 2540 | case BuiltinType::OCLIntelSubgroupAVCRefPayload: | |
| 2541 | case BuiltinType::OCLIntelSubgroupAVCSicPayload: | |
| 2542 | case BuiltinType::OCLIntelSubgroupAVCMceResult: | |
| 2543 | case BuiltinType::OCLIntelSubgroupAVCImeResult: | |
| 2544 | case BuiltinType::OCLIntelSubgroupAVCRefResult: | |
| 2545 | case BuiltinType::OCLIntelSubgroupAVCSicResult: | |
| 2546 | case BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout: | |
| 2547 | case BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout: | |
| 2548 | case BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin: | |
| 2549 | case BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin: | |
| 2158 | case clang::BuiltinType::NullPtr: | |
| 2159 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, | |
| 2160 | trans_create_node_unsigned(c, 0)); | |
| 2161 | ||
| 2162 | case clang::BuiltinType::Void: | |
| 2163 | case clang::BuiltinType::Half: | |
| 2164 | case clang::BuiltinType::ObjCId: | |
| 2165 | case clang::BuiltinType::ObjCClass: | |
| 2166 | case clang::BuiltinType::ObjCSel: | |
| 2167 | case clang::BuiltinType::OMPArraySection: | |
| 2168 | case clang::BuiltinType::Dependent: | |
| 2169 | case clang::BuiltinType::Overload: | |
| 2170 | case clang::BuiltinType::BoundMember: | |
| 2171 | case clang::BuiltinType::PseudoObject: | |
| 2172 | case clang::BuiltinType::UnknownAny: | |
| 2173 | case clang::BuiltinType::BuiltinFn: | |
| 2174 | case clang::BuiltinType::ARCUnbridgedCast: | |
| 2175 | case clang::BuiltinType::OCLImage1dRO: | |
| 2176 | case clang::BuiltinType::OCLImage1dArrayRO: | |
| 2177 | case clang::BuiltinType::OCLImage1dBufferRO: | |
| 2178 | case clang::BuiltinType::OCLImage2dRO: | |
| 2179 | case clang::BuiltinType::OCLImage2dArrayRO: | |
| 2180 | case clang::BuiltinType::OCLImage2dDepthRO: | |
| 2181 | case clang::BuiltinType::OCLImage2dArrayDepthRO: | |
| 2182 | case clang::BuiltinType::OCLImage2dMSAARO: | |
| 2183 | case clang::BuiltinType::OCLImage2dArrayMSAARO: | |
| 2184 | case clang::BuiltinType::OCLImage2dMSAADepthRO: | |
| 2185 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRO: | |
| 2186 | case clang::BuiltinType::OCLImage3dRO: | |
| 2187 | case clang::BuiltinType::OCLImage1dWO: | |
| 2188 | case clang::BuiltinType::OCLImage1dArrayWO: | |
| 2189 | case clang::BuiltinType::OCLImage1dBufferWO: | |
| 2190 | case clang::BuiltinType::OCLImage2dWO: | |
| 2191 | case clang::BuiltinType::OCLImage2dArrayWO: | |
| 2192 | case clang::BuiltinType::OCLImage2dDepthWO: | |
| 2193 | case clang::BuiltinType::OCLImage2dArrayDepthWO: | |
| 2194 | case clang::BuiltinType::OCLImage2dMSAAWO: | |
| 2195 | case clang::BuiltinType::OCLImage2dArrayMSAAWO: | |
| 2196 | case clang::BuiltinType::OCLImage2dMSAADepthWO: | |
| 2197 | case clang::BuiltinType::OCLImage2dArrayMSAADepthWO: | |
| 2198 | case clang::BuiltinType::OCLImage3dWO: | |
| 2199 | case clang::BuiltinType::OCLImage1dRW: | |
| 2200 | case clang::BuiltinType::OCLImage1dArrayRW: | |
| 2201 | case clang::BuiltinType::OCLImage1dBufferRW: | |
| 2202 | case clang::BuiltinType::OCLImage2dRW: | |
| 2203 | case clang::BuiltinType::OCLImage2dArrayRW: | |
| 2204 | case clang::BuiltinType::OCLImage2dDepthRW: | |
| 2205 | case clang::BuiltinType::OCLImage2dArrayDepthRW: | |
| 2206 | case clang::BuiltinType::OCLImage2dMSAARW: | |
| 2207 | case clang::BuiltinType::OCLImage2dArrayMSAARW: | |
| 2208 | case clang::BuiltinType::OCLImage2dMSAADepthRW: | |
| 2209 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRW: | |
| 2210 | case clang::BuiltinType::OCLImage3dRW: | |
| 2211 | case clang::BuiltinType::OCLSampler: | |
| 2212 | case clang::BuiltinType::OCLEvent: | |
| 2213 | case clang::BuiltinType::OCLClkEvent: | |
| 2214 | case clang::BuiltinType::OCLQueue: | |
| 2215 | case clang::BuiltinType::OCLReserveID: | |
| 2216 | case clang::BuiltinType::ShortAccum: | |
| 2217 | case clang::BuiltinType::Accum: | |
| 2218 | case clang::BuiltinType::LongAccum: | |
| 2219 | case clang::BuiltinType::UShortAccum: | |
| 2220 | case clang::BuiltinType::UAccum: | |
| 2221 | case clang::BuiltinType::ULongAccum: | |
| 2222 | case clang::BuiltinType::ShortFract: | |
| 2223 | case clang::BuiltinType::Fract: | |
| 2224 | case clang::BuiltinType::LongFract: | |
| 2225 | case clang::BuiltinType::UShortFract: | |
| 2226 | case clang::BuiltinType::UFract: | |
| 2227 | case clang::BuiltinType::ULongFract: | |
| 2228 | case clang::BuiltinType::SatShortAccum: | |
| 2229 | case clang::BuiltinType::SatAccum: | |
| 2230 | case clang::BuiltinType::SatLongAccum: | |
| 2231 | case clang::BuiltinType::SatUShortAccum: | |
| 2232 | case clang::BuiltinType::SatUAccum: | |
| 2233 | case clang::BuiltinType::SatULongAccum: | |
| 2234 | case clang::BuiltinType::SatShortFract: | |
| 2235 | case clang::BuiltinType::SatFract: | |
| 2236 | case clang::BuiltinType::SatLongFract: | |
| 2237 | case clang::BuiltinType::SatUShortFract: | |
| 2238 | case clang::BuiltinType::SatUFract: | |
| 2239 | case clang::BuiltinType::SatULongFract: | |
| 2240 | case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload: | |
| 2241 | case clang::BuiltinType::OCLIntelSubgroupAVCImePayload: | |
| 2242 | case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload: | |
| 2243 | case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload: | |
| 2244 | case clang::BuiltinType::OCLIntelSubgroupAVCMceResult: | |
| 2245 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResult: | |
| 2246 | case clang::BuiltinType::OCLIntelSubgroupAVCRefResult: | |
| 2247 | case clang::BuiltinType::OCLIntelSubgroupAVCSicResult: | |
| 2248 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout: | |
| 2249 | case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout: | |
| 2250 | case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin: | |
| 2251 | case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin: | |
| 2550 | 2252 | return res; |
| 2551 | 2253 | } |
| 2552 | 2254 | break; |
| 2553 | 2255 | } |
| 2554 | case Type::Pointer: | |
| 2555 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | |
| 2256 | case clang::Type::Pointer: | |
| 2257 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, | |
| 2258 | trans_create_node_unsigned(c, 0)); | |
| 2556 | 2259 | |
| 2557 | case Type::Typedef: | |
| 2260 | case clang::Type::Typedef: | |
| 2558 | 2261 | { |
| 2559 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | |
| 2560 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 2262 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); | |
| 2263 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | |
| 2561 | 2264 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); |
| 2562 | 2265 | if (existing_entry) { |
| 2563 | 2266 | return existing_entry->value; |
| ... | ... | @@ -2566,79 +2269,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2566 | 2269 | return res; |
| 2567 | 2270 | } |
| 2568 | 2271 | |
| 2569 | case Type::Enum: | |
| 2272 | case clang::Type::Enum: | |
| 2570 | 2273 | { |
| 2571 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | |
| 2274 | const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty); | |
| 2572 | 2275 | AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl()); |
| 2573 | 2276 | return to_enum_zero_cmp(c, res, enum_type); |
| 2574 | 2277 | } |
| 2575 | 2278 | |
| 2576 | case Type::Elaborated: | |
| 2279 | case clang::Type::Elaborated: | |
| 2577 | 2280 | { |
| 2578 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | |
| 2281 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); | |
| 2579 | 2282 | switch (elaborated_ty->getKeyword()) { |
| 2580 | case ETK_Enum: { | |
| 2581 | AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc()); | |
| 2283 | case clang::ETK_Enum: { | |
| 2284 | AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginloc()); | |
| 2582 | 2285 | return to_enum_zero_cmp(c, res, enum_type); |
| 2583 | 2286 | } |
| 2584 | case ETK_Struct: | |
| 2585 | case ETK_Union: | |
| 2586 | case ETK_Interface: | |
| 2587 | case ETK_Class: | |
| 2588 | case ETK_Typename: | |
| 2589 | case ETK_None: | |
| 2287 | case clang::ETK_Struct: | |
| 2288 | case clang::ETK_Union: | |
| 2289 | case clang::ETK_Interface: | |
| 2290 | case clang::ETK_Class: | |
| 2291 | case clang::ETK_Typename: | |
| 2292 | case clang::ETK_None: | |
| 2590 | 2293 | return res; |
| 2591 | 2294 | } |
| 2592 | 2295 | } |
| 2593 | 2296 | |
| 2594 | case Type::FunctionProto: | |
| 2595 | case Type::Record: | |
| 2596 | case Type::ConstantArray: | |
| 2597 | case Type::Paren: | |
| 2598 | case Type::Decayed: | |
| 2599 | case Type::Attributed: | |
| 2600 | case Type::IncompleteArray: | |
| 2601 | case Type::BlockPointer: | |
| 2602 | case Type::LValueReference: | |
| 2603 | case Type::RValueReference: | |
| 2604 | case Type::MemberPointer: | |
| 2605 | case Type::VariableArray: | |
| 2606 | case Type::DependentSizedArray: | |
| 2607 | case Type::DependentSizedExtVector: | |
| 2608 | case Type::Vector: | |
| 2609 | case Type::ExtVector: | |
| 2610 | case Type::FunctionNoProto: | |
| 2611 | case Type::UnresolvedUsing: | |
| 2612 | case Type::Adjusted: | |
| 2613 | case Type::TypeOfExpr: | |
| 2614 | case Type::TypeOf: | |
| 2615 | case Type::Decltype: | |
| 2616 | case Type::UnaryTransform: | |
| 2617 | case Type::TemplateTypeParm: | |
| 2618 | case Type::SubstTemplateTypeParm: | |
| 2619 | case Type::SubstTemplateTypeParmPack: | |
| 2620 | case Type::TemplateSpecialization: | |
| 2621 | case Type::Auto: | |
| 2622 | case Type::InjectedClassName: | |
| 2623 | case Type::DependentName: | |
| 2624 | case Type::DependentTemplateSpecialization: | |
| 2625 | case Type::PackExpansion: | |
| 2626 | case Type::ObjCObject: | |
| 2627 | case Type::ObjCInterface: | |
| 2628 | case Type::Complex: | |
| 2629 | case Type::ObjCObjectPointer: | |
| 2630 | case Type::Atomic: | |
| 2631 | case Type::Pipe: | |
| 2632 | case Type::ObjCTypeParam: | |
| 2633 | case Type::DeducedTemplateSpecialization: | |
| 2634 | case Type::DependentAddressSpace: | |
| 2635 | case Type::DependentVector: | |
| 2297 | case clang::Type::FunctionProto: | |
| 2298 | case clang::Type::Record: | |
| 2299 | case clang::Type::ConstantArray: | |
| 2300 | case clang::Type::Paren: | |
| 2301 | case clang::Type::Decayed: | |
| 2302 | case clang::Type::Attributed: | |
| 2303 | case clang::Type::IncompleteArray: | |
| 2304 | case clang::Type::BlockPointer: | |
| 2305 | case clang::Type::LValueReference: | |
| 2306 | case clang::Type::RValueReference: | |
| 2307 | case clang::Type::MemberPointer: | |
| 2308 | case clang::Type::VariableArray: | |
| 2309 | case clang::Type::DependentSizedArray: | |
| 2310 | case clang::Type::DependentSizedExtVector: | |
| 2311 | case clang::Type::Vector: | |
| 2312 | case clang::Type::ExtVector: | |
| 2313 | case clang::Type::FunctionNoProto: | |
| 2314 | case clang::Type::UnresolvedUsing: | |
| 2315 | case clang::Type::Adjusted: | |
| 2316 | case clang::Type::TypeOfExpr: | |
| 2317 | case clang::Type::TypeOf: | |
| 2318 | case clang::Type::Decltype: | |
| 2319 | case clang::Type::UnaryTransform: | |
| 2320 | case clang::Type::TemplateTypeParm: | |
| 2321 | case clang::Type::SubstTemplateTypeParm: | |
| 2322 | case clang::Type::SubstTemplateTypeParmPack: | |
| 2323 | case clang::Type::TemplateSpecialization: | |
| 2324 | case clang::Type::Auto: | |
| 2325 | case clang::Type::InjectedClassName: | |
| 2326 | case clang::Type::DependentName: | |
| 2327 | case clang::Type::DependentTemplateSpecialization: | |
| 2328 | case clang::Type::PackExpansion: | |
| 2329 | case clang::Type::ObjCObject: | |
| 2330 | case clang::Type::ObjCInterface: | |
| 2331 | case clang::Type::Complex: | |
| 2332 | case clang::Type::ObjCObjectPointer: | |
| 2333 | case clang::Type::Atomic: | |
| 2334 | case clang::Type::Pipe: | |
| 2335 | case clang::Type::ObjCTypeParam: | |
| 2336 | case clang::Type::DeducedTemplateSpecialization: | |
| 2337 | case clang::Type::DependentAddressSpace: | |
| 2338 | case clang::Type::DependentVector: | |
| 2636 | 2339 | return res; |
| 2637 | 2340 | } |
| 2638 | 2341 | zig_unreachable(); |
| 2639 | 2342 | } |
| 2640 | 2343 | |
| 2641 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { | |
| 2344 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) { | |
| 2642 | 2345 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 2643 | 2346 | |
| 2644 | 2347 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| ... | ... | @@ -2653,7 +2356,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt |
| 2653 | 2356 | return while_scope->node; |
| 2654 | 2357 | } |
| 2655 | 2358 | |
| 2656 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { | |
| 2359 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::IfStmt *stmt) { | |
| 2657 | 2360 | // if (c) t |
| 2658 | 2361 | // if (c) t else e |
| 2659 | 2362 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| ... | ... | @@ -2675,7 +2378,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2675 | 2378 | return if_node; |
| 2676 | 2379 | } |
| 2677 | 2380 | |
| 2678 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { | |
| 2381 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) { | |
| 2679 | 2382 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2680 | 2383 | |
| 2681 | 2384 | AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue); |
| ... | ... | @@ -2683,16 +2386,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2683 | 2386 | return nullptr; |
| 2684 | 2387 | |
| 2685 | 2388 | bool is_ptr = false; |
| 2686 | const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr); | |
| 2389 | const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr); | |
| 2687 | 2390 | AstNode *callee_node = nullptr; |
| 2688 | 2391 | if (is_ptr && fn_ty) { |
| 2689 | if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) { | |
| 2690 | const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee()); | |
| 2691 | if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) { | |
| 2692 | if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) { | |
| 2693 | const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr()); | |
| 2694 | const Decl *decl = decl_ref->getFoundDecl(); | |
| 2695 | if (decl->getKind() == Decl::Function) { | |
| 2392 | if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { | |
| 2393 | const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee()); | |
| 2394 | if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) { | |
| 2395 | if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) { | |
| 2396 | const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr()); | |
| 2397 | const clang::Decl *decl = decl_ref->getFoundDecl(); | |
| 2398 | if (decl->getKind() == clang::Decl::Function) { | |
| 2696 | 2399 | callee_node = callee_raw_node; |
| 2697 | 2400 | } |
| 2698 | 2401 | } |
| ... | ... | @@ -2708,7 +2411,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2708 | 2411 | node->data.fn_call_expr.fn_ref_expr = callee_node; |
| 2709 | 2412 | |
| 2710 | 2413 | unsigned num_args = stmt->getNumArgs(); |
| 2711 | const Expr * const* args = stmt->getArgs(); | |
| 2414 | const clang::Expr * const* args = stmt->getArgs(); | |
| 2712 | 2415 | for (unsigned i = 0; i < num_args; i += 1) { |
| 2713 | 2416 | AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue); |
| 2714 | 2417 | if (arg_node == nullptr) |
| ... | ... | @@ -2724,7 +2427,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2724 | 2427 | return node; |
| 2725 | 2428 | } |
| 2726 | 2429 | |
| 2727 | static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) { | |
| 2430 | static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) { | |
| 2728 | 2431 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2729 | 2432 | if (container_node == nullptr) |
| 2730 | 2433 | return nullptr; |
| ... | ... | @@ -2739,7 +2442,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp |
| 2739 | 2442 | return node; |
| 2740 | 2443 | } |
| 2741 | 2444 | |
| 2742 | static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) { | |
| 2445 | static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) { | |
| 2743 | 2446 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2744 | 2447 | if (container_node == nullptr) |
| 2745 | 2448 | return nullptr; |
| ... | ... | @@ -2756,7 +2459,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const |
| 2756 | 2459 | } |
| 2757 | 2460 | |
| 2758 | 2461 | static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 2759 | const CStyleCastExpr *stmt, TransLRValue lrvalue) | |
| 2462 | const clang::CStyleCastExpr *stmt, TransLRValue lrvalue) | |
| 2760 | 2463 | { |
| 2761 | 2464 | AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue); |
| 2762 | 2465 | if (sub_expr_node == nullptr) |
| ... | ... | @@ -2766,7 +2469,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran |
| 2766 | 2469 | } |
| 2767 | 2470 | |
| 2768 | 2471 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, |
| 2769 | const UnaryExprOrTypeTraitExpr *stmt) | |
| 2472 | const clang::UnaryExprOrTypeTraitExpr *stmt) | |
| 2770 | 2473 | { |
| 2771 | 2474 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc()); |
| 2772 | 2475 | if (type_node == nullptr) |
| ... | ... | @@ -2777,14 +2480,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop |
| 2777 | 2480 | return node; |
| 2778 | 2481 | } |
| 2779 | 2482 | |
| 2780 | static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) { | |
| 2483 | static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) { | |
| 2781 | 2484 | TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope); |
| 2782 | 2485 | |
| 2783 | 2486 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2784 | 2487 | |
| 2785 | 2488 | AstNode *body_node; |
| 2786 | 2489 | TransScope *child_scope; |
| 2787 | if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) { | |
| 2490 | if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) { | |
| 2788 | 2491 | // there's already a block in C, so we'll append our condition to it. |
| 2789 | 2492 | // c: do { |
| 2790 | 2493 | // c: a; |
| ... | ... | @@ -2837,11 +2540,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt |
| 2837 | 2540 | return while_scope->node; |
| 2838 | 2541 | } |
| 2839 | 2542 | |
| 2840 | static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) { | |
| 2543 | static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang::ForStmt *stmt) { | |
| 2841 | 2544 | AstNode *loop_block_node; |
| 2842 | 2545 | TransScopeWhile *while_scope; |
| 2843 | 2546 | TransScope *cond_scope; |
| 2844 | const Stmt *init_stmt = stmt->getInit(); | |
| 2547 | const clang::Stmt *init_stmt = stmt->getInit(); | |
| 2845 | 2548 | if (init_stmt == nullptr) { |
| 2846 | 2549 | while_scope = trans_scope_while_create(c, parent_scope); |
| 2847 | 2550 | loop_block_node = while_scope->node; |
| ... | ... | @@ -2862,12 +2565,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2862 | 2565 | child_scope->node->data.block.statements.append(while_scope->node); |
| 2863 | 2566 | } |
| 2864 | 2567 | |
| 2865 | const Stmt *cond_stmt = stmt->getCond(); | |
| 2568 | const clang::Stmt *cond_stmt = stmt->getCond(); | |
| 2866 | 2569 | if (cond_stmt == nullptr) { |
| 2867 | 2570 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2868 | 2571 | } else { |
| 2869 | if (Expr::classof(cond_stmt)) { | |
| 2870 | const Expr *cond_expr = static_cast<const Expr*>(cond_stmt); | |
| 2572 | if (clang::Expr::classof(cond_stmt)) { | |
| 2573 | const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt); | |
| 2871 | 2574 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue); |
| 2872 | 2575 | |
| 2873 | 2576 | if (while_scope->node->data.while_expr.condition == nullptr) |
| ... | ... | @@ -2880,7 +2583,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2880 | 2583 | } |
| 2881 | 2584 | } |
| 2882 | 2585 | |
| 2883 | const Stmt *inc_stmt = stmt->getInc(); | |
| 2586 | const clang::Stmt *inc_stmt = stmt->getInc(); | |
| 2884 | 2587 | if (inc_stmt != nullptr) { |
| 2885 | 2588 | AstNode *inc_node; |
| 2886 | 2589 | TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node); |
| ... | ... | @@ -2903,12 +2606,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2903 | 2606 | return loop_block_node; |
| 2904 | 2607 | } |
| 2905 | 2608 | |
| 2906 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { | |
| 2609 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const clang::SwitchStmt *stmt) { | |
| 2907 | 2610 | TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope); |
| 2908 | 2611 | |
| 2909 | 2612 | TransScopeSwitch *switch_scope; |
| 2910 | 2613 | |
| 2911 | const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); | |
| 2614 | const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); | |
| 2912 | 2615 | if (var_decl_stmt == nullptr) { |
| 2913 | 2616 | switch_scope = trans_scope_switch_create(c, &block_scope->base); |
| 2914 | 2617 | } else { |
| ... | ... | @@ -2927,7 +2630,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2927 | 2630 | switch_scope->end_label_name = end_label_name; |
| 2928 | 2631 | block_scope->node->data.block.name = end_label_name; |
| 2929 | 2632 | |
| 2930 | const Expr *cond_expr = stmt->getCond(); | |
| 2633 | const clang::Expr *cond_expr = stmt->getCond(); | |
| 2931 | 2634 | assert(cond_expr != nullptr); |
| 2932 | 2635 | |
| 2933 | 2636 | AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue); |
| ... | ... | @@ -2936,9 +2639,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2936 | 2639 | switch_scope->switch_node->data.switch_expr.expr = expr_node; |
| 2937 | 2640 | |
| 2938 | 2641 | AstNode *body_node; |
| 2939 | const Stmt *body_stmt = stmt->getBody(); | |
| 2940 | if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) { | |
| 2941 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt, | |
| 2642 | const clang::Stmt *body_stmt = stmt->getBody(); | |
| 2643 | if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) { | |
| 2644 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt, | |
| 2942 | 2645 | block_scope->node, nullptr)) |
| 2943 | 2646 | { |
| 2944 | 2647 | return nullptr; |
| ... | ... | @@ -2970,7 +2673,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) { |
| 2970 | 2673 | return nullptr; |
| 2971 | 2674 | } |
| 2972 | 2675 | |
| 2973 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, | |
| 2676 | static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::CaseStmt *stmt, AstNode **out_node, | |
| 2974 | 2677 | TransScope **out_scope) { |
| 2975 | 2678 | *out_node = nullptr; |
| 2976 | 2679 | |
| ... | ... | @@ -3015,7 +2718,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm |
| 3015 | 2718 | return ErrorNone; |
| 3016 | 2719 | } |
| 3017 | 2720 | |
| 3018 | static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node, | |
| 2721 | static int trans_switch_default(Context *c, TransScope *parent_scope, const clang::DefaultStmt *stmt, AstNode **out_node, | |
| 3019 | 2722 | TransScope **out_scope) |
| 3020 | 2723 | { |
| 3021 | 2724 | *out_node = nullptr; |
| ... | ... | @@ -3052,25 +2755,27 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa |
| 3052 | 2755 | return ErrorNone; |
| 3053 | 2756 | } |
| 3054 | 2757 | |
| 3055 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) { | |
| 2758 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) { | |
| 3056 | 2759 | switch (stmt->getKind()) { |
| 3057 | case StringLiteral::Ascii: | |
| 3058 | case StringLiteral::UTF8: | |
| 2760 | case clang::StringLiteral::Ascii: | |
| 2761 | case clang::StringLiteral::UTF8: | |
| 3059 | 2762 | return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString())); |
| 3060 | case StringLiteral::UTF16: | |
| 2763 | case clang::StringLiteral::UTF16: | |
| 3061 | 2764 | emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals"); |
| 3062 | 2765 | return nullptr; |
| 3063 | case StringLiteral::UTF32: | |
| 2766 | case clang::StringLiteral::UTF32: | |
| 3064 | 2767 | emit_warning(c, stmt->getBeginLoc(), "TODO support UTF32 string literals"); |
| 2768 | case clang::StringLiteral::UTF32: | |
| 2769 | emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals"); | |
| 3065 | 2770 | return nullptr; |
| 3066 | case StringLiteral::Wide: | |
| 2771 | case clang::StringLiteral::Wide: | |
| 3067 | 2772 | emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals"); |
| 3068 | 2773 | return nullptr; |
| 3069 | 2774 | } |
| 3070 | 2775 | zig_unreachable(); |
| 3071 | 2776 | } |
| 3072 | 2777 | |
| 3073 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { | |
| 2778 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const clang::BreakStmt *stmt) { | |
| 3074 | 2779 | TransScope *cur_scope = scope; |
| 3075 | 2780 | while (cur_scope != nullptr) { |
| 3076 | 2781 | if (cur_scope->id == TransScopeIdWhile) { |
| ... | ... | @@ -3084,7 +2789,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt |
| 3084 | 2789 | zig_unreachable(); |
| 3085 | 2790 | } |
| 3086 | 2791 | |
| 3087 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { | |
| 2792 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::ContinueStmt *stmt) { | |
| 3088 | 2793 | return trans_create_node(c, NodeTypeContinue); |
| 3089 | 2794 | } |
| 3090 | 2795 | |
| ... | ... | @@ -3097,47 +2802,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_ |
| 3097 | 2802 | return ErrorNone; |
| 3098 | 2803 | } |
| 3099 | 2804 | |
| 3100 | static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | |
| 2805 | static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt, | |
| 3101 | 2806 | ResultUsed result_used, TransLRValue lrvalue, |
| 3102 | 2807 | AstNode **out_node, TransScope **out_child_scope, |
| 3103 | 2808 | TransScope **out_node_scope) |
| 3104 | 2809 | { |
| 3105 | Stmt::StmtClass sc = stmt->getStmtClass(); | |
| 2810 | clang::Stmt::StmtClass sc = stmt->getStmtClass(); | |
| 3106 | 2811 | switch (sc) { |
| 3107 | case Stmt::ReturnStmtClass: | |
| 2812 | case clang::Stmt::ReturnStmtClass: | |
| 3108 | 2813 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3109 | trans_return_stmt(c, scope, (const ReturnStmt *)stmt)); | |
| 3110 | case Stmt::CompoundStmtClass: | |
| 2814 | trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt)); | |
| 2815 | case clang::Stmt::CompoundStmtClass: | |
| 3111 | 2816 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3112 | trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope)); | |
| 3113 | case Stmt::IntegerLiteralClass: | |
| 2817 | trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope)); | |
| 2818 | case clang::Stmt::IntegerLiteralClass: | |
| 3114 | 2819 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3115 | trans_integer_literal(c, (const IntegerLiteral *)stmt)); | |
| 3116 | case Stmt::ConditionalOperatorClass: | |
| 2820 | trans_integer_literal(c, (const clang::IntegerLiteral *)stmt)); | |
| 2821 | case clang::Stmt::ConditionalOperatorClass: | |
| 3117 | 2822 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3118 | trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt)); | |
| 3119 | case Stmt::BinaryOperatorClass: | |
| 2823 | trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt)); | |
| 2824 | case clang::Stmt::BinaryOperatorClass: | |
| 3120 | 2825 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3121 | trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt)); | |
| 3122 | case Stmt::CompoundAssignOperatorClass: | |
| 2826 | trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt)); | |
| 2827 | case clang::Stmt::CompoundAssignOperatorClass: | |
| 3123 | 2828 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3124 | trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt)); | |
| 3125 | case Stmt::ImplicitCastExprClass: | |
| 2829 | trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt)); | |
| 2830 | case clang::Stmt::ImplicitCastExprClass: | |
| 3126 | 2831 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3127 | trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt)); | |
| 3128 | case Stmt::DeclRefExprClass: | |
| 2832 | trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt)); | |
| 2833 | case clang::Stmt::DeclRefExprClass: | |
| 3129 | 2834 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3130 | trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue)); | |
| 3131 | case Stmt::UnaryOperatorClass: | |
| 2835 | trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue)); | |
| 2836 | case clang::Stmt::UnaryOperatorClass: | |
| 3132 | 2837 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3133 | trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt)); | |
| 3134 | case Stmt::DeclStmtClass: | |
| 3135 | return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope); | |
| 3136 | case Stmt::DoStmtClass: | |
| 3137 | case Stmt::WhileStmtClass: { | |
| 3138 | AstNode *while_node = sc == Stmt::DoStmtClass | |
| 3139 | ? trans_do_loop(c, scope, (const DoStmt *)stmt) | |
| 3140 | : trans_while_loop(c, scope, (const WhileStmt *)stmt); | |
| 2838 | trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt)); | |
| 2839 | case clang::Stmt::DeclStmtClass: | |
| 2840 | return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope); | |
| 2841 | case clang::Stmt::DoStmtClass: | |
| 2842 | case clang::Stmt::WhileStmtClass: { | |
| 2843 | AstNode *while_node = sc == clang::Stmt::DoStmtClass | |
| 2844 | ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt) | |
| 2845 | : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt); | |
| 3141 | 2846 | |
| 3142 | 2847 | if (while_node == nullptr) |
| 3143 | 2848 | return ErrorUnexpected; |
| ... | ... | @@ -3148,567 +2853,63 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 3148 | 2853 | |
| 3149 | 2854 | return wrap_stmt(out_node, out_child_scope, scope, while_node); |
| 3150 | 2855 | } |
| 3151 | case Stmt::IfStmtClass: | |
| 2856 | case clang::Stmt::IfStmtClass: | |
| 3152 | 2857 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3153 | trans_if_statement(c, scope, (const IfStmt *)stmt)); | |
| 3154 | case Stmt::CallExprClass: | |
| 2858 | trans_if_statement(c, scope, (const clang::IfStmt *)stmt)); | |
| 2859 | case clang::Stmt::CallExprClass: | |
| 3155 | 2860 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3156 | trans_call_expr(c, result_used, scope, (const CallExpr *)stmt)); | |
| 3157 | case Stmt::NullStmtClass: | |
| 2861 | trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt)); | |
| 2862 | case clang::Stmt::NullStmtClass: | |
| 3158 | 2863 | *out_node = nullptr; |
| 3159 | 2864 | *out_child_scope = scope; |
| 3160 | 2865 | return ErrorNone; |
| 3161 | case Stmt::MemberExprClass: | |
| 2866 | case clang::Stmt::MemberExprClass: | |
| 3162 | 2867 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3163 | trans_member_expr(c, scope, (const MemberExpr *)stmt)); | |
| 3164 | case Stmt::ArraySubscriptExprClass: | |
| 2868 | trans_member_expr(c, scope, (const clang::MemberExpr *)stmt)); | |
| 2869 | case clang::Stmt::ArraySubscriptExprClass: | |
| 3165 | 2870 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3166 | trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt)); | |
| 3167 | case Stmt::CStyleCastExprClass: | |
| 2871 | trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt)); | |
| 2872 | case clang::Stmt::CStyleCastExprClass: | |
| 3168 | 2873 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3169 | trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue)); | |
| 3170 | case Stmt::UnaryExprOrTypeTraitExprClass: | |
| 2874 | trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue)); | |
| 2875 | case clang::Stmt::UnaryExprOrTypeTraitExprClass: | |
| 3171 | 2876 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3172 | trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt)); | |
| 3173 | case Stmt::ForStmtClass: { | |
| 3174 | AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt); | |
| 2877 | trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt)); | |
| 2878 | case clang::Stmt::ForStmtClass: { | |
| 2879 | AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt); | |
| 3175 | 2880 | return wrap_stmt(out_node, out_child_scope, scope, node); |
| 3176 | 2881 | } |
| 3177 | case Stmt::StringLiteralClass: | |
| 2882 | case clang::Stmt::StringLiteralClass: | |
| 3178 | 2883 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3179 | trans_string_literal(c, scope, (const StringLiteral *)stmt)); | |
| 3180 | case Stmt::BreakStmtClass: | |
| 2884 | trans_string_literal(c, scope, (const clang::StringLiteral *)stmt)); | |
| 2885 | case clang::Stmt::BreakStmtClass: | |
| 3181 | 2886 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3182 | trans_break_stmt(c, scope, (const BreakStmt *)stmt)); | |
| 3183 | case Stmt::ContinueStmtClass: | |
| 2887 | trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt)); | |
| 2888 | case clang::Stmt::ContinueStmtClass: | |
| 3184 | 2889 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3185 | trans_continue_stmt(c, scope, (const ContinueStmt *)stmt)); | |
| 3186 | case Stmt::ParenExprClass: | |
| 2890 | trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt)); | |
| 2891 | case clang::Stmt::ParenExprClass: | |
| 3187 | 2892 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3188 | trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue)); | |
| 3189 | case Stmt::SwitchStmtClass: | |
| 2893 | trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue)); | |
| 2894 | case clang::Stmt::SwitchStmtClass: | |
| 3190 | 2895 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3191 | trans_switch_stmt(c, scope, (const SwitchStmt *)stmt)); | |
| 3192 | case Stmt::CaseStmtClass: | |
| 3193 | return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope); | |
| 3194 | case Stmt::DefaultStmtClass: | |
| 3195 | return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope); | |
| 3196 | case Stmt::ConstantExprClass: | |
| 2896 | trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt)); | |
| 2897 | case clang::Stmt::CaseStmtClass: | |
| 2898 | return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope); | |
| 2899 | case clang::Stmt::DefaultStmtClass: | |
| 2900 | return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope); | |
| 2901 | case clang::Stmt::ConstantExprClass: | |
| 3197 | 2902 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3198 | trans_constant_expr(c, (const ConstantExpr *)stmt)); | |
| 3199 | case Stmt::NoStmtClass: | |
| 2903 | trans_constant_expr(c, (const clang::ConstantExpr *)stmt)); | |
| 2904 | case clang::Stmt::NoStmtClass: | |
| 3200 | 2905 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass"); |
| 3201 | 2906 | return ErrorUnexpected; |
| 3202 | case Stmt::GCCAsmStmtClass: | |
| 3203 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GCCAsmStmtClass"); | |
| 3204 | return ErrorUnexpected; | |
| 3205 | case Stmt::MSAsmStmtClass: | |
| 3206 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSAsmStmtClass"); | |
| 3207 | return ErrorUnexpected; | |
| 3208 | case Stmt::AttributedStmtClass: | |
| 3209 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AttributedStmtClass"); | |
| 3210 | return ErrorUnexpected; | |
| 3211 | case Stmt::CXXCatchStmtClass: | |
| 3212 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXCatchStmtClass"); | |
| 3213 | return ErrorUnexpected; | |
| 3214 | case Stmt::CXXForRangeStmtClass: | |
| 3215 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXForRangeStmtClass"); | |
| 3216 | return ErrorUnexpected; | |
| 3217 | case Stmt::CXXTryStmtClass: | |
| 3218 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTryStmtClass"); | |
| 3219 | return ErrorUnexpected; | |
| 3220 | case Stmt::CapturedStmtClass: | |
| 3221 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CapturedStmtClass"); | |
| 3222 | return ErrorUnexpected; | |
| 3223 | case Stmt::CoreturnStmtClass: | |
| 3224 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoreturnStmtClass"); | |
| 3225 | return ErrorUnexpected; | |
| 3226 | case Stmt::CoroutineBodyStmtClass: | |
| 3227 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoroutineBodyStmtClass"); | |
| 3228 | return ErrorUnexpected; | |
| 3229 | case Stmt::BinaryConditionalOperatorClass: | |
| 3230 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C BinaryConditionalOperatorClass"); | |
| 3231 | return ErrorUnexpected; | |
| 3232 | case Stmt::AddrLabelExprClass: | |
| 3233 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AddrLabelExprClass"); | |
| 3234 | return ErrorUnexpected; | |
| 3235 | case Stmt::ArrayInitIndexExprClass: | |
| 3236 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitIndexExprClass"); | |
| 3237 | return ErrorUnexpected; | |
| 3238 | case Stmt::ArrayInitLoopExprClass: | |
| 3239 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitLoopExprClass"); | |
| 3240 | return ErrorUnexpected; | |
| 3241 | case Stmt::ArrayTypeTraitExprClass: | |
| 3242 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayTypeTraitExprClass"); | |
| 3243 | return ErrorUnexpected; | |
| 3244 | case Stmt::AsTypeExprClass: | |
| 3245 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AsTypeExprClass"); | |
| 3246 | return ErrorUnexpected; | |
| 3247 | case Stmt::AtomicExprClass: | |
| 3248 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C AtomicExprClass"); | |
| 3249 | return ErrorUnexpected; | |
| 3250 | case Stmt::BlockExprClass: | |
| 3251 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C BlockExprClass"); | |
| 3252 | return ErrorUnexpected; | |
| 3253 | case Stmt::CXXBindTemporaryExprClass: | |
| 3254 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBindTemporaryExprClass"); | |
| 3255 | return ErrorUnexpected; | |
| 3256 | case Stmt::CXXBoolLiteralExprClass: | |
| 3257 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBoolLiteralExprClass"); | |
| 3258 | return ErrorUnexpected; | |
| 3259 | case Stmt::CXXConstructExprClass: | |
| 3260 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructExprClass"); | |
| 3261 | return ErrorUnexpected; | |
| 3262 | case Stmt::CXXTemporaryObjectExprClass: | |
| 3263 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTemporaryObjectExprClass"); | |
| 3264 | return ErrorUnexpected; | |
| 3265 | case Stmt::CXXDefaultArgExprClass: | |
| 3266 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultArgExprClass"); | |
| 3267 | return ErrorUnexpected; | |
| 3268 | case Stmt::CXXDefaultInitExprClass: | |
| 3269 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultInitExprClass"); | |
| 3270 | return ErrorUnexpected; | |
| 3271 | case Stmt::CXXDeleteExprClass: | |
| 3272 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeleteExprClass"); | |
| 3273 | return ErrorUnexpected; | |
| 3274 | case Stmt::CXXDependentScopeMemberExprClass: | |
| 3275 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDependentScopeMemberExprClass"); | |
| 3276 | return ErrorUnexpected; | |
| 3277 | case Stmt::CXXFoldExprClass: | |
| 3278 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFoldExprClass"); | |
| 3279 | return ErrorUnexpected; | |
| 3280 | case Stmt::CXXInheritedCtorInitExprClass: | |
| 3281 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXInheritedCtorInitExprClass"); | |
| 3282 | return ErrorUnexpected; | |
| 3283 | case Stmt::CXXNewExprClass: | |
| 3284 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNewExprClass"); | |
| 3285 | return ErrorUnexpected; | |
| 3286 | case Stmt::CXXNoexceptExprClass: | |
| 3287 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNoexceptExprClass"); | |
| 3288 | return ErrorUnexpected; | |
| 3289 | case Stmt::CXXNullPtrLiteralExprClass: | |
| 3290 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNullPtrLiteralExprClass"); | |
| 3291 | return ErrorUnexpected; | |
| 3292 | case Stmt::CXXPseudoDestructorExprClass: | |
| 3293 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXPseudoDestructorExprClass"); | |
| 3294 | return ErrorUnexpected; | |
| 3295 | case Stmt::CXXScalarValueInitExprClass: | |
| 3296 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXScalarValueInitExprClass"); | |
| 3297 | return ErrorUnexpected; | |
| 3298 | case Stmt::CXXStdInitializerListExprClass: | |
| 3299 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStdInitializerListExprClass"); | |
| 3300 | return ErrorUnexpected; | |
| 3301 | case Stmt::CXXThisExprClass: | |
| 3302 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThisExprClass"); | |
| 3303 | return ErrorUnexpected; | |
| 3304 | case Stmt::CXXThrowExprClass: | |
| 3305 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThrowExprClass"); | |
| 3306 | return ErrorUnexpected; | |
| 3307 | case Stmt::CXXTypeidExprClass: | |
| 3308 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTypeidExprClass"); | |
| 3309 | return ErrorUnexpected; | |
| 3310 | case Stmt::CXXUnresolvedConstructExprClass: | |
| 3311 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUnresolvedConstructExprClass"); | |
| 3312 | return ErrorUnexpected; | |
| 3313 | case Stmt::CXXUuidofExprClass: | |
| 3314 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUuidofExprClass"); | |
| 3315 | return ErrorUnexpected; | |
| 3316 | case Stmt::CUDAKernelCallExprClass: | |
| 3317 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CUDAKernelCallExprClass"); | |
| 3318 | return ErrorUnexpected; | |
| 3319 | case Stmt::CXXMemberCallExprClass: | |
| 3320 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMemberCallExprClass"); | |
| 3321 | return ErrorUnexpected; | |
| 3322 | case Stmt::CXXOperatorCallExprClass: | |
| 3323 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXOperatorCallExprClass"); | |
| 3324 | return ErrorUnexpected; | |
| 3325 | case Stmt::UserDefinedLiteralClass: | |
| 3326 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C UserDefinedLiteralClass"); | |
| 3327 | return ErrorUnexpected; | |
| 3328 | case Stmt::CXXFunctionalCastExprClass: | |
| 3329 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFunctionalCastExprClass"); | |
| 3330 | return ErrorUnexpected; | |
| 3331 | case Stmt::CXXConstCastExprClass: | |
| 3332 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstCastExprClass"); | |
| 3333 | return ErrorUnexpected; | |
| 3334 | case Stmt::CXXDynamicCastExprClass: | |
| 3335 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDynamicCastExprClass"); | |
| 3336 | return ErrorUnexpected; | |
| 3337 | case Stmt::CXXReinterpretCastExprClass: | |
| 3338 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXReinterpretCastExprClass"); | |
| 3339 | return ErrorUnexpected; | |
| 3340 | case Stmt::CXXStaticCastExprClass: | |
| 3341 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStaticCastExprClass"); | |
| 3342 | return ErrorUnexpected; | |
| 3343 | case Stmt::ObjCBridgedCastExprClass: | |
| 3344 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBridgedCastExprClass"); | |
| 3345 | return ErrorUnexpected; | |
| 3346 | case Stmt::CharacterLiteralClass: | |
| 3347 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CharacterLiteralClass"); | |
| 3348 | return ErrorUnexpected; | |
| 3349 | case Stmt::ChooseExprClass: | |
| 3350 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ChooseExprClass"); | |
| 3351 | return ErrorUnexpected; | |
| 3352 | case Stmt::CompoundLiteralExprClass: | |
| 3353 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CompoundLiteralExprClass"); | |
| 3354 | return ErrorUnexpected; | |
| 3355 | case Stmt::ConvertVectorExprClass: | |
| 3356 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConvertVectorExprClass"); | |
| 3357 | return ErrorUnexpected; | |
| 3358 | case Stmt::CoawaitExprClass: | |
| 3359 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoawaitExprClass"); | |
| 3360 | return ErrorUnexpected; | |
| 3361 | case Stmt::CoyieldExprClass: | |
| 3362 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoyieldExprClass"); | |
| 3363 | return ErrorUnexpected; | |
| 3364 | case Stmt::DependentCoawaitExprClass: | |
| 3365 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentCoawaitExprClass"); | |
| 3366 | return ErrorUnexpected; | |
| 3367 | case Stmt::DependentScopeDeclRefExprClass: | |
| 3368 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentScopeDeclRefExprClass"); | |
| 3369 | return ErrorUnexpected; | |
| 3370 | case Stmt::DesignatedInitExprClass: | |
| 3371 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitExprClass"); | |
| 3372 | return ErrorUnexpected; | |
| 3373 | case Stmt::DesignatedInitUpdateExprClass: | |
| 3374 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitUpdateExprClass"); | |
| 3375 | return ErrorUnexpected; | |
| 3376 | case Stmt::ExprWithCleanupsClass: | |
| 3377 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExprWithCleanupsClass"); | |
| 3378 | return ErrorUnexpected; | |
| 3379 | case Stmt::ExpressionTraitExprClass: | |
| 3380 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExpressionTraitExprClass"); | |
| 3381 | return ErrorUnexpected; | |
| 3382 | case Stmt::ExtVectorElementExprClass: | |
| 3383 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExtVectorElementExprClass"); | |
| 3384 | return ErrorUnexpected; | |
| 3385 | case Stmt::FloatingLiteralClass: | |
| 3386 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C FloatingLiteralClass"); | |
| 3387 | return ErrorUnexpected; | |
| 3388 | case Stmt::FunctionParmPackExprClass: | |
| 3389 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionParmPackExprClass"); | |
| 3390 | return ErrorUnexpected; | |
| 3391 | case Stmt::GNUNullExprClass: | |
| 3392 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GNUNullExprClass"); | |
| 3393 | return ErrorUnexpected; | |
| 3394 | case Stmt::GenericSelectionExprClass: | |
| 3395 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GenericSelectionExprClass"); | |
| 3396 | return ErrorUnexpected; | |
| 3397 | case Stmt::ImaginaryLiteralClass: | |
| 3398 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImaginaryLiteralClass"); | |
| 3399 | return ErrorUnexpected; | |
| 3400 | case Stmt::ImplicitValueInitExprClass: | |
| 3401 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitValueInitExprClass"); | |
| 3402 | return ErrorUnexpected; | |
| 3403 | case Stmt::InitListExprClass: | |
| 3404 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C InitListExprClass"); | |
| 3405 | return ErrorUnexpected; | |
| 3406 | case Stmt::LambdaExprClass: | |
| 3407 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C LambdaExprClass"); | |
| 3408 | return ErrorUnexpected; | |
| 3409 | case Stmt::MSPropertyRefExprClass: | |
| 3410 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertyRefExprClass"); | |
| 3411 | return ErrorUnexpected; | |
| 3412 | case Stmt::MSPropertySubscriptExprClass: | |
| 3413 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertySubscriptExprClass"); | |
| 3414 | return ErrorUnexpected; | |
| 3415 | case Stmt::MaterializeTemporaryExprClass: | |
| 3416 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MaterializeTemporaryExprClass"); | |
| 3417 | return ErrorUnexpected; | |
| 3418 | case Stmt::NoInitExprClass: | |
| 3419 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoInitExprClass"); | |
| 3420 | return ErrorUnexpected; | |
| 3421 | case Stmt::OMPArraySectionExprClass: | |
| 3422 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPArraySectionExprClass"); | |
| 3423 | return ErrorUnexpected; | |
| 3424 | case Stmt::ObjCArrayLiteralClass: | |
| 3425 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCArrayLiteralClass"); | |
| 3426 | return ErrorUnexpected; | |
| 3427 | case Stmt::ObjCAvailabilityCheckExprClass: | |
| 3428 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAvailabilityCheckExprClass"); | |
| 3429 | return ErrorUnexpected; | |
| 3430 | case Stmt::ObjCBoolLiteralExprClass: | |
| 3431 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoolLiteralExprClass"); | |
| 3432 | return ErrorUnexpected; | |
| 3433 | case Stmt::ObjCBoxedExprClass: | |
| 3434 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoxedExprClass"); | |
| 3435 | return ErrorUnexpected; | |
| 3436 | case Stmt::ObjCDictionaryLiteralClass: | |
| 3437 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCDictionaryLiteralClass"); | |
| 3438 | return ErrorUnexpected; | |
| 3439 | case Stmt::ObjCEncodeExprClass: | |
| 3440 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCEncodeExprClass"); | |
| 3441 | return ErrorUnexpected; | |
| 3442 | case Stmt::ObjCIndirectCopyRestoreExprClass: | |
| 3443 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIndirectCopyRestoreExprClass"); | |
| 3444 | return ErrorUnexpected; | |
| 3445 | case Stmt::ObjCIsaExprClass: | |
| 3446 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIsaExprClass"); | |
| 3447 | return ErrorUnexpected; | |
| 3448 | case Stmt::ObjCIvarRefExprClass: | |
| 3449 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvarRefExprClass"); | |
| 3450 | return ErrorUnexpected; | |
| 3451 | case Stmt::ObjCMessageExprClass: | |
| 3452 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMessageExprClass"); | |
| 3453 | return ErrorUnexpected; | |
| 3454 | case Stmt::ObjCPropertyRefExprClass: | |
| 3455 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyRefExprClass"); | |
| 3456 | return ErrorUnexpected; | |
| 3457 | case Stmt::ObjCProtocolExprClass: | |
| 3458 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocolExprClass"); | |
| 3459 | return ErrorUnexpected; | |
| 3460 | case Stmt::ObjCSelectorExprClass: | |
| 3461 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSelectorExprClass"); | |
| 3462 | return ErrorUnexpected; | |
| 3463 | case Stmt::ObjCStringLiteralClass: | |
| 3464 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCStringLiteralClass"); | |
| 3465 | return ErrorUnexpected; | |
| 3466 | case Stmt::ObjCSubscriptRefExprClass: | |
| 3467 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSubscriptRefExprClass"); | |
| 3468 | return ErrorUnexpected; | |
| 3469 | case Stmt::OffsetOfExprClass: | |
| 3470 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OffsetOfExprClass"); | |
| 3471 | return ErrorUnexpected; | |
| 3472 | case Stmt::OpaqueValueExprClass: | |
| 3473 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OpaqueValueExprClass"); | |
| 3474 | return ErrorUnexpected; | |
| 3475 | case Stmt::UnresolvedLookupExprClass: | |
| 3476 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedLookupExprClass"); | |
| 3477 | return ErrorUnexpected; | |
| 3478 | case Stmt::UnresolvedMemberExprClass: | |
| 3479 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedMemberExprClass"); | |
| 3480 | return ErrorUnexpected; | |
| 3481 | case Stmt::PackExpansionExprClass: | |
| 3482 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C PackExpansionExprClass"); | |
| 3483 | return ErrorUnexpected; | |
| 3484 | case Stmt::ParenListExprClass: | |
| 3485 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParenListExprClass"); | |
| 3486 | return ErrorUnexpected; | |
| 3487 | case Stmt::PredefinedExprClass: | |
| 3488 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C PredefinedExprClass"); | |
| 3489 | return ErrorUnexpected; | |
| 3490 | case Stmt::PseudoObjectExprClass: | |
| 3491 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C PseudoObjectExprClass"); | |
| 3492 | return ErrorUnexpected; | |
| 3493 | case Stmt::ShuffleVectorExprClass: | |
| 3494 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ShuffleVectorExprClass"); | |
| 3495 | return ErrorUnexpected; | |
| 3496 | case Stmt::SizeOfPackExprClass: | |
| 3497 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SizeOfPackExprClass"); | |
| 3498 | return ErrorUnexpected; | |
| 3499 | case Stmt::StmtExprClass: | |
| 3500 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C StmtExprClass"); | |
| 3501 | return ErrorUnexpected; | |
| 3502 | case Stmt::SubstNonTypeTemplateParmExprClass: | |
| 3503 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmExprClass"); | |
| 3504 | return ErrorUnexpected; | |
| 3505 | case Stmt::SubstNonTypeTemplateParmPackExprClass: | |
| 3506 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); | |
| 3507 | return ErrorUnexpected; | |
| 3508 | case Stmt::TypeTraitExprClass: | |
| 3509 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeTraitExprClass"); | |
| 3510 | return ErrorUnexpected; | |
| 3511 | case Stmt::TypoExprClass: | |
| 3512 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypoExprClass"); | |
| 3513 | return ErrorUnexpected; | |
| 3514 | case Stmt::VAArgExprClass: | |
| 3515 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C VAArgExprClass"); | |
| 3516 | return ErrorUnexpected; | |
| 3517 | case Stmt::GotoStmtClass: | |
| 3518 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C GotoStmtClass"); | |
| 3519 | return ErrorUnexpected; | |
| 3520 | case Stmt::IndirectGotoStmtClass: | |
| 3521 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectGotoStmtClass"); | |
| 3522 | return ErrorUnexpected; | |
| 3523 | case Stmt::LabelStmtClass: | |
| 3524 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C LabelStmtClass"); | |
| 3525 | return ErrorUnexpected; | |
| 3526 | case Stmt::MSDependentExistsStmtClass: | |
| 3527 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSDependentExistsStmtClass"); | |
| 3528 | return ErrorUnexpected; | |
| 3529 | case Stmt::OMPAtomicDirectiveClass: | |
| 3530 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPAtomicDirectiveClass"); | |
| 3531 | return ErrorUnexpected; | |
| 3532 | case Stmt::OMPBarrierDirectiveClass: | |
| 3533 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPBarrierDirectiveClass"); | |
| 3534 | return ErrorUnexpected; | |
| 3535 | case Stmt::OMPCancelDirectiveClass: | |
| 3536 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancelDirectiveClass"); | |
| 3537 | return ErrorUnexpected; | |
| 3538 | case Stmt::OMPCancellationPointDirectiveClass: | |
| 3539 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancellationPointDirectiveClass"); | |
| 3540 | return ErrorUnexpected; | |
| 3541 | case Stmt::OMPCriticalDirectiveClass: | |
| 3542 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCriticalDirectiveClass"); | |
| 3543 | return ErrorUnexpected; | |
| 3544 | case Stmt::OMPFlushDirectiveClass: | |
| 3545 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPFlushDirectiveClass"); | |
| 3546 | return ErrorUnexpected; | |
| 3547 | case Stmt::OMPDistributeDirectiveClass: | |
| 3548 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeDirectiveClass"); | |
| 3549 | return ErrorUnexpected; | |
| 3550 | case Stmt::OMPDistributeParallelForDirectiveClass: | |
| 3551 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForDirectiveClass"); | |
| 3552 | return ErrorUnexpected; | |
| 3553 | case Stmt::OMPDistributeParallelForSimdDirectiveClass: | |
| 3554 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | |
| 3555 | return ErrorUnexpected; | |
| 3556 | case Stmt::OMPDistributeSimdDirectiveClass: | |
| 3557 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeSimdDirectiveClass"); | |
| 3558 | return ErrorUnexpected; | |
| 3559 | case Stmt::OMPForDirectiveClass: | |
| 3560 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForDirectiveClass"); | |
| 3561 | return ErrorUnexpected; | |
| 3562 | case Stmt::OMPForSimdDirectiveClass: | |
| 3563 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForSimdDirectiveClass"); | |
| 3564 | return ErrorUnexpected; | |
| 3565 | case Stmt::OMPParallelForDirectiveClass: | |
| 3566 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForDirectiveClass"); | |
| 3567 | return ErrorUnexpected; | |
| 3568 | case Stmt::OMPParallelForSimdDirectiveClass: | |
| 3569 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForSimdDirectiveClass"); | |
| 3570 | return ErrorUnexpected; | |
| 3571 | case Stmt::OMPSimdDirectiveClass: | |
| 3572 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSimdDirectiveClass"); | |
| 3573 | return ErrorUnexpected; | |
| 3574 | case Stmt::OMPTargetParallelForSimdDirectiveClass: | |
| 3575 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); | |
| 3576 | return ErrorUnexpected; | |
| 3577 | case Stmt::OMPTargetSimdDirectiveClass: | |
| 3578 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetSimdDirectiveClass"); | |
| 3579 | return ErrorUnexpected; | |
| 3580 | case Stmt::OMPTargetTeamsDistributeDirectiveClass: | |
| 3581 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | |
| 3582 | return ErrorUnexpected; | |
| 3583 | case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: | |
| 3584 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | |
| 3585 | return ErrorUnexpected; | |
| 3586 | case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | |
| 3587 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | |
| 3588 | return ErrorUnexpected; | |
| 3589 | case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: | |
| 3590 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | |
| 3591 | return ErrorUnexpected; | |
| 3592 | case Stmt::OMPTaskLoopDirectiveClass: | |
| 3593 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopDirectiveClass"); | |
| 3594 | return ErrorUnexpected; | |
| 3595 | case Stmt::OMPTaskLoopSimdDirectiveClass: | |
| 3596 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopSimdDirectiveClass"); | |
| 3597 | return ErrorUnexpected; | |
| 3598 | case Stmt::OMPTeamsDistributeDirectiveClass: | |
| 3599 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeDirectiveClass"); | |
| 3600 | return ErrorUnexpected; | |
| 3601 | case Stmt::OMPTeamsDistributeParallelForDirectiveClass: | |
| 3602 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | |
| 3603 | return ErrorUnexpected; | |
| 3604 | case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: | |
| 3605 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | |
| 3606 | return ErrorUnexpected; | |
| 3607 | case Stmt::OMPTeamsDistributeSimdDirectiveClass: | |
| 3608 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | |
| 3609 | return ErrorUnexpected; | |
| 3610 | case Stmt::OMPMasterDirectiveClass: | |
| 3611 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPMasterDirectiveClass"); | |
| 3612 | return ErrorUnexpected; | |
| 3613 | case Stmt::OMPOrderedDirectiveClass: | |
| 3614 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPOrderedDirectiveClass"); | |
| 3615 | return ErrorUnexpected; | |
| 3616 | case Stmt::OMPParallelDirectiveClass: | |
| 3617 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelDirectiveClass"); | |
| 3618 | return ErrorUnexpected; | |
| 3619 | case Stmt::OMPParallelSectionsDirectiveClass: | |
| 3620 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelSectionsDirectiveClass"); | |
| 3621 | return ErrorUnexpected; | |
| 3622 | case Stmt::OMPSectionDirectiveClass: | |
| 3623 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionDirectiveClass"); | |
| 3624 | return ErrorUnexpected; | |
| 3625 | case Stmt::OMPSectionsDirectiveClass: | |
| 3626 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionsDirectiveClass"); | |
| 3627 | return ErrorUnexpected; | |
| 3628 | case Stmt::OMPSingleDirectiveClass: | |
| 3629 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSingleDirectiveClass"); | |
| 3630 | return ErrorUnexpected; | |
| 3631 | case Stmt::OMPTargetDataDirectiveClass: | |
| 3632 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDataDirectiveClass"); | |
| 3633 | return ErrorUnexpected; | |
| 3634 | case Stmt::OMPTargetDirectiveClass: | |
| 3635 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDirectiveClass"); | |
| 3636 | return ErrorUnexpected; | |
| 3637 | case Stmt::OMPTargetEnterDataDirectiveClass: | |
| 3638 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetEnterDataDirectiveClass"); | |
| 3639 | return ErrorUnexpected; | |
| 3640 | case Stmt::OMPTargetExitDataDirectiveClass: | |
| 3641 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetExitDataDirectiveClass"); | |
| 3642 | return ErrorUnexpected; | |
| 3643 | case Stmt::OMPTargetParallelDirectiveClass: | |
| 3644 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelDirectiveClass"); | |
| 3645 | return ErrorUnexpected; | |
| 3646 | case Stmt::OMPTargetParallelForDirectiveClass: | |
| 3647 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForDirectiveClass"); | |
| 3648 | return ErrorUnexpected; | |
| 3649 | case Stmt::OMPTargetTeamsDirectiveClass: | |
| 3650 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDirectiveClass"); | |
| 3651 | return ErrorUnexpected; | |
| 3652 | case Stmt::OMPTargetUpdateDirectiveClass: | |
| 3653 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetUpdateDirectiveClass"); | |
| 3654 | return ErrorUnexpected; | |
| 3655 | case Stmt::OMPTaskDirectiveClass: | |
| 3656 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskDirectiveClass"); | |
| 3657 | return ErrorUnexpected; | |
| 3658 | case Stmt::OMPTaskgroupDirectiveClass: | |
| 3659 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskgroupDirectiveClass"); | |
| 3660 | return ErrorUnexpected; | |
| 3661 | case Stmt::OMPTaskwaitDirectiveClass: | |
| 3662 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskwaitDirectiveClass"); | |
| 3663 | return ErrorUnexpected; | |
| 3664 | case Stmt::OMPTaskyieldDirectiveClass: | |
| 3665 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskyieldDirectiveClass"); | |
| 3666 | return ErrorUnexpected; | |
| 3667 | case Stmt::OMPTeamsDirectiveClass: | |
| 3668 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDirectiveClass"); | |
| 3669 | return ErrorUnexpected; | |
| 3670 | case Stmt::ObjCAtCatchStmtClass: | |
| 3671 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtCatchStmtClass"); | |
| 3672 | return ErrorUnexpected; | |
| 3673 | case Stmt::ObjCAtFinallyStmtClass: | |
| 3674 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtFinallyStmtClass"); | |
| 3675 | return ErrorUnexpected; | |
| 3676 | case Stmt::ObjCAtSynchronizedStmtClass: | |
| 3677 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtSynchronizedStmtClass"); | |
| 3678 | return ErrorUnexpected; | |
| 3679 | case Stmt::ObjCAtThrowStmtClass: | |
| 3680 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtThrowStmtClass"); | |
| 3681 | return ErrorUnexpected; | |
| 3682 | case Stmt::ObjCAtTryStmtClass: | |
| 3683 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtTryStmtClass"); | |
| 3684 | return ErrorUnexpected; | |
| 3685 | case Stmt::ObjCAutoreleasePoolStmtClass: | |
| 3686 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAutoreleasePoolStmtClass"); | |
| 3687 | return ErrorUnexpected; | |
| 3688 | case Stmt::ObjCForCollectionStmtClass: | |
| 3689 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCForCollectionStmtClass"); | |
| 3690 | return ErrorUnexpected; | |
| 3691 | case Stmt::SEHExceptStmtClass: | |
| 3692 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHExceptStmtClass"); | |
| 3693 | return ErrorUnexpected; | |
| 3694 | case Stmt::SEHFinallyStmtClass: | |
| 3695 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHFinallyStmtClass"); | |
| 3696 | return ErrorUnexpected; | |
| 3697 | case Stmt::SEHLeaveStmtClass: | |
| 3698 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHLeaveStmtClass"); | |
| 3699 | return ErrorUnexpected; | |
| 3700 | case Stmt::SEHTryStmtClass: | |
| 3701 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHTryStmtClass"); | |
| 3702 | return ErrorUnexpected; | |
| 3703 | case Stmt::FixedPointLiteralClass: | |
| 3704 | emit_warning(c, stmt->getBeginLoc(), "TODO handle C FixedPointLiteralClass"); | |
| 3705 | return ErrorUnexpected; | |
| 3706 | 2907 | } |
| 3707 | 2908 | zig_unreachable(); |
| 3708 | 2909 | } |
| 3709 | 2910 | |
| 3710 | 2911 | // Returns null if there was an error |
| 3711 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, | |
| 2912 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, | |
| 3712 | 2913 | TransLRValue lrval) |
| 3713 | 2914 | { |
| 3714 | 2915 | AstNode *result_node; |
| ... | ... | @@ -3721,7 +2922,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope |
| 3721 | 2922 | |
| 3722 | 2923 | // Statements have no result and no concept of L or R value. |
| 3723 | 2924 | // Returns child scope, or null if there was an error |
| 3724 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node) { | |
| 2925 | static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) { | |
| 3725 | 2926 | TransScope *child_scope; |
| 3726 | 2927 | if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) { |
| 3727 | 2928 | return nullptr; |
| ... | ... | @@ -3729,7 +2930,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A |
| 3729 | 2930 | return child_scope; |
| 3730 | 2931 | } |
| 3731 | 2932 | |
| 3732 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | |
| 2933 | static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { | |
| 3733 | 2934 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); |
| 3734 | 2935 | |
| 3735 | 2936 | if (get_global(c, fn_name)) { |
| ... | ... | @@ -3746,13 +2947,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3746 | 2947 | proto_node->data.fn_proto.name = fn_name; |
| 3747 | 2948 | proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); |
| 3748 | 2949 | |
| 3749 | StorageClass sc = fn_decl->getStorageClass(); | |
| 3750 | if (sc == SC_None) { | |
| 2950 | clang::StorageClass sc = fn_decl->getStorageClass(); | |
| 2951 | if (sc == clang::SC_None) { | |
| 3751 | 2952 | proto_node->data.fn_proto.visib_mod = c->visib_mod; |
| 3752 | 2953 | proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false; |
| 3753 | } else if (sc == SC_Extern || sc == SC_Static) { | |
| 2954 | } else if (sc == clang::SC_Extern || sc == clang::SC_Static) { | |
| 3754 | 2955 | proto_node->data.fn_proto.visib_mod = c->visib_mod; |
| 3755 | } else if (sc == SC_PrivateExtern) { | |
| 2956 | } else if (sc == clang::SC_PrivateExtern) { | |
| 3756 | 2957 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); |
| 3757 | 2958 | return; |
| 3758 | 2959 | } else { |
| ... | ... | @@ -3764,7 +2965,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3764 | 2965 | |
| 3765 | 2966 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 3766 | 2967 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 3767 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | |
| 2968 | const clang::ParmVarDecl *param = fn_decl->getParamDecl(i); | |
| 3768 | 2969 | const char *name = decl_name(param); |
| 3769 | 2970 | |
| 3770 | 2971 | Buf *proto_param_name; |
| ... | ... | @@ -3791,7 +2992,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3791 | 2992 | |
| 3792 | 2993 | // actual function definition with body |
| 3793 | 2994 | c->ptr_params.clear(); |
| 3794 | Stmt *body = fn_decl->getBody(); | |
| 2995 | clang::Stmt *body = fn_decl->getBody(); | |
| 3795 | 2996 | AstNode *actual_body_node; |
| 3796 | 2997 | TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node); |
| 3797 | 2998 | if (result_scope == nullptr) { |
| ... | ... | @@ -3833,19 +3034,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3833 | 3034 | add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node); |
| 3834 | 3035 | } |
| 3835 | 3036 | |
| 3836 | static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) { | |
| 3037 | static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) { | |
| 3837 | 3038 | AstNode *node = trans_create_node_symbol_str(c, primitive_name); |
| 3838 | 3039 | c->decl_table.put(typedef_decl, node); |
| 3839 | 3040 | return node; |
| 3840 | 3041 | } |
| 3841 | 3042 | |
| 3842 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { | |
| 3043 | static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) { | |
| 3843 | 3044 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); |
| 3844 | 3045 | if (existing_entry) { |
| 3845 | 3046 | return existing_entry->value; |
| 3846 | 3047 | } |
| 3847 | 3048 | |
| 3848 | QualType child_qt = typedef_decl->getUnderlyingType(); | |
| 3049 | clang::QualType child_qt = typedef_decl->getUnderlyingType(); | |
| 3849 | 3050 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); |
| 3850 | 3051 | |
| 3851 | 3052 | if (buf_eql_str(type_name, "uint8_t")) { |
| ... | ... | @@ -3894,7 +3095,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_ |
| 3894 | 3095 | return symbol_node; |
| 3895 | 3096 | } |
| 3896 | 3097 | |
| 3897 | struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, | |
| 3098 | struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl, | |
| 3898 | 3099 | Buf *full_type_name, Buf *bare_name) |
| 3899 | 3100 | { |
| 3900 | 3101 | AstNode *opaque_node = trans_create_node_opaque(c); |
| ... | ... | @@ -3909,7 +3110,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, |
| 3909 | 3110 | return symbol_node; |
| 3910 | 3111 | } |
| 3911 | 3112 | |
| 3912 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | |
| 3113 | static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) { | |
| 3913 | 3114 | auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl()); |
| 3914 | 3115 | if (existing_entry) { |
| 3915 | 3116 | return existing_entry->value; |
| ... | ... | @@ -3920,7 +3121,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3920 | 3121 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); |
| 3921 | 3122 | Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); |
| 3922 | 3123 | |
| 3923 | const EnumDecl *enum_def = enum_decl->getDefinition(); | |
| 3124 | const clang::EnumDecl *enum_def = enum_decl->getDefinition(); | |
| 3924 | 3125 | if (!enum_def) { |
| 3925 | 3126 | return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name); |
| 3926 | 3127 | } |
| ... | ... | @@ -3932,7 +3133,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3932 | 3133 | it_end = enum_def->enumerator_end(); |
| 3933 | 3134 | it != it_end; ++it, field_count += 1) |
| 3934 | 3135 | { |
| 3935 | const EnumConstantDecl *enum_const = *it; | |
| 3136 | const clang::EnumConstantDecl *enum_const = *it; | |
| 3936 | 3137 | if (enum_const->getInitExpr()) { |
| 3937 | 3138 | pure_enum = false; |
| 3938 | 3139 | } |
| ... | ... | @@ -3946,8 +3147,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3946 | 3147 | // TODO only emit this tag type if the enum tag type is not the default. |
| 3947 | 3148 | // I don't know what the default is, need to figure out how clang is deciding. |
| 3948 | 3149 | // it appears to at least be different across gcc/msvc |
| 3949 | if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) && | |
| 3950 | !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int)) | |
| 3150 | if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) && | |
| 3151 | !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int)) | |
| 3951 | 3152 | { |
| 3952 | 3153 | enum_node->data.container_decl.init_arg_expr = tag_int_type; |
| 3953 | 3154 | } |
| ... | ... | @@ -3957,7 +3158,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3957 | 3158 | it_end = enum_def->enumerator_end(); |
| 3958 | 3159 | it != it_end; ++it, i += 1) |
| 3959 | 3160 | { |
| 3960 | const EnumConstantDecl *enum_const = *it; | |
| 3161 | const clang::EnumConstantDecl *enum_const = *it; | |
| 3961 | 3162 | |
| 3962 | 3163 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); |
| 3963 | 3164 | Buf *field_name; |
| ... | ... | @@ -3998,7 +3199,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3998 | 3199 | } |
| 3999 | 3200 | } |
| 4000 | 3201 | |
| 4001 | static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl, | |
| 3202 | static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl, | |
| 4002 | 3203 | Buf *full_type_name, Buf *bare_name) |
| 4003 | 3204 | { |
| 4004 | 3205 | AstNode *opaque_node = trans_create_node_opaque(c); |
| ... | ... | @@ -4013,7 +3214,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec |
| 4013 | 3214 | return symbol_node; |
| 4014 | 3215 | } |
| 4015 | 3216 | |
| 4016 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | |
| 3217 | static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) { | |
| 4017 | 3218 | auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); |
| 4018 | 3219 | if (existing_entry) { |
| 4019 | 3220 | return existing_entry->value; |
| ... | ... | @@ -4039,7 +3240,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4039 | 3240 | Buf *full_type_name = (bare_name == nullptr) ? |
| 4040 | 3241 | nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name)); |
| 4041 | 3242 | |
| 4042 | RecordDecl *record_def = record_decl->getDefinition(); | |
| 3243 | clang::RecordDecl *record_def = record_decl->getDefinition(); | |
| 4043 | 3244 | if (record_def == nullptr) { |
| 4044 | 3245 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); |
| 4045 | 3246 | } |
| ... | ... | @@ -4050,7 +3251,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4050 | 3251 | it_end = record_def->field_end(); |
| 4051 | 3252 | it != it_end; ++it, field_count += 1) |
| 4052 | 3253 | { |
| 4053 | const FieldDecl *field_decl = *it; | |
| 3254 | const clang::FieldDecl *field_decl = *it; | |
| 4054 | 3255 | |
| 4055 | 3256 | if (field_decl->isBitField()) { |
| 4056 | 3257 | emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield", |
| ... | ... | @@ -4080,7 +3281,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4080 | 3281 | it_end = record_def->field_end(); |
| 4081 | 3282 | it != it_end; ++it, i += 1) |
| 4082 | 3283 | { |
| 4083 | const FieldDecl *field_decl = *it; | |
| 3284 | const clang::FieldDecl *field_decl = *it; | |
| 4084 | 3285 | |
| 4085 | 3286 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); |
| 4086 | 3287 | field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); |
| ... | ... | @@ -4107,13 +3308,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4107 | 3308 | } |
| 4108 | 3309 | } |
| 4109 | 3310 | |
| 4110 | static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) { | |
| 3311 | static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) { | |
| 4111 | 3312 | switch (ap_value->getKind()) { |
| 4112 | case APValue::Int: | |
| 3313 | case clang::APValue::Int: | |
| 4113 | 3314 | return trans_create_node_apint(c, ap_value->getInt()); |
| 4114 | case APValue::Uninitialized: | |
| 3315 | case clang::APValue::Uninitialized: | |
| 4115 | 3316 | return trans_create_node(c, NodeTypeUndefinedLiteral); |
| 4116 | case APValue::Array: { | |
| 3317 | case clang::APValue::Array: { | |
| 4117 | 3318 | emit_warning(c, source_loc, "TODO add a test case for this code"); |
| 4118 | 3319 | |
| 4119 | 3320 | unsigned init_count = ap_value->getArrayInitializedElts(); |
| ... | ... | @@ -4121,13 +3322,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const |
| 4121 | 3322 | unsigned leftover_count = all_count - init_count; |
| 4122 | 3323 | AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr); |
| 4123 | 3324 | AstNode *arr_type_node = trans_qual_type(c, qt, source_loc); |
| 3325 | if (leftover_count != 0) { // We can't use the size of the final array for a partial initializer. | |
| 3326 | bigint_init_unsigned(arr_type_node->data.array_type.size->data.int_literal.bigint, init_count); | |
| 3327 | } | |
| 4124 | 3328 | init_node->data.container_init_expr.type = arr_type_node; |
| 4125 | 3329 | init_node->data.container_init_expr.kind = ContainerInitKindArray; |
| 4126 | 3330 | |
| 4127 | QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType(); | |
| 3331 | clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType(); | |
| 4128 | 3332 | |
| 4129 | 3333 | for (size_t i = 0; i < init_count; i += 1) { |
| 4130 | APValue &elem_ap_val = ap_value->getArrayInitializedElt(i); | |
| 3334 | clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i); | |
| 4131 | 3335 | AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc); |
| 4132 | 3336 | if (elem_node == nullptr) |
| 4133 | 3337 | return nullptr; |
| ... | ... | @@ -4137,15 +3341,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const |
| 4137 | 3341 | return init_node; |
| 4138 | 3342 | } |
| 4139 | 3343 | |
| 4140 | APValue &filler_ap_val = ap_value->getArrayFiller(); | |
| 3344 | clang::APValue &filler_ap_val = ap_value->getArrayFiller(); | |
| 4141 | 3345 | AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc); |
| 4142 | 3346 | if (filler_node == nullptr) |
| 4143 | 3347 | return nullptr; |
| 4144 | 3348 | |
| 3349 | AstNode* filler_arr_type = trans_create_node(c, NodeTypeArrayType); | |
| 3350 | *filler_arr_type = *arr_type_node; | |
| 3351 | filler_arr_type->data.array_type.size = trans_create_node_unsigned(c, 1); | |
| 3352 | ||
| 4145 | 3353 | AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr); |
| 4146 | init_node->data.container_init_expr.type = arr_type_node; | |
| 4147 | init_node->data.container_init_expr.kind = ContainerInitKindArray; | |
| 4148 | init_node->data.container_init_expr.entries.append(filler_node); | |
| 3354 | filler_arr_1->data.container_init_expr.type = filler_arr_type; | |
| 3355 | filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray; | |
| 3356 | filler_arr_1->data.container_init_expr.entries.append(filler_node); | |
| 4149 | 3357 | |
| 4150 | 3358 | AstNode *rhs_node; |
| 4151 | 3359 | if (leftover_count == 1) { |
| ... | ... | @@ -4155,62 +3363,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const |
| 4155 | 3363 | rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node); |
| 4156 | 3364 | } |
| 4157 | 3365 | |
| 3366 | if (init_count == 0) { | |
| 3367 | return rhs_node; | |
| 3368 | } | |
| 3369 | ||
| 4158 | 3370 | return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node); |
| 4159 | 3371 | } |
| 4160 | case APValue::LValue: { | |
| 4161 | const APValue::LValueBase lval_base = ap_value->getLValueBase(); | |
| 4162 | if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) { | |
| 3372 | case clang::APValue::LValue: { | |
| 3373 | const clang::APValue::LValueBase lval_base = ap_value->getLValueBase(); | |
| 3374 | if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) { | |
| 4163 | 3375 | return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue); |
| 4164 | 3376 | } |
| 4165 | //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>(); | |
| 4166 | emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl"); | |
| 3377 | //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>(); | |
| 3378 | emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl"); | |
| 4167 | 3379 | return nullptr; |
| 4168 | 3380 | } |
| 4169 | case APValue::Float: | |
| 3381 | case clang::APValue::Float: | |
| 4170 | 3382 | emit_warning(c, source_loc, "unsupported initializer value kind: Float"); |
| 4171 | 3383 | return nullptr; |
| 4172 | case APValue::ComplexInt: | |
| 3384 | case clang::APValue::ComplexInt: | |
| 4173 | 3385 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt"); |
| 4174 | 3386 | return nullptr; |
| 4175 | case APValue::ComplexFloat: | |
| 3387 | case clang::APValue::ComplexFloat: | |
| 4176 | 3388 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat"); |
| 4177 | 3389 | return nullptr; |
| 4178 | case APValue::Vector: | |
| 3390 | case clang::APValue::Vector: | |
| 4179 | 3391 | emit_warning(c, source_loc, "unsupported initializer value kind: Vector"); |
| 4180 | 3392 | return nullptr; |
| 4181 | case APValue::Struct: | |
| 3393 | case clang::APValue::Struct: | |
| 4182 | 3394 | emit_warning(c, source_loc, "unsupported initializer value kind: Struct"); |
| 4183 | 3395 | return nullptr; |
| 4184 | case APValue::Union: | |
| 3396 | case clang::APValue::Union: | |
| 4185 | 3397 | emit_warning(c, source_loc, "unsupported initializer value kind: Union"); |
| 4186 | 3398 | return nullptr; |
| 4187 | case APValue::MemberPointer: | |
| 3399 | case clang::APValue::MemberPointer: | |
| 4188 | 3400 | emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer"); |
| 4189 | 3401 | return nullptr; |
| 4190 | case APValue::AddrLabelDiff: | |
| 3402 | case clang::APValue::AddrLabelDiff: | |
| 4191 | 3403 | emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff"); |
| 4192 | 3404 | return nullptr; |
| 4193 | 3405 | } |
| 4194 | 3406 | zig_unreachable(); |
| 4195 | 3407 | } |
| 4196 | 3408 | |
| 4197 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { | |
| 3409 | static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) { | |
| 4198 | 3410 | Buf *name = buf_create_from_str(decl_name(var_decl)); |
| 4199 | 3411 | |
| 4200 | 3412 | switch (var_decl->getTLSKind()) { |
| 4201 | case VarDecl::TLS_None: | |
| 3413 | case clang::VarDecl::TLS_None: | |
| 4202 | 3414 | break; |
| 4203 | case VarDecl::TLS_Static: | |
| 3415 | case clang::VarDecl::TLS_Static: | |
| 4204 | 3416 | emit_warning(c, var_decl->getLocation(), |
| 4205 | 3417 | "ignoring variable '%s' - static thread local storage", buf_ptr(name)); |
| 4206 | 3418 | return; |
| 4207 | case VarDecl::TLS_Dynamic: | |
| 3419 | case clang::VarDecl::TLS_Dynamic: | |
| 4208 | 3420 | emit_warning(c, var_decl->getLocation(), |
| 4209 | 3421 | "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); |
| 4210 | 3422 | return; |
| 4211 | 3423 | } |
| 4212 | 3424 | |
| 4213 | QualType qt = var_decl->getType(); | |
| 3425 | clang::QualType qt = var_decl->getType(); | |
| 4214 | 3426 | AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); |
| 4215 | 3427 | if (var_type == nullptr) { |
| 4216 | 3428 | emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); |
| ... | ... | @@ -4224,7 +3436,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 4224 | 3436 | if (is_static && !is_extern) { |
| 4225 | 3437 | AstNode *init_node; |
| 4226 | 3438 | if (var_decl->hasInit()) { |
| 4227 | APValue *ap_value = var_decl->evaluateValue(); | |
| 3439 | clang::APValue *ap_value = var_decl->evaluateValue(); | |
| 4228 | 3440 | if (ap_value == nullptr) { |
| 4229 | 3441 | emit_warning(c, var_decl->getLocation(), |
| 4230 | 3442 | "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); |
| ... | ... | @@ -4254,24 +3466,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 4254 | 3466 | return; |
| 4255 | 3467 | } |
| 4256 | 3468 | |
| 4257 | static bool decl_visitor(void *context, const Decl *decl) { | |
| 3469 | static bool decl_visitor(void *context, const ZigClangDecl *zdecl) { | |
| 3470 | const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl); | |
| 4258 | 3471 | Context *c = (Context*)context; |
| 4259 | 3472 | |
| 4260 | 3473 | switch (decl->getKind()) { |
| 4261 | case Decl::Function: | |
| 4262 | visit_fn_decl(c, static_cast<const FunctionDecl*>(decl)); | |
| 3474 | case clang::Decl::Function: | |
| 3475 | visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl)); | |
| 4263 | 3476 | break; |
| 4264 | case Decl::Typedef: | |
| 4265 | resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); | |
| 3477 | case clang::Decl::Typedef: | |
| 3478 | resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl)); | |
| 4266 | 3479 | break; |
| 4267 | case Decl::Enum: | |
| 4268 | resolve_enum_decl(c, static_cast<const EnumDecl *>(decl)); | |
| 3480 | case clang::Decl::Enum: | |
| 3481 | resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl)); | |
| 4269 | 3482 | break; |
| 4270 | case Decl::Record: | |
| 4271 | resolve_record_decl(c, static_cast<const RecordDecl *>(decl)); | |
| 3483 | case clang::Decl::Record: | |
| 3484 | resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl)); | |
| 4272 | 3485 | break; |
| 4273 | case Decl::Var: | |
| 4274 | visit_var_decl(c, static_cast<const VarDecl *>(decl)); | |
| 3486 | case clang::Decl::Var: | |
| 3487 | visit_var_decl(c, static_cast<const clang::VarDecl *>(decl)); | |
| 4275 | 3488 | break; |
| 4276 | 3489 | default: |
| 4277 | 3490 | emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); |
| ... | ... | @@ -4613,7 +3826,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t |
| 4613 | 3826 | } else if (first_tok->id == CTokIdAsterisk) { |
| 4614 | 3827 | *tok_i += 1; |
| 4615 | 3828 | |
| 4616 | node = trans_create_node_ptr_type(c, false, false, node, PtrLenUnknown); | |
| 3829 | node = trans_create_node_ptr_type(c, false, false, node, PtrLenC); | |
| 4617 | 3830 | } else { |
| 4618 | 3831 | return node; |
| 4619 | 3832 | } |
| ... | ... | @@ -4692,24 +3905,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 4692 | 3905 | c->macro_table.put(name, result_node); |
| 4693 | 3906 | } |
| 4694 | 3907 | |
| 4695 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | |
| 3908 | static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { | |
| 3909 | clang::ASTUnit *unit = reinterpret_cast<clang::ASTUnit *>(zunit); | |
| 4696 | 3910 | CTokenize ctok = {{0}}; |
| 4697 | 3911 | |
| 4698 | 3912 | // TODO if we see #undef, delete it from the table |
| 4699 | 3913 | |
| 4700 | for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) { | |
| 3914 | for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) { | |
| 4701 | 3915 | switch (entity->getKind()) { |
| 4702 | case PreprocessedEntity::InvalidKind: | |
| 4703 | case PreprocessedEntity::InclusionDirectiveKind: | |
| 4704 | case PreprocessedEntity::MacroExpansionKind: | |
| 3916 | case clang::PreprocessedEntity::InvalidKind: | |
| 3917 | case clang::PreprocessedEntity::InclusionDirectiveKind: | |
| 3918 | case clang::PreprocessedEntity::MacroExpansionKind: | |
| 4705 | 3919 | continue; |
| 4706 | case PreprocessedEntity::MacroDefinitionKind: | |
| 3920 | case clang::PreprocessedEntity::MacroDefinitionKind: | |
| 4707 | 3921 | { |
| 4708 | MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity); | |
| 3922 | clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity); | |
| 4709 | 3923 | const char *raw_name = macro->getName()->getNameStart(); |
| 4710 | SourceRange range = macro->getSourceRange(); | |
| 4711 | SourceLocation begin_loc = range.getBegin(); | |
| 4712 | SourceLocation end_loc = range.getEnd(); | |
| 3924 | clang::SourceRange range = macro->getSourceRange(); | |
| 3925 | clang::SourceLocation begin_loc = range.getBegin(); | |
| 3926 | clang::SourceLocation end_loc = range.getEnd(); | |
| 4713 | 3927 | |
| 4714 | 3928 | if (begin_loc == end_loc) { |
| 4715 | 3929 | // this means it is a macro without a value |
| ... | ... | @@ -4721,7 +3935,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 4721 | 3935 | continue; |
| 4722 | 3936 | } |
| 4723 | 3937 | |
| 4724 | const char *begin_c = c->source_manager->getCharacterData(begin_loc); | |
| 3938 | const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc)); | |
| 4725 | 3939 | process_macro(c, &ctok, name, begin_c); |
| 4726 | 3940 | } |
| 4727 | 3941 | } |
| ... | ... | @@ -4772,7 +3986,16 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4772 | 3986 | clang_argv.append("-x"); |
| 4773 | 3987 | clang_argv.append("c"); |
| 4774 | 3988 | |
| 4775 | if (c->codegen->is_native_target) { | |
| 3989 | Buf *out_dep_path = nullptr; | |
| 3990 | if (codegen->enable_cache) { | |
| 3991 | Buf *prefix = buf_sprintf("%s" OS_SEP, buf_ptr(&codegen->cache_dir)); | |
| 3992 | out_dep_path = os_tmp_filename(prefix, buf_create_from_str(".d")); | |
| 3993 | clang_argv.append("-MD"); | |
| 3994 | clang_argv.append("-MF"); | |
| 3995 | clang_argv.append(buf_ptr(out_dep_path)); | |
| 3996 | } | |
| 3997 | ||
| 3998 | if (c->codegen->zig_target->is_native) { | |
| 4776 | 3999 | char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS"); |
| 4777 | 4000 | if (ZIG_PARSEC_CFLAGS) { |
| 4778 | 4001 | Buf tmp_buf = BUF_INIT; |
| ... | ... | @@ -4791,12 +4014,24 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4791 | 4014 | } |
| 4792 | 4015 | } |
| 4793 | 4016 | |
| 4017 | clang_argv.append("-nobuiltininc"); | |
| 4018 | clang_argv.append("-nostdinc"); | |
| 4019 | clang_argv.append("-nostdinc++"); | |
| 4020 | if (codegen->libc_link_lib == nullptr) { | |
| 4021 | clang_argv.append("-nolibc"); | |
| 4022 | } | |
| 4023 | ||
| 4794 | 4024 | clang_argv.append("-isystem"); |
| 4795 | 4025 | clang_argv.append(buf_ptr(codegen->zig_c_headers_dir)); |
| 4796 | 4026 | |
| 4797 | if (codegen->libc_include_dir != nullptr) { | |
| 4027 | if (codegen->libc != nullptr) { | |
| 4798 | 4028 | clang_argv.append("-isystem"); |
| 4799 | clang_argv.append(buf_ptr(codegen->libc_include_dir)); | |
| 4029 | clang_argv.append(buf_ptr(&codegen->libc->include_dir)); | |
| 4030 | ||
| 4031 | if (!buf_eql_buf(&codegen->libc->include_dir, &codegen->libc->sys_include_dir)) { | |
| 4032 | clang_argv.append("-isystem"); | |
| 4033 | clang_argv.append(buf_ptr(&codegen->libc->sys_include_dir)); | |
| 4034 | } | |
| 4800 | 4035 | } |
| 4801 | 4036 | |
| 4802 | 4037 | // windows c runtime requires -D_DEBUG if using debug libraries |
| ... | ... | @@ -4816,7 +4051,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4816 | 4051 | clang_argv.append("-Xclang"); |
| 4817 | 4052 | clang_argv.append("-detailed-preprocessing-record"); |
| 4818 | 4053 | |
| 4819 | if (!c->codegen->is_native_target) { | |
| 4054 | if (c->codegen->zig_target->is_native) { | |
| 4055 | clang_argv.append("-march=native"); | |
| 4056 | } else { | |
| 4820 | 4057 | clang_argv.append("-target"); |
| 4821 | 4058 | clang_argv.append(buf_ptr(&c->codegen->triple_str)); |
| 4822 | 4059 | } |
| ... | ... | @@ -4834,9 +4071,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4834 | 4071 | // to make the [start...end] argument work |
| 4835 | 4072 | clang_argv.append(nullptr); |
| 4836 | 4073 | |
| 4837 | IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); | |
| 4074 | clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions)); | |
| 4838 | 4075 | |
| 4839 | std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>(); | |
| 4076 | std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>(); | |
| 4840 | 4077 | |
| 4841 | 4078 | bool only_local_decls = true; |
| 4842 | 4079 | bool capture_diagnostics = true; |
| ... | ... | @@ -4845,13 +4082,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4845 | 4082 | bool single_file_parse = false; |
| 4846 | 4083 | bool for_serialization = false; |
| 4847 | 4084 | const char *resources_path = buf_ptr(codegen->zig_c_headers_dir); |
| 4848 | std::unique_ptr<ASTUnit> err_unit; | |
| 4849 | std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine( | |
| 4085 | std::unique_ptr<clang::ASTUnit> err_unit; | |
| 4086 | ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine( | |
| 4850 | 4087 | &clang_argv.at(0), &clang_argv.last(), |
| 4851 | 4088 | pch_container_ops, diags, resources_path, |
| 4852 | only_local_decls, capture_diagnostics, None, true, 0, TU_Complete, | |
| 4853 | false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None, | |
| 4854 | single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit, | |
| 4089 | only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete, | |
| 4090 | false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None, | |
| 4091 | single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit, | |
| 4855 | 4092 | nullptr)); |
| 4856 | 4093 | |
| 4857 | 4094 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. |
| ... | ... | @@ -4861,29 +4098,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4861 | 4098 | |
| 4862 | 4099 | if (diags->getClient()->getNumErrors() > 0) { |
| 4863 | 4100 | if (ast_unit) { |
| 4864 | err_unit = std::move(ast_unit); | |
| 4101 | err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit)); | |
| 4865 | 4102 | } |
| 4866 | 4103 | |
| 4867 | for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | |
| 4104 | for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | |
| 4868 | 4105 | it_end = err_unit->stored_diag_end(); |
| 4869 | 4106 | it != it_end; ++it) |
| 4870 | 4107 | { |
| 4871 | 4108 | switch (it->getLevel()) { |
| 4872 | case DiagnosticsEngine::Ignored: | |
| 4873 | case DiagnosticsEngine::Note: | |
| 4874 | case DiagnosticsEngine::Remark: | |
| 4875 | case DiagnosticsEngine::Warning: | |
| 4109 | case clang::DiagnosticsEngine::Ignored: | |
| 4110 | case clang::DiagnosticsEngine::Note: | |
| 4111 | case clang::DiagnosticsEngine::Remark: | |
| 4112 | case clang::DiagnosticsEngine::Warning: | |
| 4876 | 4113 | continue; |
| 4877 | case DiagnosticsEngine::Error: | |
| 4878 | case DiagnosticsEngine::Fatal: | |
| 4114 | case clang::DiagnosticsEngine::Error: | |
| 4115 | case clang::DiagnosticsEngine::Fatal: | |
| 4879 | 4116 | break; |
| 4880 | 4117 | } |
| 4881 | 4118 | StringRef msg_str_ref = it->getMessage(); |
| 4882 | 4119 | Buf *msg = string_ref_to_buf(msg_str_ref); |
| 4883 | FullSourceLoc fsl = it->getLocation(); | |
| 4120 | clang::FullSourceLoc fsl = it->getLocation(); | |
| 4884 | 4121 | if (fsl.hasManager()) { |
| 4885 | FileID file_id = fsl.getFileID(); | |
| 4886 | StringRef filename = fsl.getManager().getFilename(fsl); | |
| 4122 | clang::FileID file_id = fsl.getFileID(); | |
| 4123 | clang::StringRef filename = fsl.getManager().getFilename(fsl); | |
| 4887 | 4124 | unsigned line = fsl.getSpellingLineNumber() - 1; |
| 4888 | 4125 | unsigned column = fsl.getSpellingColumnNumber() - 1; |
| 4889 | 4126 | unsigned offset = fsl.getManager().getFileOffset(fsl); |
| ... | ... | @@ -4908,14 +4145,25 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4908 | 4145 | return ErrorCCompileErrors; |
| 4909 | 4146 | } |
| 4910 | 4147 | |
| 4911 | c->ctx = &ast_unit->getASTContext(); | |
| 4912 | c->source_manager = &ast_unit->getSourceManager(); | |
| 4148 | if (codegen->enable_cache) { | |
| 4149 | Error err; | |
| 4150 | assert(out_dep_path != nullptr); | |
| 4151 | if ((err = cache_add_dep_file(&codegen->cache_hash, out_dep_path, codegen->verbose_cimport))) { | |
| 4152 | if (codegen->verbose_cimport) { | |
| 4153 | fprintf(stderr, "translate-c: aborting due to failed cache operation: %s\n", err_str(err)); | |
| 4154 | } | |
| 4155 | return err; | |
| 4156 | } | |
| 4157 | } | |
| 4158 | ||
| 4159 | c->ctx = ZigClangASTUnit_getASTContext(ast_unit); | |
| 4160 | c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit); | |
| 4913 | 4161 | c->root = trans_create_node(c, NodeTypeContainerDecl); |
| 4914 | 4162 | c->root->data.container_decl.is_root = true; |
| 4915 | 4163 | |
| 4916 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); | |
| 4164 | ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor); | |
| 4917 | 4165 | |
| 4918 | process_preprocessor_entities(c, *ast_unit); | |
| 4166 | process_preprocessor_entities(c, ast_unit); | |
| 4919 | 4167 | |
| 4920 | 4168 | render_macros(c); |
| 4921 | 4169 | render_aliases(c); |
src/util.hpp+7-4| ... | ... | @@ -147,11 +147,14 @@ static inline T clamp(T min_value, T value, T max_value) { |
| 147 | 147 | return max(min(value, max_value), min_value); |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) { | |
| 151 | size_t str_len = strlen(str); | |
| 152 | if (str_len != mem_len) | |
| 150 | static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) { | |
| 151 | if (a_len != b_len) | |
| 153 | 152 | return false; |
| 154 | return memcmp(mem, str, mem_len) == 0; | |
| 153 | return memcmp(a_ptr, b_ptr, a_len) == 0; | |
| 154 | } | |
| 155 | ||
| 156 | static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) { | |
| 157 | return mem_eql_mem(mem, mem_len, str, strlen(str)); | |
| 155 | 158 | } |
| 156 | 159 | |
| 157 | 160 | static inline bool is_power_of_2(uint64_t x) { |
src/zig_clang.cpp created+214| ... | ... | @@ -0,0 +1,214 @@ |
| 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 | ||
| 9 | /* | |
| 10 | * The point of this file is to contain all the Clang C++ API interaction so that: | |
| 11 | * 1. The compile time of other files is kept under control. | |
| 12 | * 2. Provide a C interface to the Clang functions we need for self-hosting purposes. | |
| 13 | * 3. Prevent C++ from infecting the rest of the project. | |
| 14 | */ | |
| 15 | #include "zig_clang.h" | |
| 16 | ||
| 17 | #if __GNUC__ >= 8 | |
| 18 | #pragma GCC diagnostic push | |
| 19 | #pragma GCC diagnostic ignored "-Wclass-memaccess" | |
| 20 | #endif | |
| 21 | ||
| 22 | #include <clang/Frontend/ASTUnit.h> | |
| 23 | #include <clang/Frontend/CompilerInstance.h> | |
| 24 | #include <clang/AST/Expr.h> | |
| 25 | ||
| 26 | #if __GNUC__ >= 8 | |
| 27 | #pragma GCC diagnostic pop | |
| 28 | #endif | |
| 29 | ||
| 30 | // Detect additions to the enum | |
| 31 | void zig2clang_BO(ZigClangBO op) { | |
| 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: | |
| 66 | break; | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Add == clang::BO_Add, ""); | |
| 71 | static_assert((clang::BinaryOperatorKind)ZigClangBO_AddAssign == clang::BO_AddAssign, ""); | |
| 72 | static_assert((clang::BinaryOperatorKind)ZigClangBO_And == clang::BO_And, ""); | |
| 73 | static_assert((clang::BinaryOperatorKind)ZigClangBO_AndAssign == clang::BO_AndAssign, ""); | |
| 74 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Assign == clang::BO_Assign, ""); | |
| 75 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Cmp == clang::BO_Cmp, ""); | |
| 76 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Comma == clang::BO_Comma, ""); | |
| 77 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Div == clang::BO_Div, ""); | |
| 78 | static_assert((clang::BinaryOperatorKind)ZigClangBO_DivAssign == clang::BO_DivAssign, ""); | |
| 79 | static_assert((clang::BinaryOperatorKind)ZigClangBO_EQ == clang::BO_EQ, ""); | |
| 80 | static_assert((clang::BinaryOperatorKind)ZigClangBO_GE == clang::BO_GE, ""); | |
| 81 | static_assert((clang::BinaryOperatorKind)ZigClangBO_GT == clang::BO_GT, ""); | |
| 82 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LAnd == clang::BO_LAnd, ""); | |
| 83 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LE == clang::BO_LE, ""); | |
| 84 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LOr == clang::BO_LOr, ""); | |
| 85 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LT == clang::BO_LT, ""); | |
| 86 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Mul == clang::BO_Mul, ""); | |
| 87 | static_assert((clang::BinaryOperatorKind)ZigClangBO_MulAssign == clang::BO_MulAssign, ""); | |
| 88 | static_assert((clang::BinaryOperatorKind)ZigClangBO_NE == clang::BO_NE, ""); | |
| 89 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Or == clang::BO_Or, ""); | |
| 90 | static_assert((clang::BinaryOperatorKind)ZigClangBO_OrAssign == clang::BO_OrAssign, ""); | |
| 91 | static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemD == clang::BO_PtrMemD, ""); | |
| 92 | static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemI == clang::BO_PtrMemI, ""); | |
| 93 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Rem == clang::BO_Rem, ""); | |
| 94 | static_assert((clang::BinaryOperatorKind)ZigClangBO_RemAssign == clang::BO_RemAssign, ""); | |
| 95 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Shl == clang::BO_Shl, ""); | |
| 96 | static_assert((clang::BinaryOperatorKind)ZigClangBO_ShlAssign == clang::BO_ShlAssign, ""); | |
| 97 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Shr == clang::BO_Shr, ""); | |
| 98 | static_assert((clang::BinaryOperatorKind)ZigClangBO_ShrAssign == clang::BO_ShrAssign, ""); | |
| 99 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Sub == clang::BO_Sub, ""); | |
| 100 | static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAssign, ""); | |
| 101 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, ""); | |
| 102 | static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, ""); | |
| 103 | ||
| 104 | // This function detects additions to the enum | |
| 105 | void zig2clang_UO(ZigClangUO op) { | |
| 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: | |
| 121 | break; | |
| 122 | } | |
| 123 | } | |
| 124 | ||
| 125 | static_assert((clang::UnaryOperatorKind)ZigClangUO_AddrOf == clang::UO_AddrOf, ""); | |
| 126 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Coawait == clang::UO_Coawait, ""); | |
| 127 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Deref == clang::UO_Deref, ""); | |
| 128 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Extension == clang::UO_Extension, ""); | |
| 129 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Imag == clang::UO_Imag, ""); | |
| 130 | static_assert((clang::UnaryOperatorKind)ZigClangUO_LNot == clang::UO_LNot, ""); | |
| 131 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Minus == clang::UO_Minus, ""); | |
| 132 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Not == clang::UO_Not, ""); | |
| 133 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Plus == clang::UO_Plus, ""); | |
| 134 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PostDec == clang::UO_PostDec, ""); | |
| 135 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PostInc == clang::UO_PostInc, ""); | |
| 136 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, ""); | |
| 137 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, ""); | |
| 138 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, ""); | |
| 139 | ||
| 140 | static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), ""); | |
| 141 | static ZigClangSourceLocation bitcast(clang::SourceLocation src) { | |
| 142 | ZigClangSourceLocation dest; | |
| 143 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangSourceLocation)); | |
| 144 | return dest; | |
| 145 | } | |
| 146 | static clang::SourceLocation bitcast(ZigClangSourceLocation src) { | |
| 147 | clang::SourceLocation dest; | |
| 148 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangSourceLocation)); | |
| 149 | return dest; | |
| 150 | } | |
| 151 | ||
| 152 | static_assert(sizeof(ZigClangQualType) == sizeof(clang::QualType), ""); | |
| 153 | static ZigClangQualType bitcast(clang::QualType src) { | |
| 154 | ZigClangQualType dest; | |
| 155 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); | |
| 156 | return dest; | |
| 157 | } | |
| 158 | static clang::QualType bitcast(ZigClangQualType src) { | |
| 159 | clang::QualType dest; | |
| 160 | memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType)); | |
| 161 | return dest; | |
| 162 | } | |
| 163 | ||
| 164 | ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self, | |
| 165 | ZigClangSourceLocation Loc) | |
| 166 | { | |
| 167 | return bitcast(reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLoc(bitcast(Loc))); | |
| 168 | } | |
| 169 | ||
| 170 | const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *self, | |
| 171 | ZigClangSourceLocation SpellingLoc) | |
| 172 | { | |
| 173 | StringRef s = reinterpret_cast<const clang::SourceManager *>(self)->getFilename(bitcast(SpellingLoc)); | |
| 174 | return (const char *)s.bytes_begin(); | |
| 175 | } | |
| 176 | ||
| 177 | unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *self, | |
| 178 | ZigClangSourceLocation Loc) | |
| 179 | { | |
| 180 | return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLineNumber(bitcast(Loc)); | |
| 181 | } | |
| 182 | ||
| 183 | unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *self, | |
| 184 | ZigClangSourceLocation Loc) | |
| 185 | { | |
| 186 | return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingColumnNumber(bitcast(Loc)); | |
| 187 | } | |
| 188 | ||
| 189 | const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *self, | |
| 190 | ZigClangSourceLocation SL) | |
| 191 | { | |
| 192 | return reinterpret_cast<const clang::SourceManager *>(self)->getCharacterData(bitcast(SL)); | |
| 193 | } | |
| 194 | ||
| 195 | ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* self, ZigClangQualType T) { | |
| 196 | return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T))); | |
| 197 | } | |
| 198 | ||
| 199 | ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) { | |
| 200 | clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext(); | |
| 201 | return reinterpret_cast<ZigClangASTContext *>(result); | |
| 202 | } | |
| 203 | ||
| 204 | ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) { | |
| 205 | clang::SourceManager *result = &reinterpret_cast<clang::ASTUnit *>(self)->getSourceManager(); | |
| 206 | return reinterpret_cast<ZigClangSourceManager *>(result); | |
| 207 | } | |
| 208 | ||
| 209 | bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context, | |
| 210 | bool (*Fn)(void *context, const ZigClangDecl *decl)) | |
| 211 | { | |
| 212 | return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context, | |
| 213 | reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn)); | |
| 214 | } |
src/zig_clang.h created+259| ... | ... | @@ -0,0 +1,259 @@ |
| 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_ZIG_CLANG_H | |
| 9 | #define ZIG_ZIG_CLANG_H | |
| 10 | ||
| 11 | #ifdef __cplusplus | |
| 12 | #define ZIG_EXTERN_C extern "C" | |
| 13 | #else | |
| 14 | #define ZIG_EXTERN_C | |
| 15 | #endif | |
| 16 | ||
| 17 | // ATTENTION: If you modify this file, be sure to update the corresponding | |
| 18 | // extern function declarations in the self-hosted compiler. | |
| 19 | ||
| 20 | struct ZigClangSourceLocation { | |
| 21 | unsigned ID; | |
| 22 | }; | |
| 23 | ||
| 24 | struct ZigClangQualType { | |
| 25 | void *ptr; | |
| 26 | }; | |
| 27 | ||
| 28 | struct ZigClangAPValue; | |
| 29 | struct ZigClangASTContext; | |
| 30 | struct ZigClangASTUnit; | |
| 31 | struct ZigClangArraySubscriptExpr; | |
| 32 | struct ZigClangArrayType; | |
| 33 | struct ZigClangAttributedType; | |
| 34 | struct ZigClangBinaryOperator; | |
| 35 | struct ZigClangBreakStmt; | |
| 36 | struct ZigClangBuiltinType; | |
| 37 | struct ZigClangCStyleCastExpr; | |
| 38 | struct ZigClangCallExpr; | |
| 39 | struct ZigClangCaseStmt; | |
| 40 | struct ZigClangCompoundAssignOperator; | |
| 41 | struct ZigClangCompoundStmt; | |
| 42 | struct ZigClangConditionalOperator; | |
| 43 | struct ZigClangConstantArrayType; | |
| 44 | struct ZigClangContinueStmt; | |
| 45 | struct ZigClangDecayedType; | |
| 46 | struct ZigClangDecl; | |
| 47 | struct ZigClangDeclRefExpr; | |
| 48 | struct ZigClangDeclStmt; | |
| 49 | struct ZigClangDefaultStmt; | |
| 50 | struct ZigClangDiagnosticOptions; | |
| 51 | struct ZigClangDiagnosticsEngine; | |
| 52 | struct ZigClangDoStmt; | |
| 53 | struct ZigClangElaboratedType; | |
| 54 | struct ZigClangEnumConstantDecl; | |
| 55 | struct ZigClangEnumDecl; | |
| 56 | struct ZigClangEnumType; | |
| 57 | struct ZigClangExpr; | |
| 58 | struct ZigClangFieldDecl; | |
| 59 | struct ZigClangFileID; | |
| 60 | struct ZigClangForStmt; | |
| 61 | struct ZigClangFullSourceLoc; | |
| 62 | struct ZigClangFunctionDecl; | |
| 63 | struct ZigClangFunctionProtoType; | |
| 64 | struct ZigClangIfStmt; | |
| 65 | struct ZigClangImplicitCastExpr; | |
| 66 | struct ZigClangIncompleteArrayType; | |
| 67 | struct ZigClangIntegerLiteral; | |
| 68 | struct ZigClangMacroDefinitionRecord; | |
| 69 | struct ZigClangMemberExpr; | |
| 70 | struct ZigClangNamedDecl; | |
| 71 | struct ZigClangNone; | |
| 72 | struct ZigClangPCHContainerOperations; | |
| 73 | struct ZigClangParenExpr; | |
| 74 | struct ZigClangParenType; | |
| 75 | struct ZigClangParmVarDecl; | |
| 76 | struct ZigClangPointerType; | |
| 77 | struct ZigClangPreprocessedEntity; | |
| 78 | struct ZigClangRecordDecl; | |
| 79 | struct ZigClangRecordType; | |
| 80 | struct ZigClangReturnStmt; | |
| 81 | struct ZigClangSkipFunctionBodiesScope; | |
| 82 | struct ZigClangSourceManager; | |
| 83 | struct ZigClangSourceRange; | |
| 84 | struct ZigClangStmt; | |
| 85 | struct ZigClangStorageClass; | |
| 86 | struct ZigClangStringLiteral; | |
| 87 | struct ZigClangStringRef; | |
| 88 | struct ZigClangSwitchStmt; | |
| 89 | struct ZigClangType; | |
| 90 | struct ZigClangTypedefNameDecl; | |
| 91 | struct ZigClangTypedefType; | |
| 92 | struct ZigClangUnaryExprOrTypeTraitExpr; | |
| 93 | struct ZigClangUnaryOperator; | |
| 94 | struct ZigClangValueDecl; | |
| 95 | struct ZigClangVarDecl; | |
| 96 | struct ZigClangWhileStmt; | |
| 97 | ||
| 98 | enum ZigClangBO { | |
| 99 | ZigClangBO_PtrMemD, | |
| 100 | ZigClangBO_PtrMemI, | |
| 101 | ZigClangBO_Mul, | |
| 102 | ZigClangBO_Div, | |
| 103 | ZigClangBO_Rem, | |
| 104 | ZigClangBO_Add, | |
| 105 | ZigClangBO_Sub, | |
| 106 | ZigClangBO_Shl, | |
| 107 | ZigClangBO_Shr, | |
| 108 | ZigClangBO_Cmp, | |
| 109 | ZigClangBO_LT, | |
| 110 | ZigClangBO_GT, | |
| 111 | ZigClangBO_LE, | |
| 112 | ZigClangBO_GE, | |
| 113 | ZigClangBO_EQ, | |
| 114 | ZigClangBO_NE, | |
| 115 | ZigClangBO_And, | |
| 116 | ZigClangBO_Xor, | |
| 117 | ZigClangBO_Or, | |
| 118 | ZigClangBO_LAnd, | |
| 119 | ZigClangBO_LOr, | |
| 120 | ZigClangBO_Assign, | |
| 121 | ZigClangBO_MulAssign, | |
| 122 | ZigClangBO_DivAssign, | |
| 123 | ZigClangBO_RemAssign, | |
| 124 | ZigClangBO_AddAssign, | |
| 125 | ZigClangBO_SubAssign, | |
| 126 | ZigClangBO_ShlAssign, | |
| 127 | ZigClangBO_ShrAssign, | |
| 128 | ZigClangBO_AndAssign, | |
| 129 | ZigClangBO_XorAssign, | |
| 130 | ZigClangBO_OrAssign, | |
| 131 | ZigClangBO_Comma, | |
| 132 | }; | |
| 133 | ||
| 134 | enum ZigClangUO { | |
| 135 | ZigClangUO_PostInc, | |
| 136 | ZigClangUO_PostDec, | |
| 137 | ZigClangUO_PreInc, | |
| 138 | ZigClangUO_PreDec, | |
| 139 | ZigClangUO_AddrOf, | |
| 140 | ZigClangUO_Deref, | |
| 141 | ZigClangUO_Plus, | |
| 142 | ZigClangUO_Minus, | |
| 143 | ZigClangUO_Not, | |
| 144 | ZigClangUO_LNot, | |
| 145 | ZigClangUO_Real, | |
| 146 | ZigClangUO_Imag, | |
| 147 | ZigClangUO_Extension, | |
| 148 | ZigClangUO_Coawait, | |
| 149 | }; | |
| 150 | ||
| 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)); | |
| 259 | #endif |
src/zig_clang_cc1_main.cpp created+226| ... | ... | @@ -0,0 +1,226 @@ |
| 1 | //===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Compiler Infrastructure | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // This is the entry point to the clang -cc1 functionality, which implements the | |
| 11 | // core compiler functionality along with a number of additional tools for | |
| 12 | // demonstration and testing purposes. | |
| 13 | // | |
| 14 | //===----------------------------------------------------------------------===// | |
| 15 | ||
| 16 | #include "llvm/Option/Arg.h" | |
| 17 | #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" | |
| 18 | #include "clang/Config/config.h" | |
| 19 | #include "clang/Basic/Stack.h" | |
| 20 | #include "clang/Driver/DriverDiagnostic.h" | |
| 21 | #include "clang/Driver/Options.h" | |
| 22 | #include "clang/Frontend/CompilerInstance.h" | |
| 23 | #include "clang/Frontend/CompilerInvocation.h" | |
| 24 | #include "clang/Frontend/FrontendDiagnostic.h" | |
| 25 | #include "clang/Frontend/TextDiagnosticBuffer.h" | |
| 26 | #include "clang/Frontend/TextDiagnosticPrinter.h" | |
| 27 | #include "clang/Frontend/Utils.h" | |
| 28 | #include "clang/FrontendTool/Utils.h" | |
| 29 | #include "llvm/ADT/Statistic.h" | |
| 30 | #include "llvm/Config/llvm-config.h" | |
| 31 | #include "llvm/LinkAllPasses.h" | |
| 32 | #include "llvm/Option/ArgList.h" | |
| 33 | #include "llvm/Option/OptTable.h" | |
| 34 | #include "llvm/Support/Compiler.h" | |
| 35 | #include "llvm/Support/ErrorHandling.h" | |
| 36 | #include "llvm/Support/ManagedStatic.h" | |
| 37 | #include "llvm/Support/Signals.h" | |
| 38 | #include "llvm/Support/TargetSelect.h" | |
| 39 | #include "llvm/Support/Timer.h" | |
| 40 | #include "llvm/Support/raw_ostream.h" | |
| 41 | #include <cstdio> | |
| 42 | ||
| 43 | #ifdef CLANG_HAVE_RLIMITS | |
| 44 | #include <sys/resource.h> | |
| 45 | #endif | |
| 46 | ||
| 47 | using namespace clang; | |
| 48 | using namespace llvm::opt; | |
| 49 | ||
| 50 | //===----------------------------------------------------------------------===// | |
| 51 | // Main driver | |
| 52 | //===----------------------------------------------------------------------===// | |
| 53 | ||
| 54 | static void LLVMErrorHandler(void *UserData, const std::string &Message, | |
| 55 | bool GenCrashDiag) { | |
| 56 | DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); | |
| 57 | ||
| 58 | Diags.Report(diag::err_fe_error_backend) << Message; | |
| 59 | ||
| 60 | // Run the interrupt handlers to make sure any special cleanups get done, in | |
| 61 | // particular that we remove files registered with RemoveFileOnSignal. | |
| 62 | llvm::sys::RunInterruptHandlers(); | |
| 63 | ||
| 64 | // We cannot recover from llvm errors. When reporting a fatal error, exit | |
| 65 | // with status 70 to generate crash diagnostics. For BSD systems this is | |
| 66 | // defined as an internal software error. Otherwise, exit with status 1. | |
| 67 | exit(GenCrashDiag ? 70 : 1); | |
| 68 | } | |
| 69 | ||
| 70 | #ifdef CLANG_HAVE_RLIMITS | |
| 71 | #if defined(__linux__) && defined(__PIE__) | |
| 72 | static size_t getCurrentStackAllocation() { | |
| 73 | // If we can't compute the current stack usage, allow for 512K of command | |
| 74 | // line arguments and environment. | |
| 75 | size_t Usage = 512 * 1024; | |
| 76 | if (FILE *StatFile = fopen("/proc/self/stat", "r")) { | |
| 77 | // We assume that the stack extends from its current address to the end of | |
| 78 | // the environment space. In reality, there is another string literal (the | |
| 79 | // program name) after the environment, but this is close enough (we only | |
| 80 | // need to be within 100K or so). | |
| 81 | unsigned long StackPtr, EnvEnd; | |
| 82 | // Disable silly GCC -Wformat warning that complains about length | |
| 83 | // modifiers on ignored format specifiers. We want to retain these | |
| 84 | // for documentation purposes even though they have no effect. | |
| 85 | #if defined(__GNUC__) && !defined(__clang__) | |
| 86 | #pragma GCC diagnostic push | |
| 87 | #pragma GCC diagnostic ignored "-Wformat" | |
| 88 | #endif | |
| 89 | if (fscanf(StatFile, | |
| 90 | "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu " | |
| 91 | "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu " | |
| 92 | "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d " | |
| 93 | "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d", | |
| 94 | &StackPtr, &EnvEnd) == 2) { | |
| 95 | #if defined(__GNUC__) && !defined(__clang__) | |
| 96 | #pragma GCC diagnostic pop | |
| 97 | #endif | |
| 98 | Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd; | |
| 99 | } | |
| 100 | fclose(StatFile); | |
| 101 | } | |
| 102 | return Usage; | |
| 103 | } | |
| 104 | ||
| 105 | #include <alloca.h> | |
| 106 | ||
| 107 | LLVM_ATTRIBUTE_NOINLINE | |
| 108 | static void ensureStackAddressSpace() { | |
| 109 | // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary | |
| 110 | // relatively close to the stack (they are only guaranteed to be 128MiB | |
| 111 | // apart). This results in crashes if we happen to heap-allocate more than | |
| 112 | // 128MiB before we reach our stack high-water mark. | |
| 113 | // | |
| 114 | // To avoid these crashes, ensure that we have sufficient virtual memory | |
| 115 | // pages allocated before we start running. | |
| 116 | size_t Curr = getCurrentStackAllocation(); | |
| 117 | const int kTargetStack = DesiredStackSize - 256 * 1024; | |
| 118 | if (Curr < kTargetStack) { | |
| 119 | volatile char *volatile Alloc = | |
| 120 | static_cast<volatile char *>(alloca(kTargetStack - Curr)); | |
| 121 | Alloc[0] = 0; | |
| 122 | Alloc[kTargetStack - Curr - 1] = 0; | |
| 123 | } | |
| 124 | } | |
| 125 | #else | |
| 126 | static void ensureStackAddressSpace() {} | |
| 127 | #endif | |
| 128 | ||
| 129 | /// Attempt to ensure that we have at least 8MiB of usable stack space. | |
| 130 | static void ensureSufficientStack() { | |
| 131 | struct rlimit rlim; | |
| 132 | if (getrlimit(RLIMIT_STACK, &rlim) != 0) | |
| 133 | return; | |
| 134 | ||
| 135 | // Increase the soft stack limit to our desired level, if necessary and | |
| 136 | // possible. | |
| 137 | if (rlim.rlim_cur != RLIM_INFINITY && | |
| 138 | rlim.rlim_cur < rlim_t(DesiredStackSize)) { | |
| 139 | // Try to allocate sufficient stack. | |
| 140 | if (rlim.rlim_max == RLIM_INFINITY || | |
| 141 | rlim.rlim_max >= rlim_t(DesiredStackSize)) | |
| 142 | rlim.rlim_cur = DesiredStackSize; | |
| 143 | else if (rlim.rlim_cur == rlim.rlim_max) | |
| 144 | return; | |
| 145 | else | |
| 146 | rlim.rlim_cur = rlim.rlim_max; | |
| 147 | ||
| 148 | if (setrlimit(RLIMIT_STACK, &rlim) != 0 || | |
| 149 | rlim.rlim_cur != DesiredStackSize) | |
| 150 | return; | |
| 151 | } | |
| 152 | ||
| 153 | // We should now have a stack of size at least DesiredStackSize. Ensure | |
| 154 | // that we can actually use that much, if necessary. | |
| 155 | ensureStackAddressSpace(); | |
| 156 | } | |
| 157 | #else | |
| 158 | static void ensureSufficientStack() {} | |
| 159 | #endif | |
| 160 | ||
| 161 | int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { | |
| 162 | ensureSufficientStack(); | |
| 163 | ||
| 164 | std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); | |
| 165 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); | |
| 166 | ||
| 167 | // Register the support for object-file-wrapped Clang modules. | |
| 168 | auto PCHOps = Clang->getPCHContainerOperations(); | |
| 169 | PCHOps->registerWriter(llvm::make_unique<ObjectFilePCHContainerWriter>()); | |
| 170 | PCHOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>()); | |
| 171 | ||
| 172 | // Initialize targets first, so that --version shows registered targets. | |
| 173 | llvm::InitializeAllTargets(); | |
| 174 | llvm::InitializeAllTargetMCs(); | |
| 175 | llvm::InitializeAllAsmPrinters(); | |
| 176 | llvm::InitializeAllAsmParsers(); | |
| 177 | ||
| 178 | // Buffer diagnostics from argument parsing so that we can output them using a | |
| 179 | // well formed diagnostic object. | |
| 180 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); | |
| 181 | TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; | |
| 182 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); | |
| 183 | bool Success = CompilerInvocation::CreateFromArgs( | |
| 184 | Clang->getInvocation(), Argv.begin(), Argv.end(), Diags); | |
| 185 | ||
| 186 | // Infer the builtin include path if unspecified. | |
| 187 | if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && | |
| 188 | Clang->getHeaderSearchOpts().ResourceDir.empty()) | |
| 189 | Clang->getHeaderSearchOpts().ResourceDir = | |
| 190 | CompilerInvocation::GetResourcesPath(Argv0, MainAddr); | |
| 191 | ||
| 192 | // Create the actual diagnostics engine. | |
| 193 | Clang->createDiagnostics(); | |
| 194 | if (!Clang->hasDiagnostics()) | |
| 195 | return 1; | |
| 196 | ||
| 197 | // Set an error handler, so that any LLVM backend diagnostics go through our | |
| 198 | // error handler. | |
| 199 | llvm::install_fatal_error_handler(LLVMErrorHandler, | |
| 200 | static_cast<void*>(&Clang->getDiagnostics())); | |
| 201 | ||
| 202 | DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); | |
| 203 | if (!Success) | |
| 204 | return 1; | |
| 205 | ||
| 206 | // Execute the frontend actions. | |
| 207 | Success = ExecuteCompilerInvocation(Clang.get()); | |
| 208 | ||
| 209 | // If any timers were active but haven't been destroyed yet, print their | |
| 210 | // results now. This happens in -disable-free mode. | |
| 211 | llvm::TimerGroup::printAll(llvm::errs()); | |
| 212 | ||
| 213 | // Our error handler depends on the Diagnostics object, which we're | |
| 214 | // potentially about to delete. Uninstall the handler now so that any | |
| 215 | // later errors use the default handling behavior instead. | |
| 216 | llvm::remove_fatal_error_handler(); | |
| 217 | ||
| 218 | // When running with -disable-free, don't do any destruction or shutdown. | |
| 219 | if (Clang->getFrontendOpts().DisableFree) { | |
| 220 | BuryPointer(std::move(Clang)); | |
| 221 | return !Success; | |
| 222 | } | |
| 223 | ||
| 224 | return !Success; | |
| 225 | } | |
| 226 |
src/zig_clang_cc1as_main.cpp created+573| ... | ... | @@ -0,0 +1,573 @@ |
| 1 | //===-- cc1as_main.cpp - Clang Assembler ---------------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Compiler Infrastructure | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // This is the entry point to the clang -cc1as functionality, which implements | |
| 11 | // the direct interface to the LLVM MC based assembler. | |
| 12 | // | |
| 13 | //===----------------------------------------------------------------------===// | |
| 14 | ||
| 15 | #include "clang/Basic/Diagnostic.h" | |
| 16 | #include "clang/Basic/DiagnosticOptions.h" | |
| 17 | #include "clang/Driver/DriverDiagnostic.h" | |
| 18 | #include "clang/Driver/Options.h" | |
| 19 | #include "clang/Frontend/FrontendDiagnostic.h" | |
| 20 | #include "clang/Frontend/TextDiagnosticPrinter.h" | |
| 21 | #include "clang/Frontend/Utils.h" | |
| 22 | #include "llvm/ADT/STLExtras.h" | |
| 23 | #include "llvm/ADT/StringSwitch.h" | |
| 24 | #include "llvm/ADT/Triple.h" | |
| 25 | #include "llvm/IR/DataLayout.h" | |
| 26 | #include "llvm/MC/MCAsmBackend.h" | |
| 27 | #include "llvm/MC/MCAsmInfo.h" | |
| 28 | #include "llvm/MC/MCCodeEmitter.h" | |
| 29 | #include "llvm/MC/MCContext.h" | |
| 30 | #include "llvm/MC/MCInstrInfo.h" | |
| 31 | #include "llvm/MC/MCObjectFileInfo.h" | |
| 32 | #include "llvm/MC/MCObjectWriter.h" | |
| 33 | #include "llvm/MC/MCParser/MCAsmParser.h" | |
| 34 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" | |
| 35 | #include "llvm/MC/MCRegisterInfo.h" | |
| 36 | #include "llvm/MC/MCStreamer.h" | |
| 37 | #include "llvm/MC/MCSubtargetInfo.h" | |
| 38 | #include "llvm/MC/MCTargetOptions.h" | |
| 39 | #include "llvm/Option/Arg.h" | |
| 40 | #include "llvm/Option/ArgList.h" | |
| 41 | #include "llvm/Option/OptTable.h" | |
| 42 | #include "llvm/Support/CommandLine.h" | |
| 43 | #include "llvm/Support/ErrorHandling.h" | |
| 44 | #include "llvm/Support/FileSystem.h" | |
| 45 | #include "llvm/Support/FormattedStream.h" | |
| 46 | #include "llvm/Support/Host.h" | |
| 47 | #include "llvm/Support/MemoryBuffer.h" | |
| 48 | #include "llvm/Support/Path.h" | |
| 49 | #include "llvm/Support/Signals.h" | |
| 50 | #include "llvm/Support/SourceMgr.h" | |
| 51 | #include "llvm/Support/TargetRegistry.h" | |
| 52 | #include "llvm/Support/TargetSelect.h" | |
| 53 | #include "llvm/Support/Timer.h" | |
| 54 | #include "llvm/Support/raw_ostream.h" | |
| 55 | #include <memory> | |
| 56 | #include <system_error> | |
| 57 | using namespace clang; | |
| 58 | using namespace clang::driver; | |
| 59 | using namespace clang::driver::options; | |
| 60 | using namespace llvm; | |
| 61 | using namespace llvm::opt; | |
| 62 | ||
| 63 | namespace { | |
| 64 | ||
| 65 | /// Helper class for representing a single invocation of the assembler. | |
| 66 | struct AssemblerInvocation { | |
| 67 | /// @name Target Options | |
| 68 | /// @{ | |
| 69 | ||
| 70 | /// The name of the target triple to assemble for. | |
| 71 | std::string Triple; | |
| 72 | ||
| 73 | /// If given, the name of the target CPU to determine which instructions | |
| 74 | /// are legal. | |
| 75 | std::string CPU; | |
| 76 | ||
| 77 | /// The list of target specific features to enable or disable -- this should | |
| 78 | /// be a list of strings starting with '+' or '-'. | |
| 79 | std::vector<std::string> Features; | |
| 80 | ||
| 81 | /// The list of symbol definitions. | |
| 82 | std::vector<std::string> SymbolDefs; | |
| 83 | ||
| 84 | /// @} | |
| 85 | /// @name Language Options | |
| 86 | /// @{ | |
| 87 | ||
| 88 | std::vector<std::string> IncludePaths; | |
| 89 | unsigned NoInitialTextSection : 1; | |
| 90 | unsigned SaveTemporaryLabels : 1; | |
| 91 | unsigned GenDwarfForAssembly : 1; | |
| 92 | unsigned RelaxELFRelocations : 1; | |
| 93 | unsigned DwarfVersion; | |
| 94 | std::string DwarfDebugFlags; | |
| 95 | std::string DwarfDebugProducer; | |
| 96 | std::string DebugCompilationDir; | |
| 97 | std::map<const std::string, const std::string> DebugPrefixMap; | |
| 98 | llvm::DebugCompressionType CompressDebugSections = | |
| 99 | llvm::DebugCompressionType::None; | |
| 100 | std::string MainFileName; | |
| 101 | std::string SplitDwarfFile; | |
| 102 | ||
| 103 | /// @} | |
| 104 | /// @name Frontend Options | |
| 105 | /// @{ | |
| 106 | ||
| 107 | std::string InputFile; | |
| 108 | std::vector<std::string> LLVMArgs; | |
| 109 | std::string OutputPath; | |
| 110 | enum FileType { | |
| 111 | FT_Asm, ///< Assembly (.s) output, transliterate mode. | |
| 112 | FT_Null, ///< No output, for timing purposes. | |
| 113 | FT_Obj ///< Object file output. | |
| 114 | }; | |
| 115 | FileType OutputType; | |
| 116 | unsigned ShowHelp : 1; | |
| 117 | unsigned ShowVersion : 1; | |
| 118 | ||
| 119 | /// @} | |
| 120 | /// @name Transliterate Options | |
| 121 | /// @{ | |
| 122 | ||
| 123 | unsigned OutputAsmVariant; | |
| 124 | unsigned ShowEncoding : 1; | |
| 125 | unsigned ShowInst : 1; | |
| 126 | ||
| 127 | /// @} | |
| 128 | /// @name Assembler Options | |
| 129 | /// @{ | |
| 130 | ||
| 131 | unsigned RelaxAll : 1; | |
| 132 | unsigned NoExecStack : 1; | |
| 133 | unsigned FatalWarnings : 1; | |
| 134 | unsigned IncrementalLinkerCompatible : 1; | |
| 135 | ||
| 136 | /// The name of the relocation model to use. | |
| 137 | std::string RelocationModel; | |
| 138 | ||
| 139 | /// @} | |
| 140 | ||
| 141 | public: | |
| 142 | AssemblerInvocation() { | |
| 143 | Triple = ""; | |
| 144 | NoInitialTextSection = 0; | |
| 145 | InputFile = "-"; | |
| 146 | OutputPath = "-"; | |
| 147 | OutputType = FT_Asm; | |
| 148 | OutputAsmVariant = 0; | |
| 149 | ShowInst = 0; | |
| 150 | ShowEncoding = 0; | |
| 151 | RelaxAll = 0; | |
| 152 | NoExecStack = 0; | |
| 153 | FatalWarnings = 0; | |
| 154 | IncrementalLinkerCompatible = 0; | |
| 155 | DwarfVersion = 0; | |
| 156 | } | |
| 157 | ||
| 158 | static bool CreateFromArgs(AssemblerInvocation &Res, | |
| 159 | ArrayRef<const char *> Argv, | |
| 160 | DiagnosticsEngine &Diags); | |
| 161 | }; | |
| 162 | ||
| 163 | } | |
| 164 | ||
| 165 | bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, | |
| 166 | ArrayRef<const char *> Argv, | |
| 167 | DiagnosticsEngine &Diags) { | |
| 168 | bool Success = true; | |
| 169 | ||
| 170 | // Parse the arguments. | |
| 171 | std::unique_ptr<OptTable> OptTbl(createDriverOptTable()); | |
| 172 | ||
| 173 | const unsigned IncludedFlagsBitmask = options::CC1AsOption; | |
| 174 | unsigned MissingArgIndex, MissingArgCount; | |
| 175 | InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount, | |
| 176 | IncludedFlagsBitmask); | |
| 177 | ||
| 178 | // Check for missing argument error. | |
| 179 | if (MissingArgCount) { | |
| 180 | Diags.Report(diag::err_drv_missing_argument) | |
| 181 | << Args.getArgString(MissingArgIndex) << MissingArgCount; | |
| 182 | Success = false; | |
| 183 | } | |
| 184 | ||
| 185 | // Issue errors on unknown arguments. | |
| 186 | for (const Arg *A : Args.filtered(OPT_UNKNOWN)) { | |
| 187 | auto ArgString = A->getAsString(Args); | |
| 188 | std::string Nearest; | |
| 189 | if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1) | |
| 190 | Diags.Report(diag::err_drv_unknown_argument) << ArgString; | |
| 191 | else | |
| 192 | Diags.Report(diag::err_drv_unknown_argument_with_suggestion) | |
| 193 | << ArgString << Nearest; | |
| 194 | Success = false; | |
| 195 | } | |
| 196 | ||
| 197 | // Construct the invocation. | |
| 198 | ||
| 199 | // Target Options | |
| 200 | Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); | |
| 201 | Opts.CPU = Args.getLastArgValue(OPT_target_cpu); | |
| 202 | Opts.Features = Args.getAllArgValues(OPT_target_feature); | |
| 203 | ||
| 204 | // Use the default target triple if unspecified. | |
| 205 | if (Opts.Triple.empty()) | |
| 206 | Opts.Triple = llvm::sys::getDefaultTargetTriple(); | |
| 207 | ||
| 208 | // Language Options | |
| 209 | Opts.IncludePaths = Args.getAllArgValues(OPT_I); | |
| 210 | Opts.NoInitialTextSection = Args.hasArg(OPT_n); | |
| 211 | Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels); | |
| 212 | // Any DebugInfoKind implies GenDwarfForAssembly. | |
| 213 | Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ); | |
| 214 | ||
| 215 | if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections, | |
| 216 | OPT_compress_debug_sections_EQ)) { | |
| 217 | if (A->getOption().getID() == OPT_compress_debug_sections) { | |
| 218 | // TODO: be more clever about the compression type auto-detection | |
| 219 | Opts.CompressDebugSections = llvm::DebugCompressionType::GNU; | |
| 220 | } else { | |
| 221 | Opts.CompressDebugSections = | |
| 222 | llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue()) | |
| 223 | .Case("none", llvm::DebugCompressionType::None) | |
| 224 | .Case("zlib", llvm::DebugCompressionType::Z) | |
| 225 | .Case("zlib-gnu", llvm::DebugCompressionType::GNU) | |
| 226 | .Default(llvm::DebugCompressionType::None); | |
| 227 | } | |
| 228 | } | |
| 229 | ||
| 230 | Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); | |
| 231 | Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); | |
| 232 | Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); | |
| 233 | Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer); | |
| 234 | Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); | |
| 235 | Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); | |
| 236 | ||
| 237 | for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) | |
| 238 | Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); | |
| 239 | ||
| 240 | // Frontend Options | |
| 241 | if (Args.hasArg(OPT_INPUT)) { | |
| 242 | bool First = true; | |
| 243 | for (const Arg *A : Args.filtered(OPT_INPUT)) { | |
| 244 | if (First) { | |
| 245 | Opts.InputFile = A->getValue(); | |
| 246 | First = false; | |
| 247 | } else { | |
| 248 | Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args); | |
| 249 | Success = false; | |
| 250 | } | |
| 251 | } | |
| 252 | } | |
| 253 | Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); | |
| 254 | Opts.OutputPath = Args.getLastArgValue(OPT_o); | |
| 255 | Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); | |
| 256 | if (Arg *A = Args.getLastArg(OPT_filetype)) { | |
| 257 | StringRef Name = A->getValue(); | |
| 258 | unsigned OutputType = StringSwitch<unsigned>(Name) | |
| 259 | .Case("asm", FT_Asm) | |
| 260 | .Case("null", FT_Null) | |
| 261 | .Case("obj", FT_Obj) | |
| 262 | .Default(~0U); | |
| 263 | if (OutputType == ~0U) { | |
| 264 | Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; | |
| 265 | Success = false; | |
| 266 | } else | |
| 267 | Opts.OutputType = FileType(OutputType); | |
| 268 | } | |
| 269 | Opts.ShowHelp = Args.hasArg(OPT_help); | |
| 270 | Opts.ShowVersion = Args.hasArg(OPT_version); | |
| 271 | ||
| 272 | // Transliterate Options | |
| 273 | Opts.OutputAsmVariant = | |
| 274 | getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags); | |
| 275 | Opts.ShowEncoding = Args.hasArg(OPT_show_encoding); | |
| 276 | Opts.ShowInst = Args.hasArg(OPT_show_inst); | |
| 277 | ||
| 278 | // Assemble Options | |
| 279 | Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); | |
| 280 | Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); | |
| 281 | Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); | |
| 282 | Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); | |
| 283 | Opts.IncrementalLinkerCompatible = | |
| 284 | Args.hasArg(OPT_mincremental_linker_compatible); | |
| 285 | Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym); | |
| 286 | ||
| 287 | return Success; | |
| 288 | } | |
| 289 | ||
| 290 | static std::unique_ptr<raw_fd_ostream> | |
| 291 | getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) { | |
| 292 | // Make sure that the Out file gets unlinked from the disk if we get a | |
| 293 | // SIGINT. | |
| 294 | if (Path != "-") | |
| 295 | sys::RemoveFileOnSignal(Path); | |
| 296 | ||
| 297 | std::error_code EC; | |
| 298 | auto Out = llvm::make_unique<raw_fd_ostream>( | |
| 299 | Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text)); | |
| 300 | if (EC) { | |
| 301 | Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message(); | |
| 302 | return nullptr; | |
| 303 | } | |
| 304 | ||
| 305 | return Out; | |
| 306 | } | |
| 307 | ||
| 308 | static bool ExecuteAssembler(AssemblerInvocation &Opts, | |
| 309 | DiagnosticsEngine &Diags) { | |
| 310 | // Get the target specific parser. | |
| 311 | std::string Error; | |
| 312 | const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error); | |
| 313 | if (!TheTarget) | |
| 314 | return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; | |
| 315 | ||
| 316 | ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = | |
| 317 | MemoryBuffer::getFileOrSTDIN(Opts.InputFile); | |
| 318 | ||
| 319 | if (std::error_code EC = Buffer.getError()) { | |
| 320 | Error = EC.message(); | |
| 321 | return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile; | |
| 322 | } | |
| 323 | ||
| 324 | SourceMgr SrcMgr; | |
| 325 | ||
| 326 | // Tell SrcMgr about this buffer, which is what the parser will pick up. | |
| 327 | SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc()); | |
| 328 | ||
| 329 | // Record the location of the include directories so that the lexer can find | |
| 330 | // it later. | |
| 331 | SrcMgr.setIncludeDirs(Opts.IncludePaths); | |
| 332 | ||
| 333 | std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); | |
| 334 | assert(MRI && "Unable to create target register info!"); | |
| 335 | ||
| 336 | std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple)); | |
| 337 | assert(MAI && "Unable to create target asm info!"); | |
| 338 | ||
| 339 | // Ensure MCAsmInfo initialization occurs before any use, otherwise sections | |
| 340 | // may be created with a combination of default and explicit settings. | |
| 341 | MAI->setCompressDebugSections(Opts.CompressDebugSections); | |
| 342 | ||
| 343 | MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations); | |
| 344 | ||
| 345 | bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; | |
| 346 | if (Opts.OutputPath.empty()) | |
| 347 | Opts.OutputPath = "-"; | |
| 348 | std::unique_ptr<raw_fd_ostream> FDOS = | |
| 349 | getOutputStream(Opts.OutputPath, Diags, IsBinary); | |
| 350 | if (!FDOS) | |
| 351 | return true; | |
| 352 | std::unique_ptr<raw_fd_ostream> DwoOS; | |
| 353 | if (!Opts.SplitDwarfFile.empty()) | |
| 354 | DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary); | |
| 355 | ||
| 356 | // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and | |
| 357 | // MCObjectFileInfo needs a MCContext reference in order to initialize itself. | |
| 358 | std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); | |
| 359 | ||
| 360 | MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); | |
| 361 | ||
| 362 | bool PIC = false; | |
| 363 | if (Opts.RelocationModel == "static") { | |
| 364 | PIC = false; | |
| 365 | } else if (Opts.RelocationModel == "pic") { | |
| 366 | PIC = true; | |
| 367 | } else { | |
| 368 | assert(Opts.RelocationModel == "dynamic-no-pic" && | |
| 369 | "Invalid PIC model!"); | |
| 370 | PIC = false; | |
| 371 | } | |
| 372 | ||
| 373 | MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx); | |
| 374 | if (Opts.SaveTemporaryLabels) | |
| 375 | Ctx.setAllowTemporaryLabels(false); | |
| 376 | if (Opts.GenDwarfForAssembly) | |
| 377 | Ctx.setGenDwarfForAssembly(true); | |
| 378 | if (!Opts.DwarfDebugFlags.empty()) | |
| 379 | Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags)); | |
| 380 | if (!Opts.DwarfDebugProducer.empty()) | |
| 381 | Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer)); | |
| 382 | if (!Opts.DebugCompilationDir.empty()) | |
| 383 | Ctx.setCompilationDir(Opts.DebugCompilationDir); | |
| 384 | if (!Opts.DebugPrefixMap.empty()) | |
| 385 | for (const auto &KV : Opts.DebugPrefixMap) | |
| 386 | Ctx.addDebugPrefixMapEntry(KV.first, KV.second); | |
| 387 | if (!Opts.MainFileName.empty()) | |
| 388 | Ctx.setMainFileName(StringRef(Opts.MainFileName)); | |
| 389 | Ctx.setDwarfVersion(Opts.DwarfVersion); | |
| 390 | ||
| 391 | // Build up the feature string from the target feature list. | |
| 392 | std::string FS; | |
| 393 | if (!Opts.Features.empty()) { | |
| 394 | FS = Opts.Features[0]; | |
| 395 | for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i) | |
| 396 | FS += "," + Opts.Features[i]; | |
| 397 | } | |
| 398 | ||
| 399 | std::unique_ptr<MCStreamer> Str; | |
| 400 | ||
| 401 | std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); | |
| 402 | std::unique_ptr<MCSubtargetInfo> STI( | |
| 403 | TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS)); | |
| 404 | ||
| 405 | raw_pwrite_stream *Out = FDOS.get(); | |
| 406 | std::unique_ptr<buffer_ostream> BOS; | |
| 407 | ||
| 408 | // FIXME: There is a bit of code duplication with addPassesToEmitFile. | |
| 409 | if (Opts.OutputType == AssemblerInvocation::FT_Asm) { | |
| 410 | MCInstPrinter *IP = TheTarget->createMCInstPrinter( | |
| 411 | llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI); | |
| 412 | ||
| 413 | std::unique_ptr<MCCodeEmitter> CE; | |
| 414 | if (Opts.ShowEncoding) | |
| 415 | CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); | |
| 416 | MCTargetOptions MCOptions; | |
| 417 | std::unique_ptr<MCAsmBackend> MAB( | |
| 418 | TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); | |
| 419 | ||
| 420 | auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out); | |
| 421 | Str.reset(TheTarget->createAsmStreamer( | |
| 422 | Ctx, std::move(FOut), /*asmverbose*/ true, | |
| 423 | /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB), | |
| 424 | Opts.ShowInst)); | |
| 425 | } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { | |
| 426 | Str.reset(createNullStreamer(Ctx)); | |
| 427 | } else { | |
| 428 | assert(Opts.OutputType == AssemblerInvocation::FT_Obj && | |
| 429 | "Invalid file type!"); | |
| 430 | if (!FDOS->supportsSeeking()) { | |
| 431 | BOS = make_unique<buffer_ostream>(*FDOS); | |
| 432 | Out = BOS.get(); | |
| 433 | } | |
| 434 | ||
| 435 | std::unique_ptr<MCCodeEmitter> CE( | |
| 436 | TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); | |
| 437 | MCTargetOptions MCOptions; | |
| 438 | std::unique_ptr<MCAsmBackend> MAB( | |
| 439 | TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); | |
| 440 | std::unique_ptr<MCObjectWriter> OW = | |
| 441 | DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS) | |
| 442 | : MAB->createObjectWriter(*Out); | |
| 443 | ||
| 444 | Triple T(Opts.Triple); | |
| 445 | Str.reset(TheTarget->createMCObjectStreamer( | |
| 446 | T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI, | |
| 447 | Opts.RelaxAll, Opts.IncrementalLinkerCompatible, | |
| 448 | /*DWARFMustBeAtTheEnd*/ true)); | |
| 449 | Str.get()->InitSections(Opts.NoExecStack); | |
| 450 | } | |
| 451 | ||
| 452 | // Assembly to object compilation should leverage assembly info. | |
| 453 | Str->setUseAssemblerInfoForParsing(true); | |
| 454 | ||
| 455 | bool Failed = false; | |
| 456 | ||
| 457 | std::unique_ptr<MCAsmParser> Parser( | |
| 458 | createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); | |
| 459 | ||
| 460 | // FIXME: init MCTargetOptions from sanitizer flags here. | |
| 461 | MCTargetOptions Options; | |
| 462 | std::unique_ptr<MCTargetAsmParser> TAP( | |
| 463 | TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options)); | |
| 464 | if (!TAP) | |
| 465 | Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; | |
| 466 | ||
| 467 | // Set values for symbols, if any. | |
| 468 | for (auto &S : Opts.SymbolDefs) { | |
| 469 | auto Pair = StringRef(S).split('='); | |
| 470 | auto Sym = Pair.first; | |
| 471 | auto Val = Pair.second; | |
| 472 | int64_t Value; | |
| 473 | // We have already error checked this in the driver. | |
| 474 | Val.getAsInteger(0, Value); | |
| 475 | Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value); | |
| 476 | } | |
| 477 | ||
| 478 | if (!Failed) { | |
| 479 | Parser->setTargetParser(*TAP.get()); | |
| 480 | Failed = Parser->Run(Opts.NoInitialTextSection); | |
| 481 | } | |
| 482 | ||
| 483 | // Close Streamer first. | |
| 484 | // It might have a reference to the output stream. | |
| 485 | Str.reset(); | |
| 486 | // Close the output stream early. | |
| 487 | BOS.reset(); | |
| 488 | FDOS.reset(); | |
| 489 | ||
| 490 | // Delete output file if there were errors. | |
| 491 | if (Failed) { | |
| 492 | if (Opts.OutputPath != "-") | |
| 493 | sys::fs::remove(Opts.OutputPath); | |
| 494 | if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-") | |
| 495 | sys::fs::remove(Opts.SplitDwarfFile); | |
| 496 | } | |
| 497 | ||
| 498 | return Failed; | |
| 499 | } | |
| 500 | ||
| 501 | static void LLVMErrorHandler(void *UserData, const std::string &Message, | |
| 502 | bool GenCrashDiag) { | |
| 503 | DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); | |
| 504 | ||
| 505 | Diags.Report(diag::err_fe_error_backend) << Message; | |
| 506 | ||
| 507 | // We cannot recover from llvm errors. | |
| 508 | exit(1); | |
| 509 | } | |
| 510 | ||
| 511 | int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { | |
| 512 | // Initialize targets and assembly printers/parsers. | |
| 513 | InitializeAllTargetInfos(); | |
| 514 | InitializeAllTargetMCs(); | |
| 515 | InitializeAllAsmParsers(); | |
| 516 | ||
| 517 | // Construct our diagnostic client. | |
| 518 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); | |
| 519 | TextDiagnosticPrinter *DiagClient | |
| 520 | = new TextDiagnosticPrinter(errs(), &*DiagOpts); | |
| 521 | DiagClient->setPrefix("clang -cc1as"); | |
| 522 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); | |
| 523 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); | |
| 524 | ||
| 525 | // Set an error handler, so that any LLVM backend diagnostics go through our | |
| 526 | // error handler. | |
| 527 | ScopedFatalErrorHandler FatalErrorHandler | |
| 528 | (LLVMErrorHandler, static_cast<void*>(&Diags)); | |
| 529 | ||
| 530 | // Parse the arguments. | |
| 531 | AssemblerInvocation Asm; | |
| 532 | if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags)) | |
| 533 | return 1; | |
| 534 | ||
| 535 | if (Asm.ShowHelp) { | |
| 536 | std::unique_ptr<OptTable> Opts(driver::createDriverOptTable()); | |
| 537 | Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler", | |
| 538 | /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0, | |
| 539 | /*ShowAllAliases=*/false); | |
| 540 | return 0; | |
| 541 | } | |
| 542 | ||
| 543 | // Honor -version. | |
| 544 | // | |
| 545 | // FIXME: Use a better -version message? | |
| 546 | if (Asm.ShowVersion) { | |
| 547 | llvm::cl::PrintVersionMessage(); | |
| 548 | return 0; | |
| 549 | } | |
| 550 | ||
| 551 | // Honor -mllvm. | |
| 552 | // | |
| 553 | // FIXME: Remove this, one day. | |
| 554 | if (!Asm.LLVMArgs.empty()) { | |
| 555 | unsigned NumArgs = Asm.LLVMArgs.size(); | |
| 556 | auto Args = llvm::make_unique<const char*[]>(NumArgs + 2); | |
| 557 | Args[0] = "clang (LLVM option parsing)"; | |
| 558 | for (unsigned i = 0; i != NumArgs; ++i) | |
| 559 | Args[i + 1] = Asm.LLVMArgs[i].c_str(); | |
| 560 | Args[NumArgs + 1] = nullptr; | |
| 561 | llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); | |
| 562 | } | |
| 563 | ||
| 564 | // Execute the invocation, unless there were parsing errors. | |
| 565 | bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags); | |
| 566 | ||
| 567 | // If any timers were active but haven't been destroyed yet, print their | |
| 568 | // results now. | |
| 569 | TimerGroup::printAll(errs()); | |
| 570 | ||
| 571 | return !!Failed; | |
| 572 | } | |
| 573 |
src/zig_clang_driver.cpp created+513| ... | ... | @@ -0,0 +1,513 @@ |
| 1 | //===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Compiler Infrastructure | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // This is the entry point to the clang driver; it is a thin wrapper | |
| 11 | // for functionality in the Driver clang library. | |
| 12 | // | |
| 13 | //===----------------------------------------------------------------------===// | |
| 14 | ||
| 15 | #include "clang/Driver/Driver.h" | |
| 16 | #include "clang/Basic/DiagnosticOptions.h" | |
| 17 | #include "clang/Driver/Compilation.h" | |
| 18 | #include "clang/Driver/DriverDiagnostic.h" | |
| 19 | #include "clang/Driver/Options.h" | |
| 20 | #include "clang/Driver/ToolChain.h" | |
| 21 | #include "clang/Frontend/ChainedDiagnosticConsumer.h" | |
| 22 | #include "clang/Frontend/CompilerInvocation.h" | |
| 23 | #include "clang/Frontend/SerializedDiagnosticPrinter.h" | |
| 24 | #include "clang/Frontend/TextDiagnosticPrinter.h" | |
| 25 | #include "clang/Frontend/Utils.h" | |
| 26 | #include "llvm/ADT/ArrayRef.h" | |
| 27 | #include "llvm/ADT/SmallString.h" | |
| 28 | #include "llvm/ADT/SmallVector.h" | |
| 29 | #include "llvm/Option/ArgList.h" | |
| 30 | #include "llvm/Option/OptTable.h" | |
| 31 | #include "llvm/Option/Option.h" | |
| 32 | #include "llvm/Support/CommandLine.h" | |
| 33 | #include "llvm/Support/ErrorHandling.h" | |
| 34 | #include "llvm/Support/FileSystem.h" | |
| 35 | #include "llvm/Support/Host.h" | |
| 36 | #include "llvm/Support/InitLLVM.h" | |
| 37 | #include "llvm/Support/Path.h" | |
| 38 | #include "llvm/Support/Process.h" | |
| 39 | #include "llvm/Support/Program.h" | |
| 40 | #include "llvm/Support/Regex.h" | |
| 41 | #include "llvm/Support/Signals.h" | |
| 42 | #include "llvm/Support/StringSaver.h" | |
| 43 | #include "llvm/Support/TargetSelect.h" | |
| 44 | #include "llvm/Support/Timer.h" | |
| 45 | #include "llvm/Support/raw_ostream.h" | |
| 46 | #include <memory> | |
| 47 | #include <set> | |
| 48 | #include <system_error> | |
| 49 | using namespace clang; | |
| 50 | using namespace clang::driver; | |
| 51 | using namespace llvm::opt; | |
| 52 | ||
| 53 | std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { | |
| 54 | if (!CanonicalPrefixes) { | |
| 55 | SmallString<128> ExecutablePath(Argv0); | |
| 56 | // Do a PATH lookup if Argv0 isn't a valid path. | |
| 57 | if (!llvm::sys::fs::exists(ExecutablePath)) | |
| 58 | if (llvm::ErrorOr<std::string> P = | |
| 59 | llvm::sys::findProgramByName(ExecutablePath)) | |
| 60 | ExecutablePath = *P; | |
| 61 | return ExecutablePath.str(); | |
| 62 | } | |
| 63 | ||
| 64 | // This just needs to be some symbol in the binary; C++ doesn't | |
| 65 | // allow taking the address of ::main however. | |
| 66 | void *P = (void*) (intptr_t) GetExecutablePath; | |
| 67 | return llvm::sys::fs::getMainExecutable(Argv0, P); | |
| 68 | } | |
| 69 | ||
| 70 | static const char *GetStableCStr(std::set<std::string> &SavedStrings, | |
| 71 | StringRef S) { | |
| 72 | return SavedStrings.insert(S).first->c_str(); | |
| 73 | } | |
| 74 | ||
| 75 | /// ApplyQAOverride - Apply a list of edits to the input argument lists. | |
| 76 | /// | |
| 77 | /// The input string is a space separate list of edits to perform, | |
| 78 | /// they are applied in order to the input argument lists. Edits | |
| 79 | /// should be one of the following forms: | |
| 80 | /// | |
| 81 | /// '#': Silence information about the changes to the command line arguments. | |
| 82 | /// | |
| 83 | /// '^': Add FOO as a new argument at the beginning of the command line. | |
| 84 | /// | |
| 85 | /// '+': Add FOO as a new argument at the end of the command line. | |
| 86 | /// | |
| 87 | /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command | |
| 88 | /// line. | |
| 89 | /// | |
| 90 | /// 'xOPTION': Removes all instances of the literal argument OPTION. | |
| 91 | /// | |
| 92 | /// 'XOPTION': Removes all instances of the literal argument OPTION, | |
| 93 | /// and the following argument. | |
| 94 | /// | |
| 95 | /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' | |
| 96 | /// at the end of the command line. | |
| 97 | /// | |
| 98 | /// \param OS - The stream to write edit information to. | |
| 99 | /// \param Args - The vector of command line arguments. | |
| 100 | /// \param Edit - The override command to perform. | |
| 101 | /// \param SavedStrings - Set to use for storing string representations. | |
| 102 | static void ApplyOneQAOverride(raw_ostream &OS, | |
| 103 | SmallVectorImpl<const char*> &Args, | |
| 104 | StringRef Edit, | |
| 105 | std::set<std::string> &SavedStrings) { | |
| 106 | // This does not need to be efficient. | |
| 107 | ||
| 108 | if (Edit[0] == '^') { | |
| 109 | const char *Str = | |
| 110 | GetStableCStr(SavedStrings, Edit.substr(1)); | |
| 111 | OS << "### Adding argument " << Str << " at beginning\n"; | |
| 112 | Args.insert(Args.begin() + 1, Str); | |
| 113 | } else if (Edit[0] == '+') { | |
| 114 | const char *Str = | |
| 115 | GetStableCStr(SavedStrings, Edit.substr(1)); | |
| 116 | OS << "### Adding argument " << Str << " at end\n"; | |
| 117 | Args.push_back(Str); | |
| 118 | } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && | |
| 119 | Edit.slice(2, Edit.size()-1).find('/') != StringRef::npos) { | |
| 120 | StringRef MatchPattern = Edit.substr(2).split('/').first; | |
| 121 | StringRef ReplPattern = Edit.substr(2).split('/').second; | |
| 122 | ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); | |
| 123 | ||
| 124 | for (unsigned i = 1, e = Args.size(); i != e; ++i) { | |
| 125 | // Ignore end-of-line response file markers | |
| 126 | if (Args[i] == nullptr) | |
| 127 | continue; | |
| 128 | std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); | |
| 129 | ||
| 130 | if (Repl != Args[i]) { | |
| 131 | OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; | |
| 132 | Args[i] = GetStableCStr(SavedStrings, Repl); | |
| 133 | } | |
| 134 | } | |
| 135 | } else if (Edit[0] == 'x' || Edit[0] == 'X') { | |
| 136 | auto Option = Edit.substr(1); | |
| 137 | for (unsigned i = 1; i < Args.size();) { | |
| 138 | if (Option == Args[i]) { | |
| 139 | OS << "### Deleting argument " << Args[i] << '\n'; | |
| 140 | Args.erase(Args.begin() + i); | |
| 141 | if (Edit[0] == 'X') { | |
| 142 | if (i < Args.size()) { | |
| 143 | OS << "### Deleting argument " << Args[i] << '\n'; | |
| 144 | Args.erase(Args.begin() + i); | |
| 145 | } else | |
| 146 | OS << "### Invalid X edit, end of command line!\n"; | |
| 147 | } | |
| 148 | } else | |
| 149 | ++i; | |
| 150 | } | |
| 151 | } else if (Edit[0] == 'O') { | |
| 152 | for (unsigned i = 1; i < Args.size();) { | |
| 153 | const char *A = Args[i]; | |
| 154 | // Ignore end-of-line response file markers | |
| 155 | if (A == nullptr) | |
| 156 | continue; | |
| 157 | if (A[0] == '-' && A[1] == 'O' && | |
| 158 | (A[2] == '\0' || | |
| 159 | (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || | |
| 160 | ('0' <= A[2] && A[2] <= '9'))))) { | |
| 161 | OS << "### Deleting argument " << Args[i] << '\n'; | |
| 162 | Args.erase(Args.begin() + i); | |
| 163 | } else | |
| 164 | ++i; | |
| 165 | } | |
| 166 | OS << "### Adding argument " << Edit << " at end\n"; | |
| 167 | Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str())); | |
| 168 | } else { | |
| 169 | OS << "### Unrecognized edit: " << Edit << "\n"; | |
| 170 | } | |
| 171 | } | |
| 172 | ||
| 173 | /// ApplyQAOverride - Apply a comma separate list of edits to the | |
| 174 | /// input argument lists. See ApplyOneQAOverride. | |
| 175 | static void ApplyQAOverride(SmallVectorImpl<const char*> &Args, | |
| 176 | const char *OverrideStr, | |
| 177 | std::set<std::string> &SavedStrings) { | |
| 178 | raw_ostream *OS = &llvm::errs(); | |
| 179 | ||
| 180 | if (OverrideStr[0] == '#') { | |
| 181 | ++OverrideStr; | |
| 182 | OS = &llvm::nulls(); | |
| 183 | } | |
| 184 | ||
| 185 | *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n"; | |
| 186 | ||
| 187 | // This does not need to be efficient. | |
| 188 | ||
| 189 | const char *S = OverrideStr; | |
| 190 | while (*S) { | |
| 191 | const char *End = ::strchr(S, ' '); | |
| 192 | if (!End) | |
| 193 | End = S + strlen(S); | |
| 194 | if (End != S) | |
| 195 | ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings); | |
| 196 | S = End; | |
| 197 | if (*S != '\0') | |
| 198 | ++S; | |
| 199 | } | |
| 200 | } | |
| 201 | ||
| 202 | extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, | |
| 203 | void *MainAddr); | |
| 204 | extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, | |
| 205 | void *MainAddr); | |
| 206 | ||
| 207 | static void insertTargetAndModeArgs(const ParsedClangName &NameParts, | |
| 208 | SmallVectorImpl<const char *> &ArgVector, | |
| 209 | std::set<std::string> &SavedStrings) { | |
| 210 | // Put target and mode arguments at the start of argument list so that | |
| 211 | // arguments specified in command line could override them. Avoid putting | |
| 212 | // them at index 0, as an option like '-cc1' must remain the first. | |
| 213 | int InsertionPoint = 0; | |
| 214 | if (ArgVector.size() > 0) | |
| 215 | ++InsertionPoint; | |
| 216 | ||
| 217 | if (NameParts.DriverMode) { | |
| 218 | // Add the mode flag to the arguments. | |
| 219 | ArgVector.insert(ArgVector.begin() + InsertionPoint, | |
| 220 | GetStableCStr(SavedStrings, NameParts.DriverMode)); | |
| 221 | } | |
| 222 | ||
| 223 | if (NameParts.TargetIsValid) { | |
| 224 | const char *arr[] = {"-target", GetStableCStr(SavedStrings, | |
| 225 | NameParts.TargetPrefix)}; | |
| 226 | ArgVector.insert(ArgVector.begin() + InsertionPoint, | |
| 227 | std::begin(arr), std::end(arr)); | |
| 228 | } | |
| 229 | } | |
| 230 | ||
| 231 | static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver, | |
| 232 | SmallVectorImpl<const char *> &Opts) { | |
| 233 | llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts); | |
| 234 | // The first instance of '#' should be replaced with '=' in each option. | |
| 235 | for (const char *Opt : Opts) | |
| 236 | if (char *NumberSignPtr = const_cast<char *>(::strchr(Opt, '#'))) | |
| 237 | *NumberSignPtr = '='; | |
| 238 | } | |
| 239 | ||
| 240 | static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { | |
| 241 | // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. | |
| 242 | TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); | |
| 243 | if (TheDriver.CCPrintOptions) | |
| 244 | TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE"); | |
| 245 | ||
| 246 | // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE. | |
| 247 | TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS"); | |
| 248 | if (TheDriver.CCPrintHeaders) | |
| 249 | TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE"); | |
| 250 | ||
| 251 | // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE. | |
| 252 | TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); | |
| 253 | if (TheDriver.CCLogDiagnostics) | |
| 254 | TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE"); | |
| 255 | } | |
| 256 | ||
| 257 | static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, | |
| 258 | const std::string &Path) { | |
| 259 | // If the clang binary happens to be named cl.exe for compatibility reasons, | |
| 260 | // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC. | |
| 261 | StringRef ExeBasename(llvm::sys::path::filename(Path)); | |
| 262 | if (ExeBasename.equals_lower("cl.exe")) | |
| 263 | ExeBasename = "clang-cl.exe"; | |
| 264 | DiagClient->setPrefix(ExeBasename); | |
| 265 | } | |
| 266 | ||
| 267 | // This lets us create the DiagnosticsEngine with a properly-filled-out | |
| 268 | // DiagnosticOptions instance. | |
| 269 | static DiagnosticOptions * | |
| 270 | CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) { | |
| 271 | auto *DiagOpts = new DiagnosticOptions; | |
| 272 | std::unique_ptr<OptTable> Opts(createDriverOptTable()); | |
| 273 | unsigned MissingArgIndex, MissingArgCount; | |
| 274 | InputArgList Args = | |
| 275 | Opts->ParseArgs(argv.slice(1), MissingArgIndex, MissingArgCount); | |
| 276 | // We ignore MissingArgCount and the return value of ParseDiagnosticArgs. | |
| 277 | // Any errors that would be diagnosed here will also be diagnosed later, | |
| 278 | // when the DiagnosticsEngine actually exists. | |
| 279 | (void)ParseDiagnosticArgs(*DiagOpts, Args); | |
| 280 | return DiagOpts; | |
| 281 | } | |
| 282 | ||
| 283 | static void SetInstallDir(SmallVectorImpl<const char *> &argv, | |
| 284 | Driver &TheDriver, bool CanonicalPrefixes) { | |
| 285 | // Attempt to find the original path used to invoke the driver, to determine | |
| 286 | // the installed path. We do this manually, because we want to support that | |
| 287 | // path being a symlink. | |
| 288 | SmallString<128> InstalledPath(argv[0]); | |
| 289 | ||
| 290 | // Do a PATH lookup, if there are no directory components. | |
| 291 | if (llvm::sys::path::filename(InstalledPath) == InstalledPath) | |
| 292 | if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName( | |
| 293 | llvm::sys::path::filename(InstalledPath.str()))) | |
| 294 | InstalledPath = *Tmp; | |
| 295 | ||
| 296 | // FIXME: We don't actually canonicalize this, we just make it absolute. | |
| 297 | if (CanonicalPrefixes) | |
| 298 | llvm::sys::fs::make_absolute(InstalledPath); | |
| 299 | ||
| 300 | StringRef InstalledPathParent(llvm::sys::path::parent_path(InstalledPath)); | |
| 301 | if (llvm::sys::fs::exists(InstalledPathParent)) | |
| 302 | TheDriver.setInstalledDir(InstalledPathParent); | |
| 303 | } | |
| 304 | ||
| 305 | static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) { | |
| 306 | void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; | |
| 307 | if (Tool == "") | |
| 308 | return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP); | |
| 309 | if (Tool == "as") | |
| 310 | return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP); | |
| 311 | ||
| 312 | // Reject unknown tools. | |
| 313 | llvm::errs() << "error: unknown integrated tool '" << Tool << "'. " | |
| 314 | << "Valid tools include '-cc1' and '-cc1as'.\n"; | |
| 315 | return 1; | |
| 316 | } | |
| 317 | ||
| 318 | extern "C" int ZigClang_main(int argc_, const char **argv_); | |
| 319 | int ZigClang_main(int argc_, const char **argv_) { | |
| 320 | llvm::InitLLVM X(argc_, argv_); | |
| 321 | size_t argv_offset = (strcmp(argv_[1], "-cc1") == 0 || strcmp(argv_[1], "-cc1as") == 0) ? 0 : 1; | |
| 322 | SmallVector<const char *, 256> argv(argv_ + argv_offset, argv_ + argc_); | |
| 323 | ||
| 324 | if (llvm::sys::Process::FixupStandardFileDescriptors()) | |
| 325 | return 1; | |
| 326 | ||
| 327 | llvm::InitializeAllTargets(); | |
| 328 | auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]); | |
| 329 | ||
| 330 | llvm::BumpPtrAllocator A; | |
| 331 | llvm::StringSaver Saver(A); | |
| 332 | ||
| 333 | // Parse response files using the GNU syntax, unless we're in CL mode. There | |
| 334 | // are two ways to put clang in CL compatibility mode: argv[0] is either | |
| 335 | // clang-cl or cl, or --driver-mode=cl is on the command line. The normal | |
| 336 | // command line parsing can't happen until after response file parsing, so we | |
| 337 | // have to manually search for a --driver-mode=cl argument the hard way. | |
| 338 | // Finally, our -cc1 tools don't care which tokenization mode we use because | |
| 339 | // response files written by clang will tokenize the same way in either mode. | |
| 340 | bool ClangCLMode = false; | |
| 341 | if (StringRef(TargetAndMode.DriverMode).equals("--driver-mode=cl") || | |
| 342 | std::find_if(argv.begin(), argv.end(), [](const char *F) { | |
| 343 | return F && strcmp(F, "--driver-mode=cl") == 0; | |
| 344 | }) != argv.end()) { | |
| 345 | ClangCLMode = true; | |
| 346 | } | |
| 347 | enum { Default, POSIX, Windows } RSPQuoting = Default; | |
| 348 | for (const char *F : argv) { | |
| 349 | if (strcmp(F, "--rsp-quoting=posix") == 0) | |
| 350 | RSPQuoting = POSIX; | |
| 351 | else if (strcmp(F, "--rsp-quoting=windows") == 0) | |
| 352 | RSPQuoting = Windows; | |
| 353 | } | |
| 354 | ||
| 355 | // Determines whether we want nullptr markers in argv to indicate response | |
| 356 | // files end-of-lines. We only use this for the /LINK driver argument with | |
| 357 | // clang-cl.exe on Windows. | |
| 358 | bool MarkEOLs = ClangCLMode; | |
| 359 | ||
| 360 | llvm::cl::TokenizerCallback Tokenizer; | |
| 361 | if (RSPQuoting == Windows || (RSPQuoting == Default && ClangCLMode)) | |
| 362 | Tokenizer = &llvm::cl::TokenizeWindowsCommandLine; | |
| 363 | else | |
| 364 | Tokenizer = &llvm::cl::TokenizeGNUCommandLine; | |
| 365 | ||
| 366 | if (MarkEOLs && argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) | |
| 367 | MarkEOLs = false; | |
| 368 | llvm::cl::ExpandResponseFiles(Saver, Tokenizer, argv, MarkEOLs); | |
| 369 | ||
| 370 | // Handle -cc1 integrated tools, even if -cc1 was expanded from a response | |
| 371 | // file. | |
| 372 | auto FirstArg = std::find_if(argv.begin() + 1, argv.end(), | |
| 373 | [](const char *A) { return A != nullptr; }); | |
| 374 | if (FirstArg != argv.end() && StringRef(*FirstArg).startswith("-cc1")) { | |
| 375 | // If -cc1 came from a response file, remove the EOL sentinels. | |
| 376 | if (MarkEOLs) { | |
| 377 | auto newEnd = std::remove(argv.begin(), argv.end(), nullptr); | |
| 378 | argv.resize(newEnd - argv.begin()); | |
| 379 | } | |
| 380 | return ExecuteCC1Tool(argv, argv[1] + 4); | |
| 381 | } | |
| 382 | ||
| 383 | bool CanonicalPrefixes = true; | |
| 384 | for (int i = 1, size = argv.size(); i < size; ++i) { | |
| 385 | // Skip end-of-line response file markers | |
| 386 | if (argv[i] == nullptr) | |
| 387 | continue; | |
| 388 | if (StringRef(argv[i]) == "-no-canonical-prefixes") { | |
| 389 | CanonicalPrefixes = false; | |
| 390 | break; | |
| 391 | } | |
| 392 | } | |
| 393 | ||
| 394 | // Handle CL and _CL_ which permits additional command line options to be | |
| 395 | // prepended or appended. | |
| 396 | if (ClangCLMode) { | |
| 397 | // Arguments in "CL" are prepended. | |
| 398 | llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL"); | |
| 399 | if (OptCL.hasValue()) { | |
| 400 | SmallVector<const char *, 8> PrependedOpts; | |
| 401 | getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts); | |
| 402 | ||
| 403 | // Insert right after the program name to prepend to the argument list. | |
| 404 | argv.insert(argv.begin() + 1, PrependedOpts.begin(), PrependedOpts.end()); | |
| 405 | } | |
| 406 | // Arguments in "_CL_" are appended. | |
| 407 | llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_"); | |
| 408 | if (Opt_CL_.hasValue()) { | |
| 409 | SmallVector<const char *, 8> AppendedOpts; | |
| 410 | getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts); | |
| 411 | ||
| 412 | // Insert at the end of the argument list to append. | |
| 413 | argv.append(AppendedOpts.begin(), AppendedOpts.end()); | |
| 414 | } | |
| 415 | } | |
| 416 | ||
| 417 | std::set<std::string> SavedStrings; | |
| 418 | // Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the | |
| 419 | // scenes. | |
| 420 | if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) { | |
| 421 | // FIXME: Driver shouldn't take extra initial argument. | |
| 422 | ApplyQAOverride(argv, OverrideStr, SavedStrings); | |
| 423 | } | |
| 424 | ||
| 425 | std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes); | |
| 426 | ||
| 427 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = | |
| 428 | CreateAndPopulateDiagOpts(argv); | |
| 429 | ||
| 430 | TextDiagnosticPrinter *DiagClient | |
| 431 | = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); | |
| 432 | FixupDiagPrefixExeName(DiagClient, Path); | |
| 433 | ||
| 434 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); | |
| 435 | ||
| 436 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); | |
| 437 | ||
| 438 | if (!DiagOpts->DiagnosticSerializationFile.empty()) { | |
| 439 | auto SerializedConsumer = | |
| 440 | clang::serialized_diags::create(DiagOpts->DiagnosticSerializationFile, | |
| 441 | &*DiagOpts, /*MergeChildRecords=*/true); | |
| 442 | Diags.setClient(new ChainedDiagnosticConsumer( | |
| 443 | Diags.takeClient(), std::move(SerializedConsumer))); | |
| 444 | } | |
| 445 | ||
| 446 | ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); | |
| 447 | ||
| 448 | Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); | |
| 449 | SetInstallDir(argv, TheDriver, CanonicalPrefixes); | |
| 450 | TheDriver.setTargetAndMode(TargetAndMode); | |
| 451 | ||
| 452 | insertTargetAndModeArgs(TargetAndMode, argv, SavedStrings); | |
| 453 | ||
| 454 | SetBackdoorDriverOutputsFromEnvVars(TheDriver); | |
| 455 | ||
| 456 | std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv)); | |
| 457 | int Res = 1; | |
| 458 | if (C && !C->containsError()) { | |
| 459 | SmallVector<std::pair<int, const Command *>, 4> FailingCommands; | |
| 460 | Res = TheDriver.ExecuteCompilation(*C, FailingCommands); | |
| 461 | ||
| 462 | // Force a crash to test the diagnostics. | |
| 463 | if (TheDriver.GenReproducer) { | |
| 464 | Diags.Report(diag::err_drv_force_crash) | |
| 465 | << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"); | |
| 466 | ||
| 467 | // Pretend that every command failed. | |
| 468 | FailingCommands.clear(); | |
| 469 | for (const auto &J : C->getJobs()) | |
| 470 | if (const Command *C = dyn_cast<Command>(&J)) | |
| 471 | FailingCommands.push_back(std::make_pair(-1, C)); | |
| 472 | } | |
| 473 | ||
| 474 | for (const auto &P : FailingCommands) { | |
| 475 | int CommandRes = P.first; | |
| 476 | const Command *FailingCommand = P.second; | |
| 477 | if (!Res) | |
| 478 | Res = CommandRes; | |
| 479 | ||
| 480 | // If result status is < 0, then the driver command signalled an error. | |
| 481 | // If result status is 70, then the driver command reported a fatal error. | |
| 482 | // On Windows, abort will return an exit code of 3. In these cases, | |
| 483 | // generate additional diagnostic information if possible. | |
| 484 | bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70; | |
| 485 | #ifdef _WIN32 | |
| 486 | DiagnoseCrash |= CommandRes == 3; | |
| 487 | #endif | |
| 488 | if (DiagnoseCrash) { | |
| 489 | TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); | |
| 490 | break; | |
| 491 | } | |
| 492 | } | |
| 493 | } | |
| 494 | ||
| 495 | Diags.getClient()->finish(); | |
| 496 | ||
| 497 | // If any timers were active but haven't been destroyed yet, print their | |
| 498 | // results now. This happens in -disable-free mode. | |
| 499 | llvm::TimerGroup::printAll(llvm::errs()); | |
| 500 | ||
| 501 | #ifdef _WIN32 | |
| 502 | // Exit status should not be negative on Win32, unless abnormal termination. | |
| 503 | // Once abnormal termiation was caught, negative status should not be | |
| 504 | // propagated. | |
| 505 | if (Res < 0) | |
| 506 | Res = 1; | |
| 507 | #endif | |
| 508 | ||
| 509 | // If we have multiple failing commands, we return the result of the first | |
| 510 | // failing command. | |
| 511 | return Res; | |
| 512 | } | |
| 513 |
src/zig_llvm.cpp+1-1| ... | ... | @@ -732,7 +732,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su |
| 732 | 732 | const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { |
| 733 | 733 | switch (sub_arch) { |
| 734 | 734 | case ZigLLVM_NoSubArch: |
| 735 | return "(none)"; | |
| 735 | return ""; | |
| 736 | 736 | case ZigLLVM_ARMSubArch_v8_5a: |
| 737 | 737 | return "v8_5a"; |
| 738 | 738 | case ZigLLVM_ARMSubArch_v8_4a: |
src/zig_llvm.h+3-2| ... | ... | @@ -215,7 +215,7 @@ ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const |
| 215 | 215 | |
| 216 | 216 | |
| 217 | 217 | // copied from include/llvm/ADT/Triple.h |
| 218 | ||
| 218 | // synchronize with target.cpp::arch_list | |
| 219 | 219 | enum ZigLLVM_ArchType { |
| 220 | 220 | ZigLLVM_UnknownArch, |
| 221 | 221 | |
| ... | ... | @@ -272,6 +272,7 @@ enum ZigLLVM_ArchType { |
| 272 | 272 | ZigLLVM_LastArchType = ZigLLVM_renderscript64 |
| 273 | 273 | }; |
| 274 | 274 | |
| 275 | // synchronize with lists in target.cpp | |
| 275 | 276 | enum ZigLLVM_SubArchType { |
| 276 | 277 | ZigLLVM_NoSubArch, |
| 277 | 278 | |
| ... | ... | @@ -409,7 +410,7 @@ ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch); |
| 409 | 410 | ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch); |
| 410 | 411 | ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor); |
| 411 | 412 | ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os); |
| 412 | ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType env_type); | |
| 413 | ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi); | |
| 413 | 414 | |
| 414 | 415 | ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, |
| 415 | 416 | void (*append_diagnostic)(void *, const char *, size_t), void *context); |
std/buf_set.zig+4| ... | ... | @@ -32,6 +32,10 @@ pub const BufSet = struct { |
| 32 | 32 | } |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | pub fn exists(self: BufSet, key: []const u8) bool { | |
| 36 | return self.hash_map.get(key) != null; | |
| 37 | } | |
| 38 | ||
| 35 | 39 | pub fn delete(self: *BufSet, key: []const u8) void { |
| 36 | 40 | const entry = self.hash_map.remove(key) orelse return; |
| 37 | 41 | self.free(entry.key); |
std/build.zig+205-724| ... | ... | @@ -15,6 +15,8 @@ const BufSet = std.BufSet; |
| 15 | 15 | const BufMap = std.BufMap; |
| 16 | 16 | const fmt_lib = std.fmt; |
| 17 | 17 | |
| 18 | pub const FmtStep = @import("build/fmt.zig").FmtStep; | |
| 19 | ||
| 18 | 20 | pub const Builder = struct { |
| 19 | 21 | uninstall_tls: TopLevelStep, |
| 20 | 22 | install_tls: TopLevelStep, |
| ... | ... | @@ -31,6 +33,7 @@ pub const Builder = struct { |
| 31 | 33 | verbose_tokenize: bool, |
| 32 | 34 | verbose_ast: bool, |
| 33 | 35 | verbose_link: bool, |
| 36 | verbose_cc: bool, | |
| 34 | 37 | verbose_ir: bool, |
| 35 | 38 | verbose_llvm_ir: bool, |
| 36 | 39 | verbose_cimport: bool, |
| ... | ... | @@ -99,6 +102,7 @@ pub const Builder = struct { |
| 99 | 102 | .verbose_tokenize = false, |
| 100 | 103 | .verbose_ast = false, |
| 101 | 104 | .verbose_link = false, |
| 105 | .verbose_cc = false, | |
| 102 | 106 | .verbose_ir = false, |
| 103 | 107 | .verbose_llvm_ir = false, |
| 104 | 108 | .verbose_cimport = false, |
| ... | ... | @@ -157,7 +161,7 @@ pub const Builder = struct { |
| 157 | 161 | return LibExeObjStep.createExecutable(self, name, root_src, true); |
| 158 | 162 | } |
| 159 | 163 | |
| 160 | pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { | |
| 164 | pub fn addObject(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | |
| 161 | 165 | return LibExeObjStep.createObject(self, name, root_src); |
| 162 | 166 | } |
| 163 | 167 | |
| ... | ... | @@ -169,10 +173,8 @@ pub const Builder = struct { |
| 169 | 173 | return LibExeObjStep.createStaticLibrary(self, name, root_src); |
| 170 | 174 | } |
| 171 | 175 | |
| 172 | pub fn addTest(self: *Builder, root_src: []const u8) *TestStep { | |
| 173 | const test_step = self.allocator.create(TestStep) catch unreachable; | |
| 174 | test_step.* = TestStep.init(self, root_src); | |
| 175 | return test_step; | |
| 176 | pub fn addTest(self: *Builder, root_src: []const u8) *LibExeObjStep { | |
| 177 | return LibExeObjStep.createTest(self, "test", root_src); | |
| 176 | 178 | } |
| 177 | 179 | |
| 178 | 180 | pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep { |
| ... | ... | @@ -181,22 +183,6 @@ pub const Builder = struct { |
| 181 | 183 | return obj_step; |
| 182 | 184 | } |
| 183 | 185 | |
| 184 | pub fn addCStaticLibrary(self: *Builder, name: []const u8) *LibExeObjStep { | |
| 185 | return LibExeObjStep.createCStaticLibrary(self, name); | |
| 186 | } | |
| 187 | ||
| 188 | pub fn addCSharedLibrary(self: *Builder, name: []const u8, ver: Version) *LibExeObjStep { | |
| 189 | return LibExeObjStep.createCSharedLibrary(self, name, ver); | |
| 190 | } | |
| 191 | ||
| 192 | pub fn addCExecutable(self: *Builder, name: []const u8) *LibExeObjStep { | |
| 193 | return LibExeObjStep.createCExecutable(self, name); | |
| 194 | } | |
| 195 | ||
| 196 | pub fn addCObject(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep { | |
| 197 | return LibExeObjStep.createCObject(self, name, src); | |
| 198 | } | |
| 199 | ||
| 200 | 186 | /// ::argv is copied. |
| 201 | 187 | pub fn addCommand(self: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep { |
| 202 | 188 | return CommandStep.create(self, cwd, env_map, argv); |
| ... | ... | @@ -221,6 +207,10 @@ pub const Builder = struct { |
| 221 | 207 | return remove_dir_step; |
| 222 | 208 | } |
| 223 | 209 | |
| 210 | pub fn addFmt(self: *Builder, paths: []const []const u8) *FmtStep { | |
| 211 | return FmtStep.create(self, paths); | |
| 212 | } | |
| 213 | ||
| 224 | 214 | pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version { |
| 225 | 215 | return Version{ |
| 226 | 216 | .major = major, |
| ... | ... | @@ -663,14 +653,6 @@ pub const Builder = struct { |
| 663 | 653 | return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable; |
| 664 | 654 | } |
| 665 | 655 | |
| 666 | fn getCCExe(self: *Builder) []const u8 { | |
| 667 | if (builtin.environ == builtin.Environ.msvc) { | |
| 668 | return "cl.exe"; | |
| 669 | } else { | |
| 670 | return os.getEnvVarOwned(self.allocator, "CC") catch |err| if (err == error.EnvironmentVariableNotFound) ([]const u8)("cc") else debug.panic("Unable to get environment variable: {}", err); | |
| 671 | } | |
| 672 | } | |
| 673 | ||
| 674 | 656 | pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 { |
| 675 | 657 | // TODO report error for ambiguous situations |
| 676 | 658 | const exe_extension = (Target{ .Native = {} }).exeFileExt(); |
| ... | ... | @@ -755,20 +737,40 @@ const Version = struct { |
| 755 | 737 | const CrossTarget = struct { |
| 756 | 738 | arch: builtin.Arch, |
| 757 | 739 | os: builtin.Os, |
| 758 | environ: builtin.Environ, | |
| 740 | abi: builtin.Abi, | |
| 759 | 741 | }; |
| 760 | 742 | |
| 761 | 743 | pub const Target = union(enum) { |
| 762 | 744 | Native: void, |
| 763 | 745 | Cross: CrossTarget, |
| 764 | 746 | |
| 747 | fn archSubArchName(arch: builtin.Arch) []const u8 { | |
| 748 | return switch (arch) { | |
| 749 | builtin.Arch.arm => |sub| @tagName(sub), | |
| 750 | builtin.Arch.armeb => |sub| @tagName(sub), | |
| 751 | builtin.Arch.thumb => |sub| @tagName(sub), | |
| 752 | builtin.Arch.thumbeb => |sub| @tagName(sub), | |
| 753 | builtin.Arch.aarch64 => |sub| @tagName(sub), | |
| 754 | builtin.Arch.aarch64_be => |sub| @tagName(sub), | |
| 755 | builtin.Arch.kalimba => |sub| @tagName(sub), | |
| 756 | else => "", | |
| 757 | }; | |
| 758 | } | |
| 759 | ||
| 760 | pub fn subArchName(self: Target) []const u8 { | |
| 761 | switch (self) { | |
| 762 | Target.Native => return archSubArchName(builtin.arch), | |
| 763 | Target.Cross => |cross| return archSubArchName(cross.arch), | |
| 764 | } | |
| 765 | } | |
| 766 | ||
| 765 | 767 | pub fn oFileExt(self: *const Target) []const u8 { |
| 766 | const environ = switch (self.*) { | |
| 767 | Target.Native => builtin.environ, | |
| 768 | Target.Cross => |t| t.environ, | |
| 768 | const abi = switch (self.*) { | |
| 769 | Target.Native => builtin.abi, | |
| 770 | Target.Cross => |t| t.abi, | |
| 769 | 771 | }; |
| 770 | return switch (environ) { | |
| 771 | builtin.Environ.msvc => ".obj", | |
| 772 | return switch (abi) { | |
| 773 | builtin.Abi.msvc => ".obj", | |
| 772 | 774 | else => ".o", |
| 773 | 775 | }; |
| 774 | 776 | } |
| ... | ... | @@ -825,6 +827,11 @@ const Pkg = struct { |
| 825 | 827 | path: []const u8, |
| 826 | 828 | }; |
| 827 | 829 | |
| 830 | const CSourceFile = struct { | |
| 831 | source_path: []const u8, | |
| 832 | args: []const []const u8, | |
| 833 | }; | |
| 834 | ||
| 828 | 835 | pub const LibExeObjStep = struct { |
| 829 | 836 | step: Step, |
| 830 | 837 | builder: *Builder, |
| ... | ... | @@ -834,6 +841,7 @@ pub const LibExeObjStep = struct { |
| 834 | 841 | linker_script: ?[]const u8, |
| 835 | 842 | out_filename: []const u8, |
| 836 | 843 | output_path: ?[]const u8, |
| 844 | output_lib_path: ?[]const u8, | |
| 837 | 845 | static: bool, |
| 838 | 846 | version: Version, |
| 839 | 847 | object_files: ArrayList([]const u8), |
| ... | ... | @@ -844,33 +852,34 @@ pub const LibExeObjStep = struct { |
| 844 | 852 | strip: bool, |
| 845 | 853 | full_path_libs: ArrayList([]const u8), |
| 846 | 854 | need_flat_namespace_hack: bool, |
| 847 | is_zig: bool, | |
| 848 | cflags: ArrayList([]const u8), | |
| 849 | 855 | include_dirs: ArrayList([]const u8), |
| 850 | 856 | lib_paths: ArrayList([]const u8), |
| 851 | disable_libc: bool, | |
| 852 | 857 | frameworks: BufSet, |
| 853 | 858 | verbose_link: bool, |
| 854 | no_rosegment: bool, | |
| 859 | verbose_cc: bool, | |
| 855 | 860 | c_std: Builder.CStd, |
| 861 | override_std_dir: ?[]const u8, | |
| 862 | exec_cmd_args: ?[]const ?[]const u8, | |
| 863 | name_prefix: []const u8, | |
| 864 | filter: ?[]const u8, | |
| 856 | 865 | |
| 857 | // zig only stuff | |
| 858 | 866 | root_src: ?[]const u8, |
| 859 | 867 | output_h_path: ?[]const u8, |
| 860 | 868 | out_h_filename: []const u8, |
| 869 | out_lib_filename: []const u8, | |
| 861 | 870 | assembly_files: ArrayList([]const u8), |
| 862 | 871 | packages: ArrayList(Pkg), |
| 863 | 872 | build_options_contents: std.Buffer, |
| 864 | 873 | system_linker_hack: bool, |
| 865 | 874 | |
| 866 | // C only stuff | |
| 867 | source_files: ArrayList([]const u8), | |
| 875 | c_source_files: ArrayList(*CSourceFile), | |
| 868 | 876 | object_src: []const u8, |
| 869 | 877 | |
| 870 | 878 | const Kind = enum { |
| 871 | 879 | Exe, |
| 872 | 880 | Lib, |
| 873 | 881 | Obj, |
| 882 | Test, | |
| 874 | 883 | }; |
| 875 | 884 | |
| 876 | 885 | pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep { |
| ... | ... | @@ -879,55 +888,36 @@ pub const LibExeObjStep = struct { |
| 879 | 888 | return self; |
| 880 | 889 | } |
| 881 | 890 | |
| 882 | pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep { | |
| 883 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; | |
| 884 | self.* = initC(builder, name, Kind.Lib, version, false); | |
| 885 | return self; | |
| 886 | } | |
| 887 | ||
| 888 | 891 | pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| 889 | 892 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 890 | 893 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); |
| 891 | 894 | return self; |
| 892 | 895 | } |
| 893 | 896 | |
| 894 | pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep { | |
| 895 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; | |
| 896 | self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); | |
| 897 | return self; | |
| 898 | } | |
| 899 | ||
| 900 | pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { | |
| 897 | pub fn createObject(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | |
| 901 | 898 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 902 | 899 | self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); |
| 903 | 900 | return self; |
| 904 | 901 | } |
| 905 | 902 | |
| 906 | pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep { | |
| 907 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; | |
| 908 | self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); | |
| 909 | self.object_src = src; | |
| 910 | return self; | |
| 911 | } | |
| 912 | ||
| 913 | 903 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep { |
| 914 | 904 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 915 | 905 | self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0)); |
| 916 | 906 | return self; |
| 917 | 907 | } |
| 918 | 908 | |
| 919 | pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep { | |
| 909 | pub fn createTest(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { | |
| 920 | 910 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 921 | self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); | |
| 911 | self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, builder.version(0, 0, 0)); | |
| 922 | 912 | return self; |
| 923 | 913 | } |
| 924 | 914 | |
| 925 | 915 | fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: Version) LibExeObjStep { |
| 926 | 916 | var self = LibExeObjStep{ |
| 927 | .no_rosegment = false, | |
| 928 | 917 | .strip = false, |
| 929 | 918 | .builder = builder, |
| 930 | 919 | .verbose_link = false, |
| 920 | .verbose_cc = false, | |
| 931 | 921 | .build_mode = builtin.Mode.Debug, |
| 932 | 922 | .static = static, |
| 933 | 923 | .kind = kind, |
| ... | ... | @@ -939,80 +929,35 @@ pub const LibExeObjStep = struct { |
| 939 | 929 | .frameworks = BufSet.init(builder.allocator), |
| 940 | 930 | .step = Step.init(name, builder.allocator, make), |
| 941 | 931 | .output_path = null, |
| 932 | .output_lib_path = null, | |
| 942 | 933 | .output_h_path = null, |
| 943 | 934 | .version = ver, |
| 944 | 935 | .out_filename = undefined, |
| 945 | 936 | .out_h_filename = builder.fmt("{}.h", name), |
| 937 | .out_lib_filename = undefined, | |
| 946 | 938 | .major_only_filename = undefined, |
| 947 | 939 | .name_only_filename = undefined, |
| 948 | 940 | .object_files = ArrayList([]const u8).init(builder.allocator), |
| 949 | 941 | .assembly_files = ArrayList([]const u8).init(builder.allocator), |
| 950 | 942 | .packages = ArrayList(Pkg).init(builder.allocator), |
| 951 | .is_zig = true, | |
| 952 | 943 | .full_path_libs = ArrayList([]const u8).init(builder.allocator), |
| 953 | 944 | .need_flat_namespace_hack = false, |
| 954 | .cflags = ArrayList([]const u8).init(builder.allocator), | |
| 955 | .source_files = undefined, | |
| 945 | .c_source_files = ArrayList(*CSourceFile).init(builder.allocator), | |
| 956 | 946 | .include_dirs = ArrayList([]const u8).init(builder.allocator), |
| 957 | 947 | .lib_paths = ArrayList([]const u8).init(builder.allocator), |
| 958 | 948 | .object_src = undefined, |
| 959 | .disable_libc = true, | |
| 960 | 949 | .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable, |
| 961 | 950 | .c_std = Builder.CStd.C99, |
| 962 | 951 | .system_linker_hack = false, |
| 952 | .override_std_dir = null, | |
| 953 | .exec_cmd_args = null, | |
| 954 | .name_prefix = "", | |
| 955 | .filter = null, | |
| 963 | 956 | }; |
| 964 | 957 | self.computeOutFileNames(); |
| 965 | 958 | return self; |
| 966 | 959 | } |
| 967 | 960 | |
| 968 | fn initC(builder: *Builder, name: []const u8, kind: Kind, version: Version, static: bool) LibExeObjStep { | |
| 969 | var self = LibExeObjStep{ | |
| 970 | .no_rosegment = false, | |
| 971 | .builder = builder, | |
| 972 | .name = name, | |
| 973 | .kind = kind, | |
| 974 | .version = version, | |
| 975 | .static = static, | |
| 976 | .target = Target.Native, | |
| 977 | .cflags = ArrayList([]const u8).init(builder.allocator), | |
| 978 | .source_files = ArrayList([]const u8).init(builder.allocator), | |
| 979 | .object_files = ArrayList([]const u8).init(builder.allocator), | |
| 980 | .step = Step.init(name, builder.allocator, make), | |
| 981 | .link_libs = BufSet.init(builder.allocator), | |
| 982 | .frameworks = BufSet.init(builder.allocator), | |
| 983 | .full_path_libs = ArrayList([]const u8).init(builder.allocator), | |
| 984 | .include_dirs = ArrayList([]const u8).init(builder.allocator), | |
| 985 | .lib_paths = ArrayList([]const u8).init(builder.allocator), | |
| 986 | .output_path = null, | |
| 987 | .out_filename = undefined, | |
| 988 | .major_only_filename = undefined, | |
| 989 | .name_only_filename = undefined, | |
| 990 | .object_src = undefined, | |
| 991 | .build_mode = builtin.Mode.Debug, | |
| 992 | .strip = false, | |
| 993 | .need_flat_namespace_hack = false, | |
| 994 | .disable_libc = false, | |
| 995 | .is_zig = false, | |
| 996 | .linker_script = null, | |
| 997 | .c_std = Builder.CStd.C99, | |
| 998 | .system_linker_hack = false, | |
| 999 | ||
| 1000 | .root_src = undefined, | |
| 1001 | .verbose_link = false, | |
| 1002 | .output_h_path = undefined, | |
| 1003 | .out_h_filename = undefined, | |
| 1004 | .assembly_files = undefined, | |
| 1005 | .packages = undefined, | |
| 1006 | .build_options_contents = undefined, | |
| 1007 | }; | |
| 1008 | self.computeOutFileNames(); | |
| 1009 | return self; | |
| 1010 | } | |
| 1011 | ||
| 1012 | pub fn setNoRoSegment(self: *LibExeObjStep, value: bool) void { | |
| 1013 | self.no_rosegment = value; | |
| 1014 | } | |
| 1015 | ||
| 1016 | 961 | fn computeOutFileNames(self: *LibExeObjStep) void { |
| 1017 | 962 | switch (self.kind) { |
| 1018 | 963 | Kind.Obj => { |
| ... | ... | @@ -1021,23 +966,37 @@ pub const LibExeObjStep = struct { |
| 1021 | 966 | Kind.Exe => { |
| 1022 | 967 | self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt()); |
| 1023 | 968 | }, |
| 969 | Kind.Test => { | |
| 970 | self.out_filename = self.builder.fmt("test{}", self.target.exeFileExt()); | |
| 971 | }, | |
| 1024 | 972 | Kind.Lib => { |
| 1025 | 973 | if (self.static) { |
| 1026 | self.out_filename = self.builder.fmt("lib{}.a", self.name); | |
| 974 | switch (self.target.getOs()) { | |
| 975 | builtin.Os.windows => { | |
| 976 | self.out_filename = self.builder.fmt("{}.lib", self.name); | |
| 977 | }, | |
| 978 | else => { | |
| 979 | self.out_filename = self.builder.fmt("lib{}.a", self.name); | |
| 980 | }, | |
| 981 | } | |
| 982 | self.out_lib_filename = self.out_filename; | |
| 1027 | 983 | } else { |
| 1028 | 984 | switch (self.target.getOs()) { |
| 1029 | 985 | builtin.Os.ios, builtin.Os.macosx => { |
| 1030 | 986 | self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch); |
| 1031 | 987 | self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major); |
| 1032 | 988 | self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name); |
| 989 | self.out_lib_filename = self.out_filename; | |
| 1033 | 990 | }, |
| 1034 | 991 | builtin.Os.windows => { |
| 1035 | 992 | self.out_filename = self.builder.fmt("{}.dll", self.name); |
| 993 | self.out_lib_filename = self.builder.fmt("{}.lib", self.name); | |
| 1036 | 994 | }, |
| 1037 | 995 | else => { |
| 1038 | 996 | self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch); |
| 1039 | 997 | self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major); |
| 1040 | 998 | self.name_only_filename = self.builder.fmt("lib{}.so", self.name); |
| 999 | self.out_lib_filename = self.out_filename; | |
| 1041 | 1000 | }, |
| 1042 | 1001 | } |
| 1043 | 1002 | } |
| ... | ... | @@ -1045,12 +1004,17 @@ pub const LibExeObjStep = struct { |
| 1045 | 1004 | } |
| 1046 | 1005 | } |
| 1047 | 1006 | |
| 1048 | pub fn setTarget(self: *LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { | |
| 1007 | pub fn setTarget( | |
| 1008 | self: *LibExeObjStep, | |
| 1009 | target_arch: builtin.Arch, | |
| 1010 | target_os: builtin.Os, | |
| 1011 | target_abi: builtin.Abi, | |
| 1012 | ) void { | |
| 1049 | 1013 | self.target = Target{ |
| 1050 | 1014 | .Cross = CrossTarget{ |
| 1051 | 1015 | .arch = target_arch, |
| 1052 | 1016 | .os = target_os, |
| 1053 | .environ = target_environ, | |
| 1017 | .abi = target_abi, | |
| 1054 | 1018 | }, |
| 1055 | 1019 | }; |
| 1056 | 1020 | self.computeOutFileNames(); |
| ... | ... | @@ -1072,7 +1036,15 @@ pub const LibExeObjStep = struct { |
| 1072 | 1036 | |
| 1073 | 1037 | self.step.dependOn(&lib.step); |
| 1074 | 1038 | |
| 1075 | self.full_path_libs.append(lib.getOutputPath()) catch unreachable; | |
| 1039 | if (lib.static or self.target.isWindows()) { | |
| 1040 | self.object_files.append(lib.getOutputLibPath()) catch unreachable; | |
| 1041 | } else { | |
| 1042 | self.full_path_libs.append(lib.getOutputPath()) catch unreachable; | |
| 1043 | } | |
| 1044 | ||
| 1045 | if (lib.link_libs.exists("c")) { | |
| 1046 | self.link_libs.put("c") catch unreachable; | |
| 1047 | } | |
| 1076 | 1048 | |
| 1077 | 1049 | // TODO should be some kind of isolated directory that only has this header in it |
| 1078 | 1050 | self.include_dirs.append(self.builder.cache_root) catch unreachable; |
| ... | ... | @@ -1088,24 +1060,44 @@ pub const LibExeObjStep = struct { |
| 1088 | 1060 | } |
| 1089 | 1061 | |
| 1090 | 1062 | pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void { |
| 1091 | assert(self.kind != Kind.Obj); | |
| 1092 | 1063 | self.link_libs.put(name) catch unreachable; |
| 1093 | 1064 | } |
| 1094 | 1065 | |
| 1095 | pub fn addSourceFile(self: *LibExeObjStep, file: []const u8) void { | |
| 1096 | assert(self.kind != Kind.Obj); | |
| 1097 | assert(!self.is_zig); | |
| 1098 | self.source_files.append(file) catch unreachable; | |
| 1066 | pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void { | |
| 1067 | assert(self.kind == Kind.Test); | |
| 1068 | self.name_prefix = text; | |
| 1069 | } | |
| 1070 | ||
| 1071 | pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void { | |
| 1072 | assert(self.kind == Kind.Test); | |
| 1073 | self.filter = text; | |
| 1074 | } | |
| 1075 | ||
| 1076 | pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void { | |
| 1077 | const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable; | |
| 1078 | c_source_file.* = CSourceFile{ | |
| 1079 | .source_path = file, | |
| 1080 | .args = args, | |
| 1081 | }; | |
| 1082 | self.c_source_files.append(c_source_file) catch unreachable; | |
| 1099 | 1083 | } |
| 1100 | 1084 | |
| 1101 | 1085 | pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void { |
| 1102 | 1086 | self.verbose_link = value; |
| 1103 | 1087 | } |
| 1104 | 1088 | |
| 1089 | pub fn setVerboseCC(self: *LibExeObjStep, value: bool) void { | |
| 1090 | self.verbose_cc = value; | |
| 1091 | } | |
| 1092 | ||
| 1105 | 1093 | pub fn setBuildMode(self: *LibExeObjStep, mode: builtin.Mode) void { |
| 1106 | 1094 | self.build_mode = mode; |
| 1107 | 1095 | } |
| 1108 | 1096 | |
| 1097 | pub fn overrideStdDir(self: *LibExeObjStep, dir_path: []const u8) void { | |
| 1098 | self.override_std_dir = dir_path; | |
| 1099 | } | |
| 1100 | ||
| 1109 | 1101 | pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void { |
| 1110 | 1102 | self.output_path = file_path; |
| 1111 | 1103 | |
| ... | ... | @@ -1122,6 +1114,22 @@ pub const LibExeObjStep = struct { |
| 1122 | 1114 | ) catch unreachable; |
| 1123 | 1115 | } |
| 1124 | 1116 | |
| 1117 | pub fn setOutputLibPath(self: *LibExeObjStep, file_path: []const u8) void { | |
| 1118 | assert(self.kind == Kind.Lib); | |
| 1119 | if (self.static) | |
| 1120 | return self.setOutputPath(file_path); | |
| 1121 | ||
| 1122 | self.output_lib_path = file_path; | |
| 1123 | } | |
| 1124 | ||
| 1125 | pub fn getOutputLibPath(self: *LibExeObjStep) []const u8 { | |
| 1126 | assert(self.kind == Kind.Lib); | |
| 1127 | return if (self.output_lib_path) |output_lib_path| output_lib_path else os.path.join( | |
| 1128 | self.builder.allocator, | |
| 1129 | [][]const u8{ self.builder.cache_root, self.out_lib_filename }, | |
| 1130 | ) catch unreachable; | |
| 1131 | } | |
| 1132 | ||
| 1125 | 1133 | pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void { |
| 1126 | 1134 | self.output_h_path = file_path; |
| 1127 | 1135 | |
| ... | ... | @@ -1156,17 +1164,15 @@ pub const LibExeObjStep = struct { |
| 1156 | 1164 | |
| 1157 | 1165 | self.object_files.append(obj.getOutputPath()) catch unreachable; |
| 1158 | 1166 | |
| 1159 | // TODO make this lazy instead of stateful | |
| 1160 | if (!obj.disable_libc) { | |
| 1161 | self.disable_libc = false; | |
| 1162 | } | |
| 1163 | ||
| 1164 | 1167 | // TODO should be some kind of isolated directory that only has this header in it |
| 1165 | 1168 | self.include_dirs.append(self.builder.cache_root) catch unreachable; |
| 1169 | ||
| 1170 | if (obj.link_libs.exists("c")) { | |
| 1171 | self.link_libs.put("c") catch unreachable; | |
| 1172 | } | |
| 1166 | 1173 | } |
| 1167 | 1174 | |
| 1168 | 1175 | pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void { |
| 1169 | assert(self.is_zig); | |
| 1170 | 1176 | const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream; |
| 1171 | 1177 | out.print("pub const {} = {};\n", name, value) catch unreachable; |
| 1172 | 1178 | } |
| ... | ... | @@ -1180,23 +1186,15 @@ pub const LibExeObjStep = struct { |
| 1180 | 1186 | } |
| 1181 | 1187 | |
| 1182 | 1188 | pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { |
| 1183 | assert(self.is_zig); | |
| 1184 | ||
| 1185 | 1189 | self.packages.append(Pkg{ |
| 1186 | 1190 | .name = name, |
| 1187 | 1191 | .path = pkg_index_path, |
| 1188 | 1192 | }) catch unreachable; |
| 1189 | 1193 | } |
| 1190 | 1194 | |
| 1191 | pub fn addCompileFlags(self: *LibExeObjStep, flags: []const []const u8) void { | |
| 1192 | for (flags) |flag| { | |
| 1193 | self.cflags.append(flag) catch unreachable; | |
| 1194 | } | |
| 1195 | } | |
| 1196 | ||
| 1197 | pub fn setNoStdLib(self: *LibExeObjStep, disable: bool) void { | |
| 1198 | assert(!self.is_zig); | |
| 1199 | self.disable_libc = disable; | |
| 1195 | pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void { | |
| 1196 | assert(self.kind == Kind.Test); | |
| 1197 | self.exec_cmd_args = args; | |
| 1200 | 1198 | } |
| 1201 | 1199 | |
| 1202 | 1200 | pub fn enableSystemLinkerHack(self: *LibExeObjStep) void { |
| ... | ... | @@ -1205,15 +1203,11 @@ pub const LibExeObjStep = struct { |
| 1205 | 1203 | |
| 1206 | 1204 | fn make(step: *Step) !void { |
| 1207 | 1205 | const self = @fieldParentPtr(LibExeObjStep, "step", step); |
| 1208 | return if (self.is_zig) self.makeZig() else self.makeC(); | |
| 1209 | } | |
| 1210 | ||
| 1211 | fn makeZig(self: *LibExeObjStep) !void { | |
| 1212 | 1206 | const builder = self.builder; |
| 1213 | 1207 | |
| 1214 | assert(self.is_zig); | |
| 1215 | ||
| 1216 | if (self.root_src == null and self.object_files.len == 0 and self.assembly_files.len == 0) { | |
| 1208 | if (self.root_src == null and self.object_files.len == 0 and | |
| 1209 | self.assembly_files.len == 0 and self.c_source_files.len == 0) | |
| 1210 | { | |
| 1217 | 1211 | warn("{}: linker needs 1 or more objects to link\n", self.step.name); |
| 1218 | 1212 | return error.NeedAnObject; |
| 1219 | 1213 | } |
| ... | ... | @@ -1227,6 +1221,7 @@ pub const LibExeObjStep = struct { |
| 1227 | 1221 | Kind.Lib => "build-lib", |
| 1228 | 1222 | Kind.Exe => "build-exe", |
| 1229 | 1223 | Kind.Obj => "build-obj", |
| 1224 | Kind.Test => "test", | |
| 1230 | 1225 | }; |
| 1231 | 1226 | zig_args.append(cmd) catch unreachable; |
| 1232 | 1227 | |
| ... | ... | @@ -1234,6 +1229,14 @@ pub const LibExeObjStep = struct { |
| 1234 | 1229 | zig_args.append(builder.pathFromRoot(root_src)) catch unreachable; |
| 1235 | 1230 | } |
| 1236 | 1231 | |
| 1232 | for (self.c_source_files.toSliceConst()) |c_source_file| { | |
| 1233 | try zig_args.append("--c-source"); | |
| 1234 | for (c_source_file.args) |arg| { | |
| 1235 | try zig_args.append(arg); | |
| 1236 | } | |
| 1237 | try zig_args.append(self.builder.pathFromRoot(c_source_file.source_path)); | |
| 1238 | } | |
| 1239 | ||
| 1237 | 1240 | if (self.build_options_contents.len() > 0) { |
| 1238 | 1241 | const build_options_file = try os.path.join( |
| 1239 | 1242 | builder.allocator, |
| ... | ... | @@ -1246,6 +1249,16 @@ pub const LibExeObjStep = struct { |
| 1246 | 1249 | try zig_args.append("--pkg-end"); |
| 1247 | 1250 | } |
| 1248 | 1251 | |
| 1252 | if (self.filter) |filter| { | |
| 1253 | try zig_args.append("--test-filter"); | |
| 1254 | try zig_args.append(filter); | |
| 1255 | } | |
| 1256 | ||
| 1257 | if (self.name_prefix.len != 0) { | |
| 1258 | try zig_args.append("--test-name-prefix"); | |
| 1259 | try zig_args.append(self.name_prefix); | |
| 1260 | } | |
| 1261 | ||
| 1249 | 1262 | for (self.object_files.toSliceConst()) |object_file| { |
| 1250 | 1263 | zig_args.append("--object") catch unreachable; |
| 1251 | 1264 | zig_args.append(builder.pathFromRoot(object_file)) catch unreachable; |
| ... | ... | @@ -1262,6 +1275,7 @@ pub const LibExeObjStep = struct { |
| 1262 | 1275 | if (builder.verbose_ir) zig_args.append("--verbose-ir") catch unreachable; |
| 1263 | 1276 | if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable; |
| 1264 | 1277 | if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; |
| 1278 | if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; | |
| 1265 | 1279 | |
| 1266 | 1280 | if (self.strip) { |
| 1267 | 1281 | zig_args.append("--strip") catch unreachable; |
| ... | ... | @@ -1281,7 +1295,13 @@ pub const LibExeObjStep = struct { |
| 1281 | 1295 | zig_args.append("--output") catch unreachable; |
| 1282 | 1296 | zig_args.append(output_path) catch unreachable; |
| 1283 | 1297 | |
| 1284 | if (self.kind != Kind.Exe) { | |
| 1298 | if (self.kind == Kind.Lib and !self.static) { | |
| 1299 | const output_lib_path = builder.pathFromRoot(self.getOutputLibPath()); | |
| 1300 | zig_args.append("--output-lib") catch unreachable; | |
| 1301 | zig_args.append(output_lib_path) catch unreachable; | |
| 1302 | } | |
| 1303 | ||
| 1304 | if (self.kind != Kind.Exe and self.root_src != null) { | |
| 1285 | 1305 | const output_h_path = self.getOutputHPath(); |
| 1286 | 1306 | zig_args.append("--output-h") catch unreachable; |
| 1287 | 1307 | zig_args.append(builder.pathFromRoot(output_h_path)) catch unreachable; |
| ... | ... | @@ -1300,21 +1320,23 @@ pub const LibExeObjStep = struct { |
| 1300 | 1320 | zig_args.append("--ver-patch") catch unreachable; |
| 1301 | 1321 | zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable; |
| 1302 | 1322 | } |
| 1303 | if (self.kind == Kind.Exe and self.static) { | |
| 1323 | if ((self.kind == Kind.Exe or self.kind == Kind.Test) and self.static) { | |
| 1304 | 1324 | zig_args.append("--static") catch unreachable; |
| 1305 | 1325 | } |
| 1306 | 1326 | |
| 1307 | 1327 | switch (self.target) { |
| 1308 | 1328 | Target.Native => {}, |
| 1309 | 1329 | Target.Cross => |cross_target| { |
| 1310 | zig_args.append("--target-arch") catch unreachable; | |
| 1311 | zig_args.append(@tagName(cross_target.arch)) catch unreachable; | |
| 1312 | ||
| 1313 | zig_args.append("--target-os") catch unreachable; | |
| 1314 | zig_args.append(@tagName(cross_target.os)) catch unreachable; | |
| 1315 | ||
| 1316 | zig_args.append("--target-environ") catch unreachable; | |
| 1317 | zig_args.append(@tagName(cross_target.environ)) catch unreachable; | |
| 1330 | const triple = builder.fmt( | |
| 1331 | "{}{}-{}-{}", | |
| 1332 | @tagName(cross_target.arch), | |
| 1333 | Target.archSubArchName(cross_target.arch), | |
| 1334 | @tagName(cross_target.os), | |
| 1335 | @tagName(cross_target.abi), | |
| 1336 | ); | |
| 1337 | ||
| 1338 | try zig_args.append("-target"); | |
| 1339 | try zig_args.append(triple); | |
| 1318 | 1340 | }, |
| 1319 | 1341 | } |
| 1320 | 1342 | |
| ... | ... | @@ -1332,11 +1354,16 @@ pub const LibExeObjStep = struct { |
| 1332 | 1354 | } |
| 1333 | 1355 | } |
| 1334 | 1356 | |
| 1335 | if (!self.disable_libc) { | |
| 1336 | zig_args.append("--library") catch unreachable; | |
| 1337 | zig_args.append("c") catch unreachable; | |
| 1357 | if (self.exec_cmd_args) |exec_cmd_args| { | |
| 1358 | for (exec_cmd_args) |cmd_arg| { | |
| 1359 | if (cmd_arg) |arg| { | |
| 1360 | try zig_args.append("--test-cmd"); | |
| 1361 | try zig_args.append(arg); | |
| 1362 | } else { | |
| 1363 | try zig_args.append("--test-cmd-bin"); | |
| 1364 | } | |
| 1365 | } | |
| 1338 | 1366 | } |
| 1339 | ||
| 1340 | 1367 | for (self.packages.toSliceConst()) |pkg| { |
| 1341 | 1368 | zig_args.append("--pkg-begin") catch unreachable; |
| 1342 | 1369 | zig_args.append(pkg.name) catch unreachable; |
| ... | ... | @@ -1370,8 +1397,14 @@ pub const LibExeObjStep = struct { |
| 1370 | 1397 | } |
| 1371 | 1398 | |
| 1372 | 1399 | for (self.full_path_libs.toSliceConst()) |full_path_lib| { |
| 1373 | zig_args.append("--library") catch unreachable; | |
| 1374 | zig_args.append(builder.pathFromRoot(full_path_lib)) catch unreachable; | |
| 1400 | try zig_args.append("--library"); | |
| 1401 | try zig_args.append(builder.pathFromRoot(full_path_lib)); | |
| 1402 | ||
| 1403 | const full_path_lib_abs = builder.pathFromRoot(full_path_lib); | |
| 1404 | if (os.path.dirname(full_path_lib_abs)) |dirname| { | |
| 1405 | try zig_args.append("-rpath"); | |
| 1406 | try zig_args.append(dirname); | |
| 1407 | } | |
| 1375 | 1408 | } |
| 1376 | 1409 | |
| 1377 | 1410 | if (self.target.isDarwin()) { |
| ... | ... | @@ -1382,574 +1415,20 @@ pub const LibExeObjStep = struct { |
| 1382 | 1415 | } |
| 1383 | 1416 | } |
| 1384 | 1417 | |
| 1385 | if (self.no_rosegment) { | |
| 1386 | try zig_args.append("--no-rosegment"); | |
| 1387 | } | |
| 1388 | 1418 | if (self.system_linker_hack) { |
| 1389 | 1419 | try zig_args.append("--system-linker-hack"); |
| 1390 | 1420 | } |
| 1391 | 1421 | |
| 1392 | try builder.spawnChild(zig_args.toSliceConst()); | |
| 1393 | ||
| 1394 | if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) { | |
| 1395 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); | |
| 1396 | } | |
| 1397 | } | |
| 1398 | ||
| 1399 | fn appendCompileFlags(self: *LibExeObjStep, args: *ArrayList([]const u8)) void { | |
| 1400 | if (!self.strip) { | |
| 1401 | args.append("-g") catch unreachable; | |
| 1402 | } | |
| 1403 | switch (self.build_mode) { | |
| 1404 | builtin.Mode.Debug => { | |
| 1405 | if (self.disable_libc) { | |
| 1406 | args.append("-fno-stack-protector") catch unreachable; | |
| 1407 | } else { | |
| 1408 | args.append("-fstack-protector-strong") catch unreachable; | |
| 1409 | args.append("--param") catch unreachable; | |
| 1410 | args.append("ssp-buffer-size=4") catch unreachable; | |
| 1411 | } | |
| 1412 | }, | |
| 1413 | builtin.Mode.ReleaseSafe => { | |
| 1414 | args.append("-O2") catch unreachable; | |
| 1415 | if (self.disable_libc) { | |
| 1416 | args.append("-fno-stack-protector") catch unreachable; | |
| 1417 | } else { | |
| 1418 | args.append("-D_FORTIFY_SOURCE=2") catch unreachable; | |
| 1419 | args.append("-fstack-protector-strong") catch unreachable; | |
| 1420 | args.append("--param") catch unreachable; | |
| 1421 | args.append("ssp-buffer-size=4") catch unreachable; | |
| 1422 | } | |
| 1423 | }, | |
| 1424 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => { | |
| 1425 | args.append("-O2") catch unreachable; | |
| 1426 | args.append("-fno-stack-protector") catch unreachable; | |
| 1427 | }, | |
| 1428 | } | |
| 1429 | ||
| 1430 | for (self.include_dirs.toSliceConst()) |dir| { | |
| 1431 | args.append("-I") catch unreachable; | |
| 1432 | args.append(self.builder.pathFromRoot(dir)) catch unreachable; | |
| 1433 | } | |
| 1434 | ||
| 1435 | for (self.cflags.toSliceConst()) |cflag| { | |
| 1436 | args.append(cflag) catch unreachable; | |
| 1437 | } | |
| 1438 | ||
| 1439 | if (self.disable_libc) { | |
| 1440 | args.append("-nostdlib") catch unreachable; | |
| 1441 | } | |
| 1442 | } | |
| 1443 | ||
| 1444 | fn makeC(self: *LibExeObjStep) !void { | |
| 1445 | const builder = self.builder; | |
| 1446 | ||
| 1447 | const cc = builder.getCCExe(); | |
| 1448 | ||
| 1449 | assert(!self.is_zig); | |
| 1450 | ||
| 1451 | var cc_args = ArrayList([]const u8).init(builder.allocator); | |
| 1452 | defer cc_args.deinit(); | |
| 1453 | ||
| 1454 | cc_args.append(cc) catch unreachable; | |
| 1455 | ||
| 1456 | const is_darwin = self.target.isDarwin(); | |
| 1457 | ||
| 1458 | const c_std_arg = switch (self.c_std) { | |
| 1459 | Builder.CStd.C89 => "-std=c89", | |
| 1460 | Builder.CStd.C99 => "-std=c99", | |
| 1461 | Builder.CStd.C11 => "-std=c11", | |
| 1462 | }; | |
| 1463 | try cc_args.append(c_std_arg); | |
| 1464 | ||
| 1465 | switch (self.kind) { | |
| 1466 | Kind.Obj => { | |
| 1467 | cc_args.append("-c") catch unreachable; | |
| 1468 | cc_args.append(builder.pathFromRoot(self.object_src)) catch unreachable; | |
| 1469 | ||
| 1470 | const output_path = builder.pathFromRoot(self.getOutputPath()); | |
| 1471 | cc_args.append("-o") catch unreachable; | |
| 1472 | cc_args.append(output_path) catch unreachable; | |
| 1473 | ||
| 1474 | self.appendCompileFlags(&cc_args); | |
| 1475 | ||
| 1476 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1477 | }, | |
| 1478 | Kind.Lib => { | |
| 1479 | for (self.source_files.toSliceConst()) |source_file| { | |
| 1480 | cc_args.resize(0) catch unreachable; | |
| 1481 | cc_args.append(cc) catch unreachable; | |
| 1482 | ||
| 1483 | if (!self.static) { | |
| 1484 | cc_args.append("-fPIC") catch unreachable; | |
| 1485 | } | |
| 1486 | ||
| 1487 | const abs_source_file = builder.pathFromRoot(source_file); | |
| 1488 | cc_args.append("-c") catch unreachable; | |
| 1489 | cc_args.append(abs_source_file) catch unreachable; | |
| 1490 | ||
| 1491 | const cache_o_src = os.path.join( | |
| 1492 | builder.allocator, | |
| 1493 | [][]const u8{ builder.cache_root, source_file }, | |
| 1494 | ) catch unreachable; | |
| 1495 | if (os.path.dirname(cache_o_src)) |cache_o_dir| { | |
| 1496 | try builder.makePath(cache_o_dir); | |
| 1497 | } | |
| 1498 | const cache_o_file = builder.fmt("{}{}", cache_o_src, self.target.oFileExt()); | |
| 1499 | cc_args.append("-o") catch unreachable; | |
| 1500 | cc_args.append(builder.pathFromRoot(cache_o_file)) catch unreachable; | |
| 1501 | ||
| 1502 | self.appendCompileFlags(&cc_args); | |
| 1503 | ||
| 1504 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1505 | ||
| 1506 | self.object_files.append(cache_o_file) catch unreachable; | |
| 1507 | } | |
| 1508 | ||
| 1509 | if (self.static) { | |
| 1510 | // ar | |
| 1511 | cc_args.resize(0) catch unreachable; | |
| 1512 | cc_args.append("ar") catch unreachable; | |
| 1513 | ||
| 1514 | cc_args.append("qc") catch unreachable; | |
| 1515 | ||
| 1516 | const output_path = builder.pathFromRoot(self.getOutputPath()); | |
| 1517 | cc_args.append(output_path) catch unreachable; | |
| 1518 | ||
| 1519 | for (self.object_files.toSliceConst()) |object_file| { | |
| 1520 | cc_args.append(builder.pathFromRoot(object_file)) catch unreachable; | |
| 1521 | } | |
| 1522 | ||
| 1523 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1524 | ||
| 1525 | // ranlib | |
| 1526 | cc_args.resize(0) catch unreachable; | |
| 1527 | cc_args.append("ranlib") catch unreachable; | |
| 1528 | cc_args.append(output_path) catch unreachable; | |
| 1529 | ||
| 1530 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1531 | } else { | |
| 1532 | cc_args.resize(0) catch unreachable; | |
| 1533 | cc_args.append(cc) catch unreachable; | |
| 1534 | ||
| 1535 | if (is_darwin) { | |
| 1536 | cc_args.append("-dynamiclib") catch unreachable; | |
| 1537 | ||
| 1538 | cc_args.append("-Wl,-headerpad_max_install_names") catch unreachable; | |
| 1539 | ||
| 1540 | cc_args.append("-compatibility_version") catch unreachable; | |
| 1541 | cc_args.append(builder.fmt("{}.0.0", self.version.major)) catch unreachable; | |
| 1542 | ||
| 1543 | cc_args.append("-current_version") catch unreachable; | |
| 1544 | cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable; | |
| 1545 | ||
| 1546 | const install_name = builder.pathFromRoot(os.path.join( | |
| 1547 | builder.allocator, | |
| 1548 | [][]const u8{ builder.cache_root, self.major_only_filename }, | |
| 1549 | ) catch unreachable); | |
| 1550 | cc_args.append("-install_name") catch unreachable; | |
| 1551 | cc_args.append(install_name) catch unreachable; | |
| 1552 | } else { | |
| 1553 | cc_args.append("-fPIC") catch unreachable; | |
| 1554 | cc_args.append("-shared") catch unreachable; | |
| 1555 | ||
| 1556 | const soname_arg = builder.fmt("-Wl,-soname,lib{}.so.{d}", self.name, self.version.major); | |
| 1557 | defer builder.allocator.free(soname_arg); | |
| 1558 | cc_args.append(soname_arg) catch unreachable; | |
| 1559 | } | |
| 1560 | ||
| 1561 | const output_path = builder.pathFromRoot(self.getOutputPath()); | |
| 1562 | cc_args.append("-o") catch unreachable; | |
| 1563 | cc_args.append(output_path) catch unreachable; | |
| 1564 | ||
| 1565 | for (self.object_files.toSliceConst()) |object_file| { | |
| 1566 | cc_args.append(builder.pathFromRoot(object_file)) catch unreachable; | |
| 1567 | } | |
| 1568 | ||
| 1569 | if (!is_darwin) { | |
| 1570 | const rpath_arg = builder.fmt("-Wl,-rpath,{}", try os.path.realAlloc( | |
| 1571 | builder.allocator, | |
| 1572 | builder.pathFromRoot(builder.cache_root), | |
| 1573 | )); | |
| 1574 | defer builder.allocator.free(rpath_arg); | |
| 1575 | try cc_args.append(rpath_arg); | |
| 1576 | ||
| 1577 | try cc_args.append("-rdynamic"); | |
| 1578 | } | |
| 1579 | ||
| 1580 | for (self.full_path_libs.toSliceConst()) |full_path_lib| { | |
| 1581 | cc_args.append(builder.pathFromRoot(full_path_lib)) catch unreachable; | |
| 1582 | } | |
| 1583 | ||
| 1584 | { | |
| 1585 | var it = self.link_libs.iterator(); | |
| 1586 | while (it.next()) |entry| { | |
| 1587 | cc_args.append(builder.fmt("-l{}", entry.key)) catch unreachable; | |
| 1588 | } | |
| 1589 | } | |
| 1590 | ||
| 1591 | if (is_darwin and !self.static) { | |
| 1592 | var it = self.frameworks.iterator(); | |
| 1593 | while (it.next()) |entry| { | |
| 1594 | cc_args.append("-framework") catch unreachable; | |
| 1595 | cc_args.append(entry.key) catch unreachable; | |
| 1596 | } | |
| 1597 | } | |
| 1598 | ||
| 1599 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1600 | ||
| 1601 | if (self.target.wantSharedLibSymLinks()) { | |
| 1602 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); | |
| 1603 | } | |
| 1604 | } | |
| 1605 | }, | |
| 1606 | Kind.Exe => { | |
| 1607 | for (self.source_files.toSliceConst()) |source_file| { | |
| 1608 | cc_args.resize(0) catch unreachable; | |
| 1609 | cc_args.append(cc) catch unreachable; | |
| 1610 | ||
| 1611 | const abs_source_file = builder.pathFromRoot(source_file); | |
| 1612 | cc_args.append("-c") catch unreachable; | |
| 1613 | cc_args.append(abs_source_file) catch unreachable; | |
| 1614 | ||
| 1615 | const cache_o_src = os.path.join( | |
| 1616 | builder.allocator, | |
| 1617 | [][]const u8{ builder.cache_root, source_file }, | |
| 1618 | ) catch unreachable; | |
| 1619 | if (os.path.dirname(cache_o_src)) |cache_o_dir| { | |
| 1620 | try builder.makePath(cache_o_dir); | |
| 1621 | } | |
| 1622 | const cache_o_file = builder.fmt("{}{}", cache_o_src, self.target.oFileExt()); | |
| 1623 | cc_args.append("-o") catch unreachable; | |
| 1624 | cc_args.append(builder.pathFromRoot(cache_o_file)) catch unreachable; | |
| 1625 | ||
| 1626 | for (self.cflags.toSliceConst()) |cflag| { | |
| 1627 | cc_args.append(cflag) catch unreachable; | |
| 1628 | } | |
| 1629 | ||
| 1630 | for (self.include_dirs.toSliceConst()) |dir| { | |
| 1631 | cc_args.append("-I") catch unreachable; | |
| 1632 | cc_args.append(builder.pathFromRoot(dir)) catch unreachable; | |
| 1633 | } | |
| 1634 | ||
| 1635 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1636 | ||
| 1637 | self.object_files.append(cache_o_file) catch unreachable; | |
| 1638 | } | |
| 1639 | ||
| 1640 | cc_args.resize(0) catch unreachable; | |
| 1641 | cc_args.append(cc) catch unreachable; | |
| 1642 | ||
| 1643 | for (self.object_files.toSliceConst()) |object_file| { | |
| 1644 | cc_args.append(builder.pathFromRoot(object_file)) catch unreachable; | |
| 1645 | } | |
| 1646 | ||
| 1647 | const output_path = builder.pathFromRoot(self.getOutputPath()); | |
| 1648 | cc_args.append("-o") catch unreachable; | |
| 1649 | cc_args.append(output_path) catch unreachable; | |
| 1650 | ||
| 1651 | const rpath_arg = builder.fmt("-Wl,-rpath,{}", try os.path.realAlloc( | |
| 1652 | builder.allocator, | |
| 1653 | builder.pathFromRoot(builder.cache_root), | |
| 1654 | )); | |
| 1655 | defer builder.allocator.free(rpath_arg); | |
| 1656 | try cc_args.append(rpath_arg); | |
| 1657 | ||
| 1658 | try cc_args.append("-rdynamic"); | |
| 1659 | ||
| 1660 | { | |
| 1661 | var it = self.link_libs.iterator(); | |
| 1662 | while (it.next()) |entry| { | |
| 1663 | cc_args.append(builder.fmt("-l{}", entry.key)) catch unreachable; | |
| 1664 | } | |
| 1665 | } | |
| 1666 | ||
| 1667 | if (is_darwin) { | |
| 1668 | if (self.need_flat_namespace_hack) { | |
| 1669 | cc_args.append("-Wl,-flat_namespace") catch unreachable; | |
| 1670 | } | |
| 1671 | cc_args.append("-Wl,-search_paths_first") catch unreachable; | |
| 1672 | } | |
| 1673 | ||
| 1674 | for (self.full_path_libs.toSliceConst()) |full_path_lib| { | |
| 1675 | cc_args.append(builder.pathFromRoot(full_path_lib)) catch unreachable; | |
| 1676 | } | |
| 1677 | ||
| 1678 | if (is_darwin) { | |
| 1679 | var it = self.frameworks.iterator(); | |
| 1680 | while (it.next()) |entry| { | |
| 1681 | cc_args.append("-framework") catch unreachable; | |
| 1682 | cc_args.append(entry.key) catch unreachable; | |
| 1683 | } | |
| 1684 | } | |
| 1685 | ||
| 1686 | try builder.spawnChild(cc_args.toSliceConst()); | |
| 1687 | }, | |
| 1688 | } | |
| 1689 | } | |
| 1690 | }; | |
| 1691 | ||
| 1692 | pub const TestStep = struct { | |
| 1693 | step: Step, | |
| 1694 | builder: *Builder, | |
| 1695 | root_src: []const u8, | |
| 1696 | build_mode: builtin.Mode, | |
| 1697 | verbose: bool, | |
| 1698 | link_libs: BufSet, | |
| 1699 | name_prefix: []const u8, | |
| 1700 | filter: ?[]const u8, | |
| 1701 | target: Target, | |
| 1702 | exec_cmd_args: ?[]const ?[]const u8, | |
| 1703 | include_dirs: ArrayList([]const u8), | |
| 1704 | lib_paths: ArrayList([]const u8), | |
| 1705 | packages: ArrayList(Pkg), | |
| 1706 | object_files: ArrayList([]const u8), | |
| 1707 | no_rosegment: bool, | |
| 1708 | output_path: ?[]const u8, | |
| 1709 | system_linker_hack: bool, | |
| 1710 | override_std_dir: ?[]const u8, | |
| 1711 | ||
| 1712 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { | |
| 1713 | const step_name = builder.fmt("test {}", root_src); | |
| 1714 | return TestStep{ | |
| 1715 | .step = Step.init(step_name, builder.allocator, make), | |
| 1716 | .builder = builder, | |
| 1717 | .root_src = root_src, | |
| 1718 | .build_mode = builtin.Mode.Debug, | |
| 1719 | .verbose = false, | |
| 1720 | .name_prefix = "", | |
| 1721 | .filter = null, | |
| 1722 | .link_libs = BufSet.init(builder.allocator), | |
| 1723 | .target = Target{ .Native = {} }, | |
| 1724 | .exec_cmd_args = null, | |
| 1725 | .include_dirs = ArrayList([]const u8).init(builder.allocator), | |
| 1726 | .lib_paths = ArrayList([]const u8).init(builder.allocator), | |
| 1727 | .packages = ArrayList(Pkg).init(builder.allocator), | |
| 1728 | .object_files = ArrayList([]const u8).init(builder.allocator), | |
| 1729 | .no_rosegment = false, | |
| 1730 | .output_path = null, | |
| 1731 | .system_linker_hack = false, | |
| 1732 | .override_std_dir = null, | |
| 1733 | }; | |
| 1734 | } | |
| 1735 | ||
| 1736 | pub fn setNoRoSegment(self: *TestStep, value: bool) void { | |
| 1737 | self.no_rosegment = value; | |
| 1738 | } | |
| 1739 | ||
| 1740 | pub fn addLibPath(self: *TestStep, path: []const u8) void { | |
| 1741 | self.lib_paths.append(path) catch unreachable; | |
| 1742 | } | |
| 1743 | ||
| 1744 | pub fn addPackagePath(self: *TestStep, name: []const u8, pkg_index_path: []const u8) void { | |
| 1745 | self.packages.append(Pkg{ | |
| 1746 | .name = name, | |
| 1747 | .path = pkg_index_path, | |
| 1748 | }) catch unreachable; | |
| 1749 | } | |
| 1750 | ||
| 1751 | pub fn setVerbose(self: *TestStep, value: bool) void { | |
| 1752 | self.verbose = value; | |
| 1753 | } | |
| 1754 | ||
| 1755 | pub fn addIncludeDir(self: *TestStep, path: []const u8) void { | |
| 1756 | self.include_dirs.append(path) catch unreachable; | |
| 1757 | } | |
| 1758 | ||
| 1759 | pub fn setBuildMode(self: *TestStep, mode: builtin.Mode) void { | |
| 1760 | self.build_mode = mode; | |
| 1761 | } | |
| 1762 | ||
| 1763 | pub fn overrideStdDir(self: *TestStep, dir_path: []const u8) void { | |
| 1764 | self.override_std_dir = dir_path; | |
| 1765 | } | |
| 1766 | ||
| 1767 | pub fn setOutputPath(self: *TestStep, file_path: []const u8) void { | |
| 1768 | self.output_path = file_path; | |
| 1769 | ||
| 1770 | // catch a common mistake | |
| 1771 | if (mem.eql(u8, self.builder.pathFromRoot(file_path), self.builder.pathFromRoot("."))) { | |
| 1772 | debug.panic("setOutputPath wants a file path, not a directory\n"); | |
| 1773 | } | |
| 1774 | } | |
| 1775 | ||
| 1776 | pub fn getOutputPath(self: *TestStep) []const u8 { | |
| 1777 | if (self.output_path) |output_path| { | |
| 1778 | return output_path; | |
| 1779 | } else { | |
| 1780 | const basename = self.builder.fmt("test{}", self.target.exeFileExt()); | |
| 1781 | return os.path.join( | |
| 1782 | self.builder.allocator, | |
| 1783 | [][]const u8{ self.builder.cache_root, basename }, | |
| 1784 | ) catch unreachable; | |
| 1785 | } | |
| 1786 | } | |
| 1787 | ||
| 1788 | pub fn linkSystemLibrary(self: *TestStep, name: []const u8) void { | |
| 1789 | self.link_libs.put(name) catch unreachable; | |
| 1790 | } | |
| 1791 | ||
| 1792 | pub fn setNamePrefix(self: *TestStep, text: []const u8) void { | |
| 1793 | self.name_prefix = text; | |
| 1794 | } | |
| 1795 | ||
| 1796 | pub fn setFilter(self: *TestStep, text: ?[]const u8) void { | |
| 1797 | self.filter = text; | |
| 1798 | } | |
| 1799 | ||
| 1800 | pub fn addObject(self: *TestStep, obj: *LibExeObjStep) void { | |
| 1801 | assert(obj.kind == LibExeObjStep.Kind.Obj); | |
| 1802 | ||
| 1803 | self.step.dependOn(&obj.step); | |
| 1804 | ||
| 1805 | self.object_files.append(obj.getOutputPath()) catch unreachable; | |
| 1806 | ||
| 1807 | // TODO should be some kind of isolated directory that only has this header in it | |
| 1808 | self.include_dirs.append(self.builder.cache_root) catch unreachable; | |
| 1809 | } | |
| 1810 | ||
| 1811 | pub fn addObjectFile(self: *TestStep, path: []const u8) void { | |
| 1812 | self.object_files.append(path) catch unreachable; | |
| 1813 | } | |
| 1814 | ||
| 1815 | pub fn setTarget(self: *TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { | |
| 1816 | self.target = Target{ | |
| 1817 | .Cross = CrossTarget{ | |
| 1818 | .arch = target_arch, | |
| 1819 | .os = target_os, | |
| 1820 | .environ = target_environ, | |
| 1821 | }, | |
| 1822 | }; | |
| 1823 | } | |
| 1824 | ||
| 1825 | pub fn setExecCmd(self: *TestStep, args: []const ?[]const u8) void { | |
| 1826 | self.exec_cmd_args = args; | |
| 1827 | } | |
| 1828 | ||
| 1829 | pub fn enableSystemLinkerHack(self: *TestStep) void { | |
| 1830 | self.system_linker_hack = true; | |
| 1831 | } | |
| 1832 | ||
| 1833 | fn make(step: *Step) !void { | |
| 1834 | const self = @fieldParentPtr(TestStep, "step", step); | |
| 1835 | const builder = self.builder; | |
| 1836 | ||
| 1837 | var zig_args = ArrayList([]const u8).init(builder.allocator); | |
| 1838 | defer zig_args.deinit(); | |
| 1839 | ||
| 1840 | try zig_args.append(builder.zig_exe); | |
| 1841 | ||
| 1842 | try zig_args.append("test"); | |
| 1843 | try zig_args.append(builder.pathFromRoot(self.root_src)); | |
| 1844 | ||
| 1845 | if (self.verbose) { | |
| 1846 | try zig_args.append("--verbose"); | |
| 1847 | } | |
| 1848 | ||
| 1849 | switch (self.build_mode) { | |
| 1850 | builtin.Mode.Debug => {}, | |
| 1851 | builtin.Mode.ReleaseSafe => try zig_args.append("--release-safe"), | |
| 1852 | builtin.Mode.ReleaseFast => try zig_args.append("--release-fast"), | |
| 1853 | builtin.Mode.ReleaseSmall => try zig_args.append("--release-small"), | |
| 1854 | } | |
| 1855 | ||
| 1856 | const output_path = builder.pathFromRoot(self.getOutputPath()); | |
| 1857 | try zig_args.append("--output"); | |
| 1858 | try zig_args.append(output_path); | |
| 1859 | ||
| 1860 | switch (self.target) { | |
| 1861 | Target.Native => {}, | |
| 1862 | Target.Cross => |cross_target| { | |
| 1863 | try zig_args.append("--target-arch"); | |
| 1864 | try zig_args.append(@tagName(cross_target.arch)); | |
| 1865 | ||
| 1866 | try zig_args.append("--target-os"); | |
| 1867 | try zig_args.append(@tagName(cross_target.os)); | |
| 1868 | ||
| 1869 | try zig_args.append("--target-environ"); | |
| 1870 | try zig_args.append(@tagName(cross_target.environ)); | |
| 1871 | }, | |
| 1872 | } | |
| 1873 | ||
| 1874 | if (self.filter) |filter| { | |
| 1875 | try zig_args.append("--test-filter"); | |
| 1876 | try zig_args.append(filter); | |
| 1877 | } | |
| 1878 | ||
| 1879 | if (self.name_prefix.len != 0) { | |
| 1880 | try zig_args.append("--test-name-prefix"); | |
| 1881 | try zig_args.append(self.name_prefix); | |
| 1882 | } | |
| 1883 | ||
| 1884 | for (self.object_files.toSliceConst()) |object_file| { | |
| 1885 | try zig_args.append("--object"); | |
| 1886 | try zig_args.append(builder.pathFromRoot(object_file)); | |
| 1887 | } | |
| 1888 | ||
| 1889 | { | |
| 1890 | var it = self.link_libs.iterator(); | |
| 1891 | while (true) { | |
| 1892 | const entry = it.next() orelse break; | |
| 1893 | try zig_args.append("--library"); | |
| 1894 | try zig_args.append(entry.key); | |
| 1895 | } | |
| 1896 | } | |
| 1897 | ||
| 1898 | if (self.exec_cmd_args) |exec_cmd_args| { | |
| 1899 | for (exec_cmd_args) |cmd_arg| { | |
| 1900 | if (cmd_arg) |arg| { | |
| 1901 | try zig_args.append("--test-cmd"); | |
| 1902 | try zig_args.append(arg); | |
| 1903 | } else { | |
| 1904 | try zig_args.append("--test-cmd-bin"); | |
| 1905 | } | |
| 1906 | } | |
| 1907 | } | |
| 1908 | ||
| 1909 | for (self.include_dirs.toSliceConst()) |include_path| { | |
| 1910 | try zig_args.append("-isystem"); | |
| 1911 | try zig_args.append(builder.pathFromRoot(include_path)); | |
| 1912 | } | |
| 1913 | ||
| 1914 | for (builder.include_paths.toSliceConst()) |include_path| { | |
| 1915 | try zig_args.append("-isystem"); | |
| 1916 | try zig_args.append(builder.pathFromRoot(include_path)); | |
| 1917 | } | |
| 1918 | ||
| 1919 | for (builder.rpaths.toSliceConst()) |rpath| { | |
| 1920 | try zig_args.append("-rpath"); | |
| 1921 | try zig_args.append(rpath); | |
| 1922 | } | |
| 1923 | ||
| 1924 | for (self.lib_paths.toSliceConst()) |lib_path| { | |
| 1925 | try zig_args.append("--library-path"); | |
| 1926 | try zig_args.append(lib_path); | |
| 1927 | } | |
| 1928 | ||
| 1929 | for (builder.lib_paths.toSliceConst()) |lib_path| { | |
| 1930 | try zig_args.append("--library-path"); | |
| 1931 | try zig_args.append(lib_path); | |
| 1932 | } | |
| 1933 | ||
| 1934 | for (self.packages.toSliceConst()) |pkg| { | |
| 1935 | zig_args.append("--pkg-begin") catch unreachable; | |
| 1936 | zig_args.append(pkg.name) catch unreachable; | |
| 1937 | zig_args.append(builder.pathFromRoot(pkg.path)) catch unreachable; | |
| 1938 | zig_args.append("--pkg-end") catch unreachable; | |
| 1939 | } | |
| 1940 | ||
| 1941 | if (self.no_rosegment) { | |
| 1942 | try zig_args.append("--no-rosegment"); | |
| 1943 | } | |
| 1944 | if (self.system_linker_hack) { | |
| 1945 | try zig_args.append("--system-linker-hack"); | |
| 1946 | } | |
| 1947 | 1422 | if (self.override_std_dir) |dir| { |
| 1948 | 1423 | try zig_args.append("--override-std-dir"); |
| 1949 | 1424 | try zig_args.append(builder.pathFromRoot(dir)); |
| 1950 | 1425 | } |
| 1951 | 1426 | |
| 1952 | 1427 | try builder.spawnChild(zig_args.toSliceConst()); |
| 1428 | ||
| 1429 | if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) { | |
| 1430 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); | |
| 1431 | } | |
| 1953 | 1432 | } |
| 1954 | 1433 | }; |
| 1955 | 1434 | |
| ... | ... | @@ -1995,6 +1474,7 @@ const InstallArtifactStep = struct { |
| 1995 | 1474 | pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self { |
| 1996 | 1475 | const dest_dir = switch (artifact.kind) { |
| 1997 | 1476 | LibExeObjStep.Kind.Obj => unreachable, |
| 1477 | LibExeObjStep.Kind.Test => unreachable, | |
| 1998 | 1478 | LibExeObjStep.Kind.Exe => builder.exe_dir, |
| 1999 | 1479 | LibExeObjStep.Kind.Lib => builder.lib_dir, |
| 2000 | 1480 | }; |
| ... | ... | @@ -2031,6 +1511,7 @@ const InstallArtifactStep = struct { |
| 2031 | 1511 | builtin.Os.windows => {}, |
| 2032 | 1512 | else => switch (self.artifact.kind) { |
| 2033 | 1513 | LibExeObjStep.Kind.Obj => unreachable, |
| 1514 | LibExeObjStep.Kind.Test => unreachable, | |
| 2034 | 1515 | LibExeObjStep.Kind.Exe => u32(0o755), |
| 2035 | 1516 | LibExeObjStep.Kind.Lib => if (self.artifact.static) u32(0o666) else u32(0o755), |
| 2036 | 1517 | }, |
std/build/fmt.zig created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | const std = @import("../index.zig"); | |
| 2 | const build = @import("../build.zig"); | |
| 3 | const Step = build.Step; | |
| 4 | const Builder = build.Builder; | |
| 5 | const BufMap = std.BufMap; | |
| 6 | const mem = std.mem; | |
| 7 | ||
| 8 | pub const FmtStep = struct { | |
| 9 | step: Step, | |
| 10 | builder: *Builder, | |
| 11 | argv: [][]const u8, | |
| 12 | ||
| 13 | pub fn create(builder: *Builder, paths: []const []const u8) *FmtStep { | |
| 14 | const self = builder.allocator.create(FmtStep) catch unreachable; | |
| 15 | const name = "zig fmt"; | |
| 16 | self.* = FmtStep{ | |
| 17 | .step = Step.init(name, builder.allocator, make), | |
| 18 | .builder = builder, | |
| 19 | .argv = builder.allocator.alloc([]u8, paths.len + 2) catch unreachable, | |
| 20 | }; | |
| 21 | ||
| 22 | self.argv[0] = builder.zig_exe; | |
| 23 | self.argv[1] = "fmt"; | |
| 24 | for (paths) |path, i| { | |
| 25 | self.argv[2 + i] = builder.pathFromRoot(path); | |
| 26 | } | |
| 27 | return self; | |
| 28 | } | |
| 29 | ||
| 30 | fn make(step: *Step) !void { | |
| 31 | const self = @fieldParentPtr(FmtStep, "step", step); | |
| 32 | ||
| 33 | return self.builder.spawnChild(self.argv); | |
| 34 | } | |
| 35 | }; |
std/c/darwin.zig+10-1| ... | ... | @@ -36,11 +36,20 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi |
| 36 | 36 | pub extern "c" fn bind(socket: c_int, address: ?*const sockaddr, address_len: socklen_t) c_int; |
| 37 | 37 | pub extern "c" fn socket(domain: c_int, type: c_int, protocol: c_int) c_int; |
| 38 | 38 | |
| 39 | const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header; | |
| 40 | ||
| 39 | 41 | /// The value of the link editor defined symbol _MH_EXECUTE_SYM is the address |
| 40 | 42 | /// of the mach header in a Mach-O executable file type. It does not appear in |
| 41 | 43 | /// any file type other than a MH_EXECUTE file type. The type of the symbol is |
| 42 | 44 | /// absolute as the header is not part of any section. |
| 43 | pub extern "c" var _mh_execute_header: if (@sizeOf(usize) == 8) mach_header_64 else mach_header; | |
| 45 | /// This symbol is populated when linking the system's libc, which is guaranteed | |
| 46 | /// on this operating system. However when building object files or libraries, | |
| 47 | /// the system libc won't be linked until the final executable. So we | |
| 48 | /// export a weak symbol here, to be overridden by the real one. | |
| 49 | pub extern "c" var _mh_execute_header: mach_hdr = undefined; | |
| 50 | comptime { | |
| 51 | @export("__mh_execute_header", _mh_execute_header, @import("builtin").GlobalLinkage.Weak); | |
| 52 | } | |
| 44 | 53 | |
| 45 | 54 | pub const mach_header_64 = macho.mach_header_64; |
| 46 | 55 | pub const mach_header = macho.mach_header; |
std/c/index.zig+1| ... | ... | @@ -6,6 +6,7 @@ pub use switch (builtin.os) { |
| 6 | 6 | Os.windows => @import("windows.zig"), |
| 7 | 7 | Os.macosx, Os.ios => @import("darwin.zig"), |
| 8 | 8 | Os.freebsd => @import("freebsd.zig"), |
| 9 | Os.netbsd => @import("netbsd.zig"), | |
| 9 | 10 | else => empty_import, |
| 10 | 11 | }; |
| 11 | 12 | const empty_import = @import("../empty.zig"); |
std/c/netbsd.zig created+116| ... | ... | @@ -0,0 +1,116 @@ |
| 1 | extern "c" fn __errno() *c_int; | |
| 2 | pub const _errno = __errno; | |
| 3 | ||
| 4 | pub extern "c" fn kqueue() c_int; | |
| 5 | pub extern "c" fn kevent( | |
| 6 | kq: c_int, | |
| 7 | changelist: [*]const Kevent, | |
| 8 | nchanges: c_int, | |
| 9 | eventlist: [*]Kevent, | |
| 10 | nevents: c_int, | |
| 11 | timeout: ?*const timespec, | |
| 12 | ) c_int; | |
| 13 | pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; | |
| 14 | pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; | |
| 15 | pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int; | |
| 16 | pub extern "c" fn getdirentries(fd: c_int, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize; | |
| 17 | pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize; | |
| 18 | pub extern "c" fn pipe2(arg0: *[2]c_int, arg1: u32) c_int; | |
| 19 | pub extern "c" fn preadv(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize; | |
| 20 | pub extern "c" fn pwritev(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize; | |
| 21 | pub extern "c" fn openat(fd: c_int, path: ?[*]const u8, flags: c_int) c_int; | |
| 22 | pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int; | |
| 23 | pub extern "c" fn setuid(uid: c_uint) c_int; | |
| 24 | pub extern "c" fn kill(pid: c_int, sig: c_int) c_int; | |
| 25 | pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int; | |
| 26 | pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int; | |
| 27 | ||
| 28 | /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. | |
| 29 | pub const Kevent = extern struct { | |
| 30 | ident: usize, | |
| 31 | filter: i32, | |
| 32 | flags: u32, | |
| 33 | fflags: u32, | |
| 34 | data: i64, | |
| 35 | udata: usize, | |
| 36 | }; | |
| 37 | ||
| 38 | pub const pthread_attr_t = extern struct { | |
| 39 | pta_magic: u32, | |
| 40 | pta_flags: c_int, | |
| 41 | pta_private: *c_void, | |
| 42 | }; | |
| 43 | ||
| 44 | pub const msghdr = extern struct { | |
| 45 | msg_name: *u8, | |
| 46 | msg_namelen: socklen_t, | |
| 47 | msg_iov: *iovec, | |
| 48 | msg_iovlen: i32, | |
| 49 | __pad1: i32, | |
| 50 | msg_control: *u8, | |
| 51 | msg_controllen: socklen_t, | |
| 52 | __pad2: socklen_t, | |
| 53 | msg_flags: i32, | |
| 54 | }; | |
| 55 | ||
| 56 | pub const Stat = extern struct { | |
| 57 | dev: u64, | |
| 58 | mode: u32, | |
| 59 | ino: u64, | |
| 60 | nlink: usize, | |
| 61 | ||
| 62 | uid: u32, | |
| 63 | gid: u32, | |
| 64 | rdev: u64, | |
| 65 | ||
| 66 | atim: timespec, | |
| 67 | mtim: timespec, | |
| 68 | ctim: timespec, | |
| 69 | birthtim: timespec, | |
| 70 | ||
| 71 | size: i64, | |
| 72 | blocks: i64, | |
| 73 | blksize: isize, | |
| 74 | flags: u32, | |
| 75 | gen: u32, | |
| 76 | __spare: [2]u32, | |
| 77 | }; | |
| 78 | ||
| 79 | pub const timespec = extern struct { | |
| 80 | tv_sec: i64, | |
| 81 | tv_nsec: isize, | |
| 82 | }; | |
| 83 | ||
| 84 | pub const dirent = extern struct { | |
| 85 | d_fileno: u64, | |
| 86 | d_reclen: u16, | |
| 87 | d_namlen: u16, | |
| 88 | d_type: u8, | |
| 89 | d_off: i64, | |
| 90 | d_name: [512]u8, | |
| 91 | }; | |
| 92 | ||
| 93 | pub const in_port_t = u16; | |
| 94 | pub const sa_family_t = u8; | |
| 95 | ||
| 96 | pub const sockaddr = extern union { | |
| 97 | in: sockaddr_in, | |
| 98 | in6: sockaddr_in6, | |
| 99 | }; | |
| 100 | ||
| 101 | pub const sockaddr_in = extern struct { | |
| 102 | len: u8, | |
| 103 | family: sa_family_t, | |
| 104 | port: in_port_t, | |
| 105 | addr: u32, | |
| 106 | zero: [8]u8, | |
| 107 | }; | |
| 108 | ||
| 109 | pub const sockaddr_in6 = extern struct { | |
| 110 | len: u8, | |
| 111 | family: sa_family_t, | |
| 112 | port: in_port_t, | |
| 113 | flowinfo: u32, | |
| 114 | addr: [16]u8, | |
| 115 | scope_id: u32, | |
| 116 | }; |
std/debug/index.zig+66-16| ... | ... | @@ -90,9 +90,60 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 90 | 90 | }; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | /// Returns a slice with the same pointer as addresses, with a potentially smaller len. | |
| 94 | /// On Windows, when first_address is not null, we ask for at least 32 stack frames, | |
| 95 | /// and then try to find the first address. If addresses.len is more than 32, we | |
| 96 | /// capture that many stack frames exactly, and then look for the first address, | |
| 97 | /// chopping off the irrelevant frames and shifting so that the returned addresses pointer | |
| 98 | /// equals the passed in addresses pointer. | |
| 99 | pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void { | |
| 100 | switch (builtin.os) { | |
| 101 | builtin.Os.windows => { | |
| 102 | const addrs = stack_trace.instruction_addresses; | |
| 103 | const u32_addrs_len = @intCast(u32, addrs.len); | |
| 104 | const first_addr = first_address orelse { | |
| 105 | stack_trace.index = windows.RtlCaptureStackBackTrace( | |
| 106 | 0, | |
| 107 | u32_addrs_len, | |
| 108 | @ptrCast(**c_void, addrs.ptr), | |
| 109 | null, | |
| 110 | ); | |
| 111 | return; | |
| 112 | }; | |
| 113 | var addr_buf_stack: [32]usize = undefined; | |
| 114 | const addr_buf = if (addr_buf_stack.len > addrs.len) addr_buf_stack[0..] else addrs; | |
| 115 | const n = windows.RtlCaptureStackBackTrace(0, u32_addrs_len, @ptrCast(**c_void, addr_buf.ptr), null); | |
| 116 | const first_index = for (addr_buf[0..n]) |addr, i| { | |
| 117 | if (addr == first_addr) { | |
| 118 | break i; | |
| 119 | } | |
| 120 | } else { | |
| 121 | stack_trace.index = 0; | |
| 122 | return; | |
| 123 | }; | |
| 124 | const slice = addr_buf[first_index..n]; | |
| 125 | // We use a for loop here because slice and addrs may alias. | |
| 126 | for (slice) |addr, i| { | |
| 127 | addrs[i] = addr; | |
| 128 | } | |
| 129 | stack_trace.index = slice.len; | |
| 130 | }, | |
| 131 | else => { | |
| 132 | var it = StackIterator.init(first_address); | |
| 133 | for (stack_trace.instruction_addresses) |*addr, i| { | |
| 134 | addr.* = it.next() orelse { | |
| 135 | stack_trace.index = i; | |
| 136 | return; | |
| 137 | }; | |
| 138 | } | |
| 139 | stack_trace.index = stack_trace.instruction_addresses.len; | |
| 140 | }, | |
| 141 | } | |
| 142 | } | |
| 143 | ||
| 93 | 144 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. |
| 94 | 145 | /// TODO multithreaded awareness |
| 95 | pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { | |
| 146 | pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { | |
| 96 | 147 | const stderr = getStderrStream() catch return; |
| 97 | 148 | const debug_info = getSelfDebugInfo() catch |err| { |
| 98 | 149 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| ... | ... | @@ -141,7 +192,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c |
| 141 | 192 | const stderr = getStderrStream() catch os.abort(); |
| 142 | 193 | stderr.print(format ++ "\n", args) catch os.abort(); |
| 143 | 194 | if (trace) |t| { |
| 144 | dumpStackTrace(t); | |
| 195 | dumpStackTrace(t.*); | |
| 145 | 196 | } |
| 146 | 197 | dumpCurrentStackTrace(first_trace_addr); |
| 147 | 198 | |
| ... | ... | @@ -155,16 +206,15 @@ const WHITE = "\x1b[37;1m"; |
| 155 | 206 | const DIM = "\x1b[2m"; |
| 156 | 207 | const RESET = "\x1b[0m"; |
| 157 | 208 | |
| 158 | pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, tty_color: bool) !void { | |
| 159 | var frame_index: usize = undefined; | |
| 160 | var frames_left: usize = undefined; | |
| 161 | if (stack_trace.index < stack_trace.instruction_addresses.len) { | |
| 162 | frame_index = 0; | |
| 163 | frames_left = stack_trace.index; | |
| 164 | } else { | |
| 165 | frame_index = (stack_trace.index + 1) % stack_trace.instruction_addresses.len; | |
| 166 | frames_left = stack_trace.instruction_addresses.len; | |
| 167 | } | |
| 209 | pub fn writeStackTrace( | |
| 210 | stack_trace: builtin.StackTrace, | |
| 211 | out_stream: var, | |
| 212 | allocator: *mem.Allocator, | |
| 213 | debug_info: *DebugInfo, | |
| 214 | tty_color: bool, | |
| 215 | ) !void { | |
| 216 | var frame_index: usize = 0; | |
| 217 | var frames_left: usize = stack_trace.index; | |
| 168 | 218 | |
| 169 | 219 | while (frames_left != 0) : ({ |
| 170 | 220 | frames_left -= 1; |
| ... | ... | @@ -240,7 +290,7 @@ pub fn writeCurrentStackTraceWindows( |
| 240 | 290 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { |
| 241 | 291 | switch (builtin.os) { |
| 242 | 292 | builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color), |
| 243 | builtin.Os.linux, builtin.Os.freebsd => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color), | |
| 293 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color), | |
| 244 | 294 | builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color), |
| 245 | 295 | else => return error.UnsupportedOperatingSystem, |
| 246 | 296 | } |
| ... | ... | @@ -574,7 +624,7 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach |
| 574 | 624 | } |
| 575 | 625 | |
| 576 | 626 | fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { |
| 577 | const base_addr = @ptrToInt(&std.c._mh_execute_header); | |
| 627 | const base_addr = std.os.getBaseAddress(); | |
| 578 | 628 | const adjusted_addr = 0x100000000 + (address - base_addr); |
| 579 | 629 | |
| 580 | 630 | const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse { |
| ... | ... | @@ -717,7 +767,7 @@ pub const OpenSelfDebugInfoError = error{ |
| 717 | 767 | |
| 718 | 768 | pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { |
| 719 | 769 | switch (builtin.os) { |
| 720 | builtin.Os.linux, builtin.Os.freebsd => return openSelfDebugInfoLinux(allocator), | |
| 770 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => return openSelfDebugInfoLinux(allocator), | |
| 721 | 771 | builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator), |
| 722 | 772 | builtin.Os.windows => return openSelfDebugInfoWindows(allocator), |
| 723 | 773 | else => return error.UnsupportedOperatingSystem, |
| ... | ... | @@ -1141,7 +1191,7 @@ pub const DebugInfo = switch (builtin.os) { |
| 1141 | 1191 | sect_contribs: []pdb.SectionContribEntry, |
| 1142 | 1192 | modules: []Module, |
| 1143 | 1193 | }, |
| 1144 | builtin.Os.linux, builtin.Os.freebsd => DwarfInfo, | |
| 1194 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => DwarfInfo, | |
| 1145 | 1195 | else => @compileError("Unsupported OS"), |
| 1146 | 1196 | }; |
| 1147 | 1197 |
std/event/fs.zig+23-8| ... | ... | @@ -85,6 +85,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o |
| 85 | 85 | builtin.Os.macosx, |
| 86 | 86 | builtin.Os.linux, |
| 87 | 87 | builtin.Os.freebsd, |
| 88 | builtin.Os.netbsd, | |
| 88 | 89 | => { |
| 89 | 90 | const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len); |
| 90 | 91 | defer loop.allocator.free(iovecs); |
| ... | ... | @@ -222,6 +223,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: |
| 222 | 223 | builtin.Os.macosx, |
| 223 | 224 | builtin.Os.linux, |
| 224 | 225 | builtin.Os.freebsd, |
| 226 | builtin.Os.netbsd, | |
| 225 | 227 | => { |
| 226 | 228 | const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len); |
| 227 | 229 | defer loop.allocator.free(iovecs); |
| ... | ... | @@ -402,7 +404,11 @@ pub async fn openPosix( |
| 402 | 404 | |
| 403 | 405 | pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle { |
| 404 | 406 | switch (builtin.os) { |
| 405 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => { | |
| 407 | builtin.Os.macosx, | |
| 408 | builtin.Os.linux, | |
| 409 | builtin.Os.freebsd, | |
| 410 | builtin.Os.netbsd | |
| 411 | => { | |
| 406 | 412 | const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC; |
| 407 | 413 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); |
| 408 | 414 | }, |
| ... | ... | @@ -431,6 +437,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os |
| 431 | 437 | builtin.Os.macosx, |
| 432 | 438 | builtin.Os.linux, |
| 433 | 439 | builtin.Os.freebsd, |
| 440 | builtin.Os.netbsd, | |
| 434 | 441 | => { |
| 435 | 442 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC; |
| 436 | 443 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); |
| ... | ... | @@ -453,7 +460,7 @@ pub async fn openReadWrite( |
| 453 | 460 | mode: os.File.Mode, |
| 454 | 461 | ) os.File.OpenError!os.FileHandle { |
| 455 | 462 | switch (builtin.os) { |
| 456 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => { | |
| 463 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 457 | 464 | const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC; |
| 458 | 465 | return await (async openPosix(loop, path, flags, mode) catch unreachable); |
| 459 | 466 | }, |
| ... | ... | @@ -481,7 +488,7 @@ pub const CloseOperation = struct { |
| 481 | 488 | os_data: OsData, |
| 482 | 489 | |
| 483 | 490 | const OsData = switch (builtin.os) { |
| 484 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => OsDataPosix, | |
| 491 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => OsDataPosix, | |
| 485 | 492 | |
| 486 | 493 | builtin.Os.windows => struct { |
| 487 | 494 | handle: ?os.FileHandle, |
| ... | ... | @@ -500,7 +507,7 @@ pub const CloseOperation = struct { |
| 500 | 507 | self.* = CloseOperation{ |
| 501 | 508 | .loop = loop, |
| 502 | 509 | .os_data = switch (builtin.os) { |
| 503 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => initOsDataPosix(self), | |
| 510 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => initOsDataPosix(self), | |
| 504 | 511 | builtin.Os.windows => OsData{ .handle = null }, |
| 505 | 512 | else => @compileError("Unsupported OS"), |
| 506 | 513 | }, |
| ... | ... | @@ -530,6 +537,7 @@ pub const CloseOperation = struct { |
| 530 | 537 | builtin.Os.linux, |
| 531 | 538 | builtin.Os.macosx, |
| 532 | 539 | builtin.Os.freebsd, |
| 540 | builtin.Os.netbsd, | |
| 533 | 541 | => { |
| 534 | 542 | if (self.os_data.have_fd) { |
| 535 | 543 | self.loop.posixFsRequest(&self.os_data.close_req_node); |
| ... | ... | @@ -552,6 +560,7 @@ pub const CloseOperation = struct { |
| 552 | 560 | builtin.Os.linux, |
| 553 | 561 | builtin.Os.macosx, |
| 554 | 562 | builtin.Os.freebsd, |
| 563 | builtin.Os.netbsd, | |
| 555 | 564 | => { |
| 556 | 565 | self.os_data.close_req_node.data.msg.Close.fd = handle; |
| 557 | 566 | self.os_data.have_fd = true; |
| ... | ... | @@ -569,6 +578,7 @@ pub const CloseOperation = struct { |
| 569 | 578 | builtin.Os.linux, |
| 570 | 579 | builtin.Os.macosx, |
| 571 | 580 | builtin.Os.freebsd, |
| 581 | builtin.Os.netbsd, | |
| 572 | 582 | => { |
| 573 | 583 | self.os_data.have_fd = false; |
| 574 | 584 | }, |
| ... | ... | @@ -584,6 +594,7 @@ pub const CloseOperation = struct { |
| 584 | 594 | builtin.Os.linux, |
| 585 | 595 | builtin.Os.macosx, |
| 586 | 596 | builtin.Os.freebsd, |
| 597 | builtin.Os.netbsd, | |
| 587 | 598 | => { |
| 588 | 599 | assert(self.os_data.have_fd); |
| 589 | 600 | return self.os_data.close_req_node.data.msg.Close.fd; |
| ... | ... | @@ -608,6 +619,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, |
| 608 | 619 | builtin.Os.linux, |
| 609 | 620 | builtin.Os.macosx, |
| 610 | 621 | builtin.Os.freebsd, |
| 622 | builtin.Os.netbsd, | |
| 611 | 623 | => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable), |
| 612 | 624 | builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable), |
| 613 | 625 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -713,7 +725,7 @@ pub fn Watch(comptime V: type) type { |
| 713 | 725 | os_data: OsData, |
| 714 | 726 | |
| 715 | 727 | const OsData = switch (builtin.os) { |
| 716 | builtin.Os.macosx, builtin.Os.freebsd => struct { | |
| 728 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => struct { | |
| 717 | 729 | file_table: FileTable, |
| 718 | 730 | table_lock: event.Lock, |
| 719 | 731 | |
| ... | ... | @@ -802,7 +814,7 @@ pub fn Watch(comptime V: type) type { |
| 802 | 814 | return self; |
| 803 | 815 | }, |
| 804 | 816 | |
| 805 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 817 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 806 | 818 | const self = try loop.allocator.create(Self); |
| 807 | 819 | errdefer loop.allocator.destroy(self); |
| 808 | 820 | |
| ... | ... | @@ -822,7 +834,7 @@ pub fn Watch(comptime V: type) type { |
| 822 | 834 | /// All addFile calls and removeFile calls must have completed. |
| 823 | 835 | pub fn destroy(self: *Self) void { |
| 824 | 836 | switch (builtin.os) { |
| 825 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 837 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 826 | 838 | // TODO we need to cancel the coroutines before destroying the lock |
| 827 | 839 | self.os_data.table_lock.deinit(); |
| 828 | 840 | var it = self.os_data.file_table.iterator(); |
| ... | ... | @@ -864,7 +876,10 @@ pub fn Watch(comptime V: type) type { |
| 864 | 876 | |
| 865 | 877 | pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V { |
| 866 | 878 | switch (builtin.os) { |
| 867 | builtin.Os.macosx, builtin.Os.freebsd => return await (async addFileKEvent(self, file_path, value) catch unreachable), | |
| 879 | builtin.Os.macosx, | |
| 880 | builtin.Os.freebsd, | |
| 881 | builtin.Os.netbsd | |
| 882 | => return await (async addFileKEvent(self, file_path, value) catch unreachable), | |
| 868 | 883 | builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable), |
| 869 | 884 | builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable), |
| 870 | 885 | else => @compileError("Unsupported OS"), |
std/event/loop.zig+11-10| ... | ... | @@ -50,7 +50,7 @@ pub const Loop = struct { |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | 52 | pub const EventFd = switch (builtin.os) { |
| 53 | builtin.Os.macosx, builtin.Os.freebsd => KEventFd, | |
| 53 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventFd, | |
| 54 | 54 | builtin.Os.linux => struct { |
| 55 | 55 | base: ResumeNode, |
| 56 | 56 | epoll_op: u32, |
| ... | ... | @@ -69,7 +69,7 @@ pub const Loop = struct { |
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | 71 | pub const Basic = switch (builtin.os) { |
| 72 | builtin.Os.macosx, builtin.Os.freebsd => KEventBasic, | |
| 72 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventBasic, | |
| 73 | 73 | builtin.Os.linux => struct { |
| 74 | 74 | base: ResumeNode, |
| 75 | 75 | }, |
| ... | ... | @@ -221,7 +221,7 @@ pub const Loop = struct { |
| 221 | 221 | self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun); |
| 222 | 222 | } |
| 223 | 223 | }, |
| 224 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 224 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 225 | 225 | self.os_data.kqfd = try os.bsdKQueue(); |
| 226 | 226 | errdefer os.close(self.os_data.kqfd); |
| 227 | 227 | |
| ... | ... | @@ -386,7 +386,7 @@ pub const Loop = struct { |
| 386 | 386 | os.close(self.os_data.epollfd); |
| 387 | 387 | self.allocator.free(self.eventfd_resume_nodes); |
| 388 | 388 | }, |
| 389 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 389 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 390 | 390 | os.close(self.os_data.kqfd); |
| 391 | 391 | os.close(self.os_data.fs_kqfd); |
| 392 | 392 | }, |
| ... | ... | @@ -501,7 +501,7 @@ pub const Loop = struct { |
| 501 | 501 | const eventfd_node = &resume_stack_node.data; |
| 502 | 502 | eventfd_node.base.handle = next_tick_node.data; |
| 503 | 503 | switch (builtin.os) { |
| 504 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 504 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 505 | 505 | const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent); |
| 506 | 506 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 507 | 507 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { |
| ... | ... | @@ -564,6 +564,7 @@ pub const Loop = struct { |
| 564 | 564 | builtin.Os.linux, |
| 565 | 565 | builtin.Os.macosx, |
| 566 | 566 | builtin.Os.freebsd, |
| 567 | builtin.Os.netbsd, | |
| 567 | 568 | => self.os_data.fs_thread.wait(), |
| 568 | 569 | else => {}, |
| 569 | 570 | } |
| ... | ... | @@ -628,7 +629,7 @@ pub const Loop = struct { |
| 628 | 629 | os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable; |
| 629 | 630 | return; |
| 630 | 631 | }, |
| 631 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 632 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 632 | 633 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 633 | 634 | const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent); |
| 634 | 635 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| ... | ... | @@ -686,7 +687,7 @@ pub const Loop = struct { |
| 686 | 687 | } |
| 687 | 688 | } |
| 688 | 689 | }, |
| 689 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 690 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 690 | 691 | var eventlist: [1]posix.Kevent = undefined; |
| 691 | 692 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 692 | 693 | const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; |
| ... | ... | @@ -749,7 +750,7 @@ pub const Loop = struct { |
| 749 | 750 | self.beginOneEvent(); // finished in posixFsRun after processing the msg |
| 750 | 751 | self.os_data.fs_queue.put(request_node); |
| 751 | 752 | switch (builtin.os) { |
| 752 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 753 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 753 | 754 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake); |
| 754 | 755 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 755 | 756 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; |
| ... | ... | @@ -819,7 +820,7 @@ pub const Loop = struct { |
| 819 | 820 | else => unreachable, |
| 820 | 821 | } |
| 821 | 822 | }, |
| 822 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 823 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 823 | 824 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait); |
| 824 | 825 | var out_kevs: [1]posix.Kevent = undefined; |
| 825 | 826 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; |
| ... | ... | @@ -831,7 +832,7 @@ pub const Loop = struct { |
| 831 | 832 | |
| 832 | 833 | const OsData = switch (builtin.os) { |
| 833 | 834 | builtin.Os.linux => LinuxOsData, |
| 834 | builtin.Os.macosx, builtin.Os.freebsd => KEventData, | |
| 835 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventData, | |
| 835 | 836 | builtin.Os.windows => struct { |
| 836 | 837 | io_port: windows.HANDLE, |
| 837 | 838 | extra_thread_count: usize, |
std/fmt/index.zig+11-2| ... | ... | @@ -236,6 +236,9 @@ pub fn formatType( |
| 236 | 236 | const casted_value = ([]const u8)(value); |
| 237 | 237 | return output(context, casted_value); |
| 238 | 238 | }, |
| 239 | builtin.TypeInfo.Pointer.Size.C => { | |
| 240 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); | |
| 241 | }, | |
| 239 | 242 | }, |
| 240 | 243 | builtin.TypeId.Array => |info| { |
| 241 | 244 | if (info.child == u8) { |
| ... | ... | @@ -828,7 +831,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned |
| 828 | 831 | return x; |
| 829 | 832 | } |
| 830 | 833 | |
| 831 | test "parseUnsigned" { | |
| 834 | test "fmt.parseUnsigned" { | |
| 832 | 835 | testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124); |
| 833 | 836 | testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535); |
| 834 | 837 | testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10)); |
| ... | ... | @@ -855,6 +858,12 @@ test "parseUnsigned" { |
| 855 | 858 | testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16)); |
| 856 | 859 | } |
| 857 | 860 | |
| 861 | pub const parseFloat = @import("parse_float.zig").parseFloat; | |
| 862 | ||
| 863 | test "fmt.parseFloat" { | |
| 864 | _ = @import("parse_float.zig"); | |
| 865 | } | |
| 866 | ||
| 858 | 867 | pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { |
| 859 | 868 | const value = switch (c) { |
| 860 | 869 | '0'...'9' => c - '0', |
| ... | ... | @@ -1109,7 +1118,7 @@ test "fmt.format" { |
| 1109 | 1118 | const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64); |
| 1110 | 1119 | testing.expect(mem.eql(u8, result, "f64: nan\n")); |
| 1111 | 1120 | } |
| 1112 | if (builtin.arch != builtin.Arch.armv8) { | |
| 1121 | if (builtin.arch != builtin.Arch.arm) { | |
| 1113 | 1122 | // negative nan is not defined by IEE 754, |
| 1114 | 1123 | // and ARM thus normalizes it to positive nan |
| 1115 | 1124 | var buf1: [32]u8 = undefined; |
std/fmt/parse_float.zig created+420| ... | ... | @@ -0,0 +1,420 @@ |
| 1 | // Adapted from https://github.com/grzegorz-kraszewski/stringtofloat. | |
| 2 | ||
| 3 | // MIT License | |
| 4 | // | |
| 5 | // Copyright (c) 2016 Grzegorz Kraszewski | |
| 6 | // | |
| 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 8 | // of this software and associated documentation files (the "Software"), to deal | |
| 9 | // in the Software without restriction, including without limitation the rights | |
| 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 11 | // copies of the Software, and to permit persons to whom the Software is | |
| 12 | // furnished to do so, subject to the following conditions: | |
| 13 | // | |
| 14 | // The above copyright notice and this permission notice shall be included in all | |
| 15 | // copies or substantial portions of the Software. | |
| 16 | // | |
| 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 23 | // SOFTWARE. | |
| 24 | // | |
| 25 | ||
| 26 | // Be aware that this implementation has the following limitations: | |
| 27 | // | |
| 28 | // - Is not round-trip accurate for all values | |
| 29 | // - Only supports round-to-zero | |
| 30 | // - Does not handle denormals | |
| 31 | ||
| 32 | const std = @import("../index.zig"); | |
| 33 | ||
| 34 | const max_digits = 25; | |
| 35 | ||
| 36 | const f64_plus_zero: u64 = 0x0000000000000000; | |
| 37 | const f64_minus_zero: u64 = 0x8000000000000000; | |
| 38 | const f64_plus_infinity: u64 = 0x7FF0000000000000; | |
| 39 | const f64_minus_infinity: u64 = 0xFFF0000000000000; | |
| 40 | ||
| 41 | const Z96 = struct { | |
| 42 | d0: u32, | |
| 43 | d1: u32, | |
| 44 | d2: u32, | |
| 45 | ||
| 46 | // d = s >> 1 | |
| 47 | inline fn shiftRight1(d: *Z96, s: Z96) void { | |
| 48 | d.d0 = (s.d0 >> 1) | ((s.d1 & 1) << 31); | |
| 49 | d.d1 = (s.d1 >> 1) | ((s.d2 & 1) << 31); | |
| 50 | d.d2 = s.d2 >> 1; | |
| 51 | } | |
| 52 | ||
| 53 | // d = s << 1 | |
| 54 | inline fn shiftLeft1(d: *Z96, s: Z96) void { | |
| 55 | d.d2 = (s.d2 << 1) | ((s.d1 & (1 << 31)) >> 31); | |
| 56 | d.d1 = (s.d1 << 1) | ((s.d0 & (1 << 31)) >> 31); | |
| 57 | d.d0 = s.d0 << 1; | |
| 58 | } | |
| 59 | ||
| 60 | // d += s | |
| 61 | inline fn add(d: *Z96, s: Z96) void { | |
| 62 | var w = u64(d.d0) + u64(s.d0); | |
| 63 | d.d0 = @truncate(u32, w); | |
| 64 | ||
| 65 | w >>= 32; | |
| 66 | w += u64(d.d1) + u64(s.d1); | |
| 67 | d.d1 = @truncate(u32, w); | |
| 68 | ||
| 69 | w >>= 32; | |
| 70 | w += u64(d.d2) + u64(s.d2); | |
| 71 | d.d2 = @truncate(u32, w); | |
| 72 | } | |
| 73 | ||
| 74 | // d -= s | |
| 75 | inline fn sub(d: *Z96, s: Z96) void { | |
| 76 | var w = u64(d.d0) -% u64(s.d0); | |
| 77 | d.d0 = @truncate(u32, w); | |
| 78 | ||
| 79 | w >>= 32; | |
| 80 | w += u64(d.d1) -% u64(s.d1); | |
| 81 | d.d1 = @truncate(u32, w); | |
| 82 | ||
| 83 | w >>= 32; | |
| 84 | w += u64(d.d2) -% u64(s.d2); | |
| 85 | d.d2 = @truncate(u32, w); | |
| 86 | } | |
| 87 | }; | |
| 88 | ||
| 89 | const FloatRepr = struct { | |
| 90 | negative: bool, | |
| 91 | exponent: i32, | |
| 92 | mantissa: u64, | |
| 93 | }; | |
| 94 | ||
| 95 | fn convertRepr(comptime T: type, n: FloatRepr) T { | |
| 96 | const mask28: u32 = 0xf << 28; | |
| 97 | ||
| 98 | var s: Z96 = undefined; | |
| 99 | var q: Z96 = undefined; | |
| 100 | var r: Z96 = undefined; | |
| 101 | ||
| 102 | s.d0 = @truncate(u32, n.mantissa); | |
| 103 | s.d1 = @truncate(u32, n.mantissa >> 32); | |
| 104 | s.d2 = 0; | |
| 105 | ||
| 106 | var binary_exponent: u64 = 92; | |
| 107 | var exp = n.exponent; | |
| 108 | ||
| 109 | while (exp > 0) : (exp -= 1) { | |
| 110 | q.shiftLeft1(s); // q = p << 1 | |
| 111 | r.shiftLeft1(q); // r = p << 2 | |
| 112 | s.shiftLeft1(r); // p = p << 3 | |
| 113 | q.add(s); // p = (p << 3) + (p << 1) | |
| 114 | ||
| 115 | exp -= 1; | |
| 116 | ||
| 117 | while (s.d2 & mask28 != 0) { | |
| 118 | q.shiftRight1(s); | |
| 119 | binary_exponent += 1; | |
| 120 | s = q; | |
| 121 | } | |
| 122 | } | |
| 123 | ||
| 124 | while (exp < 0) { | |
| 125 | while (s.d2 & (1 << 31) == 0) { | |
| 126 | q.shiftLeft1(s); | |
| 127 | binary_exponent -= 1; | |
| 128 | s = q; | |
| 129 | } | |
| 130 | ||
| 131 | q.d2 = s.d2 / 10; | |
| 132 | r.d1 = s.d2 % 10; | |
| 133 | r.d2 = (s.d1 >> 8) | (r.d1 << 24); | |
| 134 | q.d1 = r.d2 / 10; | |
| 135 | r.d1 = r.d2 % 10; | |
| 136 | r.d2 = ((s.d1 & 0xff) << 16) | (s.d0 >> 16) | (r.d1 << 24); | |
| 137 | r.d0 = r.d2 / 10; | |
| 138 | r.d1 = r.d2 % 10; | |
| 139 | q.d1 = (q.d1 << 8) | ((r.d0 & 0x00ff0000) >> 16); | |
| 140 | q.d0 = r.d0 << 16; | |
| 141 | r.d2 = (s.d0 *% 0xffff) | (r.d1 << 16); | |
| 142 | q.d0 |= r.d2 / 10; | |
| 143 | s = q; | |
| 144 | ||
| 145 | exp += 1; | |
| 146 | } | |
| 147 | ||
| 148 | if (s.d0 != 0 or s.d1 != 0 or s.d2 != 0) { | |
| 149 | while (s.d2 & mask28 == 0) { | |
| 150 | q.shiftLeft1(s); | |
| 151 | binary_exponent -= 1; | |
| 152 | s = q; | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 156 | binary_exponent += 1023; | |
| 157 | ||
| 158 | const repr: u64 = blk: { | |
| 159 | if (binary_exponent > 2046) { | |
| 160 | break :blk if (n.negative) f64_minus_infinity else f64_plus_infinity; | |
| 161 | } else if (binary_exponent < 1) { | |
| 162 | break :blk if (n.negative) f64_minus_zero else f64_plus_zero; | |
| 163 | } else if (s.d2 != 0) { | |
| 164 | const binexs2 = u64(binary_exponent) << 52; | |
| 165 | const rr = (u64(s.d2 & ~mask28) << 24) | ((u64(s.d1) + 128) >> 8) | binexs2; | |
| 166 | break :blk if (n.negative) rr | (1 << 63) else rr; | |
| 167 | } else { | |
| 168 | break :blk 0; | |
| 169 | } | |
| 170 | }; | |
| 171 | ||
| 172 | const f = @bitCast(f64, repr); | |
| 173 | return @floatCast(T, f); | |
| 174 | } | |
| 175 | ||
| 176 | const State = enum { | |
| 177 | MaybeSign, | |
| 178 | LeadingMantissaZeros, | |
| 179 | LeadingFractionalZeros, | |
| 180 | MantissaIntegral, | |
| 181 | MantissaFractional, | |
| 182 | ExponentSign, | |
| 183 | LeadingExponentZeros, | |
| 184 | Exponent, | |
| 185 | }; | |
| 186 | ||
| 187 | const ParseResult = enum { | |
| 188 | Ok, | |
| 189 | PlusZero, | |
| 190 | MinusZero, | |
| 191 | PlusInf, | |
| 192 | MinusInf, | |
| 193 | }; | |
| 194 | ||
| 195 | inline fn isDigit(c: u8) bool { | |
| 196 | return c >= '0' and c <= '9'; | |
| 197 | } | |
| 198 | ||
| 199 | inline fn isSpace(c: u8) bool { | |
| 200 | return (c >= 0x09 and c <= 0x13) or c == 0x20; | |
| 201 | } | |
| 202 | ||
| 203 | fn parseRepr(s: []const u8, n: *FloatRepr) !ParseResult { | |
| 204 | var digit_index: usize = 0; | |
| 205 | var negative = false; | |
| 206 | var negative_exp = false; | |
| 207 | var exponent: i32 = 0; | |
| 208 | ||
| 209 | var state = State.MaybeSign; | |
| 210 | ||
| 211 | var i: usize = 0; | |
| 212 | loop: while (i < s.len) { | |
| 213 | const c = s[i]; | |
| 214 | ||
| 215 | switch (state) { | |
| 216 | State.MaybeSign => { | |
| 217 | state = State.LeadingMantissaZeros; | |
| 218 | ||
| 219 | if (c == '+') { | |
| 220 | i += 1; | |
| 221 | } else if (c == '-') { | |
| 222 | n.negative = true; | |
| 223 | i += 1; | |
| 224 | } else if (isDigit(c) or c == '.') { | |
| 225 | // continue | |
| 226 | } else { | |
| 227 | return error.InvalidCharacter; | |
| 228 | } | |
| 229 | }, | |
| 230 | ||
| 231 | State.LeadingMantissaZeros => { | |
| 232 | if (c == '0') { | |
| 233 | i += 1; | |
| 234 | } else if (c == '.') { | |
| 235 | i += 1; | |
| 236 | state = State.LeadingFractionalZeros; | |
| 237 | } else { | |
| 238 | state = State.MantissaIntegral; | |
| 239 | } | |
| 240 | }, | |
| 241 | ||
| 242 | State.LeadingFractionalZeros => { | |
| 243 | if (c == '0') { | |
| 244 | i += 1; | |
| 245 | if (n.exponent > std.math.minInt(i32)) { | |
| 246 | n.exponent -= 1; | |
| 247 | } | |
| 248 | } else { | |
| 249 | state = State.MantissaFractional; | |
| 250 | } | |
| 251 | }, | |
| 252 | ||
| 253 | State.MantissaIntegral => { | |
| 254 | if (isDigit(c)) { | |
| 255 | if (digit_index < max_digits) { | |
| 256 | n.mantissa *%= 10; | |
| 257 | n.mantissa += s[i] - '0'; | |
| 258 | digit_index += 1; | |
| 259 | } else if (n.exponent < std.math.maxInt(i32)) { | |
| 260 | n.exponent += 1; | |
| 261 | } | |
| 262 | ||
| 263 | i += 1; | |
| 264 | } else if (c == '.') { | |
| 265 | i += 1; | |
| 266 | state = State.MantissaFractional; | |
| 267 | } else { | |
| 268 | state = State.MantissaFractional; | |
| 269 | } | |
| 270 | }, | |
| 271 | ||
| 272 | State.MantissaFractional => { | |
| 273 | if (isDigit(c)) { | |
| 274 | if (digit_index < max_digits) { | |
| 275 | n.mantissa *%= 10; | |
| 276 | n.mantissa += c - '0'; | |
| 277 | n.exponent -%= 1; | |
| 278 | digit_index += 1; | |
| 279 | } | |
| 280 | ||
| 281 | i += 1; | |
| 282 | } else if (c == 'e' or c == 'E') { | |
| 283 | i += 1; | |
| 284 | state = State.ExponentSign; | |
| 285 | } else { | |
| 286 | state = State.ExponentSign; | |
| 287 | } | |
| 288 | }, | |
| 289 | ||
| 290 | State.ExponentSign => { | |
| 291 | if (c == '+') { | |
| 292 | i += 1; | |
| 293 | } else if (c == '-') { | |
| 294 | negative_exp = true; | |
| 295 | i += 1; | |
| 296 | } | |
| 297 | ||
| 298 | state = State.LeadingExponentZeros; | |
| 299 | }, | |
| 300 | ||
| 301 | State.LeadingExponentZeros => { | |
| 302 | if (c == '0') { | |
| 303 | i += 1; | |
| 304 | } else { | |
| 305 | state = State.Exponent; | |
| 306 | } | |
| 307 | }, | |
| 308 | ||
| 309 | State.Exponent => { | |
| 310 | if (isDigit(c)) { | |
| 311 | if (exponent < std.math.maxInt(i32)) { | |
| 312 | exponent *= 10; | |
| 313 | exponent += @intCast(i32, c - '0'); | |
| 314 | } | |
| 315 | ||
| 316 | i += 1; | |
| 317 | } else { | |
| 318 | return error.InvalidCharacter; | |
| 319 | } | |
| 320 | }, | |
| 321 | } | |
| 322 | } | |
| 323 | ||
| 324 | if (negative_exp) exponent = -exponent; | |
| 325 | n.exponent += exponent; | |
| 326 | ||
| 327 | if (n.mantissa == 0) { | |
| 328 | return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero; | |
| 329 | } else if (n.exponent > 309) { | |
| 330 | return if (n.negative) ParseResult.MinusInf else ParseResult.PlusInf; | |
| 331 | } else if (n.exponent < -328) { | |
| 332 | return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero; | |
| 333 | } | |
| 334 | ||
| 335 | return ParseResult.Ok; | |
| 336 | } | |
| 337 | ||
| 338 | inline fn isLower(c: u8) bool { | |
| 339 | return c -% 'a' < 26; | |
| 340 | } | |
| 341 | ||
| 342 | inline fn toUpper(c: u8) u8 { | |
| 343 | return if (isLower(c)) (c & 0x5f) else c; | |
| 344 | } | |
| 345 | ||
| 346 | fn caseInEql(a: []const u8, b: []const u8) bool { | |
| 347 | if (a.len != b.len) return false; | |
| 348 | ||
| 349 | for (a) |_, i| { | |
| 350 | if (toUpper(a[i]) != toUpper(b[i])) { | |
| 351 | return false; | |
| 352 | } | |
| 353 | } | |
| 354 | ||
| 355 | return true; | |
| 356 | } | |
| 357 | ||
| 358 | pub fn parseFloat(comptime T: type, s: []const u8) !T { | |
| 359 | if (s.len == 0) { | |
| 360 | return error.InvalidCharacter; | |
| 361 | } | |
| 362 | ||
| 363 | if (caseInEql(s, "nan")) { | |
| 364 | return std.math.nan(T); | |
| 365 | } else if (caseInEql(s, "inf") or caseInEql(s, "+inf")) { | |
| 366 | return std.math.inf(T); | |
| 367 | } else if (caseInEql(s, "-inf")) { | |
| 368 | return -std.math.inf(T); | |
| 369 | } | |
| 370 | ||
| 371 | var r = FloatRepr{ | |
| 372 | .negative = false, | |
| 373 | .exponent = 0, | |
| 374 | .mantissa = 0, | |
| 375 | }; | |
| 376 | ||
| 377 | return switch (try parseRepr(s, &r)) { | |
| 378 | ParseResult.Ok => convertRepr(T, r), | |
| 379 | ParseResult.PlusZero => 0.0, | |
| 380 | ParseResult.MinusZero => -T(0.0), | |
| 381 | ParseResult.PlusInf => std.math.inf(T), | |
| 382 | ParseResult.MinusInf => -std.math.inf(T), | |
| 383 | }; | |
| 384 | } | |
| 385 | ||
| 386 | test "fmt.parseFloat" { | |
| 387 | const testing = std.testing; | |
| 388 | const expect = testing.expect; | |
| 389 | const expectEqual = testing.expectEqual; | |
| 390 | const approxEq = std.math.approxEq; | |
| 391 | const epsilon = 1e-7; | |
| 392 | ||
| 393 | inline for ([]type{ f16, f32, f64, f128 }) |T| { | |
| 394 | const Z = @IntType(false, T.bit_count); | |
| 395 | ||
| 396 | testing.expectError(error.InvalidCharacter, parseFloat(T, "")); | |
| 397 | testing.expectError(error.InvalidCharacter, parseFloat(T, " 1")); | |
| 398 | testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc")); | |
| 399 | ||
| 400 | expectEqual(try parseFloat(T, "0"), 0.0); | |
| 401 | expectEqual((try parseFloat(T, "0")), 0.0); | |
| 402 | expectEqual((try parseFloat(T, "+0")), 0.0); | |
| 403 | expectEqual((try parseFloat(T, "-0")), 0.0); | |
| 404 | ||
| 405 | expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon)); | |
| 406 | expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon)); | |
| 407 | ||
| 408 | expectEqual((try parseFloat(T, "1e-700")), 0); | |
| 409 | expectEqual((try parseFloat(T, "1e+700")), std.math.inf(T)); | |
| 410 | ||
| 411 | expectEqual(@bitCast(Z, try parseFloat(T, "nAn")), @bitCast(Z, std.math.nan(T))); | |
| 412 | expectEqual((try parseFloat(T, "inF")), std.math.inf(T)); | |
| 413 | expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T)); | |
| 414 | ||
| 415 | if (T != f16) { | |
| 416 | expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon)); | |
| 417 | expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon)); | |
| 418 | } | |
| 419 | } | |
| 420 | } |
std/hash_map.zig+2| ... | ... | @@ -496,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type |
| 496 | 496 | builtin.TypeId.Pointer => |info| switch (info.size) { |
| 497 | 497 | builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"), |
| 498 | 498 | builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"), |
| 499 | builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto hash C pointers"), | |
| 499 | 500 | builtin.TypeInfo.Pointer.Size.Slice => { |
| 500 | 501 | const interval = std.math.max(1, key.len / 256); |
| 501 | 502 | var i: usize = 0; |
| ... | ... | @@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { |
| 543 | 544 | builtin.TypeId.Pointer => |info| switch (info.size) { |
| 544 | 545 | builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"), |
| 545 | 546 | builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"), |
| 547 | builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto eql for C pointers"), | |
| 546 | 548 | builtin.TypeInfo.Pointer.Size.Slice => { |
| 547 | 549 | if (a.len != b.len) return false; |
| 548 | 550 | for (a) |a_item, i| { |
std/heap.zig+3-3| ... | ... | @@ -71,7 +71,7 @@ pub const DirectAllocator = struct { |
| 71 | 71 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 72 | 72 | |
| 73 | 73 | switch (builtin.os) { |
| 74 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 74 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 75 | 75 | const p = os.posix; |
| 76 | 76 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; |
| 77 | 77 | const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0); |
| ... | ... | @@ -120,7 +120,7 @@ pub const DirectAllocator = struct { |
| 120 | 120 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 121 | 121 | |
| 122 | 122 | switch (builtin.os) { |
| 123 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 123 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 124 | 124 | if (new_size <= old_mem.len) { |
| 125 | 125 | const base_addr = @ptrToInt(old_mem.ptr); |
| 126 | 126 | const old_addr_end = base_addr + old_mem.len; |
| ... | ... | @@ -164,7 +164,7 @@ pub const DirectAllocator = struct { |
| 164 | 164 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 165 | 165 | |
| 166 | 166 | switch (builtin.os) { |
| 167 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 167 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 168 | 168 | _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len); |
| 169 | 169 | }, |
| 170 | 170 | Os.windows => { |
std/index.zig+3-1| ... | ... | @@ -9,6 +9,7 @@ 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 PriorityQueue = @import("priority_queue.zig").PriorityQueue; | |
| 12 | 13 | pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex; |
| 13 | 14 | pub const SegmentedList = @import("segmented_list.zig").SegmentedList; |
| 14 | 15 | pub const SpinLock = @import("spinlock.zig").SpinLock; |
| ... | ... | @@ -59,7 +60,7 @@ test "std" { |
| 59 | 60 | _ = @import("statically_initialized_mutex.zig"); |
| 60 | 61 | _ = @import("segmented_list.zig"); |
| 61 | 62 | _ = @import("spinlock.zig"); |
| 62 | ||
| 63 | ||
| 63 | 64 | _ = @import("base64.zig"); |
| 64 | 65 | _ = @import("build.zig"); |
| 65 | 66 | _ = @import("c/index.zig"); |
| ... | ... | @@ -85,6 +86,7 @@ test "std" { |
| 85 | 86 | _ = @import("net.zig"); |
| 86 | 87 | _ = @import("os/index.zig"); |
| 87 | 88 | _ = @import("pdb.zig"); |
| 89 | _ = @import("priority_queue.zig"); | |
| 88 | 90 | _ = @import("rand/index.zig"); |
| 89 | 91 | _ = @import("sort.zig"); |
| 90 | 92 | _ = @import("testing.zig"); |
std/io.zig+61-22| ... | ... | @@ -343,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) |
| 343 | 343 | const amt_buffered = self.end_index - self.start_index; |
| 344 | 344 | if (amt_buffered == 0) { |
| 345 | 345 | assert(self.end_index <= buffer_size); |
| 346 | if (self.end_index == buffer_size) { | |
| 347 | // we can read more data from the unbuffered stream | |
| 348 | if (dest_space < buffer_size) { | |
| 349 | self.start_index = 0; | |
| 350 | self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]); | |
| 351 | } else { | |
| 352 | // asking for so much data that buffering is actually less efficient. | |
| 353 | // forward the request directly to the unbuffered stream | |
| 354 | const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]); | |
| 355 | return dest_index + amt_read; | |
| 356 | } | |
| 357 | } else { | |
| 358 | // reading from the unbuffered stream returned less than we asked for | |
| 359 | // so we cannot read any more data. | |
| 346 | // Make sure the last read actually gave us some data | |
| 347 | if (self.end_index == 0) { | |
| 348 | // reading from the unbuffered stream returned nothing | |
| 349 | // so we have nothing left to read. | |
| 360 | 350 | return dest_index; |
| 361 | 351 | } |
| 352 | // we can read more data from the unbuffered stream | |
| 353 | if (dest_space < buffer_size) { | |
| 354 | self.start_index = 0; | |
| 355 | self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]); | |
| 356 | } else { | |
| 357 | // asking for so much data that buffering is actually less efficient. | |
| 358 | // forward the request directly to the unbuffered stream | |
| 359 | const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]); | |
| 360 | return dest_index + amt_read; | |
| 361 | } | |
| 362 | 362 | } |
| 363 | ||
| 363 | 364 | const copy_amount = math.min(dest_space, amt_buffered); |
| 364 | 365 | const copy_end_index = self.start_index + copy_amount; |
| 365 | 366 | mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]); |
| ... | ... | @@ -370,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) |
| 370 | 371 | }; |
| 371 | 372 | } |
| 372 | 373 | |
| 374 | test "io.BufferedInStream" { | |
| 375 | const OneByteReadInStream = struct { | |
| 376 | const Error = error{NoError}; | |
| 377 | const Stream = InStream(Error); | |
| 378 | ||
| 379 | stream: Stream, | |
| 380 | str: []const u8, | |
| 381 | curr: usize, | |
| 382 | ||
| 383 | fn init(str: []const u8) @This() { | |
| 384 | return @This(){ | |
| 385 | .stream = Stream{ .readFn = readFn }, | |
| 386 | .str = str, | |
| 387 | .curr = 0, | |
| 388 | }; | |
| 389 | } | |
| 390 | ||
| 391 | fn readFn(in_stream: *Stream, dest: []u8) Error!usize { | |
| 392 | const self = @fieldParentPtr(@This(), "stream", in_stream); | |
| 393 | if (self.str.len <= self.curr or dest.len == 0) | |
| 394 | return 0; | |
| 395 | ||
| 396 | dest[0] = self.str[self.curr]; | |
| 397 | self.curr += 1; | |
| 398 | return 1; | |
| 399 | } | |
| 400 | }; | |
| 401 | ||
| 402 | var buf: [100]u8 = undefined; | |
| 403 | const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; | |
| 404 | ||
| 405 | const str = "This is a test"; | |
| 406 | var one_byte_stream = OneByteReadInStream.init(str); | |
| 407 | var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream); | |
| 408 | const stream = &buf_in_stream.stream; | |
| 409 | ||
| 410 | const res = try stream.readAllAlloc(allocator, str.len + 1); | |
| 411 | testing.expectEqualSlices(u8, str, res); | |
| 412 | } | |
| 413 | ||
| 373 | 414 | /// Creates a stream which supports 'un-reading' data, so that it can be read again. |
| 374 | 415 | /// This makes look-ahead style parsing much easier. |
| 375 | 416 | pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type { |
| ... | ... | @@ -935,8 +976,6 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type { |
| 935 | 976 | }; |
| 936 | 977 | } |
| 937 | 978 | |
| 938 | ||
| 939 | ||
| 940 | 979 | pub const BufferedAtomicFile = struct { |
| 941 | 980 | atomic_file: os.AtomicFile, |
| 942 | 981 | file_stream: os.File.OutStream, |
| ... | ... | @@ -978,7 +1017,6 @@ pub const BufferedAtomicFile = struct { |
| 978 | 1017 | } |
| 979 | 1018 | }; |
| 980 | 1019 | |
| 981 | ||
| 982 | 1020 | pub fn readLine(buf: *std.Buffer) ![]u8 { |
| 983 | 1021 | var stdin = try getStdIn(); |
| 984 | 1022 | var stdin_stream = stdin.inStream(); |
| ... | ... | @@ -1073,13 +1111,13 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E |
| 1073 | 1111 | else => in_stream, |
| 1074 | 1112 | } }; |
| 1075 | 1113 | } |
| 1076 | ||
| 1114 | ||
| 1077 | 1115 | pub fn alignToByte(self: *Self) void { |
| 1078 | if(!is_packed) return; | |
| 1116 | if (!is_packed) return; | |
| 1079 | 1117 | self.in_stream.alignToByte(); |
| 1080 | 1118 | } |
| 1081 | 1119 | |
| 1082 | //@BUG: inferred error issue. See: #1386 | |
| 1120 | //@BUG: inferred error issue. See: #1386 | |
| 1083 | 1121 | fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T { |
| 1084 | 1122 | comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T)); |
| 1085 | 1123 | |
| ... | ... | @@ -1088,7 +1126,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E |
| 1088 | 1126 | |
| 1089 | 1127 | const U = @IntType(false, t_bit_count); |
| 1090 | 1128 | const Log2U = math.Log2Int(U); |
| 1091 | const int_size = @sizeOf(U); | |
| 1129 | const int_size = (U.bit_count + 7) / 8; | |
| 1092 | 1130 | |
| 1093 | 1131 | if (is_packed) { |
| 1094 | 1132 | const result = try self.in_stream.readBitsNoEof(U, t_bit_count); |
| ... | ... | @@ -1301,7 +1339,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, com |
| 1301 | 1339 | |
| 1302 | 1340 | const U = @IntType(false, t_bit_count); |
| 1303 | 1341 | const Log2U = math.Log2Int(U); |
| 1304 | const int_size = @sizeOf(U); | |
| 1342 | const int_size = (U.bit_count + 7) / 8; | |
| 1305 | 1343 | |
| 1306 | 1344 | const u_value = @bitCast(U, value); |
| 1307 | 1345 | |
| ... | ... | @@ -1414,3 +1452,4 @@ test "import io tests" { |
| 1414 | 1452 | _ = @import("io_test.zig"); |
| 1415 | 1453 | } |
| 1416 | 1454 | } |
| 1455 |
std/io_test.zig+11| ... | ... | @@ -29,6 +29,17 @@ test "write a file, read it, then delete it" { |
| 29 | 29 | try st.print("end"); |
| 30 | 30 | try buf_stream.flush(); |
| 31 | 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 | } | |
| 38 | else |err| { | |
| 39 | std.debug.assert(err == os.File.OpenError.PathAlreadyExists); | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 32 | 43 | { |
| 33 | 44 | var file = try os.File.openRead(tmp_file_name); |
| 34 | 45 | defer file.close(); |
std/json.zig+6-2| ... | ... | @@ -1345,7 +1345,7 @@ pub const Parser = struct { |
| 1345 | 1345 | return if (token.number_is_integer) |
| 1346 | 1346 | Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } |
| 1347 | 1347 | else |
| 1348 | @panic("TODO: fmt.parseFloat not yet implemented"); | |
| 1348 | Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) }; | |
| 1349 | 1349 | } |
| 1350 | 1350 | }; |
| 1351 | 1351 | |
| ... | ... | @@ -1366,7 +1366,8 @@ test "json.parser.dynamic" { |
| 1366 | 1366 | \\ }, |
| 1367 | 1367 | \\ "Animated" : false, |
| 1368 | 1368 | \\ "IDs": [116, 943, 234, 38793], |
| 1369 | \\ "ArrayOfObject": [{"n": "m"}] | |
| 1369 | \\ "ArrayOfObject": [{"n": "m"}], | |
| 1370 | \\ "double": 1.3412 | |
| 1370 | 1371 | \\ } |
| 1371 | 1372 | \\} |
| 1372 | 1373 | ; |
| ... | ... | @@ -1395,4 +1396,7 @@ test "json.parser.dynamic" { |
| 1395 | 1396 | |
| 1396 | 1397 | const obj0 = array_of_object.Array.at(0).Object.get("n").?.value; |
| 1397 | 1398 | testing.expect(mem.eql(u8, obj0.String, "m")); |
| 1399 | ||
| 1400 | const double = image.Object.get("double").?.value; | |
| 1401 | testing.expect(double.Float == 1.3412); | |
| 1398 | 1402 | } |
std/math/fabs.zig+19| ... | ... | @@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) { |
| 14 | 14 | f16 => fabs16(x), |
| 15 | 15 | f32 => fabs32(x), |
| 16 | 16 | f64 => fabs64(x), |
| 17 | f128 => fabs128(x), | |
| 17 | 18 | else => @compileError("fabs not implemented for " ++ @typeName(T)), |
| 18 | 19 | }; |
| 19 | 20 | } |
| ... | ... | @@ -36,10 +37,17 @@ fn fabs64(x: f64) f64 { |
| 36 | 37 | return @bitCast(f64, u); |
| 37 | 38 | } |
| 38 | 39 | |
| 40 | fn fabs128(x: f128) f128 { | |
| 41 | var u = @bitCast(u128, x); | |
| 42 | u &= maxInt(u128) >> 1; | |
| 43 | return @bitCast(f128, u); | |
| 44 | } | |
| 45 | ||
| 39 | 46 | test "math.fabs" { |
| 40 | 47 | expect(fabs(f16(1.0)) == fabs16(1.0)); |
| 41 | 48 | expect(fabs(f32(1.0)) == fabs32(1.0)); |
| 42 | 49 | expect(fabs(f64(1.0)) == fabs64(1.0)); |
| 50 | expect(fabs(f128(1.0)) == fabs128(1.0)); | |
| 43 | 51 | } |
| 44 | 52 | |
| 45 | 53 | test "math.fabs16" { |
| ... | ... | @@ -57,6 +65,11 @@ test "math.fabs64" { |
| 57 | 65 | expect(fabs64(-1.0) == 1.0); |
| 58 | 66 | } |
| 59 | 67 | |
| 68 | test "math.fabs128" { | |
| 69 | expect(fabs128(1.0) == 1.0); | |
| 70 | expect(fabs128(-1.0) == 1.0); | |
| 71 | } | |
| 72 | ||
| 60 | 73 | test "math.fabs16.special" { |
| 61 | 74 | expect(math.isPositiveInf(fabs(math.inf(f16)))); |
| 62 | 75 | expect(math.isPositiveInf(fabs(-math.inf(f16)))); |
| ... | ... | @@ -74,3 +87,9 @@ test "math.fabs64.special" { |
| 74 | 87 | expect(math.isPositiveInf(fabs(-math.inf(f64)))); |
| 75 | 88 | expect(math.isNan(fabs(math.nan(f64)))); |
| 76 | 89 | } |
| 90 | ||
| 91 | test "math.fabs128.special" { | |
| 92 | expect(math.isPositiveInf(fabs(math.inf(f128)))); | |
| 93 | expect(math.isPositiveInf(fabs(-math.inf(f128)))); | |
| 94 | expect(math.isNan(fabs(math.nan(f128)))); | |
| 95 | } |
std/math/index.zig+11-1| ... | ... | @@ -51,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64); |
| 51 | 51 | pub const inf_u64 = u64(0x7FF << 52); |
| 52 | 52 | pub const inf_f64 = @bitCast(f64, inf_u64); |
| 53 | 53 | |
| 54 | pub const nan_u128 = u128(0x7fff0000000000000000000000000001); | |
| 55 | pub const nan_f128 = @bitCast(f128, nan_u128); | |
| 56 | ||
| 57 | pub const inf_u128 = u128(0x7fff0000000000000000000000000000); | |
| 58 | pub const inf_f128 = @bitCast(f128, inf_u128); | |
| 59 | ||
| 54 | 60 | pub const nan = @import("nan.zig").nan; |
| 55 | 61 | pub const snan = @import("nan.zig").snan; |
| 56 | 62 | pub const inf = @import("inf.zig").inf; |
| ... | ... | @@ -379,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t |
| 379 | 385 | return u0; |
| 380 | 386 | } |
| 381 | 387 | const is_signed = from < 0; |
| 382 | const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement | |
| 388 | const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement | |
| 383 | 389 | const base = log2(largest_positive_integer); |
| 384 | 390 | const upper = (1 << base) - 1; |
| 385 | 391 | var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1; |
| ... | ... | @@ -752,6 +758,7 @@ test "minInt and maxInt" { |
| 752 | 758 | testing.expect(maxInt(u16) == 65535); |
| 753 | 759 | testing.expect(maxInt(u32) == 4294967295); |
| 754 | 760 | testing.expect(maxInt(u64) == 18446744073709551615); |
| 761 | testing.expect(maxInt(u128) == 340282366920938463463374607431768211455); | |
| 755 | 762 | |
| 756 | 763 | testing.expect(maxInt(i0) == 0); |
| 757 | 764 | testing.expect(maxInt(i1) == 0); |
| ... | ... | @@ -760,6 +767,7 @@ test "minInt and maxInt" { |
| 760 | 767 | testing.expect(maxInt(i32) == 2147483647); |
| 761 | 768 | testing.expect(maxInt(i63) == 4611686018427387903); |
| 762 | 769 | testing.expect(maxInt(i64) == 9223372036854775807); |
| 770 | testing.expect(maxInt(i128) == 170141183460469231731687303715884105727); | |
| 763 | 771 | |
| 764 | 772 | testing.expect(minInt(u0) == 0); |
| 765 | 773 | testing.expect(minInt(u1) == 0); |
| ... | ... | @@ -768,6 +776,7 @@ test "minInt and maxInt" { |
| 768 | 776 | testing.expect(minInt(u32) == 0); |
| 769 | 777 | testing.expect(minInt(u63) == 0); |
| 770 | 778 | testing.expect(minInt(u64) == 0); |
| 779 | testing.expect(minInt(u128) == 0); | |
| 771 | 780 | |
| 772 | 781 | testing.expect(minInt(i0) == 0); |
| 773 | 782 | testing.expect(minInt(i1) == -1); |
| ... | ... | @@ -776,6 +785,7 @@ test "minInt and maxInt" { |
| 776 | 785 | testing.expect(minInt(i32) == -2147483648); |
| 777 | 786 | testing.expect(minInt(i63) == -4611686018427387904); |
| 778 | 787 | testing.expect(minInt(i64) == -9223372036854775808); |
| 788 | testing.expect(minInt(i128) == -170141183460469231731687303715884105728); | |
| 779 | 789 | } |
| 780 | 790 | |
| 781 | 791 | test "max value type" { |
std/math/inf.zig+4-3| ... | ... | @@ -3,9 +3,10 @@ const math = std.math; |
| 3 | 3 | |
| 4 | 4 | pub fn inf(comptime T: type) T { |
| 5 | 5 | return switch (T) { |
| 6 | f16 => @bitCast(f16, math.inf_u16), | |
| 7 | f32 => @bitCast(f32, math.inf_u32), | |
| 8 | f64 => @bitCast(f64, math.inf_u64), | |
| 6 | f16 => math.inf_f16, | |
| 7 | f32 => math.inf_f32, | |
| 8 | f64 => math.inf_f64, | |
| 9 | f128 => math.inf_f128, | |
| 9 | 10 | else => @compileError("inf not implemented for " ++ @typeName(T)), |
| 10 | 11 | }; |
| 11 | 12 | } |
std/math/isinf.zig+22| ... | ... | @@ -18,6 +18,10 @@ pub fn isInf(x: var) bool { |
| 18 | 18 | const bits = @bitCast(u64, x); |
| 19 | 19 | return bits & (maxInt(u64) >> 1) == (0x7FF << 52); |
| 20 | 20 | }, |
| 21 | f128 => { | |
| 22 | const bits = @bitCast(u128, x); | |
| 23 | return bits & (maxInt(u128) >> 1) == (0x7FFF << 112); | |
| 24 | }, | |
| 21 | 25 | else => { |
| 22 | 26 | @compileError("isInf not implemented for " ++ @typeName(T)); |
| 23 | 27 | }, |
| ... | ... | @@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool { |
| 36 | 40 | f64 => { |
| 37 | 41 | return @bitCast(u64, x) == 0x7FF << 52; |
| 38 | 42 | }, |
| 43 | f128 => { | |
| 44 | return @bitCast(u128, x) == 0x7FFF << 112; | |
| 45 | }, | |
| 39 | 46 | else => { |
| 40 | 47 | @compileError("isPositiveInf not implemented for " ++ @typeName(T)); |
| 41 | 48 | }, |
| ... | ... | @@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool { |
| 54 | 61 | f64 => { |
| 55 | 62 | return @bitCast(u64, x) == 0xFFF << 52; |
| 56 | 63 | }, |
| 64 | f128 => { | |
| 65 | return @bitCast(u128, x) == 0xFFFF << 112; | |
| 66 | }, | |
| 57 | 67 | else => { |
| 58 | 68 | @compileError("isNegativeInf not implemented for " ++ @typeName(T)); |
| 59 | 69 | }, |
| ... | ... | @@ -67,12 +77,16 @@ test "math.isInf" { |
| 67 | 77 | expect(!isInf(f32(-0.0))); |
| 68 | 78 | expect(!isInf(f64(0.0))); |
| 69 | 79 | expect(!isInf(f64(-0.0))); |
| 80 | expect(!isInf(f128(0.0))); | |
| 81 | expect(!isInf(f128(-0.0))); | |
| 70 | 82 | expect(isInf(math.inf(f16))); |
| 71 | 83 | expect(isInf(-math.inf(f16))); |
| 72 | 84 | expect(isInf(math.inf(f32))); |
| 73 | 85 | expect(isInf(-math.inf(f32))); |
| 74 | 86 | expect(isInf(math.inf(f64))); |
| 75 | 87 | expect(isInf(-math.inf(f64))); |
| 88 | expect(isInf(math.inf(f128))); | |
| 89 | expect(isInf(-math.inf(f128))); | |
| 76 | 90 | } |
| 77 | 91 | |
| 78 | 92 | test "math.isPositiveInf" { |
| ... | ... | @@ -82,12 +96,16 @@ test "math.isPositiveInf" { |
| 82 | 96 | expect(!isPositiveInf(f32(-0.0))); |
| 83 | 97 | expect(!isPositiveInf(f64(0.0))); |
| 84 | 98 | expect(!isPositiveInf(f64(-0.0))); |
| 99 | expect(!isPositiveInf(f128(0.0))); | |
| 100 | expect(!isPositiveInf(f128(-0.0))); | |
| 85 | 101 | expect(isPositiveInf(math.inf(f16))); |
| 86 | 102 | expect(!isPositiveInf(-math.inf(f16))); |
| 87 | 103 | expect(isPositiveInf(math.inf(f32))); |
| 88 | 104 | expect(!isPositiveInf(-math.inf(f32))); |
| 89 | 105 | expect(isPositiveInf(math.inf(f64))); |
| 90 | 106 | expect(!isPositiveInf(-math.inf(f64))); |
| 107 | expect(isPositiveInf(math.inf(f128))); | |
| 108 | expect(!isPositiveInf(-math.inf(f128))); | |
| 91 | 109 | } |
| 92 | 110 | |
| 93 | 111 | test "math.isNegativeInf" { |
| ... | ... | @@ -97,10 +115,14 @@ test "math.isNegativeInf" { |
| 97 | 115 | expect(!isNegativeInf(f32(-0.0))); |
| 98 | 116 | expect(!isNegativeInf(f64(0.0))); |
| 99 | 117 | expect(!isNegativeInf(f64(-0.0))); |
| 118 | expect(!isNegativeInf(f128(0.0))); | |
| 119 | expect(!isNegativeInf(f128(-0.0))); | |
| 100 | 120 | expect(!isNegativeInf(math.inf(f16))); |
| 101 | 121 | expect(isNegativeInf(-math.inf(f16))); |
| 102 | 122 | expect(!isNegativeInf(math.inf(f32))); |
| 103 | 123 | expect(isNegativeInf(-math.inf(f32))); |
| 104 | 124 | expect(!isNegativeInf(math.inf(f64))); |
| 105 | 125 | expect(isNegativeInf(-math.inf(f64))); |
| 126 | expect(!isNegativeInf(math.inf(f128))); | |
| 127 | expect(isNegativeInf(-math.inf(f128))); | |
| 106 | 128 | } |
std/math/isnan.zig+6| ... | ... | @@ -18,6 +18,10 @@ pub fn isNan(x: var) bool { |
| 18 | 18 | const bits = @bitCast(u64, x); |
| 19 | 19 | return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52); |
| 20 | 20 | }, |
| 21 | f128 => { | |
| 22 | const bits = @bitCast(u128, x); | |
| 23 | return (bits & (maxInt(u128) >> 1)) > (u128(0x7FFF) << 112); | |
| 24 | }, | |
| 21 | 25 | else => { |
| 22 | 26 | @compileError("isNan not implemented for " ++ @typeName(T)); |
| 23 | 27 | }, |
| ... | ... | @@ -34,7 +38,9 @@ test "math.isNan" { |
| 34 | 38 | expect(isNan(math.nan(f16))); |
| 35 | 39 | expect(isNan(math.nan(f32))); |
| 36 | 40 | expect(isNan(math.nan(f64))); |
| 41 | expect(isNan(math.nan(f128))); | |
| 37 | 42 | expect(!isNan(f16(1.0))); |
| 38 | 43 | expect(!isNan(f32(1.0))); |
| 39 | 44 | expect(!isNan(f64(1.0))); |
| 45 | expect(!isNan(f128(1.0))); | |
| 40 | 46 | } |
std/math/nan.zig+4-3| ... | ... | @@ -2,9 +2,10 @@ const math = @import("index.zig"); |
| 2 | 2 | |
| 3 | 3 | pub fn nan(comptime T: type) T { |
| 4 | 4 | return switch (T) { |
| 5 | f16 => @bitCast(f16, math.nan_u16), | |
| 6 | f32 => @bitCast(f32, math.nan_u32), | |
| 7 | f64 => @bitCast(f64, math.nan_u64), | |
| 5 | f16 => math.nan_f16, | |
| 6 | f32 => math.nan_f32, | |
| 7 | f64 => math.nan_f64, | |
| 8 | f128 => math.nan_f128, | |
| 8 | 9 | else => @compileError("nan not implemented for " ++ @typeName(T)), |
| 9 | 10 | }; |
| 10 | 11 | } |
std/math/powi.zig+8-1| ... | ... | @@ -25,7 +25,7 @@ pub fn powi(comptime T: type, x: T, y: T) (error{ |
| 25 | 25 | |
| 26 | 26 | // powi(x, +-0) = 1 for any x |
| 27 | 27 | if (y == 0 or y == -0) { |
| 28 | return 0; | |
| 28 | return 1; | |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | 31 | switch (x) { |
| ... | ... | @@ -174,4 +174,11 @@ test "math.powi.special" { |
| 174 | 174 | testing.expectError(error.Overflow, powi(u64, 2, 64)); |
| 175 | 175 | testing.expectError(error.Overflow, powi(u17, 2, 17)); |
| 176 | 176 | testing.expectError(error.Overflow, powi(u42, 2, 42)); |
| 177 | ||
| 178 | testing.expect((try powi(u8, 6, 0)) == 1); | |
| 179 | testing.expect((try powi(u16, 5, 0)) == 1); | |
| 180 | testing.expect((try powi(u32, 12, 0)) == 1); | |
| 181 | testing.expect((try powi(u64, 34, 0)) == 1); | |
| 182 | testing.expect((try powi(u17, 16, 0)) == 1); | |
| 183 | testing.expect((try powi(u42, 34, 0)) == 1); | |
| 177 | 184 | } |
std/mem.zig+20-29| ... | ... | @@ -423,8 +423,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin. |
| 423 | 423 | /// This function cannot fail and cannot cause undefined behavior. |
| 424 | 424 | /// Assumes the endianness of memory is native. This means the function can |
| 425 | 425 | /// simply pointer cast memory. |
| 426 | pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { | |
| 427 | comptime assert(T.bit_count % 8 == 0); | |
| 426 | pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T { | |
| 428 | 427 | return @ptrCast(*align(1) const T, bytes).*; |
| 429 | 428 | } |
| 430 | 429 | |
| ... | ... | @@ -432,7 +431,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { |
| 432 | 431 | /// The bit count of T must be evenly divisible by 8. |
| 433 | 432 | /// This function cannot fail and cannot cause undefined behavior. |
| 434 | 433 | /// Assumes the endianness of memory is foreign, so it must byte-swap. |
| 435 | pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { | |
| 434 | pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T { | |
| 436 | 435 | return @bswap(T, readIntNative(T, bytes)); |
| 437 | 436 | } |
| 438 | 437 | |
| ... | ... | @@ -446,22 +445,20 @@ pub const readIntBig = switch (builtin.endian) { |
| 446 | 445 | builtin.Endian.Big => readIntNative, |
| 447 | 446 | }; |
| 448 | 447 | |
| 449 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 | |
| 448 | /// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0 | |
| 450 | 449 | /// and ignores extra bytes. |
| 451 | /// Note that @sizeOf(u24) is 3. | |
| 452 | 450 | /// The bit count of T must be evenly divisible by 8. |
| 453 | 451 | /// Assumes the endianness of memory is native. This means the function can |
| 454 | 452 | /// simply pointer cast memory. |
| 455 | 453 | pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T { |
| 456 | assert(@sizeOf(u24) == 3); | |
| 457 | assert(bytes.len >= @sizeOf(T)); | |
| 454 | const n = @divExact(T.bit_count, 8); | |
| 455 | assert(bytes.len >= n); | |
| 458 | 456 | // TODO https://github.com/ziglang/zig/issues/863 |
| 459 | return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr)); | |
| 457 | return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr)); | |
| 460 | 458 | } |
| 461 | 459 | |
| 462 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 | |
| 460 | /// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0 | |
| 463 | 461 | /// and ignores extra bytes. |
| 464 | /// Note that @sizeOf(u24) is 3. | |
| 465 | 462 | /// The bit count of T must be evenly divisible by 8. |
| 466 | 463 | /// Assumes the endianness of memory is foreign, so it must byte-swap. |
| 467 | 464 | pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T { |
| ... | ... | @@ -481,7 +478,7 @@ pub const readIntSliceBig = switch (builtin.endian) { |
| 481 | 478 | /// Reads an integer from memory with bit count specified by T. |
| 482 | 479 | /// The bit count of T must be evenly divisible by 8. |
| 483 | 480 | /// This function cannot fail and cannot cause undefined behavior. |
| 484 | pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T { | |
| 481 | pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T { | |
| 485 | 482 | if (endian == builtin.endian) { |
| 486 | 483 | return readIntNative(T, bytes); |
| 487 | 484 | } else { |
| ... | ... | @@ -489,15 +486,14 @@ pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.E |
| 489 | 486 | } |
| 490 | 487 | } |
| 491 | 488 | |
| 492 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 | |
| 489 | /// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0 | |
| 493 | 490 | /// and ignores extra bytes. |
| 494 | /// Note that @sizeOf(u24) is 3. | |
| 495 | 491 | /// The bit count of T must be evenly divisible by 8. |
| 496 | 492 | pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T { |
| 497 | assert(@sizeOf(u24) == 3); | |
| 498 | assert(bytes.len >= @sizeOf(T)); | |
| 493 | const n = @divExact(T.bit_count, 8); | |
| 494 | assert(bytes.len >= n); | |
| 499 | 495 | // TODO https://github.com/ziglang/zig/issues/863 |
| 500 | return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian); | |
| 496 | return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian); | |
| 501 | 497 | } |
| 502 | 498 | |
| 503 | 499 | test "comptime read/write int" { |
| ... | ... | @@ -540,7 +536,7 @@ test "readIntBig and readIntLittle" { |
| 540 | 536 | /// accepts any integer bit width. |
| 541 | 537 | /// This function stores in native endian, which means it is implemented as a simple |
| 542 | 538 | /// memory store. |
| 543 | pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | |
| 539 | pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void { | |
| 544 | 540 | @ptrCast(*align(1) T, buf).* = value; |
| 545 | 541 | } |
| 546 | 542 | |
| ... | ... | @@ -548,7 +544,7 @@ pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { |
| 548 | 544 | /// This function always succeeds, has defined behavior for all inputs, but |
| 549 | 545 | /// the integer bit width must be divisible by 8. |
| 550 | 546 | /// This function stores in foreign endian, which means it does a @bswap first. |
| 551 | pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | |
| 547 | pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void { | |
| 552 | 548 | writeIntNative(T, buf, @bswap(T, value)); |
| 553 | 549 | } |
| 554 | 550 | |
| ... | ... | @@ -565,8 +561,7 @@ pub const writeIntBig = switch (builtin.endian) { |
| 565 | 561 | /// Writes an integer to memory, storing it in twos-complement. |
| 566 | 562 | /// This function always succeeds, has defined behavior for all inputs, but |
| 567 | 563 | /// the integer bit width must be divisible by 8. |
| 568 | pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void { | |
| 569 | comptime assert(T.bit_count % 8 == 0); | |
| 564 | pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void { | |
| 570 | 565 | if (endian == builtin.endian) { |
| 571 | 566 | return writeIntNative(T, buffer, value); |
| 572 | 567 | } else { |
| ... | ... | @@ -575,15 +570,13 @@ pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: bui |
| 575 | 570 | } |
| 576 | 571 | |
| 577 | 572 | /// Writes a twos-complement little-endian integer to memory. |
| 578 | /// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. | |
| 573 | /// Asserts that buf.len >= T.bit_count / 8. | |
| 579 | 574 | /// The bit count of T must be divisible by 8. |
| 580 | 575 | /// Any extra bytes in buffer after writing the integer are set to zero. To |
| 581 | 576 | /// avoid the branch to check for extra buffer bytes, use writeIntLittle |
| 582 | 577 | /// instead. |
| 583 | 578 | pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { |
| 584 | comptime assert(@sizeOf(u24) == 3); | |
| 585 | comptime assert(T.bit_count % 8 == 0); | |
| 586 | assert(buffer.len >= @sizeOf(T)); | |
| 579 | assert(buffer.len >= @divExact(T.bit_count, 8)); | |
| 587 | 580 | |
| 588 | 581 | // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough |
| 589 | 582 | const uint = @IntType(false, T.bit_count); |
| ... | ... | @@ -595,14 +588,12 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { |
| 595 | 588 | } |
| 596 | 589 | |
| 597 | 590 | /// Writes a twos-complement big-endian integer to memory. |
| 598 | /// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. | |
| 591 | /// Asserts that buffer.len >= T.bit_count / 8. | |
| 599 | 592 | /// The bit count of T must be divisible by 8. |
| 600 | 593 | /// Any extra bytes in buffer before writing the integer are set to zero. To |
| 601 | 594 | /// avoid the branch to check for extra buffer bytes, use writeIntBig instead. |
| 602 | 595 | pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { |
| 603 | comptime assert(@sizeOf(u24) == 3); | |
| 604 | comptime assert(T.bit_count % 8 == 0); | |
| 605 | assert(buffer.len >= @sizeOf(T)); | |
| 596 | assert(buffer.len >= @divExact(T.bit_count, 8)); | |
| 606 | 597 | |
| 607 | 598 | // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough |
| 608 | 599 | const uint = @IntType(false, T.bit_count); |
| ... | ... | @@ -626,7 +617,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) { |
| 626 | 617 | }; |
| 627 | 618 | |
| 628 | 619 | /// Writes a twos-complement integer to memory, with the specified endianness. |
| 629 | /// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. | |
| 620 | /// Asserts that buf.len >= T.bit_count / 8. | |
| 630 | 621 | /// The bit count of T must be evenly divisible by 8. |
| 631 | 622 | /// Any extra bytes in buffer not part of the integer are set to zero, with |
| 632 | 623 | /// respect to endianness. To avoid the branch to check for extra buffer bytes, |
std/meta/index.zig+6-3| ... | ... | @@ -463,13 +463,16 @@ pub fn eql(a: var, b: @typeOf(a)) bool { |
| 463 | 463 | builtin.TypeId.Pointer => { |
| 464 | 464 | const info = @typeInfo(T).Pointer; |
| 465 | 465 | switch (info.size) { |
| 466 | builtin.TypeInfo.Pointer.Size.One, builtin.TypeInfo.Pointer.Size.Many => return a == b, | |
| 466 | builtin.TypeInfo.Pointer.Size.One, | |
| 467 | builtin.TypeInfo.Pointer.Size.Many, | |
| 468 | builtin.TypeInfo.Pointer.Size.C, | |
| 469 | => return a == b, | |
| 467 | 470 | builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len, |
| 468 | 471 | } |
| 469 | 472 | }, |
| 470 | 473 | builtin.TypeId.Optional => { |
| 471 | if(a == null and b == null) return true; | |
| 472 | if(a == null or b == null) return false; | |
| 474 | if (a == null and b == null) return true; | |
| 475 | if (a == null or b == null) return false; | |
| 473 | 476 | return eql(a.?, b.?); |
| 474 | 477 | }, |
| 475 | 478 | else => return a == b, |
std/os/darwin.zig+1-1| ... | ... | @@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize { |
| 665 | 665 | |
| 666 | 666 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { |
| 667 | 667 | const ptr_result = c.mmap( |
| 668 | @ptrCast(*c_void, address), | |
| 668 | @ptrCast(?*c_void, address), | |
| 669 | 669 | length, |
| 670 | 670 | @bitCast(c_int, @intCast(c_uint, prot)), |
| 671 | 671 | @bitCast(c_int, c_uint(flags)), |
std/os/file.zig+4-4| ... | ... | @@ -105,7 +105,7 @@ pub const File = struct { |
| 105 | 105 | pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File { |
| 106 | 106 | if (is_posix) { |
| 107 | 107 | const path_c = try os.toPosixPath(path); |
| 108 | return openWriteNoClobberC(path_c, file_mode); | |
| 108 | return openWriteNoClobberC(&path_c, file_mode); | |
| 109 | 109 | } else if (is_windows) { |
| 110 | 110 | const path_w = try windows_util.sliceToPrefixedFileW(path); |
| 111 | 111 | return openWriteNoClobberW(&path_w, file_mode); |
| ... | ... | @@ -237,7 +237,7 @@ pub const File = struct { |
| 237 | 237 | |
| 238 | 238 | pub fn seekForward(self: File, amount: isize) SeekError!void { |
| 239 | 239 | switch (builtin.os) { |
| 240 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 240 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 241 | 241 | const result = posix.lseek(self.handle, amount, posix.SEEK_CUR); |
| 242 | 242 | const err = posix.getErrno(result); |
| 243 | 243 | if (err > 0) { |
| ... | ... | @@ -268,7 +268,7 @@ pub const File = struct { |
| 268 | 268 | |
| 269 | 269 | pub fn seekTo(self: File, pos: usize) SeekError!void { |
| 270 | 270 | switch (builtin.os) { |
| 271 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 271 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 272 | 272 | const ipos = try math.cast(isize, pos); |
| 273 | 273 | const result = posix.lseek(self.handle, ipos, posix.SEEK_SET); |
| 274 | 274 | const err = posix.getErrno(result); |
| ... | ... | @@ -309,7 +309,7 @@ pub const File = struct { |
| 309 | 309 | |
| 310 | 310 | pub fn getPos(self: File) GetSeekPosError!usize { |
| 311 | 311 | switch (builtin.os) { |
| 312 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 312 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 313 | 313 | const result = posix.lseek(self.handle, 0, posix.SEEK_CUR); |
| 314 | 314 | const err = posix.getErrno(result); |
| 315 | 315 | if (err > 0) { |
std/os/freebsd/index.zig+1-1| ... | ... | @@ -617,7 +617,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize { |
| 617 | 617 | |
| 618 | 618 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { |
| 619 | 619 | const ptr_result = c.mmap( |
| 620 | @ptrCast(*c_void, address), | |
| 620 | @ptrCast(?*c_void, address), | |
| 621 | 621 | length, |
| 622 | 622 | @bitCast(c_int, @intCast(c_uint, prot)), |
| 623 | 623 | @bitCast(c_int, c_uint(flags)), |
std/os/get_app_data_dir.zig+1-1| ... | ... | @@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD |
| 43 | 43 | }; |
| 44 | 44 | return os.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname }); |
| 45 | 45 | }, |
| 46 | builtin.Os.linux, builtin.Os.freebsd => { | |
| 46 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 47 | 47 | const home_dir = os.getEnvPosix("HOME") orelse { |
| 48 | 48 | // TODO look in /etc/passwd |
| 49 | 49 | return error.AppDataDirUnavailable; |
std/os/get_user_id.zig+1-1| ... | ... | @@ -11,7 +11,7 @@ pub const UserInfo = struct { |
| 11 | 11 | /// POSIX function which gets a uid from username. |
| 12 | 12 | pub fn getUserInfo(name: []const u8) !UserInfo { |
| 13 | 13 | return switch (builtin.os) { |
| 14 | Os.linux, Os.macosx, Os.ios, Os.freebsd => posixGetUserInfo(name), | |
| 14 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => posixGetUserInfo(name), | |
| 15 | 15 | else => @compileError("Unsupported OS"), |
| 16 | 16 | }; |
| 17 | 17 | } |
std/os/index.zig+34-16| ... | ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const Os = builtin.Os; |
| 4 | 4 | const is_windows = builtin.os == Os.windows; |
| 5 | 5 | const is_posix = switch (builtin.os) { |
| 6 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => true, | |
| 6 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => true, | |
| 7 | 7 | else => false, |
| 8 | 8 | }; |
| 9 | 9 | const os = @This(); |
| ... | ... | @@ -30,6 +30,7 @@ pub const windows = @import("windows/index.zig"); |
| 30 | 30 | pub const darwin = @import("darwin.zig"); |
| 31 | 31 | pub const linux = @import("linux/index.zig"); |
| 32 | 32 | pub const freebsd = @import("freebsd/index.zig"); |
| 33 | pub const netbsd = @import("netbsd/index.zig"); | |
| 33 | 34 | pub const zen = @import("zen.zig"); |
| 34 | 35 | pub const uefi = @import("uefi.zig"); |
| 35 | 36 | |
| ... | ... | @@ -37,6 +38,7 @@ pub const posix = switch (builtin.os) { |
| 37 | 38 | Os.linux => linux, |
| 38 | 39 | Os.macosx, Os.ios => darwin, |
| 39 | 40 | Os.freebsd => freebsd, |
| 41 | Os.netbsd => netbsd, | |
| 40 | 42 | Os.zen => zen, |
| 41 | 43 | else => @compileError("Unsupported OS"), |
| 42 | 44 | }; |
| ... | ... | @@ -50,7 +52,7 @@ pub const time = @import("time.zig"); |
| 50 | 52 | |
| 51 | 53 | pub const page_size = 4 * 1024; |
| 52 | 54 | pub const MAX_PATH_BYTES = switch (builtin.os) { |
| 53 | Os.linux, Os.macosx, Os.ios, Os.freebsd => posix.PATH_MAX, | |
| 55 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => posix.PATH_MAX, | |
| 54 | 56 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| 55 | 57 | // If it would require 4 UTF-8 bytes, then there would be a surrogate |
| 56 | 58 | // pair in the UTF-16LE, and we (over)account 3 bytes for it that way. |
| ... | ... | @@ -125,7 +127,7 @@ pub fn getRandomBytes(buf: []u8) !void { |
| 125 | 127 | else => return unexpectedErrorPosix(errno), |
| 126 | 128 | } |
| 127 | 129 | }, |
| 128 | Os.macosx, Os.ios, Os.freebsd => return getRandomBytesDevURandom(buf), | |
| 130 | Os.macosx, Os.ios, Os.freebsd, Os.netbsd => return getRandomBytesDevURandom(buf), | |
| 129 | 131 | Os.windows => { |
| 130 | 132 | // Call RtlGenRandom() instead of CryptGetRandom() on Windows |
| 131 | 133 | // https://github.com/rust-lang-nursery/rand/issues/111 |
| ... | ... | @@ -185,7 +187,7 @@ pub fn abort() noreturn { |
| 185 | 187 | c.abort(); |
| 186 | 188 | } |
| 187 | 189 | switch (builtin.os) { |
| 188 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 190 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 189 | 191 | _ = posix.raise(posix.SIGABRT); |
| 190 | 192 | _ = posix.raise(posix.SIGKILL); |
| 191 | 193 | while (true) {} |
| ... | ... | @@ -211,7 +213,7 @@ pub fn exit(status: u8) noreturn { |
| 211 | 213 | c.exit(status); |
| 212 | 214 | } |
| 213 | 215 | switch (builtin.os) { |
| 214 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 216 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 215 | 217 | posix.exit(status); |
| 216 | 218 | }, |
| 217 | 219 | Os.windows => { |
| ... | ... | @@ -327,7 +329,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6 |
| 327 | 329 | } |
| 328 | 330 | } |
| 329 | 331 | }, |
| 330 | builtin.Os.linux, builtin.Os.freebsd => while (true) { | |
| 332 | builtin.Os.linux, builtin.Os.freebsd, Os.netbsd => while (true) { | |
| 331 | 333 | const rc = posix.preadv(fd, iov, count, offset); |
| 332 | 334 | const err = posix.getErrno(rc); |
| 333 | 335 | switch (err) { |
| ... | ... | @@ -434,7 +436,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off |
| 434 | 436 | } |
| 435 | 437 | } |
| 436 | 438 | }, |
| 437 | builtin.Os.linux, builtin.Os.freebsd => while (true) { | |
| 439 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => while (true) { | |
| 438 | 440 | const rc = posix.pwritev(fd, iov, count, offset); |
| 439 | 441 | const err = posix.getErrno(rc); |
| 440 | 442 | switch (err) { |
| ... | ... | @@ -699,7 +701,9 @@ pub fn getBaseAddress() usize { |
| 699 | 701 | const phdr = linuxGetAuxVal(std.elf.AT_PHDR); |
| 700 | 702 | return phdr - @sizeOf(std.elf.Ehdr); |
| 701 | 703 | }, |
| 702 | builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header), | |
| 704 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 705 | return @ptrToInt(&std.c._mh_execute_header); | |
| 706 | }, | |
| 703 | 707 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), |
| 704 | 708 | else => @compileError("Unsupported OS"), |
| 705 | 709 | } |
| ... | ... | @@ -1339,7 +1343,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void { |
| 1339 | 1343 | const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path); |
| 1340 | 1344 | return deleteDirW(&dir_path_w); |
| 1341 | 1345 | }, |
| 1342 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 1346 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 1343 | 1347 | const err = posix.getErrno(posix.rmdir(dir_path)); |
| 1344 | 1348 | switch (err) { |
| 1345 | 1349 | 0 => return, |
| ... | ... | @@ -1382,7 +1386,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void { |
| 1382 | 1386 | const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path); |
| 1383 | 1387 | return deleteDirW(&dir_path_w); |
| 1384 | 1388 | }, |
| 1385 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 1389 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 1386 | 1390 | const dir_path_c = try toPosixPath(dir_path); |
| 1387 | 1391 | return deleteDirC(&dir_path_c); |
| 1388 | 1392 | }, |
| ... | ... | @@ -1501,7 +1505,7 @@ pub const Dir = struct { |
| 1501 | 1505 | allocator: *Allocator, |
| 1502 | 1506 | |
| 1503 | 1507 | pub const Handle = switch (builtin.os) { |
| 1504 | Os.macosx, Os.ios, Os.freebsd => struct { | |
| 1508 | Os.macosx, Os.ios, Os.freebsd, Os.netbsd => struct { | |
| 1505 | 1509 | fd: i32, |
| 1506 | 1510 | seek: i64, |
| 1507 | 1511 | buf: []u8, |
| ... | ... | @@ -1578,7 +1582,7 @@ pub const Dir = struct { |
| 1578 | 1582 | .name_data = undefined, |
| 1579 | 1583 | }; |
| 1580 | 1584 | }, |
| 1581 | Os.macosx, Os.ios, Os.freebsd => Handle{ | |
| 1585 | Os.macosx, Os.ios, Os.freebsd, Os.netbsd => Handle{ | |
| 1582 | 1586 | .fd = try posixOpen( |
| 1583 | 1587 | dir_path, |
| 1584 | 1588 | posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC, |
| ... | ... | @@ -1609,7 +1613,7 @@ pub const Dir = struct { |
| 1609 | 1613 | Os.windows => { |
| 1610 | 1614 | _ = windows.FindClose(self.handle.handle); |
| 1611 | 1615 | }, |
| 1612 | Os.macosx, Os.ios, Os.linux, Os.freebsd => { | |
| 1616 | Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => { | |
| 1613 | 1617 | self.allocator.free(self.handle.buf); |
| 1614 | 1618 | os.close(self.handle.fd); |
| 1615 | 1619 | }, |
| ... | ... | @@ -1625,6 +1629,7 @@ pub const Dir = struct { |
| 1625 | 1629 | Os.macosx, Os.ios => return self.nextDarwin(), |
| 1626 | 1630 | Os.windows => return self.nextWindows(), |
| 1627 | 1631 | Os.freebsd => return self.nextFreebsd(), |
| 1632 | Os.netbsd => return self.nextFreebsd(), | |
| 1628 | 1633 | else => @compileError("unimplemented"), |
| 1629 | 1634 | } |
| 1630 | 1635 | } |
| ... | ... | @@ -2256,7 +2261,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { |
| 2256 | 2261 | pub fn openSelfExe() !os.File { |
| 2257 | 2262 | switch (builtin.os) { |
| 2258 | 2263 | Os.linux => return os.File.openReadC(c"/proc/self/exe"), |
| 2259 | Os.macosx, Os.ios, Os.freebsd => { | |
| 2264 | Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 2260 | 2265 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| 2261 | 2266 | const self_exe_path = try selfExePath(&buf); |
| 2262 | 2267 | buf[self_exe_path.len] = 0; |
| ... | ... | @@ -2317,6 +2322,19 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 { |
| 2317 | 2322 | else => unexpectedErrorPosix(err), |
| 2318 | 2323 | }; |
| 2319 | 2324 | }, |
| 2325 | Os.netbsd => { | |
| 2326 | var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC_ARGS, -1, posix.KERN_PROC_PATHNAME }; | |
| 2327 | var out_len: usize = out_buffer.len; | |
| 2328 | const err = posix.getErrno(posix.sysctl(&mib, 4, out_buffer, &out_len, null, 0)); | |
| 2329 | ||
| 2330 | if (err == 0) return mem.toSlice(u8, out_buffer); | |
| 2331 | ||
| 2332 | return switch (err) { | |
| 2333 | posix.EFAULT => error.BadAdress, | |
| 2334 | posix.EPERM => error.PermissionDenied, | |
| 2335 | else => unexpectedErrorPosix(err), | |
| 2336 | }; | |
| 2337 | }, | |
| 2320 | 2338 | Os.windows => { |
| 2321 | 2339 | var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined; |
| 2322 | 2340 | const utf16le_slice = try selfExePathW(&utf16le_buf); |
| ... | ... | @@ -2355,7 +2373,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 { |
| 2355 | 2373 | // will not return null. |
| 2356 | 2374 | return path.dirname(full_exe_path).?; |
| 2357 | 2375 | }, |
| 2358 | Os.windows, Os.macosx, Os.ios, Os.freebsd => { | |
| 2376 | Os.windows, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 2359 | 2377 | const self_exe_path = try selfExePath(out_buffer); |
| 2360 | 2378 | // Assume that the OS APIs return absolute paths, and therefore dirname |
| 2361 | 2379 | // will not return null. |
| ... | ... | @@ -3227,7 +3245,7 @@ pub const CpuCountError = error{ |
| 3227 | 3245 | |
| 3228 | 3246 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { |
| 3229 | 3247 | switch (builtin.os) { |
| 3230 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 3248 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | |
| 3231 | 3249 | var count: c_int = undefined; |
| 3232 | 3250 | var count_len: usize = @sizeOf(c_int); |
| 3233 | 3251 | const rc = posix.sysctlbyname(switch (builtin.os) { |
std/os/linux/index.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const vdso = @import("vdso.zig"); |
| 6 | 6 | pub use switch (builtin.arch) { |
| 7 | 7 | builtin.Arch.x86_64 => @import("x86_64.zig"), |
| 8 | 8 | builtin.Arch.i386 => @import("i386.zig"), |
| 9 | builtin.Arch.aarch64v8 => @import("arm64.zig"), | |
| 9 | builtin.Arch.aarch64 => @import("arm64.zig"), | |
| 10 | 10 | else => @compileError("unsupported arch"), |
| 11 | 11 | }; |
| 12 | 12 | pub use @import("errno.zig"); |
std/os/netbsd/errno.zig created+134| ... | ... | @@ -0,0 +1,134 @@ |
| 1 | pub const EPERM = 1; // Operation not permitted | |
| 2 | pub const ENOENT = 2; // No such file or directory | |
| 3 | pub const ESRCH = 3; // No such process | |
| 4 | pub const EINTR = 4; // Interrupted system call | |
| 5 | pub const EIO = 5; // Input/output error | |
| 6 | pub const ENXIO = 6; // Device not configured | |
| 7 | pub const E2BIG = 7; // Argument list too long | |
| 8 | pub const ENOEXEC = 8; // Exec format error | |
| 9 | pub const EBADF = 9; // Bad file descriptor | |
| 10 | pub const ECHILD = 10; // No child processes | |
| 11 | pub const EDEADLK = 11; // Resource deadlock avoided | |
| 12 | // 11 was EAGAIN | |
| 13 | pub const ENOMEM = 12; // Cannot allocate memory | |
| 14 | pub const EACCES = 13; // Permission denied | |
| 15 | pub const EFAULT = 14; // Bad address | |
| 16 | pub const ENOTBLK = 15; // Block device required | |
| 17 | pub const EBUSY = 16; // Device busy | |
| 18 | pub const EEXIST = 17; // File exists | |
| 19 | pub const EXDEV = 18; // Cross-device link | |
| 20 | pub const ENODEV = 19; // Operation not supported by device | |
| 21 | pub const ENOTDIR = 20; // Not a directory | |
| 22 | pub const EISDIR = 21; // Is a directory | |
| 23 | pub const EINVAL = 22; // Invalid argument | |
| 24 | pub const ENFILE = 23; // Too many open files in system | |
| 25 | pub const EMFILE = 24; // Too many open files | |
| 26 | pub const ENOTTY = 25; // Inappropriate ioctl for device | |
| 27 | pub const ETXTBSY = 26; // Text file busy | |
| 28 | pub const EFBIG = 27; // File too large | |
| 29 | pub const ENOSPC = 28; // No space left on device | |
| 30 | pub const ESPIPE = 29; // Illegal seek | |
| 31 | pub const EROFS = 30; // Read-only file system | |
| 32 | pub const EMLINK = 31; // Too many links | |
| 33 | pub const EPIPE = 32; // Broken pipe | |
| 34 | ||
| 35 | // math software | |
| 36 | pub const EDOM = 33; // Numerical argument out of domain | |
| 37 | pub const ERANGE = 34; // Result too large or too small | |
| 38 | ||
| 39 | // non-blocking and interrupt i/o | |
| 40 | pub const EAGAIN = 35; // Resource temporarily unavailable | |
| 41 | pub const EWOULDBLOCK = EAGAIN; // Operation would block | |
| 42 | pub const EINPROGRESS = 36; // Operation now in progress | |
| 43 | pub const EALREADY = 37; // Operation already in progress | |
| 44 | ||
| 45 | // ipc/network software -- argument errors | |
| 46 | pub const ENOTSOCK = 38; // Socket operation on non-socket | |
| 47 | pub const EDESTADDRREQ = 39; // Destination address required | |
| 48 | pub const EMSGSIZE = 40; // Message too long | |
| 49 | pub const EPROTOTYPE = 41; // Protocol wrong type for socket | |
| 50 | pub const ENOPROTOOPT = 42; // Protocol option not available | |
| 51 | pub const EPROTONOSUPPORT = 43; // Protocol not supported | |
| 52 | pub const ESOCKTNOSUPPORT = 44; // Socket type not supported | |
| 53 | pub const EOPNOTSUPP = 45; // Operation not supported | |
| 54 | pub const EPFNOSUPPORT = 46; // Protocol family not supported | |
| 55 | pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family | |
| 56 | pub const EADDRINUSE = 48; // Address already in use | |
| 57 | pub const EADDRNOTAVAIL = 49; // Can't assign requested address | |
| 58 | ||
| 59 | // ipc/network software -- operational errors | |
| 60 | pub const ENETDOWN = 50; // Network is down | |
| 61 | pub const ENETUNREACH = 51; // Network is unreachable | |
| 62 | pub const ENETRESET = 52; // Network dropped connection on reset | |
| 63 | pub const ECONNABORTED = 53; // Software caused connection abort | |
| 64 | pub const ECONNRESET = 54; // Connection reset by peer | |
| 65 | pub const ENOBUFS = 55; // No buffer space available | |
| 66 | pub const EISCONN = 56; // Socket is already connected | |
| 67 | pub const ENOTCONN = 57; // Socket is not connected | |
| 68 | pub const ESHUTDOWN = 58; // Can't send after socket shutdown | |
| 69 | pub const ETOOMANYREFS = 59; // Too many references: can't splice | |
| 70 | pub const ETIMEDOUT = 60; // Operation timed out | |
| 71 | pub const ECONNREFUSED = 61; // Connection refused | |
| 72 | ||
| 73 | pub const ELOOP = 62; // Too many levels of symbolic links | |
| 74 | pub const ENAMETOOLONG = 63; // File name too long | |
| 75 | ||
| 76 | // should be rearranged | |
| 77 | pub const EHOSTDOWN = 64; // Host is down | |
| 78 | pub const EHOSTUNREACH = 65; // No route to host | |
| 79 | pub const ENOTEMPTY = 66; // Directory not empty | |
| 80 | ||
| 81 | // quotas & mush | |
| 82 | pub const EPROCLIM = 67; // Too many processes | |
| 83 | pub const EUSERS = 68; // Too many users | |
| 84 | pub const EDQUOT = 69; // Disc quota exceeded | |
| 85 | ||
| 86 | // Network File System | |
| 87 | pub const ESTALE = 70; // Stale NFS file handle | |
| 88 | pub const EREMOTE = 71; // Too many levels of remote in path | |
| 89 | pub const EBADRPC = 72; // RPC struct is bad | |
| 90 | pub const ERPCMISMATCH = 73; // RPC version wrong | |
| 91 | pub const EPROGUNAVAIL = 74; // RPC prog. not avail | |
| 92 | pub const EPROGMISMATCH = 75; // Program version wrong | |
| 93 | pub const EPROCUNAVAIL = 76; // Bad procedure for program | |
| 94 | ||
| 95 | pub const ENOLCK = 77; // No locks available | |
| 96 | pub const ENOSYS = 78; // Function not implemented | |
| 97 | ||
| 98 | pub const EFTYPE = 79; // Inappropriate file type or format | |
| 99 | pub const EAUTH = 80; // Authentication error | |
| 100 | pub const ENEEDAUTH = 81; // Need authenticator | |
| 101 | ||
| 102 | // SystemV IPC | |
| 103 | pub const EIDRM = 82; // Identifier removed | |
| 104 | pub const ENOMSG = 83; // No message of desired type | |
| 105 | pub const EOVERFLOW = 84; // Value too large to be stored in data type | |
| 106 | ||
| 107 | // Wide/multibyte-character handling, ISO/IEC 9899/AMD1:1995 | |
| 108 | pub const EILSEQ = 85; // Illegal byte sequence | |
| 109 | ||
| 110 | // From IEEE Std 1003.1-2001 | |
| 111 | // Base, Realtime, Threads or Thread Priority Scheduling option errors | |
| 112 | pub const ENOTSUP = 86; // Not supported | |
| 113 | ||
| 114 | // Realtime option errors | |
| 115 | pub const ECANCELED = 87; // Operation canceled | |
| 116 | ||
| 117 | // Realtime, XSI STREAMS option errors | |
| 118 | pub const EBADMSG = 88; // Bad or Corrupt message | |
| 119 | ||
| 120 | // XSI STREAMS option errors | |
| 121 | pub const ENODATA = 89; // No message available | |
| 122 | pub const ENOSR = 90; // No STREAM resources | |
| 123 | pub const ENOSTR = 91; // Not a STREAM | |
| 124 | pub const ETIME = 92; // STREAM ioctl timeout | |
| 125 | ||
| 126 | // File system extended attribute errors | |
| 127 | pub const ENOATTR = 93; // Attribute not found | |
| 128 | ||
| 129 | // Realtime, XSI STREAMS option errors | |
| 130 | pub const EMULTIHOP = 94; // Multihop attempted | |
| 131 | pub const ENOLINK = 95; // Link has been severed | |
| 132 | pub const EPROTO = 96; // Protocol error | |
| 133 | ||
| 134 | pub const ELAST = 96; // Must equal largest errno |
std/os/netbsd/index.zig created+725| ... | ... | @@ -0,0 +1,725 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | pub use @import("errno.zig"); | |
| 4 | ||
| 5 | const std = @import("../../index.zig"); | |
| 6 | const c = std.c; | |
| 7 | ||
| 8 | const assert = std.debug.assert; | |
| 9 | const maxInt = std.math.maxInt; | |
| 10 | pub const Kevent = c.Kevent; | |
| 11 | ||
| 12 | pub const CTL_KERN = 1; | |
| 13 | pub const CTL_DEBUG = 5; | |
| 14 | ||
| 15 | pub const KERN_PROC_ARGS = 48; // struct: process argv/env | |
| 16 | pub const KERN_PROC_PATHNAME = 5; // path to executable | |
| 17 | ||
| 18 | pub const PATH_MAX = 1024; | |
| 19 | ||
| 20 | pub const STDIN_FILENO = 0; | |
| 21 | pub const STDOUT_FILENO = 1; | |
| 22 | pub const STDERR_FILENO = 2; | |
| 23 | ||
| 24 | pub const PROT_NONE = 0; | |
| 25 | pub const PROT_READ = 1; | |
| 26 | pub const PROT_WRITE = 2; | |
| 27 | pub const PROT_EXEC = 4; | |
| 28 | ||
| 29 | pub const CLOCK_REALTIME = 0; | |
| 30 | pub const CLOCK_VIRTUAL = 1; | |
| 31 | pub const CLOCK_PROF = 2; | |
| 32 | pub const CLOCK_MONOTONIC = 3; | |
| 33 | pub const CLOCK_THREAD_CPUTIME_ID = 0x20000000; | |
| 34 | pub const CLOCK_PROCESS_CPUTIME_ID = 0x40000000; | |
| 35 | ||
| 36 | pub const MAP_FAILED = maxInt(usize); | |
| 37 | pub const MAP_SHARED = 0x0001; | |
| 38 | pub const MAP_PRIVATE = 0x0002; | |
| 39 | pub const MAP_REMAPDUP = 0x0004; | |
| 40 | pub const MAP_FIXED = 0x0010; | |
| 41 | pub const MAP_RENAME = 0x0020; | |
| 42 | pub const MAP_NORESERVE = 0x0040; | |
| 43 | pub const MAP_INHERIT = 0x0080; | |
| 44 | pub const MAP_HASSEMAPHORE = 0x0200; | |
| 45 | pub const MAP_TRYFIXED = 0x0400; | |
| 46 | pub const MAP_WIRED = 0x0800; | |
| 47 | ||
| 48 | pub const MAP_FILE = 0x0000; | |
| 49 | pub const MAP_NOSYNC = 0x0800; | |
| 50 | pub const MAP_ANON = 0x1000; | |
| 51 | pub const MAP_ANONYMOUS = MAP_ANON; | |
| 52 | pub const MAP_STACK = 0x2000; | |
| 53 | ||
| 54 | pub const WNOHANG = 0x00000001; | |
| 55 | pub const WUNTRACED = 0x00000002; | |
| 56 | pub const WSTOPPED = WUNTRACED; | |
| 57 | pub const WCONTINUED = 0x00000010; | |
| 58 | pub const WNOWAIT = 0x00010000; | |
| 59 | pub const WEXITED = 0x00000020; | |
| 60 | pub const WTRAPPED = 0x00000040; | |
| 61 | ||
| 62 | pub const SA_ONSTACK = 0x0001; | |
| 63 | pub const SA_RESTART = 0x0002; | |
| 64 | pub const SA_RESETHAND = 0x0004; | |
| 65 | pub const SA_NOCLDSTOP = 0x0008; | |
| 66 | pub const SA_NODEFER = 0x0010; | |
| 67 | pub const SA_NOCLDWAIT = 0x0020; | |
| 68 | pub const SA_SIGINFO = 0x0040; | |
| 69 | ||
| 70 | pub const SIGHUP = 1; | |
| 71 | pub const SIGINT = 2; | |
| 72 | pub const SIGQUIT = 3; | |
| 73 | pub const SIGILL = 4; | |
| 74 | pub const SIGTRAP = 5; | |
| 75 | pub const SIGABRT = 6; | |
| 76 | pub const SIGIOT = SIGABRT; | |
| 77 | pub const SIGEMT = 7; | |
| 78 | pub const SIGFPE = 8; | |
| 79 | pub const SIGKILL = 9; | |
| 80 | pub const SIGBUS = 10; | |
| 81 | pub const SIGSEGV = 11; | |
| 82 | pub const SIGSYS = 12; | |
| 83 | pub const SIGPIPE = 13; | |
| 84 | pub const SIGALRM = 14; | |
| 85 | pub const SIGTERM = 15; | |
| 86 | pub const SIGURG = 16; | |
| 87 | pub const SIGSTOP = 17; | |
| 88 | pub const SIGTSTP = 18; | |
| 89 | pub const SIGCONT = 19; | |
| 90 | pub const SIGCHLD = 20; | |
| 91 | pub const SIGTTIN = 21; | |
| 92 | pub const SIGTTOU = 22; | |
| 93 | pub const SIGIO = 23; | |
| 94 | pub const SIGXCPU = 24; | |
| 95 | pub const SIGXFSZ = 25; | |
| 96 | pub const SIGVTALRM = 26; | |
| 97 | pub const SIGPROF = 27; | |
| 98 | pub const SIGWINCH = 28; | |
| 99 | pub const SIGINFO = 29; | |
| 100 | pub const SIGUSR1 = 30; | |
| 101 | pub const SIGUSR2 = 31; | |
| 102 | pub const SIGPWR = 32; | |
| 103 | ||
| 104 | pub const SIGRTMIN = 33; | |
| 105 | pub const SIGRTMAX = 63; | |
| 106 | ||
| 107 | // access function | |
| 108 | pub const F_OK = 0; // test for existence of file | |
| 109 | pub const X_OK = 1; // test for execute or search permission | |
| 110 | pub const W_OK = 2; // test for write permission | |
| 111 | pub const R_OK = 4; // test for read permission | |
| 112 | ||
| 113 | ||
| 114 | pub const O_RDONLY = 0x0000; | |
| 115 | pub const O_WRONLY = 0x0001; | |
| 116 | pub const O_RDWR = 0x0002; | |
| 117 | pub const O_ACCMODE = 0x0003; | |
| 118 | ||
| 119 | pub const O_CREAT = 0x0200; | |
| 120 | pub const O_EXCL = 0x0800; | |
| 121 | pub const O_NOCTTY = 0x8000; | |
| 122 | pub const O_TRUNC = 0x0400; | |
| 123 | pub const O_APPEND = 0x0008; | |
| 124 | pub const O_NONBLOCK = 0x0004; | |
| 125 | pub const O_DSYNC = 0x00010000; | |
| 126 | pub const O_SYNC = 0x0080; | |
| 127 | pub const O_RSYNC = 0x00020000; | |
| 128 | pub const O_DIRECTORY = 0x00080000; | |
| 129 | pub const O_NOFOLLOW = 0x00000100; | |
| 130 | pub const O_CLOEXEC = 0x00400000; | |
| 131 | ||
| 132 | pub const O_ASYNC = 0x0040; | |
| 133 | pub const O_DIRECT = 0x00080000; | |
| 134 | pub const O_LARGEFILE = 0; | |
| 135 | pub const O_NOATIME = 0; | |
| 136 | pub const O_PATH = 0; | |
| 137 | pub const O_TMPFILE = 0; | |
| 138 | pub const O_NDELAY = O_NONBLOCK; | |
| 139 | ||
| 140 | pub const F_DUPFD = 0; | |
| 141 | pub const F_GETFD = 1; | |
| 142 | pub const F_SETFD = 2; | |
| 143 | pub const F_GETFL = 3; | |
| 144 | pub const F_SETFL = 4; | |
| 145 | ||
| 146 | pub const F_GETOWN = 5; | |
| 147 | pub const F_SETOWN = 6; | |
| 148 | ||
| 149 | pub const F_GETLK = 7; | |
| 150 | pub const F_SETLK = 8; | |
| 151 | pub const F_SETLKW = 9; | |
| 152 | ||
| 153 | pub const SEEK_SET = 0; | |
| 154 | pub const SEEK_CUR = 1; | |
| 155 | pub const SEEK_END = 2; | |
| 156 | ||
| 157 | pub const SIG_BLOCK = 1; | |
| 158 | pub const SIG_UNBLOCK = 2; | |
| 159 | pub const SIG_SETMASK = 3; | |
| 160 | ||
| 161 | pub const SOCK_STREAM = 1; | |
| 162 | pub const SOCK_DGRAM = 2; | |
| 163 | pub const SOCK_RAW = 3; | |
| 164 | pub const SOCK_RDM = 4; | |
| 165 | pub const SOCK_SEQPACKET = 5; | |
| 166 | ||
| 167 | pub const SOCK_CLOEXEC = 0x10000000; | |
| 168 | pub const SOCK_NONBLOCK = 0x20000000; | |
| 169 | ||
| 170 | pub const PROTO_ip = 0; | |
| 171 | pub const PROTO_icmp = 1; | |
| 172 | pub const PROTO_igmp = 2; | |
| 173 | pub const PROTO_ggp = 3; | |
| 174 | pub const PROTO_ipencap = 4; | |
| 175 | pub const PROTO_tcp = 6; | |
| 176 | pub const PROTO_egp = 8; | |
| 177 | pub const PROTO_pup = 12; | |
| 178 | pub const PROTO_udp = 17; | |
| 179 | pub const PROTO_xns_idp = 22; | |
| 180 | pub const PROTO_iso_tp4 = 29; | |
| 181 | pub const PROTO_ipv6 = 41; | |
| 182 | pub const PROTO_ipv6_route = 43; | |
| 183 | pub const PROTO_ipv6_frag = 44; | |
| 184 | pub const PROTO_rsvp = 46; | |
| 185 | pub const PROTO_gre = 47; | |
| 186 | pub const PROTO_esp = 50; | |
| 187 | pub const PROTO_ah = 51; | |
| 188 | pub const PROTO_ipv6_icmp = 58; | |
| 189 | pub const PROTO_ipv6_nonxt = 59; | |
| 190 | pub const PROTO_ipv6_opts = 60; | |
| 191 | pub const PROTO_encap = 98; | |
| 192 | pub const PROTO_pim = 103; | |
| 193 | pub const PROTO_raw = 255; | |
| 194 | ||
| 195 | pub const PF_UNSPEC = 0; | |
| 196 | pub const PF_LOCAL = 1; | |
| 197 | pub const PF_UNIX = PF_LOCAL; | |
| 198 | pub const PF_FILE = PF_LOCAL; | |
| 199 | pub const PF_INET = 2; | |
| 200 | pub const PF_APPLETALK = 16; | |
| 201 | pub const PF_INET6 = 24; | |
| 202 | pub const PF_DECnet = 12; | |
| 203 | pub const PF_KEY = 29; | |
| 204 | pub const PF_ROUTE = 34; | |
| 205 | pub const PF_SNA = 11; | |
| 206 | pub const PF_MPLS = 33; | |
| 207 | pub const PF_CAN = 35; | |
| 208 | pub const PF_BLUETOOTH = 31; | |
| 209 | pub const PF_ISDN = 26; | |
| 210 | pub const PF_MAX = 37; | |
| 211 | ||
| 212 | pub const AF_UNSPEC = PF_UNSPEC; | |
| 213 | pub const AF_LOCAL = PF_LOCAL; | |
| 214 | pub const AF_UNIX = AF_LOCAL; | |
| 215 | pub const AF_FILE = AF_LOCAL; | |
| 216 | pub const AF_INET = PF_INET; | |
| 217 | pub const AF_APPLETALK = PF_APPLETALK; | |
| 218 | pub const AF_INET6 = PF_INET6; | |
| 219 | pub const AF_KEY = PF_KEY; | |
| 220 | pub const AF_ROUTE = PF_ROUTE; | |
| 221 | pub const AF_SNA = PF_SNA; | |
| 222 | pub const AF_MPLS = PF_MPLS; | |
| 223 | pub const AF_CAN = PF_CAN; | |
| 224 | pub const AF_BLUETOOTH = PF_BLUETOOTH; | |
| 225 | pub const AF_ISDN = PF_ISDN; | |
| 226 | pub const AF_MAX = PF_MAX; | |
| 227 | ||
| 228 | pub const DT_UNKNOWN = 0; | |
| 229 | pub const DT_FIFO = 1; | |
| 230 | pub const DT_CHR = 2; | |
| 231 | pub const DT_DIR = 4; | |
| 232 | pub const DT_BLK = 6; | |
| 233 | pub const DT_REG = 8; | |
| 234 | pub const DT_LNK = 10; | |
| 235 | pub const DT_SOCK = 12; | |
| 236 | pub const DT_WHT = 14; | |
| 237 | ||
| 238 | /// add event to kq (implies enable) | |
| 239 | pub const EV_ADD = 0x0001; | |
| 240 | ||
| 241 | /// delete event from kq | |
| 242 | pub const EV_DELETE = 0x0002; | |
| 243 | ||
| 244 | /// enable event | |
| 245 | pub const EV_ENABLE = 0x0004; | |
| 246 | ||
| 247 | /// disable event (not reported) | |
| 248 | pub const EV_DISABLE = 0x0008; | |
| 249 | ||
| 250 | /// only report one occurrence | |
| 251 | pub const EV_ONESHOT = 0x0010; | |
| 252 | ||
| 253 | /// clear event state after reporting | |
| 254 | pub const EV_CLEAR = 0x0020; | |
| 255 | ||
| 256 | /// force immediate event output | |
| 257 | /// ... with or without EV_ERROR | |
| 258 | /// ... use KEVENT_FLAG_ERROR_EVENTS | |
| 259 | /// on syscalls supporting flags | |
| 260 | pub const EV_RECEIPT = 0x0040; | |
| 261 | ||
| 262 | /// disable event after reporting | |
| 263 | pub const EV_DISPATCH = 0x0080; | |
| 264 | ||
| 265 | pub const EVFILT_READ = 0; | |
| 266 | pub const EVFILT_WRITE = 1; | |
| 267 | ||
| 268 | /// attached to aio requests | |
| 269 | pub const EVFILT_AIO = 2; | |
| 270 | ||
| 271 | /// attached to vnodes | |
| 272 | pub const EVFILT_VNODE = 3; | |
| 273 | ||
| 274 | /// attached to struct proc | |
| 275 | pub const EVFILT_PROC = 4; | |
| 276 | ||
| 277 | /// attached to struct proc | |
| 278 | pub const EVFILT_SIGNAL = 5; | |
| 279 | ||
| 280 | /// timers | |
| 281 | pub const EVFILT_TIMER = 6; | |
| 282 | ||
| 283 | /// Filesystem events | |
| 284 | pub const EVFILT_FS = 7; | |
| 285 | ||
| 286 | /// On input, NOTE_TRIGGER causes the event to be triggered for output. | |
| 287 | pub const NOTE_TRIGGER = 0x08000000; | |
| 288 | ||
| 289 | /// low water mark | |
| 290 | pub const NOTE_LOWAT = 0x00000001; | |
| 291 | ||
| 292 | /// vnode was removed | |
| 293 | pub const NOTE_DELETE = 0x00000001; | |
| 294 | ||
| 295 | /// data contents changed | |
| 296 | pub const NOTE_WRITE = 0x00000002; | |
| 297 | ||
| 298 | /// size increased | |
| 299 | pub const NOTE_EXTEND = 0x00000004; | |
| 300 | ||
| 301 | /// attributes changed | |
| 302 | pub const NOTE_ATTRIB = 0x00000008; | |
| 303 | ||
| 304 | /// link count changed | |
| 305 | pub const NOTE_LINK = 0x00000010; | |
| 306 | ||
| 307 | /// vnode was renamed | |
| 308 | pub const NOTE_RENAME = 0x00000020; | |
| 309 | ||
| 310 | /// vnode access was revoked | |
| 311 | pub const NOTE_REVOKE = 0x00000040; | |
| 312 | ||
| 313 | /// process exited | |
| 314 | pub const NOTE_EXIT = 0x80000000; | |
| 315 | ||
| 316 | /// process forked | |
| 317 | pub const NOTE_FORK = 0x40000000; | |
| 318 | ||
| 319 | /// process exec'd | |
| 320 | pub const NOTE_EXEC = 0x20000000; | |
| 321 | ||
| 322 | /// mask for signal & exit status | |
| 323 | pub const NOTE_PDATAMASK = 0x000fffff; | |
| 324 | pub const NOTE_PCTRLMASK = 0xf0000000; | |
| 325 | ||
| 326 | pub const TIOCCBRK = 0x2000747a; | |
| 327 | pub const TIOCCDTR = 0x20007478; | |
| 328 | pub const TIOCCONS = 0x80047462; | |
| 329 | pub const TIOCDCDTIMESTAMP = 0x40107458; | |
| 330 | pub const TIOCDRAIN = 0x2000745e; | |
| 331 | pub const TIOCEXCL = 0x2000740d; | |
| 332 | pub const TIOCEXT = 0x80047460; | |
| 333 | pub const TIOCFLAG_CDTRCTS = 0x10; | |
| 334 | pub const TIOCFLAG_CLOCAL = 0x2; | |
| 335 | pub const TIOCFLAG_CRTSCTS = 0x4; | |
| 336 | pub const TIOCFLAG_MDMBUF = 0x8; | |
| 337 | pub const TIOCFLAG_SOFTCAR = 0x1; | |
| 338 | pub const TIOCFLUSH = 0x80047410; | |
| 339 | pub const TIOCGETA = 0x402c7413; | |
| 340 | pub const TIOCGETD = 0x4004741a; | |
| 341 | pub const TIOCGFLAGS = 0x4004745d; | |
| 342 | pub const TIOCGLINED = 0x40207442; | |
| 343 | pub const TIOCGPGRP = 0x40047477; | |
| 344 | pub const TIOCGQSIZE = 0x40047481; | |
| 345 | pub const TIOCGRANTPT = 0x20007447; | |
| 346 | pub const TIOCGSID = 0x40047463; | |
| 347 | pub const TIOCGSIZE = 0x40087468; | |
| 348 | pub const TIOCGWINSZ = 0x40087468; | |
| 349 | pub const TIOCMBIC = 0x8004746b; | |
| 350 | pub const TIOCMBIS = 0x8004746c; | |
| 351 | pub const TIOCMGET = 0x4004746a; | |
| 352 | pub const TIOCMSET = 0x8004746d; | |
| 353 | pub const TIOCM_CAR = 0x40; | |
| 354 | pub const TIOCM_CD = 0x40; | |
| 355 | pub const TIOCM_CTS = 0x20; | |
| 356 | pub const TIOCM_DSR = 0x100; | |
| 357 | pub const TIOCM_DTR = 0x2; | |
| 358 | pub const TIOCM_LE = 0x1; | |
| 359 | pub const TIOCM_RI = 0x80; | |
| 360 | pub const TIOCM_RNG = 0x80; | |
| 361 | pub const TIOCM_RTS = 0x4; | |
| 362 | pub const TIOCM_SR = 0x10; | |
| 363 | pub const TIOCM_ST = 0x8; | |
| 364 | pub const TIOCNOTTY = 0x20007471; | |
| 365 | pub const TIOCNXCL = 0x2000740e; | |
| 366 | pub const TIOCOUTQ = 0x40047473; | |
| 367 | pub const TIOCPKT = 0x80047470; | |
| 368 | pub const TIOCPKT_DATA = 0x0; | |
| 369 | pub const TIOCPKT_DOSTOP = 0x20; | |
| 370 | pub const TIOCPKT_FLUSHREAD = 0x1; | |
| 371 | pub const TIOCPKT_FLUSHWRITE = 0x2; | |
| 372 | pub const TIOCPKT_IOCTL = 0x40; | |
| 373 | pub const TIOCPKT_NOSTOP = 0x10; | |
| 374 | pub const TIOCPKT_START = 0x8; | |
| 375 | pub const TIOCPKT_STOP = 0x4; | |
| 376 | pub const TIOCPTMGET = 0x40287446; | |
| 377 | pub const TIOCPTSNAME = 0x40287448; | |
| 378 | pub const TIOCRCVFRAME = 0x80087445; | |
| 379 | pub const TIOCREMOTE = 0x80047469; | |
| 380 | pub const TIOCSBRK = 0x2000747b; | |
| 381 | pub const TIOCSCTTY = 0x20007461; | |
| 382 | pub const TIOCSDTR = 0x20007479; | |
| 383 | pub const TIOCSETA = 0x802c7414; | |
| 384 | pub const TIOCSETAF = 0x802c7416; | |
| 385 | pub const TIOCSETAW = 0x802c7415; | |
| 386 | pub const TIOCSETD = 0x8004741b; | |
| 387 | pub const TIOCSFLAGS = 0x8004745c; | |
| 388 | pub const TIOCSIG = 0x2000745f; | |
| 389 | pub const TIOCSLINED = 0x80207443; | |
| 390 | pub const TIOCSPGRP = 0x80047476; | |
| 391 | pub const TIOCSQSIZE = 0x80047480; | |
| 392 | pub const TIOCSSIZE = 0x80087467; | |
| 393 | pub const TIOCSTART = 0x2000746e; | |
| 394 | pub const TIOCSTAT = 0x80047465; | |
| 395 | pub const TIOCSTI = 0x80017472; | |
| 396 | pub const TIOCSTOP = 0x2000746f; | |
| 397 | pub const TIOCSWINSZ = 0x80087467; | |
| 398 | pub const TIOCUCNTL = 0x80047466; | |
| 399 | pub const TIOCXMTFRAME = 0x80087444; | |
| 400 | ||
| 401 | pub const sockaddr = c.sockaddr; | |
| 402 | pub const sockaddr_in = c.sockaddr_in; | |
| 403 | pub const sockaddr_in6 = c.sockaddr_in6; | |
| 404 | ||
| 405 | fn unsigned(s: i32) u32 { | |
| 406 | return @bitCast(u32, s); | |
| 407 | } | |
| 408 | fn signed(s: u32) i32 { | |
| 409 | return @bitCast(i32, s); | |
| 410 | } | |
| 411 | pub fn WEXITSTATUS(s: i32) i32 { | |
| 412 | return signed((unsigned(s) >> 8) & 0xff); | |
| 413 | } | |
| 414 | pub fn WTERMSIG(s: i32) i32 { | |
| 415 | return signed(unsigned(s) & 0x7f); | |
| 416 | } | |
| 417 | pub fn WSTOPSIG(s: i32) i32 { | |
| 418 | return WEXITSTATUS(s); | |
| 419 | } | |
| 420 | pub fn WIFEXITED(s: i32) bool { | |
| 421 | return WTERMSIG(s) == 0; | |
| 422 | } | |
| 423 | ||
| 424 | pub fn WIFCONTINUED(s: i32) bool { | |
| 425 | return ((s & 0x7f) == 0xffff); | |
| 426 | } | |
| 427 | ||
| 428 | pub fn WIFSTOPPED(s: i32) bool { | |
| 429 | return ((s & 0x7f != 0x7f) and !WIFCONTINUED(s)); | |
| 430 | } | |
| 431 | ||
| 432 | pub fn WIFSIGNALED(s: i32) bool { | |
| 433 | return !WIFSTOPPED(s) and !WIFCONTINUED(s) and !WIFEXITED(s); | |
| 434 | } | |
| 435 | ||
| 436 | pub const winsize = extern struct { | |
| 437 | ws_row: u16, | |
| 438 | ws_col: u16, | |
| 439 | ws_xpixel: u16, | |
| 440 | ws_ypixel: u16, | |
| 441 | }; | |
| 442 | ||
| 443 | /// Get the errno from a syscall return value, or 0 for no error. | |
| 444 | pub fn getErrno(r: usize) usize { | |
| 445 | const signed_r = @bitCast(isize, r); | |
| 446 | return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0; | |
| 447 | } | |
| 448 | ||
| 449 | pub fn dup2(old: i32, new: i32) usize { | |
| 450 | return errnoWrap(c.dup2(old, new)); | |
| 451 | } | |
| 452 | ||
| 453 | pub fn chdir(path: [*]const u8) usize { | |
| 454 | return errnoWrap(c.chdir(path)); | |
| 455 | } | |
| 456 | ||
| 457 | pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize { | |
| 458 | return errnoWrap(c.execve(path, argv, envp)); | |
| 459 | } | |
| 460 | ||
| 461 | pub fn fork() usize { | |
| 462 | return errnoWrap(c.fork()); | |
| 463 | } | |
| 464 | ||
| 465 | pub fn access(path: [*]const u8, mode: u32) usize { | |
| 466 | return errnoWrap(c.access(path, mode)); | |
| 467 | } | |
| 468 | ||
| 469 | pub fn getcwd(buf: [*]u8, size: usize) usize { | |
| 470 | return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0; | |
| 471 | } | |
| 472 | ||
| 473 | pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize { | |
| 474 | return errnoWrap(@bitCast(isize, c.getdents(fd, drip, count))); | |
| 475 | } | |
| 476 | ||
| 477 | pub fn getdirentries(fd: i32, buf_ptr: [*]u8, buf_len: usize, basep: *i64) usize { | |
| 478 | return errnoWrap(@bitCast(isize, c.getdirentries(fd, buf_ptr, buf_len, basep))); | |
| 479 | } | |
| 480 | ||
| 481 | pub fn realpath(noalias filename: [*]const u8, noalias resolved_name: [*]u8) usize { | |
| 482 | return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0; | |
| 483 | } | |
| 484 | ||
| 485 | pub fn isatty(fd: i32) bool { | |
| 486 | return c.isatty(fd) != 0; | |
| 487 | } | |
| 488 | ||
| 489 | pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { | |
| 490 | return errnoWrap(c.readlink(path, buf_ptr, buf_len)); | |
| 491 | } | |
| 492 | ||
| 493 | pub fn mkdir(path: [*]const u8, mode: u32) usize { | |
| 494 | return errnoWrap(c.mkdir(path, mode)); | |
| 495 | } | |
| 496 | ||
| 497 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { | |
| 498 | const ptr_result = c.mmap( | |
| 499 | @ptrCast(?*c_void, address), | |
| 500 | length, | |
| 501 | @bitCast(c_int, @intCast(c_uint, prot)), | |
| 502 | @bitCast(c_int, c_uint(flags)), | |
| 503 | fd, | |
| 504 | offset, | |
| 505 | ); | |
| 506 | const isize_result = @bitCast(isize, @ptrToInt(ptr_result)); | |
| 507 | return errnoWrap(isize_result); | |
| 508 | } | |
| 509 | ||
| 510 | pub fn munmap(address: usize, length: usize) usize { | |
| 511 | return errnoWrap(c.munmap(@intToPtr(*c_void, address), length)); | |
| 512 | } | |
| 513 | ||
| 514 | pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize { | |
| 515 | return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte)); | |
| 516 | } | |
| 517 | ||
| 518 | pub fn rmdir(path: [*]const u8) usize { | |
| 519 | return errnoWrap(c.rmdir(path)); | |
| 520 | } | |
| 521 | ||
| 522 | pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { | |
| 523 | return errnoWrap(c.symlink(existing, new)); | |
| 524 | } | |
| 525 | ||
| 526 | pub fn pread(fd: i32, buf: [*]u8, nbyte: usize, offset: u64) usize { | |
| 527 | return errnoWrap(c.pread(fd, @ptrCast(*c_void, buf), nbyte, offset)); | |
| 528 | } | |
| 529 | ||
| 530 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize { | |
| 531 | return errnoWrap(c.preadv(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset)); | |
| 532 | } | |
| 533 | ||
| 534 | pub fn pipe(fd: *[2]i32) usize { | |
| 535 | return pipe2(fd, 0); | |
| 536 | } | |
| 537 | ||
| 538 | pub fn pipe2(fd: *[2]i32, flags: u32) usize { | |
| 539 | comptime assert(i32.bit_count == c_int.bit_count); | |
| 540 | return errnoWrap(c.pipe2(@ptrCast(*[2]c_int, fd), flags)); | |
| 541 | } | |
| 542 | ||
| 543 | pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize { | |
| 544 | return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte)); | |
| 545 | } | |
| 546 | ||
| 547 | pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize { | |
| 548 | return errnoWrap(c.pwrite(fd, @ptrCast(*const c_void, buf), nbyte, offset)); | |
| 549 | } | |
| 550 | ||
| 551 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize { | |
| 552 | return errnoWrap(c.pwritev(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset)); | |
| 553 | } | |
| 554 | ||
| 555 | pub fn rename(old: [*]const u8, new: [*]const u8) usize { | |
| 556 | return errnoWrap(c.rename(old, new)); | |
| 557 | } | |
| 558 | ||
| 559 | pub fn open(path: [*]const u8, flags: u32, mode: usize) usize { | |
| 560 | return errnoWrap(c.open(path, @bitCast(c_int, flags), mode)); | |
| 561 | } | |
| 562 | ||
| 563 | pub fn create(path: [*]const u8, perm: usize) usize { | |
| 564 | return arch.syscall2(SYS_creat, @ptrToInt(path), perm); | |
| 565 | } | |
| 566 | ||
| 567 | pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize { | |
| 568 | return errnoWrap(c.openat(@bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode)); | |
| 569 | } | |
| 570 | ||
| 571 | pub fn close(fd: i32) usize { | |
| 572 | return errnoWrap(c.close(fd)); | |
| 573 | } | |
| 574 | ||
| 575 | pub fn lseek(fd: i32, offset: isize, whence: c_int) usize { | |
| 576 | return errnoWrap(c.lseek(fd, offset, whence)); | |
| 577 | } | |
| 578 | ||
| 579 | pub fn exit(code: i32) noreturn { | |
| 580 | c.exit(code); | |
| 581 | } | |
| 582 | ||
| 583 | pub fn kill(pid: i32, sig: i32) usize { | |
| 584 | return errnoWrap(c.kill(pid, sig)); | |
| 585 | } | |
| 586 | ||
| 587 | pub fn unlink(path: [*]const u8) usize { | |
| 588 | return errnoWrap(c.unlink(path)); | |
| 589 | } | |
| 590 | ||
| 591 | pub fn waitpid(pid: i32, status: *i32, options: u32) usize { | |
| 592 | comptime assert(i32.bit_count == c_int.bit_count); | |
| 593 | return errnoWrap(c.waitpid(pid, @ptrCast(*c_int, status), @bitCast(c_int, options))); | |
| 594 | } | |
| 595 | ||
| 596 | pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { | |
| 597 | return errnoWrap(c.nanosleep(req, rem)); | |
| 598 | } | |
| 599 | ||
| 600 | pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { | |
| 601 | return errnoWrap(c.clock_gettime(clk_id, tp)); | |
| 602 | } | |
| 603 | ||
| 604 | pub fn clock_getres(clk_id: i32, tp: *timespec) usize { | |
| 605 | return errnoWrap(c.clock_getres(clk_id, tp)); | |
| 606 | } | |
| 607 | ||
| 608 | pub fn setuid(uid: u32) usize { | |
| 609 | return errnoWrap(c.setuid(uid)); | |
| 610 | } | |
| 611 | ||
| 612 | pub fn setgid(gid: u32) usize { | |
| 613 | return errnoWrap(c.setgid(gid)); | |
| 614 | } | |
| 615 | ||
| 616 | pub fn setreuid(ruid: u32, euid: u32) usize { | |
| 617 | return errnoWrap(c.setreuid(ruid, euid)); | |
| 618 | } | |
| 619 | ||
| 620 | pub fn setregid(rgid: u32, egid: u32) usize { | |
| 621 | return errnoWrap(c.setregid(rgid, egid)); | |
| 622 | } | |
| 623 | ||
| 624 | const NSIG = 32; | |
| 625 | ||
| 626 | pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize)); | |
| 627 | pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); | |
| 628 | pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); | |
| 629 | ||
| 630 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | |
| 631 | pub const Sigaction = extern struct { | |
| 632 | /// signal handler | |
| 633 | __sigaction_u: extern union { | |
| 634 | __sa_handler: extern fn (i32) void, | |
| 635 | __sa_sigaction: extern fn (i32, *__siginfo, usize) void, | |
| 636 | }, | |
| 637 | ||
| 638 | /// see signal options | |
| 639 | sa_flags: u32, | |
| 640 | ||
| 641 | /// signal mask to apply | |
| 642 | sa_mask: sigset_t, | |
| 643 | }; | |
| 644 | ||
| 645 | pub const _SIG_WORDS = 4; | |
| 646 | pub const _SIG_MAXSIG = 128; | |
| 647 | ||
| 648 | pub inline fn _SIG_IDX(sig: usize) usize { | |
| 649 | return sig - 1; | |
| 650 | } | |
| 651 | pub inline fn _SIG_WORD(sig: usize) usize { | |
| 652 | return_SIG_IDX(sig) >> 5; | |
| 653 | } | |
| 654 | pub inline fn _SIG_BIT(sig: usize) usize { | |
| 655 | return 1 << (_SIG_IDX(sig) & 31); | |
| 656 | } | |
| 657 | pub inline fn _SIG_VALID(sig: usize) usize { | |
| 658 | return sig <= _SIG_MAXSIG and sig > 0; | |
| 659 | } | |
| 660 | ||
| 661 | pub const sigset_t = extern struct { | |
| 662 | __bits: [_SIG_WORDS]u32, | |
| 663 | }; | |
| 664 | ||
| 665 | pub fn raise(sig: i32) usize { | |
| 666 | return errnoWrap(c.raise(sig)); | |
| 667 | } | |
| 668 | ||
| 669 | pub const Stat = c.Stat; | |
| 670 | pub const dirent = c.dirent; | |
| 671 | pub const timespec = c.timespec; | |
| 672 | ||
| 673 | pub fn fstat(fd: i32, buf: *c.Stat) usize { | |
| 674 | return errnoWrap(c.fstat(fd, buf)); | |
| 675 | } | |
| 676 | pub const iovec = extern struct { | |
| 677 | iov_base: [*]u8, | |
| 678 | iov_len: usize, | |
| 679 | }; | |
| 680 | ||
| 681 | pub const iovec_const = extern struct { | |
| 682 | iov_base: [*]const u8, | |
| 683 | iov_len: usize, | |
| 684 | }; | |
| 685 | ||
| 686 | // TODO avoid libc dependency | |
| 687 | pub fn kqueue() usize { | |
| 688 | return errnoWrap(c.kqueue()); | |
| 689 | } | |
| 690 | ||
| 691 | // TODO avoid libc dependency | |
| 692 | pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize { | |
| 693 | return errnoWrap(c.kevent( | |
| 694 | kq, | |
| 695 | changelist.ptr, | |
| 696 | @intCast(c_int, changelist.len), | |
| 697 | eventlist.ptr, | |
| 698 | @intCast(c_int, eventlist.len), | |
| 699 | timeout, | |
| 700 | )); | |
| 701 | } | |
| 702 | ||
| 703 | // TODO avoid libc dependency | |
| 704 | pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { | |
| 705 | return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen)); | |
| 706 | } | |
| 707 | ||
| 708 | // TODO avoid libc dependency | |
| 709 | pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { | |
| 710 | return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen)); | |
| 711 | } | |
| 712 | ||
| 713 | // TODO avoid libc dependency | |
| 714 | pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize { | |
| 715 | return errnoWrap(c.sysctlnametomib(name, wibp, sizep)); | |
| 716 | } | |
| 717 | ||
| 718 | // TODO avoid libc dependency | |
| 719 | ||
| 720 | /// Takes the return value from a syscall and formats it back in the way | |
| 721 | /// that the kernel represents it to libc. Errno was a mistake, let's make | |
| 722 | /// it go away forever. | |
| 723 | fn errnoWrap(value: isize) usize { | |
| 724 | return @bitCast(usize, if (value == -1) -isize(c._errno().*) else value); | |
| 725 | } |
std/os/path.zig+2-2| ... | ... | @@ -1226,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro |
| 1226 | 1226 | const pathname_w = try windows_util.cStrToPrefixedFileW(pathname); |
| 1227 | 1227 | return realW(out_buffer, pathname_w); |
| 1228 | 1228 | }, |
| 1229 | Os.freebsd, Os.macosx, Os.ios => { | |
| 1229 | Os.freebsd, Os.netbsd, Os.macosx, Os.ios => { | |
| 1230 | 1230 | // TODO instead of calling the libc function here, port the implementation to Zig |
| 1231 | 1231 | const err = posix.getErrno(posix.realpath(pathname, out_buffer)); |
| 1232 | 1232 | switch (err) { |
| ... | ... | @@ -1267,7 +1267,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError! |
| 1267 | 1267 | const pathname_w = try windows_util.sliceToPrefixedFileW(pathname); |
| 1268 | 1268 | return realW(out_buffer, &pathname_w); |
| 1269 | 1269 | }, |
| 1270 | Os.macosx, Os.ios, Os.linux, Os.freebsd => { | |
| 1270 | Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => { | |
| 1271 | 1271 | const pathname_c = try os.toPosixPath(pathname); |
| 1272 | 1272 | return realC(out_buffer, &pathname_c); |
| 1273 | 1273 | }, |
std/os/time.zig+5-5| ... | ... | @@ -14,7 +14,7 @@ pub const epoch = @import("epoch.zig"); |
| 14 | 14 | /// Sleep for the specified duration |
| 15 | 15 | pub fn sleep(nanoseconds: u64) void { |
| 16 | 16 | switch (builtin.os) { |
| 17 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 17 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 18 | 18 | const s = nanoseconds / ns_per_s; |
| 19 | 19 | const ns = nanoseconds % ns_per_s; |
| 20 | 20 | posixSleep(@intCast(u63, s), @intCast(u63, ns)); |
| ... | ... | @@ -62,7 +62,7 @@ pub fn timestamp() u64 { |
| 62 | 62 | /// Get the posix timestamp, UTC, in milliseconds |
| 63 | 63 | pub const milliTimestamp = switch (builtin.os) { |
| 64 | 64 | Os.windows => milliTimestampWindows, |
| 65 | Os.linux, Os.freebsd => milliTimestampPosix, | |
| 65 | Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix, | |
| 66 | 66 | Os.macosx, Os.ios => milliTimestampDarwin, |
| 67 | 67 | else => @compileError("Unsupported OS"), |
| 68 | 68 | }; |
| ... | ... | @@ -178,7 +178,7 @@ pub const Timer = struct { |
| 178 | 178 | debug.assert(err != windows.FALSE); |
| 179 | 179 | self.start_time = @intCast(u64, start_time); |
| 180 | 180 | }, |
| 181 | Os.linux, Os.freebsd => { | |
| 181 | Os.linux, Os.freebsd, Os.netbsd => { | |
| 182 | 182 | //On Linux, seccomp can do arbitrary things to our ability to call |
| 183 | 183 | // syscalls, including return any errno value it wants and |
| 184 | 184 | // inconsistently throwing errors. Since we can't account for |
| ... | ... | @@ -214,7 +214,7 @@ pub const Timer = struct { |
| 214 | 214 | var clock = clockNative() - self.start_time; |
| 215 | 215 | return switch (builtin.os) { |
| 216 | 216 | Os.windows => @divFloor(clock * ns_per_s, self.frequency), |
| 217 | Os.linux, Os.freebsd => clock, | |
| 217 | Os.linux, Os.freebsd, Os.netbsd => clock, | |
| 218 | 218 | Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom), |
| 219 | 219 | else => @compileError("Unsupported OS"), |
| 220 | 220 | }; |
| ... | ... | @@ -235,7 +235,7 @@ pub const Timer = struct { |
| 235 | 235 | |
| 236 | 236 | const clockNative = switch (builtin.os) { |
| 237 | 237 | Os.windows => clockWindows, |
| 238 | Os.linux, Os.freebsd => clockLinux, | |
| 238 | Os.linux, Os.freebsd, Os.netbsd => clockLinux, | |
| 239 | 239 | Os.macosx, Os.ios => clockDarwin, |
| 240 | 240 | else => @compileError("Unsupported OS"), |
| 241 | 241 | }; |
std/priority_queue.zig created+331| ... | ... | @@ -0,0 +1,331 @@ |
| 1 | const std = @import("index.zig"); | |
| 2 | const Allocator = std.mem.Allocator; | |
| 3 | const debug = std.debug; | |
| 4 | const expect = std.testing.expect; | |
| 5 | const expectEqual = std.testing.expectEqual; | |
| 6 | ||
| 7 | pub fn PriorityQueue(comptime T: type) type { | |
| 8 | return struct { | |
| 9 | const Self = @This(); | |
| 10 | ||
| 11 | items: []T, | |
| 12 | len: usize, | |
| 13 | allocator: *Allocator, | |
| 14 | compareFn: fn (a: T, b: T) bool, | |
| 15 | ||
| 16 | pub fn init(allocator: *Allocator, compareFn: fn (a: T, b: T) bool) Self { | |
| 17 | return Self{ | |
| 18 | .items = []T{}, | |
| 19 | .len = 0, | |
| 20 | .allocator = allocator, | |
| 21 | .compareFn = compareFn, | |
| 22 | }; | |
| 23 | } | |
| 24 | ||
| 25 | pub fn deinit(self: Self) void { | |
| 26 | self.allocator.free(self.items); | |
| 27 | } | |
| 28 | ||
| 29 | pub fn add(self: *Self, elem: T) !void { | |
| 30 | try ensureCapacity(self, self.len + 1); | |
| 31 | ||
| 32 | self.items[self.len] = elem; | |
| 33 | var child_index = self.len; | |
| 34 | while (child_index > 0) { | |
| 35 | var parent_index = ((child_index - 1) >> 1); | |
| 36 | const child = self.items[child_index]; | |
| 37 | const parent = self.items[parent_index]; | |
| 38 | ||
| 39 | if (!self.compareFn(child, parent)) break; | |
| 40 | ||
| 41 | self.items[parent_index] = child; | |
| 42 | self.items[child_index] = parent; | |
| 43 | child_index = parent_index; | |
| 44 | } | |
| 45 | self.len += 1; | |
| 46 | } | |
| 47 | ||
| 48 | pub fn peek(self: *Self) ?T { | |
| 49 | return if (self.len > 0) self.items[0] else null; | |
| 50 | } | |
| 51 | ||
| 52 | pub fn removeOrNull(self: *Self) ?T { | |
| 53 | return if (self.len > 0) self.remove() else null; | |
| 54 | } | |
| 55 | ||
| 56 | pub fn remove(self: *Self) T { | |
| 57 | const first = self.items[0]; | |
| 58 | const last = self.items[self.len - 1]; | |
| 59 | self.items[0] = last; | |
| 60 | self.len -= 1; | |
| 61 | siftDown(self); | |
| 62 | return first; | |
| 63 | } | |
| 64 | ||
| 65 | pub fn count(self: Self) usize { | |
| 66 | return self.len; | |
| 67 | } | |
| 68 | ||
| 69 | pub fn capacity(self: Self) usize { | |
| 70 | return self.items.len; | |
| 71 | } | |
| 72 | ||
| 73 | fn siftDown(self: *Self) void { | |
| 74 | var index: usize = 0; | |
| 75 | const half = self.len >> 1; | |
| 76 | while (true) { | |
| 77 | var left_index = (index << 1) + 1; | |
| 78 | var right_index = left_index + 1; | |
| 79 | var left = if (left_index < self.len) self.items[left_index] else null; | |
| 80 | var right = if (right_index < self.len) self.items[right_index] else null; | |
| 81 | ||
| 82 | var smallest_index = index; | |
| 83 | var smallest = self.items[index]; | |
| 84 | ||
| 85 | if (left) |e| { | |
| 86 | if (self.compareFn(e, smallest)) { | |
| 87 | smallest_index = left_index; | |
| 88 | smallest = e; | |
| 89 | } | |
| 90 | } | |
| 91 | ||
| 92 | if (right) |e| { | |
| 93 | if (self.compareFn(e, smallest)) { | |
| 94 | smallest_index = right_index; | |
| 95 | smallest = e; | |
| 96 | } | |
| 97 | } | |
| 98 | ||
| 99 | if (smallest_index == index) return; | |
| 100 | ||
| 101 | self.items[smallest_index] = self.items[index]; | |
| 102 | self.items[index] = smallest; | |
| 103 | index = smallest_index; | |
| 104 | ||
| 105 | if (index >= half) return; | |
| 106 | } | |
| 107 | } | |
| 108 | ||
| 109 | pub fn ensureCapacity(self: *Self, new_capacity: usize) !void { | |
| 110 | var better_capacity = self.capacity(); | |
| 111 | if (better_capacity >= new_capacity) return; | |
| 112 | while (true) { | |
| 113 | better_capacity += better_capacity / 2 + 8; | |
| 114 | if (better_capacity >= new_capacity) break; | |
| 115 | } | |
| 116 | self.items = try self.allocator.realloc(T, self.items, better_capacity); | |
| 117 | } | |
| 118 | ||
| 119 | pub fn resize(self: *Self, new_len: usize) !void { | |
| 120 | try self.ensureCapacity(new_len); | |
| 121 | self.len = new_len; | |
| 122 | } | |
| 123 | ||
| 124 | pub fn shrink(self: *Self, new_len: usize) void { | |
| 125 | assert(new_len <= self.len); | |
| 126 | self.len = new_len; | |
| 127 | } | |
| 128 | ||
| 129 | const Iterator = struct { | |
| 130 | queue: *PriorityQueue(T), | |
| 131 | count: usize, | |
| 132 | ||
| 133 | fn next(it: *Iterator) ?T { | |
| 134 | if (it.count > it.queue.len - 1) return null; | |
| 135 | const out = it.count; | |
| 136 | it.count += 1; | |
| 137 | return it.queue.items[out]; | |
| 138 | } | |
| 139 | ||
| 140 | fn reset(it: *Iterator) void { | |
| 141 | it.count = 0; | |
| 142 | } | |
| 143 | }; | |
| 144 | ||
| 145 | pub fn iterator(self: *Self) Iterator { | |
| 146 | return Iterator{ | |
| 147 | .queue = self, | |
| 148 | .count = 0, | |
| 149 | }; | |
| 150 | } | |
| 151 | ||
| 152 | fn dump(self: *Self) void { | |
| 153 | warn("{{ "); | |
| 154 | warn("items: "); | |
| 155 | for (self.items) |e, i| { | |
| 156 | if (i >= self.len) break; | |
| 157 | warn("{}, ", e); | |
| 158 | } | |
| 159 | warn("array: "); | |
| 160 | for (self.items) |e, i| { | |
| 161 | warn("{}, ", e); | |
| 162 | } | |
| 163 | warn("len: {} ", self.len); | |
| 164 | warn("capacity: {}", self.capacity()); | |
| 165 | warn(" }}\n"); | |
| 166 | } | |
| 167 | }; | |
| 168 | } | |
| 169 | ||
| 170 | fn lessThan(a: u32, b: u32) bool { | |
| 171 | return a < b; | |
| 172 | } | |
| 173 | ||
| 174 | fn greaterThan(a: u32, b: u32) bool { | |
| 175 | return a > b; | |
| 176 | } | |
| 177 | ||
| 178 | const PQ = PriorityQueue(u32); | |
| 179 | ||
| 180 | test "std.PriorityQueue: add and remove min heap" { | |
| 181 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 182 | defer queue.deinit(); | |
| 183 | ||
| 184 | try queue.add(54); | |
| 185 | try queue.add(12); | |
| 186 | try queue.add(7); | |
| 187 | try queue.add(23); | |
| 188 | try queue.add(25); | |
| 189 | try queue.add(13); | |
| 190 | expectEqual(u32(7), queue.remove()); | |
| 191 | expectEqual(u32(12), queue.remove()); | |
| 192 | expectEqual(u32(13), queue.remove()); | |
| 193 | expectEqual(u32(23), queue.remove()); | |
| 194 | expectEqual(u32(25), queue.remove()); | |
| 195 | expectEqual(u32(54), queue.remove()); | |
| 196 | } | |
| 197 | ||
| 198 | test "std.PriorityQueue: add and remove same min heap" { | |
| 199 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 200 | defer queue.deinit(); | |
| 201 | ||
| 202 | try queue.add(1); | |
| 203 | try queue.add(1); | |
| 204 | try queue.add(2); | |
| 205 | try queue.add(2); | |
| 206 | try queue.add(1); | |
| 207 | try queue.add(1); | |
| 208 | expectEqual(u32(1), queue.remove()); | |
| 209 | expectEqual(u32(1), queue.remove()); | |
| 210 | expectEqual(u32(1), queue.remove()); | |
| 211 | expectEqual(u32(1), queue.remove()); | |
| 212 | expectEqual(u32(2), queue.remove()); | |
| 213 | expectEqual(u32(2), queue.remove()); | |
| 214 | } | |
| 215 | ||
| 216 | test "std.PriorityQueue: removeOrNull on empty" { | |
| 217 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 218 | defer queue.deinit(); | |
| 219 | ||
| 220 | expect(queue.removeOrNull() == null); | |
| 221 | } | |
| 222 | ||
| 223 | test "std.PriorityQueue: edge case 3 elements" { | |
| 224 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 225 | defer queue.deinit(); | |
| 226 | ||
| 227 | try queue.add(9); | |
| 228 | try queue.add(3); | |
| 229 | try queue.add(2); | |
| 230 | expectEqual(u32(2), queue.remove()); | |
| 231 | expectEqual(u32(3), queue.remove()); | |
| 232 | expectEqual(u32(9), queue.remove()); | |
| 233 | } | |
| 234 | ||
| 235 | test "std.PriorityQueue: peek" { | |
| 236 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 237 | defer queue.deinit(); | |
| 238 | ||
| 239 | expect(queue.peek() == null); | |
| 240 | try queue.add(9); | |
| 241 | try queue.add(3); | |
| 242 | try queue.add(2); | |
| 243 | expectEqual(u32(2), queue.peek().?); | |
| 244 | expectEqual(u32(2), queue.peek().?); | |
| 245 | } | |
| 246 | ||
| 247 | test "std.PriorityQueue: sift up with odd indices" { | |
| 248 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 249 | defer queue.deinit(); | |
| 250 | const items = []u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 }; | |
| 251 | for (items) |e| { | |
| 252 | try queue.add(e); | |
| 253 | } | |
| 254 | ||
| 255 | expectEqual(u32(1), queue.remove()); | |
| 256 | expectEqual(u32(2), queue.remove()); | |
| 257 | expectEqual(u32(5), queue.remove()); | |
| 258 | expectEqual(u32(6), queue.remove()); | |
| 259 | expectEqual(u32(7), queue.remove()); | |
| 260 | expectEqual(u32(7), queue.remove()); | |
| 261 | expectEqual(u32(11), queue.remove()); | |
| 262 | expectEqual(u32(12), queue.remove()); | |
| 263 | expectEqual(u32(13), queue.remove()); | |
| 264 | expectEqual(u32(14), queue.remove()); | |
| 265 | expectEqual(u32(15), queue.remove()); | |
| 266 | expectEqual(u32(15), queue.remove()); | |
| 267 | expectEqual(u32(16), queue.remove()); | |
| 268 | expectEqual(u32(21), queue.remove()); | |
| 269 | expectEqual(u32(22), queue.remove()); | |
| 270 | expectEqual(u32(24), queue.remove()); | |
| 271 | expectEqual(u32(24), queue.remove()); | |
| 272 | expectEqual(u32(25), queue.remove()); | |
| 273 | } | |
| 274 | ||
| 275 | test "std.PriorityQueue: add and remove max heap" { | |
| 276 | var queue = PQ.init(debug.global_allocator, greaterThan); | |
| 277 | defer queue.deinit(); | |
| 278 | ||
| 279 | try queue.add(54); | |
| 280 | try queue.add(12); | |
| 281 | try queue.add(7); | |
| 282 | try queue.add(23); | |
| 283 | try queue.add(25); | |
| 284 | try queue.add(13); | |
| 285 | expectEqual(u32(54), queue.remove()); | |
| 286 | expectEqual(u32(25), queue.remove()); | |
| 287 | expectEqual(u32(23), queue.remove()); | |
| 288 | expectEqual(u32(13), queue.remove()); | |
| 289 | expectEqual(u32(12), queue.remove()); | |
| 290 | expectEqual(u32(7), queue.remove()); | |
| 291 | } | |
| 292 | ||
| 293 | test "std.PriorityQueue: add and remove same max heap" { | |
| 294 | var queue = PQ.init(debug.global_allocator, greaterThan); | |
| 295 | defer queue.deinit(); | |
| 296 | ||
| 297 | try queue.add(1); | |
| 298 | try queue.add(1); | |
| 299 | try queue.add(2); | |
| 300 | try queue.add(2); | |
| 301 | try queue.add(1); | |
| 302 | try queue.add(1); | |
| 303 | expectEqual(u32(2), queue.remove()); | |
| 304 | expectEqual(u32(2), queue.remove()); | |
| 305 | expectEqual(u32(1), queue.remove()); | |
| 306 | expectEqual(u32(1), queue.remove()); | |
| 307 | expectEqual(u32(1), queue.remove()); | |
| 308 | expectEqual(u32(1), queue.remove()); | |
| 309 | } | |
| 310 | ||
| 311 | test "std.PriorityQueue: iterator" { | |
| 312 | var queue = PQ.init(debug.global_allocator, lessThan); | |
| 313 | var map = std.AutoHashMap(u32, void).init(debug.global_allocator); | |
| 314 | defer { | |
| 315 | queue.deinit(); | |
| 316 | map.deinit(); | |
| 317 | } | |
| 318 | ||
| 319 | const items = []u32{ 54, 12, 7, 23, 25, 13 }; | |
| 320 | for (items) |e| { | |
| 321 | _ = try queue.add(e); | |
| 322 | _ = try map.put(e, {}); | |
| 323 | } | |
| 324 | ||
| 325 | var it = queue.iterator(); | |
| 326 | while (it.next()) |e| { | |
| 327 | _ = map.remove(e); | |
| 328 | } | |
| 329 | ||
| 330 | expectEqual(usize(0), map.count()); | |
| 331 | } |
std/special/bootstrap.zig+8-5| ... | ... | @@ -23,15 +23,15 @@ nakedcc fn _start() noreturn { |
| 23 | 23 | switch (builtin.arch) { |
| 24 | 24 | builtin.Arch.x86_64 => { |
| 25 | 25 | argc_ptr = asm ("lea (%%rsp), %[argc]" |
| 26 | : [argc] "=r" (-> [*]usize) | |
| 27 | ); | |
| 26 | : [argc] "=r" (-> [*]usize) | |
| 27 | ); | |
| 28 | 28 | }, |
| 29 | 29 | builtin.Arch.i386 => { |
| 30 | 30 | argc_ptr = asm ("lea (%%esp), %[argc]" |
| 31 | 31 | : [argc] "=r" (-> [*]usize) |
| 32 | 32 | ); |
| 33 | 33 | }, |
| 34 | builtin.Arch.aarch64v8 => { | |
| 34 | builtin.Arch.aarch64, builtin.Arch.aarch64_be => { | |
| 35 | 35 | argc_ptr = asm ("mov %[argc], sp" |
| 36 | 36 | : [argc] "=r" (-> [*]usize) |
| 37 | 37 | ); |
| ... | ... | @@ -123,7 +123,7 @@ inline fn callMain() u8 { |
| 123 | 123 | std.debug.warn("error: {}\n", @errorName(err)); |
| 124 | 124 | if (builtin.os != builtin.Os.zen) { |
| 125 | 125 | if (@errorReturnTrace()) |trace| { |
| 126 | std.debug.dumpStackTrace(trace); | |
| 126 | std.debug.dumpStackTrace(trace.*); | |
| 127 | 127 | } |
| 128 | 128 | } |
| 129 | 129 | return 1; |
| ... | ... | @@ -142,7 +142,10 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: |
| 142 | 142 | var phdr_addr = at_phdr; |
| 143 | 143 | var n = at_phnum; |
| 144 | 144 | var base: usize = 0; |
| 145 | while (n != 0) : ({n -= 1; phdr_addr += at_phent;}) { | |
| 145 | while (n != 0) : ({ | |
| 146 | n -= 1; | |
| 147 | phdr_addr += at_phent; | |
| 148 | }) { | |
| 146 | 149 | const phdr = @intToPtr(*std.elf.Phdr, phdr_addr); |
| 147 | 150 | // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917 |
| 148 | 151 | switch (phdr.p_type) { |
std/special/compiler_rt/addXf3.zig created+191| ... | ... | @@ -0,0 +1,191 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | const compiler_rt = @import("index.zig"); | |
| 8 | ||
| 9 | pub extern fn __addtf3(a: f128, b: f128) f128 { | |
| 10 | return addXf3(f128, a, b); | |
| 11 | } | |
| 12 | ||
| 13 | pub extern fn __subtf3(a: f128, b: f128) f128 { | |
| 14 | const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127)); | |
| 15 | return addXf3(f128, a, neg_b); | |
| 16 | } | |
| 17 | ||
| 18 | inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { | |
| 19 | const Z = @IntType(false, T.bit_count); | |
| 20 | const significandBits = std.math.floatMantissaBits(T); | |
| 21 | const implicitBit = Z(1) << significandBits; | |
| 22 | ||
| 23 | const shift = @clz(significand.*) - @clz(implicitBit); | |
| 24 | significand.* <<= @intCast(u7, shift); | |
| 25 | return 1 - shift; | |
| 26 | } | |
| 27 | ||
| 28 | inline fn addXf3(comptime T: type, a: T, b: T) T { | |
| 29 | const Z = @IntType(false, T.bit_count); | |
| 30 | ||
| 31 | const typeWidth = T.bit_count; | |
| 32 | const significandBits = std.math.floatMantissaBits(T); | |
| 33 | const exponentBits = std.math.floatExponentBits(T); | |
| 34 | ||
| 35 | const signBit = (Z(1) << (significandBits + exponentBits)); | |
| 36 | const maxExponent = ((1 << exponentBits) - 1); | |
| 37 | const exponentBias = (maxExponent >> 1); | |
| 38 | ||
| 39 | const implicitBit = (Z(1) << significandBits); | |
| 40 | const quietBit = implicitBit >> 1; | |
| 41 | const significandMask = implicitBit - 1; | |
| 42 | ||
| 43 | const absMask = signBit - 1; | |
| 44 | const exponentMask = absMask ^ significandMask; | |
| 45 | const qnanRep = exponentMask | quietBit; | |
| 46 | ||
| 47 | var aRep = @bitCast(Z, a); | |
| 48 | var bRep = @bitCast(Z, b); | |
| 49 | const aAbs = aRep & absMask; | |
| 50 | const bAbs = bRep & absMask; | |
| 51 | ||
| 52 | const negative = (aRep & signBit) != 0; | |
| 53 | const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias; | |
| 54 | const significand = (aAbs & significandMask) | implicitBit; | |
| 55 | ||
| 56 | const infRep = @bitCast(Z, std.math.inf(T)); | |
| 57 | ||
| 58 | // Detect if a or b is zero, infinity, or NaN. | |
| 59 | if (aAbs - Z(1) >= infRep - Z(1) or | |
| 60 | bAbs - Z(1) >= infRep - Z(1)) | |
| 61 | { | |
| 62 | // NaN + anything = qNaN | |
| 63 | if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); | |
| 64 | // anything + NaN = qNaN | |
| 65 | if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit); | |
| 66 | ||
| 67 | if (aAbs == infRep) { | |
| 68 | // +/-infinity + -/+infinity = qNaN | |
| 69 | if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) { | |
| 70 | return @bitCast(T, qnanRep); | |
| 71 | } | |
| 72 | // +/-infinity + anything remaining = +/- infinity | |
| 73 | else { | |
| 74 | return a; | |
| 75 | } | |
| 76 | } | |
| 77 | ||
| 78 | // anything remaining + +/-infinity = +/-infinity | |
| 79 | if (bAbs == infRep) return b; | |
| 80 | ||
| 81 | // zero + anything = anything | |
| 82 | if (aAbs == 0) { | |
| 83 | // but we need to get the sign right for zero + zero | |
| 84 | if (bAbs == 0) { | |
| 85 | return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b)); | |
| 86 | } else { | |
| 87 | return b; | |
| 88 | } | |
| 89 | } | |
| 90 | ||
| 91 | // anything + zero = anything | |
| 92 | if (bAbs == 0) return a; | |
| 93 | } | |
| 94 | ||
| 95 | // Swap a and b if necessary so that a has the larger absolute value. | |
| 96 | if (bAbs > aAbs) { | |
| 97 | const temp = aRep; | |
| 98 | aRep = bRep; | |
| 99 | bRep = temp; | |
| 100 | } | |
| 101 | ||
| 102 | // Extract the exponent and significand from the (possibly swapped) a and b. | |
| 103 | var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent); | |
| 104 | var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent); | |
| 105 | var aSignificand = aRep & significandMask; | |
| 106 | var bSignificand = bRep & significandMask; | |
| 107 | ||
| 108 | // Normalize any denormals, and adjust the exponent accordingly. | |
| 109 | if (aExponent == 0) aExponent = normalize(T, &aSignificand); | |
| 110 | if (bExponent == 0) bExponent = normalize(T, &bSignificand); | |
| 111 | ||
| 112 | // The sign of the result is the sign of the larger operand, a. If they | |
| 113 | // have opposite signs, we are performing a subtraction; otherwise addition. | |
| 114 | const resultSign = aRep & signBit; | |
| 115 | const subtraction = (aRep ^ bRep) & signBit != 0; | |
| 116 | ||
| 117 | // Shift the significands to give us round, guard and sticky, and or in the | |
| 118 | // implicit significand bit. (If we fell through from the denormal path it | |
| 119 | // was already set by normalize( ), but setting it twice won't hurt | |
| 120 | // anything.) | |
| 121 | aSignificand = (aSignificand | implicitBit) << 3; | |
| 122 | bSignificand = (bSignificand | implicitBit) << 3; | |
| 123 | ||
| 124 | // Shift the significand of b by the difference in exponents, with a sticky | |
| 125 | // bottom bit to get rounding correct. | |
| 126 | const @"align" = @intCast(Z, aExponent - bExponent); | |
| 127 | if (@"align" != 0) { | |
| 128 | if (@"align" < typeWidth) { | |
| 129 | const sticky = if (bSignificand << @intCast(u7, typeWidth - @"align") != 0) Z(1) else 0; | |
| 130 | bSignificand = (bSignificand >> @truncate(u7, @"align")) | sticky; | |
| 131 | } else { | |
| 132 | bSignificand = 1; // sticky; b is known to be non-zero. | |
| 133 | } | |
| 134 | } | |
| 135 | if (subtraction) { | |
| 136 | aSignificand -= bSignificand; | |
| 137 | // If a == -b, return +zero. | |
| 138 | if (aSignificand == 0) return @bitCast(T, Z(0)); | |
| 139 | ||
| 140 | // If partial cancellation occured, we need to left-shift the result | |
| 141 | // and adjust the exponent: | |
| 142 | if (aSignificand < implicitBit << 3) { | |
| 143 | const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3)); | |
| 144 | aSignificand <<= @intCast(u7, shift); | |
| 145 | aExponent -= shift; | |
| 146 | } | |
| 147 | } else { // addition | |
| 148 | aSignificand += bSignificand; | |
| 149 | ||
| 150 | // If the addition carried up, we need to right-shift the result and | |
| 151 | // adjust the exponent: | |
| 152 | if (aSignificand & (implicitBit << 4) != 0) { | |
| 153 | const sticky = aSignificand & 1; | |
| 154 | aSignificand = aSignificand >> 1 | sticky; | |
| 155 | aExponent += 1; | |
| 156 | } | |
| 157 | } | |
| 158 | ||
| 159 | // If we have overflowed the type, return +/- infinity: | |
| 160 | if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign); | |
| 161 | ||
| 162 | if (aExponent <= 0) { | |
| 163 | // Result is denormal before rounding; the exponent is zero and we | |
| 164 | // need to shift the significand. | |
| 165 | const shift = @intCast(Z, 1 - aExponent); | |
| 166 | const sticky = if (aSignificand << @intCast(u7, typeWidth - shift) != 0) Z(1) else 0; | |
| 167 | aSignificand = aSignificand >> @intCast(u7, shift | sticky); | |
| 168 | aExponent = 0; | |
| 169 | } | |
| 170 | ||
| 171 | // Low three bits are round, guard, and sticky. | |
| 172 | const roundGuardSticky = aSignificand & 0x7; | |
| 173 | ||
| 174 | // Shift the significand into place, and mask off the implicit bit. | |
| 175 | var result = (aSignificand >> 3) & significandMask; | |
| 176 | ||
| 177 | // Insert the exponent and sign. | |
| 178 | result |= @intCast(Z, aExponent) << significandBits; | |
| 179 | result |= resultSign; | |
| 180 | ||
| 181 | // Final rounding. The result may overflow to infinity, but that is the | |
| 182 | // correct result in that case. | |
| 183 | if (roundGuardSticky > 0x4) result += 1; | |
| 184 | if (roundGuardSticky == 0x4) result += result & 1; | |
| 185 | ||
| 186 | return @bitCast(T, result); | |
| 187 | } | |
| 188 | ||
| 189 | test "import addXf3" { | |
| 190 | _ = @import("addXf3_test.zig"); | |
| 191 | } |
std/special/compiler_rt/addXf3_test.zig created+85| ... | ... | @@ -0,0 +1,85 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c | |
| 4 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c | |
| 5 | ||
| 6 | const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64); | |
| 7 | const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64); | |
| 8 | ||
| 9 | const __addtf3 = @import("addXf3.zig").__addtf3; | |
| 10 | ||
| 11 | fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { | |
| 12 | const x = __addtf3(a, b); | |
| 13 | ||
| 14 | const rep = @bitCast(u128, x); | |
| 15 | const hi = @intCast(u64, rep >> 64); | |
| 16 | const lo = @truncate(u64, rep); | |
| 17 | ||
| 18 | if (hi == expected_hi and lo == expected_lo) { | |
| 19 | return; | |
| 20 | } | |
| 21 | // test other possible NaN representation (signal NaN) | |
| 22 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 23 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 24 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 25 | { | |
| 26 | return; | |
| 27 | } | |
| 28 | } | |
| 29 | ||
| 30 | @panic("__addtf3 test failure"); | |
| 31 | } | |
| 32 | ||
| 33 | test "addtf3" { | |
| 34 | test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 35 | ||
| 36 | // NaN + any = NaN | |
| 37 | test__addtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 38 | ||
| 39 | // inf + inf = inf | |
| 40 | test__addtf3(inf128, inf128, 0x7fff000000000000, 0x0); | |
| 41 | ||
| 42 | // inf + any = inf | |
| 43 | test__addtf3(inf128, 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0); | |
| 44 | ||
| 45 | // any + any | |
| 46 | test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c); | |
| 47 | } | |
| 48 | ||
| 49 | const __subtf3 = @import("addXf3.zig").__subtf3; | |
| 50 | ||
| 51 | fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { | |
| 52 | const x = __subtf3(a, b); | |
| 53 | ||
| 54 | const rep = @bitCast(u128, x); | |
| 55 | const hi = @intCast(u64, rep >> 64); | |
| 56 | const lo = @truncate(u64, rep); | |
| 57 | ||
| 58 | if (hi == expected_hi and lo == expected_lo) { | |
| 59 | return; | |
| 60 | } | |
| 61 | // test other possible NaN representation (signal NaN) | |
| 62 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 63 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 64 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 65 | { | |
| 66 | return; | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | @panic("__subtf3 test failure"); | |
| 71 | } | |
| 72 | ||
| 73 | test "subtf3" { | |
| 74 | // qNaN - any = qNaN | |
| 75 | test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 76 | ||
| 77 | // NaN + any = NaN | |
| 78 | test__subtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 79 | ||
| 80 | // inf - any = inf | |
| 81 | test__subtf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 82 | ||
| 83 | // any + any | |
| 84 | test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c); | |
| 85 | } |
std/special/compiler_rt/index.zig+8-54| ... | ... | @@ -21,6 +21,9 @@ comptime { |
| 21 | 21 | |
| 22 | 22 | @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); |
| 23 | 23 | |
| 24 | @export("__addtf3", @import("addXf3.zig").__addtf3, linkage); | |
| 25 | @export("__subtf3", @import("addXf3.zig").__subtf3, linkage); | |
| 26 | ||
| 24 | 27 | @export("__floattitf", @import("floattitf.zig").__floattitf, linkage); |
| 25 | 28 | @export("__floattidf", @import("floattidf.zig").__floattidf, linkage); |
| 26 | 29 | @export("__floattisf", @import("floattisf.zig").__floattisf, linkage); |
| ... | ... | @@ -37,6 +40,7 @@ comptime { |
| 37 | 40 | @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage); |
| 38 | 41 | |
| 39 | 42 | @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage); |
| 43 | @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage); | |
| 40 | 44 | @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage); |
| 41 | 45 | @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage); |
| 42 | 46 | |
| ... | ... | @@ -180,60 +184,10 @@ const is_arm_64 = switch (builtin.arch) { |
| 180 | 184 | }; |
| 181 | 185 | |
| 182 | 186 | const is_arm_arch = switch (builtin.arch) { |
| 183 | builtin.Arch.armv8_3a, | |
| 184 | builtin.Arch.armv8_2a, | |
| 185 | builtin.Arch.armv8_1a, | |
| 186 | builtin.Arch.armv8, | |
| 187 | builtin.Arch.armv8r, | |
| 188 | builtin.Arch.armv8m_baseline, | |
| 189 | builtin.Arch.armv8m_mainline, | |
| 190 | builtin.Arch.armv7, | |
| 191 | builtin.Arch.armv7em, | |
| 192 | builtin.Arch.armv7m, | |
| 193 | builtin.Arch.armv7s, | |
| 194 | builtin.Arch.armv7k, | |
| 195 | builtin.Arch.armv7ve, | |
| 196 | builtin.Arch.armv6, | |
| 197 | builtin.Arch.armv6m, | |
| 198 | builtin.Arch.armv6k, | |
| 199 | builtin.Arch.armv6t2, | |
| 200 | builtin.Arch.armv5, | |
| 201 | builtin.Arch.armv5te, | |
| 202 | builtin.Arch.armv4t, | |
| 203 | builtin.Arch.armebv8_3a, | |
| 204 | builtin.Arch.armebv8_2a, | |
| 205 | builtin.Arch.armebv8_1a, | |
| 206 | builtin.Arch.armebv8, | |
| 207 | builtin.Arch.armebv8r, | |
| 208 | builtin.Arch.armebv8m_baseline, | |
| 209 | builtin.Arch.armebv8m_mainline, | |
| 210 | builtin.Arch.armebv7, | |
| 211 | builtin.Arch.armebv7em, | |
| 212 | builtin.Arch.armebv7m, | |
| 213 | builtin.Arch.armebv7s, | |
| 214 | builtin.Arch.armebv7k, | |
| 215 | builtin.Arch.armebv7ve, | |
| 216 | builtin.Arch.armebv6, | |
| 217 | builtin.Arch.armebv6m, | |
| 218 | builtin.Arch.armebv6k, | |
| 219 | builtin.Arch.armebv6t2, | |
| 220 | builtin.Arch.armebv5, | |
| 221 | builtin.Arch.armebv5te, | |
| 222 | builtin.Arch.armebv4t, | |
| 223 | builtin.Arch.aarch64v8_3a, | |
| 224 | builtin.Arch.aarch64v8_2a, | |
| 225 | builtin.Arch.aarch64v8_1a, | |
| 226 | builtin.Arch.aarch64v8, | |
| 227 | builtin.Arch.aarch64v8r, | |
| 228 | builtin.Arch.aarch64v8m_baseline, | |
| 229 | builtin.Arch.aarch64v8m_mainline, | |
| 230 | builtin.Arch.aarch64_bev8_3a, | |
| 231 | builtin.Arch.aarch64_bev8_2a, | |
| 232 | builtin.Arch.aarch64_bev8_1a, | |
| 233 | builtin.Arch.aarch64_bev8, | |
| 234 | builtin.Arch.aarch64_bev8r, | |
| 235 | builtin.Arch.aarch64_bev8m_baseline, | |
| 236 | builtin.Arch.aarch64_bev8m_mainline, | |
| 187 | builtin.Arch.arm, | |
| 188 | builtin.Arch.armeb, | |
| 189 | builtin.Arch.aarch64, | |
| 190 | builtin.Arch.aarch64_be, | |
| 237 | 191 | builtin.Arch.thumb, |
| 238 | 192 | builtin.Arch.thumbeb, |
| 239 | 193 | => true, |
std/special/compiler_rt/truncXfYf2.zig+4| ... | ... | @@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 { |
| 4 | 4 | return @bitCast(u16, truncXfYf2(f16, f32, a)); |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | pub extern fn __truncdfhf2(a: f64) u16 { | |
| 8 | return @bitCast(u16, truncXfYf2(f16, f64, a)); | |
| 9 | } | |
| 10 | ||
| 7 | 11 | pub extern fn __trunctfsf2(a: f128) f32 { |
| 8 | 12 | return truncXfYf2(f32, f128, a); |
| 9 | 13 | } |
std/special/compiler_rt/truncXfYf2_test.zig+68| ... | ... | @@ -63,6 +63,74 @@ test "truncsfhf2" { |
| 63 | 63 | test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2; | |
| 67 | ||
| 68 | fn test__truncdfhf2(a: f64, expected: u16) void { | |
| 69 | const rep = @bitCast(u16, __truncdfhf2(a)); | |
| 70 | ||
| 71 | if (rep == expected) { | |
| 72 | return; | |
| 73 | } | |
| 74 | // test other possible NaN representation(signal NaN) | |
| 75 | else if (expected == 0x7e00) { | |
| 76 | if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) { | |
| 77 | return; | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | @panic("__truncdfhf2 test failure"); | |
| 82 | } | |
| 83 | ||
| 84 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { | |
| 85 | const actual = __truncdfhf2(@bitCast(f64, a)); | |
| 86 | ||
| 87 | if (actual == expected) { | |
| 88 | return; | |
| 89 | } | |
| 90 | ||
| 91 | @panic("__truncdfhf2 test failure"); | |
| 92 | } | |
| 93 | ||
| 94 | test "truncdfhf2" { | |
| 95 | test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN | |
| 96 | test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN | |
| 97 | ||
| 98 | test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf | |
| 99 | test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf | |
| 100 | ||
| 101 | test__truncdfhf2(0.0, 0x0); // zero | |
| 102 | test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero | |
| 103 | ||
| 104 | test__truncdfhf2(3.1415926535, 0x4248); | |
| 105 | test__truncdfhf2(-3.1415926535, 0xc248); | |
| 106 | ||
| 107 | test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); | |
| 108 | test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 109 | test__truncdfhf2(0x1.0p+0, 0x3c00); | |
| 110 | test__truncdfhf2(0x1.0p-14, 0x0400); | |
| 111 | ||
| 112 | // denormal | |
| 113 | test__truncdfhf2(0x1.0p-20, 0x0010); | |
| 114 | test__truncdfhf2(0x1.0p-24, 0x0001); | |
| 115 | test__truncdfhf2(-0x1.0p-24, 0x8001); | |
| 116 | test__truncdfhf2(0x1.5p-25, 0x0001); | |
| 117 | ||
| 118 | // and back to zero | |
| 119 | test__truncdfhf2(0x1.0p-25, 0x0000); | |
| 120 | test__truncdfhf2(-0x1.0p-25, 0x8000); | |
| 121 | ||
| 122 | // max (precise) | |
| 123 | test__truncdfhf2(65504.0, 0x7bff); | |
| 124 | ||
| 125 | // max (rounded) | |
| 126 | test__truncdfhf2(65519.0, 0x7bff); | |
| 127 | ||
| 128 | // max (to +inf) | |
| 129 | test__truncdfhf2(65520.0, 0x7c00); | |
| 130 | test__truncdfhf2(-65520.0, 0xfc00); | |
| 131 | test__truncdfhf2(65536.0, 0x7c00); | |
| 132 | } | |
| 133 | ||
| 66 | 134 | const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2; |
| 67 | 135 | |
| 68 | 136 | fn test__trunctfsf2(a: f128, expected: u32) void { |
std/special/fmt_runner.zig created+260| ... | ... | @@ -0,0 +1,260 @@ |
| 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/testing.zig+2-2| ... | ... | @@ -59,13 +59,14 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { |
| 59 | 59 | switch (pointer.size) { |
| 60 | 60 | builtin.TypeInfo.Pointer.Size.One, |
| 61 | 61 | builtin.TypeInfo.Pointer.Size.Many, |
| 62 | builtin.TypeInfo.Pointer.Size.C, | |
| 62 | 63 | => { |
| 63 | 64 | if (actual != expected) { |
| 64 | 65 | std.debug.panic("expected {}, found {}", expected, actual); |
| 65 | 66 | } |
| 66 | 67 | }, |
| 67 | 68 | |
| 68 | builtin.TypeInfo.Pointer.Size.Slice => { | |
| 69 | builtin.TypeInfo.Pointer.Size.Slice => { | |
| 69 | 70 | if (actual.ptr != expected.ptr) { |
| 70 | 71 | std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr); |
| 71 | 72 | } |
| ... | ... | @@ -118,7 +119,6 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { |
| 118 | 119 | } |
| 119 | 120 | } |
| 120 | 121 | }, |
| 121 | ||
| 122 | 122 | } |
| 123 | 123 | } |
| 124 | 124 |
std/zig/parse.zig+6-1| ... | ... | @@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op { |
| 3525 | 3525 | Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} }, |
| 3526 | 3526 | Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} }, |
| 3527 | 3527 | Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} }, |
| 3528 | Token.Id.Asterisk, Token.Id.AsteriskAsterisk, Token.Id.BracketStarBracket => ast.Node.PrefixOp.Op{ | |
| 3528 | ||
| 3529 | Token.Id.Asterisk, | |
| 3530 | Token.Id.AsteriskAsterisk, | |
| 3531 | Token.Id.BracketStarBracket, | |
| 3532 | Token.Id.BracketStarCBracket, | |
| 3533 | => ast.Node.PrefixOp.Op{ | |
| 3529 | 3534 | .PtrType = ast.Node.PrefixOp.PtrInfo{ |
| 3530 | 3535 | .align_info = null, |
| 3531 | 3536 | .const_token = null, |
std/zig/parser_test.zig+16| ... | ... | @@ -1,3 +1,19 @@ |
| 1 | test "zig fmt: infix operator and then multiline string literal" { | |
| 2 | try testCanonical( | |
| 3 | \\const x = "" ++ | |
| 4 | \\ \\ hi | |
| 5 | \\; | |
| 6 | \\ | |
| 7 | ); | |
| 8 | } | |
| 9 | ||
| 10 | test "zig fmt: C pointers" { | |
| 11 | try testCanonical( | |
| 12 | \\const Ptr = [*c]i32; | |
| 13 | \\ | |
| 14 | ); | |
| 15 | } | |
| 16 | ||
| 1 | 17 | test "zig fmt: threadlocal" { |
| 2 | 18 | try testCanonical( |
| 3 | 19 | \\threadlocal var x: i32 = 1234; |
std/zig/render.zig+3-2| ... | ... | @@ -340,7 +340,6 @@ fn renderExpression( |
| 340 | 340 | ast.Node.Id.InfixOp => { |
| 341 | 341 | const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); |
| 342 | 342 | |
| 343 | const op_token = tree.tokens.at(infix_op_node.op_token); | |
| 344 | 343 | const op_space = switch (infix_op_node.op) { |
| 345 | 344 | ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None, |
| 346 | 345 | else => Space.Space, |
| ... | ... | @@ -353,7 +352,9 @@ fn renderExpression( |
| 353 | 352 | }; |
| 354 | 353 | |
| 355 | 354 | try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space); |
| 356 | if (after_op_space == Space.Newline) { | |
| 355 | if (after_op_space == Space.Newline and | |
| 356 | tree.tokens.at(tree.nextToken(infix_op_node.op_token)).id != Token.Id.MultilineStringLiteralLine) | |
| 357 | { | |
| 357 | 358 | try stream.writeByteNTimes(' ', indent + indent_delta); |
| 358 | 359 | start_col.* = indent + indent_delta; |
| 359 | 360 | } |
std/zig/tokenizer.zig+22-1| ... | ... | @@ -141,6 +141,7 @@ pub const Token = struct { |
| 141 | 141 | LineComment, |
| 142 | 142 | DocComment, |
| 143 | 143 | BracketStarBracket, |
| 144 | BracketStarCBracket, | |
| 144 | 145 | ShebangLine, |
| 145 | 146 | Keyword_align, |
| 146 | 147 | Keyword_and, |
| ... | ... | @@ -279,6 +280,7 @@ pub const Tokenizer = struct { |
| 279 | 280 | SawAtSign, |
| 280 | 281 | LBracket, |
| 281 | 282 | LBracketStar, |
| 283 | LBracketStarC, | |
| 282 | 284 | }; |
| 283 | 285 | |
| 284 | 286 | pub fn next(self: *Tokenizer) Token { |
| ... | ... | @@ -456,6 +458,9 @@ pub const Tokenizer = struct { |
| 456 | 458 | }, |
| 457 | 459 | |
| 458 | 460 | State.LBracketStar => switch (c) { |
| 461 | 'c' => { | |
| 462 | state = State.LBracketStarC; | |
| 463 | }, | |
| 459 | 464 | ']' => { |
| 460 | 465 | result.id = Token.Id.BracketStarBracket; |
| 461 | 466 | self.index += 1; |
| ... | ... | @@ -467,6 +472,18 @@ pub const Tokenizer = struct { |
| 467 | 472 | }, |
| 468 | 473 | }, |
| 469 | 474 | |
| 475 | State.LBracketStarC => switch (c) { | |
| 476 | ']' => { | |
| 477 | result.id = Token.Id.BracketStarCBracket; | |
| 478 | self.index += 1; | |
| 479 | break; | |
| 480 | }, | |
| 481 | else => { | |
| 482 | result.id = Token.Id.Invalid; | |
| 483 | break; | |
| 484 | }, | |
| 485 | }, | |
| 486 | ||
| 470 | 487 | State.Ampersand => switch (c) { |
| 471 | 488 | '=' => { |
| 472 | 489 | result.id = Token.Id.AmpersandEqual; |
| ... | ... | @@ -1035,6 +1052,7 @@ pub const Tokenizer = struct { |
| 1035 | 1052 | State.CharLiteralEnd, |
| 1036 | 1053 | State.StringLiteralBackslash, |
| 1037 | 1054 | State.LBracketStar, |
| 1055 | State.LBracketStarC, | |
| 1038 | 1056 | => { |
| 1039 | 1057 | result.id = Token.Id.Invalid; |
| 1040 | 1058 | }, |
| ... | ... | @@ -1169,12 +1187,15 @@ test "tokenizer" { |
| 1169 | 1187 | testTokenize("test", []Token.Id{Token.Id.Keyword_test}); |
| 1170 | 1188 | } |
| 1171 | 1189 | |
| 1172 | test "tokenizer - unknown length pointer" { | |
| 1190 | test "tokenizer - unknown length pointer and then c pointer" { | |
| 1173 | 1191 | testTokenize( |
| 1174 | 1192 | \\[*]u8 |
| 1193 | \\[*c]u8 | |
| 1175 | 1194 | , []Token.Id{ |
| 1176 | 1195 | Token.Id.BracketStarBracket, |
| 1177 | 1196 | Token.Id.Identifier, |
| 1197 | Token.Id.BracketStarCBracket, | |
| 1198 | Token.Id.Identifier, | |
| 1178 | 1199 | }); |
| 1179 | 1200 | } |
| 1180 | 1201 |
test/build_examples.zig+2-6| ... | ... | @@ -7,12 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void { |
| 7 | 7 | cases.addC("example/hello_world/hello_libc.zig"); |
| 8 | 8 | cases.add("example/cat/main.zig"); |
| 9 | 9 | cases.add("example/guess_number/main.zig"); |
| 10 | if (!is_windows) { | |
| 11 | // TODO get this test passing on windows | |
| 12 | // See https://github.com/ziglang/zig/issues/538 | |
| 13 | cases.addBuildFile("example/shared_library/build.zig"); | |
| 14 | cases.addBuildFile("example/mix_o_files/build.zig"); | |
| 15 | } | |
| 10 | cases.addBuildFile("example/shared_library/build.zig"); | |
| 11 | cases.addBuildFile("example/mix_o_files/build.zig"); | |
| 16 | 12 | if (builtin.os != builtin.Os.macosx) { |
| 17 | 13 | // TODO https://github.com/ziglang/zig/issues/1126 |
| 18 | 14 | cases.addBuildFile("test/standalone/issue_339/build.zig"); |
test/compile_errors.zig+405-69| ... | ... | @@ -1,13 +1,330 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | |
| 3 | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest( | |
| 6 | "not an enum type", | |
| 7 | \\export fn entry() void { | |
| 8 | \\ var self: Error = undefined; | |
| 9 | \\ switch (self) { | |
| 10 | \\ InvalidToken => |x| return x.token, | |
| 11 | \\ ExpectedVarDeclOrFn => |x| return x.token, | |
| 12 | \\ } | |
| 13 | \\} | |
| 14 | \\const Error = union(enum) { | |
| 15 | \\ A: InvalidToken, | |
| 16 | \\ B: ExpectedVarDeclOrFn, | |
| 17 | \\}; | |
| 18 | \\const InvalidToken = struct {}; | |
| 19 | \\const ExpectedVarDeclOrFn = struct {}; | |
| 20 | , | |
| 21 | ".tmp_source.zig:4:9: error: not an enum type", | |
| 22 | ); | |
| 23 | ||
| 24 | cases.addTest( | |
| 25 | "binary OR operator on error sets", | |
| 26 | \\pub const A = error.A; | |
| 27 | \\pub const AB = A | error.B; | |
| 28 | \\export fn entry() void { | |
| 29 | \\ var x: AB = undefined; | |
| 30 | \\} | |
| 31 | , | |
| 32 | ".tmp_source.zig:2:18: error: invalid operands to binary expression: 'error{A}' and 'error{B}'", | |
| 33 | ); | |
| 34 | ||
| 35 | if (builtin.os == builtin.Os.linux) { | |
| 36 | cases.addTest( | |
| 37 | "implicit dependency on libc", | |
| 38 | \\extern "c" fn exit(u8) void; | |
| 39 | \\export fn entry() void { | |
| 40 | \\ exit(0); | |
| 41 | \\} | |
| 42 | , | |
| 43 | ".tmp_source.zig:3:5: error: dependency on library c must be explicitly specified in the build command", | |
| 44 | ); | |
| 45 | ||
| 46 | cases.addTest( | |
| 47 | "libc headers note", | |
| 48 | \\const c = @cImport(@cInclude("stdio.h")); | |
| 49 | \\export fn entry() void { | |
| 50 | \\ _ = c.printf(c"hello, world!\n"); | |
| 51 | \\} | |
| 52 | , | |
| 53 | ".tmp_source.zig:1:11: error: C import failed", | |
| 54 | ".tmp_source.zig:1:11: note: libc headers not available; compilation does not link against libc", | |
| 55 | ); | |
| 56 | } | |
| 57 | ||
| 58 | cases.addTest( | |
| 59 | "comptime vector overflow shows the index", | |
| 60 | \\comptime { | |
| 61 | \\ var a: @Vector(4, u8) = []u8{ 1, 2, 255, 4 }; | |
| 62 | \\ var b: @Vector(4, u8) = []u8{ 5, 6, 1, 8 }; | |
| 63 | \\ var x = a + b; | |
| 64 | \\} | |
| 65 | , | |
| 66 | ".tmp_source.zig:4:15: error: operation caused overflow", | |
| 67 | ".tmp_source.zig:4:15: note: when computing vector element at index 2", | |
| 68 | ); | |
| 69 | ||
| 70 | cases.addTest( | |
| 71 | "packed struct with fields of not allowed types", | |
| 72 | \\const A = packed struct { | |
| 73 | \\ x: anyerror, | |
| 74 | \\}; | |
| 75 | \\const B = packed struct { | |
| 76 | \\ x: [2]u24, | |
| 77 | \\}; | |
| 78 | \\const C = packed struct { | |
| 79 | \\ x: [1]anyerror, | |
| 80 | \\}; | |
| 81 | \\const D = packed struct { | |
| 82 | \\ x: [1]S, | |
| 83 | \\}; | |
| 84 | \\const E = packed struct { | |
| 85 | \\ x: [1]U, | |
| 86 | \\}; | |
| 87 | \\const F = packed struct { | |
| 88 | \\ x: ?anyerror, | |
| 89 | \\}; | |
| 90 | \\const G = packed struct { | |
| 91 | \\ x: Enum, | |
| 92 | \\}; | |
| 93 | \\export fn entry() void { | |
| 94 | \\ var a: A = undefined; | |
| 95 | \\ var b: B = undefined; | |
| 96 | \\ var r: C = undefined; | |
| 97 | \\ var d: D = undefined; | |
| 98 | \\ var e: E = undefined; | |
| 99 | \\ var f: F = undefined; | |
| 100 | \\ var g: G = undefined; | |
| 101 | \\} | |
| 102 | \\const S = struct { | |
| 103 | \\ x: i32, | |
| 104 | \\}; | |
| 105 | \\const U = struct { | |
| 106 | \\ A: i32, | |
| 107 | \\ B: u32, | |
| 108 | \\}; | |
| 109 | \\const Enum = enum { | |
| 110 | \\ A, | |
| 111 | \\ B, | |
| 112 | \\}; | |
| 113 | , | |
| 114 | ".tmp_source.zig:2:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation", | |
| 115 | ".tmp_source.zig:5:5: error: array of 'u24' not allowed in packed struct due to padding bits", | |
| 116 | ".tmp_source.zig:8:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation", | |
| 117 | ".tmp_source.zig:11:5: error: non-packed, non-extern struct 'S' not allowed in packed struct; no guaranteed in-memory representation", | |
| 118 | ".tmp_source.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation", | |
| 119 | ".tmp_source.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation", | |
| 120 | ".tmp_source.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation", | |
| 121 | ".tmp_source.zig:38:14: note: enum declaration does not specify an integer tag type", | |
| 122 | ); | |
| 123 | ||
| 124 | cases.addCase(x: { | |
| 125 | var tc = cases.create( | |
| 126 | "deduplicate undeclared identifier", | |
| 127 | \\export fn a() void { | |
| 128 | \\ x += 1; | |
| 129 | \\} | |
| 130 | \\export fn b() void { | |
| 131 | \\ x += 1; | |
| 132 | \\} | |
| 133 | , | |
| 134 | ".tmp_source.zig:2:5: error: use of undeclared identifier 'x'", | |
| 135 | ); | |
| 136 | tc.expect_exact = true; | |
| 137 | break :x tc; | |
| 138 | }); | |
| 139 | ||
| 140 | cases.addTest( | |
| 141 | "export generic function", | |
| 142 | \\export fn foo(num: var) i32 { | |
| 143 | \\ return 0; | |
| 144 | \\} | |
| 145 | , | |
| 146 | ".tmp_source.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'ccc'", | |
| 147 | ); | |
| 148 | ||
| 149 | cases.addTest( | |
| 150 | "C pointer to c_void", | |
| 151 | \\export fn a() void { | |
| 152 | \\ var x: *c_void = undefined; | |
| 153 | \\ var y: [*c]c_void = x; | |
| 154 | \\} | |
| 155 | , | |
| 156 | ".tmp_source.zig:3:12: error: C pointers cannot point opaque types", | |
| 157 | ); | |
| 158 | ||
| 159 | cases.addTest( | |
| 160 | "directly embedding opaque type in struct and union", | |
| 161 | \\const O = @OpaqueType(); | |
| 162 | \\const Foo = struct { | |
| 163 | \\ o: O, | |
| 164 | \\}; | |
| 165 | \\const Bar = union { | |
| 166 | \\ One: i32, | |
| 167 | \\ Two: O, | |
| 168 | \\}; | |
| 169 | \\export fn a() void { | |
| 170 | \\ var foo: Foo = undefined; | |
| 171 | \\} | |
| 172 | \\export fn b() void { | |
| 173 | \\ var bar: Bar = undefined; | |
| 174 | \\} | |
| 175 | , | |
| 176 | ".tmp_source.zig:3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs", | |
| 177 | ".tmp_source.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions", | |
| 178 | ); | |
| 179 | ||
| 180 | cases.addTest( | |
| 181 | "implicit cast between C pointer and Zig pointer - bad const/align/child", | |
| 182 | \\export fn a() void { | |
| 183 | \\ var x: [*c]u8 = undefined; | |
| 184 | \\ var y: *align(4) u8 = x; | |
| 185 | \\} | |
| 186 | \\export fn b() void { | |
| 187 | \\ var x: [*c]const u8 = undefined; | |
| 188 | \\ var y: *u8 = x; | |
| 189 | \\} | |
| 190 | \\export fn c() void { | |
| 191 | \\ var x: [*c]u8 = undefined; | |
| 192 | \\ var y: *u32 = x; | |
| 193 | \\} | |
| 194 | \\export fn d() void { | |
| 195 | \\ var y: *align(1) u32 = undefined; | |
| 196 | \\ var x: [*c]u32 = y; | |
| 197 | \\} | |
| 198 | \\export fn e() void { | |
| 199 | \\ var y: *const u8 = undefined; | |
| 200 | \\ var x: [*c]u8 = y; | |
| 201 | \\} | |
| 202 | \\export fn f() void { | |
| 203 | \\ var y: *u8 = undefined; | |
| 204 | \\ var x: [*c]u32 = y; | |
| 205 | \\} | |
| 206 | , | |
| 207 | ".tmp_source.zig:3:27: error: cast increases pointer alignment", | |
| 208 | ".tmp_source.zig:7:18: error: cast discards const qualifier", | |
| 209 | ".tmp_source.zig:11:19: error: expected type '*u32', found '[*c]u8'", | |
| 210 | ".tmp_source.zig:11:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'", | |
| 211 | ".tmp_source.zig:15:22: error: cast increases pointer alignment", | |
| 212 | ".tmp_source.zig:19:21: error: cast discards const qualifier", | |
| 213 | ".tmp_source.zig:23:22: error: expected type '[*c]u32', found '*u8'", | |
| 214 | ); | |
| 215 | ||
| 216 | cases.addTest( | |
| 217 | "implicit casting null c pointer to zig pointer", | |
| 218 | \\comptime { | |
| 219 | \\ var c_ptr: [*c]u8 = 0; | |
| 220 | \\ var zig_ptr: *u8 = c_ptr; | |
| 221 | \\} | |
| 222 | , | |
| 223 | ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'", | |
| 224 | ); | |
| 225 | ||
| 226 | cases.addTest( | |
| 227 | "implicit casting undefined c pointer to zig pointer", | |
| 228 | \\comptime { | |
| 229 | \\ var c_ptr: [*c]u8 = undefined; | |
| 230 | \\ var zig_ptr: *u8 = c_ptr; | |
| 231 | \\} | |
| 232 | , | |
| 233 | ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior", | |
| 234 | ); | |
| 235 | ||
| 236 | cases.addTest( | |
| 237 | "implicit casting C pointers which would mess up null semantics", | |
| 238 | \\export fn entry() void { | |
| 239 | \\ var slice: []const u8 = "aoeu"; | |
| 240 | \\ const opt_many_ptr: [*]const u8 = slice.ptr; | |
| 241 | \\ var ptr_opt_many_ptr = &opt_many_ptr; | |
| 242 | \\ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr; | |
| 243 | \\ ptr_opt_many_ptr = c_ptr; | |
| 244 | \\} | |
| 245 | \\export fn entry2() void { | |
| 246 | \\ var buf: [4]u8 = "aoeu"; | |
| 247 | \\ var slice: []u8 = &buf; | |
| 248 | \\ var opt_many_ptr: [*]u8 = slice.ptr; | |
| 249 | \\ var ptr_opt_many_ptr = &opt_many_ptr; | |
| 250 | \\ var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr; | |
| 251 | \\} | |
| 252 | , | |
| 253 | ".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'", | |
| 254 | ".tmp_source.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'", | |
| 255 | ".tmp_source.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'", | |
| 256 | ".tmp_source.zig:13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'", | |
| 257 | ".tmp_source.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'", | |
| 258 | ".tmp_source.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'", | |
| 259 | ); | |
| 260 | ||
| 261 | cases.addTest( | |
| 262 | "implicit casting too big integers to C pointers", | |
| 263 | \\export fn a() void { | |
| 264 | \\ var ptr: [*c]u8 = (1 << 64) + 1; | |
| 265 | \\} | |
| 266 | \\export fn b() void { | |
| 267 | \\ var x: @IntType(false, 65) = 0x1234; | |
| 268 | \\ var ptr: [*c]u8 = x; | |
| 269 | \\} | |
| 270 | , | |
| 271 | ".tmp_source.zig:2:33: error: integer value 71615590737044764481 cannot be implicitly casted to type 'usize'", | |
| 272 | ".tmp_source.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'", | |
| 273 | ); | |
| 274 | ||
| 275 | cases.addTest( | |
| 276 | "C pointer pointing to non C ABI compatible type or has align attr", | |
| 277 | \\const Foo = struct {}; | |
| 278 | \\export fn a() void { | |
| 279 | \\ const T = [*c]Foo; | |
| 280 | \\} | |
| 281 | , | |
| 282 | ".tmp_source.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'", | |
| 283 | ); | |
| 284 | ||
| 285 | cases.addCase(x: { | |
| 286 | var tc = cases.create( | |
| 287 | "compile log statement warning deduplication in generic fn", | |
| 288 | \\export fn entry() void { | |
| 289 | \\ inner(1); | |
| 290 | \\ inner(2); | |
| 291 | \\} | |
| 292 | \\fn inner(comptime n: usize) void { | |
| 293 | \\ comptime var i = 0; | |
| 294 | \\ inline while (i < n) : (i += 1) { @compileLog("!@#$"); } | |
| 295 | \\} | |
| 296 | , | |
| 297 | ".tmp_source.zig:7:39: error: found compile log statement", | |
| 298 | ); | |
| 299 | tc.expect_exact = true; | |
| 300 | break :x tc; | |
| 301 | }); | |
| 302 | ||
| 303 | cases.addTest( | |
| 304 | "assign to invalid dereference", | |
| 305 | \\export fn entry() void { | |
| 306 | \\ 'a'.* = 1; | |
| 307 | \\} | |
| 308 | , | |
| 309 | ".tmp_source.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int'", | |
| 310 | ); | |
| 311 | ||
| 312 | cases.addTest( | |
| 313 | "take slice of invalid dereference", | |
| 314 | \\export fn entry() void { | |
| 315 | \\ const x = 'a'.*[0..]; | |
| 316 | \\} | |
| 317 | , | |
| 318 | ".tmp_source.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int'", | |
| 319 | ); | |
| 320 | ||
| 4 | 321 | cases.addTest( |
| 5 | 322 | "@truncate undefined value", |
| 6 | 323 | \\export fn entry() void { |
| 7 | 324 | \\ var z = @truncate(u8, u16(undefined)); |
| 8 | 325 | \\} |
| 9 | 326 | , |
| 10 | ".tmp_source.zig:2:30: error: use of undefined value", | |
| 327 | ".tmp_source.zig:2:30: error: use of undefined value here causes undefined behavior", | |
| 11 | 328 | ); |
| 12 | 329 | |
| 13 | 330 | cases.addTest( |
| ... | ... | @@ -121,12 +438,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 121 | 438 | "reading past end of pointer casted array", |
| 122 | 439 | \\comptime { |
| 123 | 440 | \\ const array = "aoeu"; |
| 124 | \\ const slice = array[2..]; | |
| 441 | \\ const slice = array[1..]; | |
| 125 | 442 | \\ const int_ptr = @ptrCast(*const u24, slice.ptr); |
| 126 | 443 | \\ const deref = int_ptr.*; |
| 127 | 444 | \\} |
| 128 | 445 | , |
| 129 | ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes", | |
| 446 | ".tmp_source.zig:5:26: error: attempt to read 4 bytes from [4]u8 at index 1 which is 3 bytes", | |
| 130 | 447 | ); |
| 131 | 448 | |
| 132 | 449 | cases.add( |
| ... | ... | @@ -210,13 +527,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 210 | 527 | ); |
| 211 | 528 | |
| 212 | 529 | cases.add( |
| 213 | "Panic declared with wrong type signature in tests", | |
| 530 | "wrong panic signature, runtime function", | |
| 214 | 531 | \\test "" {} |
| 215 | 532 | \\ |
| 216 | 533 | \\pub fn panic() void {} |
| 217 | 534 | \\ |
| 218 | 535 | , |
| 219 | ".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'", | |
| 536 | ".tmp_source.zig:3:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn() void'", | |
| 537 | ); | |
| 538 | ||
| 539 | cases.add( | |
| 540 | "wrong panic signature, generic function", | |
| 541 | \\pub fn panic(comptime msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { | |
| 542 | \\ while (true) {} | |
| 543 | \\} | |
| 544 | , | |
| 545 | ".tmp_source.zig:1:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn([]const u8,var)var'", | |
| 546 | ".tmp_source.zig:1:5: note: only one of the functions is generic", | |
| 220 | 547 | ); |
| 221 | 548 | |
| 222 | 549 | cases.add( |
| ... | ... | @@ -301,7 +628,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 301 | 628 | \\ _ = a.*.len; |
| 302 | 629 | \\} |
| 303 | 630 | , |
| 304 | ".tmp_source.zig:3:12: error: attempt to dereference non-pointer type '[]u8'", | |
| 631 | ".tmp_source.zig:3:10: error: attempt to dereference non-pointer type '[]u8'", | |
| 305 | 632 | ); |
| 306 | 633 | |
| 307 | 634 | cases.add( |
| ... | ... | @@ -368,7 +695,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 368 | 695 | \\ f(i32); |
| 369 | 696 | \\} |
| 370 | 697 | , |
| 371 | ".tmp_source.zig:4:5: error: use of undefined value", | |
| 698 | ".tmp_source.zig:4:5: error: use of undefined value here causes undefined behavior", | |
| 372 | 699 | ); |
| 373 | 700 | |
| 374 | 701 | cases.add( |
| ... | ... | @@ -768,7 +1095,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 768 | 1095 | \\ command.exec(); |
| 769 | 1096 | \\} |
| 770 | 1097 | , |
| 771 | ".tmp_source.zig:6:12: error: use of undefined value", | |
| 1098 | ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior", | |
| 772 | 1099 | ); |
| 773 | 1100 | |
| 774 | 1101 | cases.add( |
| ... | ... | @@ -781,7 +1108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 781 | 1108 | \\ command.exec(); |
| 782 | 1109 | \\} |
| 783 | 1110 | , |
| 784 | ".tmp_source.zig:6:12: error: use of undefined value", | |
| 1111 | ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior", | |
| 785 | 1112 | ); |
| 786 | 1113 | |
| 787 | 1114 | cases.add( |
| ... | ... | @@ -1012,7 +1339,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1012 | 1339 | \\ Filled, |
| 1013 | 1340 | \\}; |
| 1014 | 1341 | , |
| 1015 | ".tmp_source.zig:3:17: error: invalid deref on switch target", | |
| 1342 | ".tmp_source.zig:3:17: error: attempt to dereference non-pointer type 'Tile'", | |
| 1016 | 1343 | ); |
| 1017 | 1344 | |
| 1018 | 1345 | cases.add( |
| ... | ... | @@ -2089,7 +2416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2089 | 2416 | \\} |
| 2090 | 2417 | , |
| 2091 | 2418 | ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'", |
| 2092 | ".tmp_source.zig:2:12: error: use of undeclared identifier 'i'", | |
| 2093 | 2419 | ); |
| 2094 | 2420 | |
| 2095 | 2421 | cases.add( |
| ... | ... | @@ -2752,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2752 | 3078 | \\ |
| 2753 | 3079 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } |
| 2754 | 3080 | , |
| 2755 | ".tmp_source.zig:1:15: error: use of undefined value", | |
| 3081 | ".tmp_source.zig:1:15: error: use of undefined value here causes undefined behavior", | |
| 2756 | 3082 | ); |
| 2757 | 3083 | |
| 2758 | 3084 | cases.add( |
| ... | ... | @@ -2762,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2762 | 3088 | \\ _ = a / a; |
| 2763 | 3089 | \\} |
| 2764 | 3090 | , |
| 2765 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3091 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2766 | 3092 | ); |
| 2767 | 3093 | |
| 2768 | 3094 | cases.add( |
| ... | ... | @@ -2772,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2772 | 3098 | \\ a /= a; |
| 2773 | 3099 | \\} |
| 2774 | 3100 | , |
| 2775 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3101 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2776 | 3102 | ); |
| 2777 | 3103 | |
| 2778 | 3104 | cases.add( |
| ... | ... | @@ -2782,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2782 | 3108 | \\ _ = a % a; |
| 2783 | 3109 | \\} |
| 2784 | 3110 | , |
| 2785 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3111 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2786 | 3112 | ); |
| 2787 | 3113 | |
| 2788 | 3114 | cases.add( |
| ... | ... | @@ -2792,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2792 | 3118 | \\ a %= a; |
| 2793 | 3119 | \\} |
| 2794 | 3120 | , |
| 2795 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3121 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2796 | 3122 | ); |
| 2797 | 3123 | |
| 2798 | 3124 | cases.add( |
| ... | ... | @@ -2802,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2802 | 3128 | \\ _ = a + a; |
| 2803 | 3129 | \\} |
| 2804 | 3130 | , |
| 2805 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3131 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2806 | 3132 | ); |
| 2807 | 3133 | |
| 2808 | 3134 | cases.add( |
| ... | ... | @@ -2812,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2812 | 3138 | \\ a += a; |
| 2813 | 3139 | \\} |
| 2814 | 3140 | , |
| 2815 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3141 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2816 | 3142 | ); |
| 2817 | 3143 | |
| 2818 | 3144 | cases.add( |
| ... | ... | @@ -2822,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2822 | 3148 | \\ _ = a +% a; |
| 2823 | 3149 | \\} |
| 2824 | 3150 | , |
| 2825 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3151 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2826 | 3152 | ); |
| 2827 | 3153 | |
| 2828 | 3154 | cases.add( |
| ... | ... | @@ -2832,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2832 | 3158 | \\ a +%= a; |
| 2833 | 3159 | \\} |
| 2834 | 3160 | , |
| 2835 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3161 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2836 | 3162 | ); |
| 2837 | 3163 | |
| 2838 | 3164 | cases.add( |
| ... | ... | @@ -2842,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2842 | 3168 | \\ _ = a - a; |
| 2843 | 3169 | \\} |
| 2844 | 3170 | , |
| 2845 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3171 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2846 | 3172 | ); |
| 2847 | 3173 | |
| 2848 | 3174 | cases.add( |
| ... | ... | @@ -2852,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2852 | 3178 | \\ a -= a; |
| 2853 | 3179 | \\} |
| 2854 | 3180 | , |
| 2855 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3181 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2856 | 3182 | ); |
| 2857 | 3183 | |
| 2858 | 3184 | cases.add( |
| ... | ... | @@ -2862,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2862 | 3188 | \\ _ = a -% a; |
| 2863 | 3189 | \\} |
| 2864 | 3190 | , |
| 2865 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3191 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2866 | 3192 | ); |
| 2867 | 3193 | |
| 2868 | 3194 | cases.add( |
| ... | ... | @@ -2872,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2872 | 3198 | \\ a -%= a; |
| 2873 | 3199 | \\} |
| 2874 | 3200 | , |
| 2875 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3201 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2876 | 3202 | ); |
| 2877 | 3203 | |
| 2878 | 3204 | cases.add( |
| ... | ... | @@ -2882,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2882 | 3208 | \\ _ = a * a; |
| 2883 | 3209 | \\} |
| 2884 | 3210 | , |
| 2885 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3211 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2886 | 3212 | ); |
| 2887 | 3213 | |
| 2888 | 3214 | cases.add( |
| ... | ... | @@ -2892,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2892 | 3218 | \\ a *= a; |
| 2893 | 3219 | \\} |
| 2894 | 3220 | , |
| 2895 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3221 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2896 | 3222 | ); |
| 2897 | 3223 | |
| 2898 | 3224 | cases.add( |
| ... | ... | @@ -2902,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2902 | 3228 | \\ _ = a *% a; |
| 2903 | 3229 | \\} |
| 2904 | 3230 | , |
| 2905 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3231 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2906 | 3232 | ); |
| 2907 | 3233 | |
| 2908 | 3234 | cases.add( |
| ... | ... | @@ -2912,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2912 | 3238 | \\ a *%= a; |
| 2913 | 3239 | \\} |
| 2914 | 3240 | , |
| 2915 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3241 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2916 | 3242 | ); |
| 2917 | 3243 | |
| 2918 | 3244 | cases.add( |
| ... | ... | @@ -2922,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2922 | 3248 | \\ _ = a << 2; |
| 2923 | 3249 | \\} |
| 2924 | 3250 | , |
| 2925 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3251 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2926 | 3252 | ); |
| 2927 | 3253 | |
| 2928 | 3254 | cases.add( |
| ... | ... | @@ -2932,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2932 | 3258 | \\ a <<= 2; |
| 2933 | 3259 | \\} |
| 2934 | 3260 | , |
| 2935 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3261 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2936 | 3262 | ); |
| 2937 | 3263 | |
| 2938 | 3264 | cases.add( |
| ... | ... | @@ -2942,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2942 | 3268 | \\ _ = a >> 2; |
| 2943 | 3269 | \\} |
| 2944 | 3270 | , |
| 2945 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3271 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2946 | 3272 | ); |
| 2947 | 3273 | |
| 2948 | 3274 | cases.add( |
| ... | ... | @@ -2952,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2952 | 3278 | \\ a >>= 2; |
| 2953 | 3279 | \\} |
| 2954 | 3280 | , |
| 2955 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3281 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2956 | 3282 | ); |
| 2957 | 3283 | |
| 2958 | 3284 | cases.add( |
| ... | ... | @@ -2962,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2962 | 3288 | \\ _ = a & a; |
| 2963 | 3289 | \\} |
| 2964 | 3290 | , |
| 2965 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3291 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2966 | 3292 | ); |
| 2967 | 3293 | |
| 2968 | 3294 | cases.add( |
| ... | ... | @@ -2972,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2972 | 3298 | \\ a &= a; |
| 2973 | 3299 | \\} |
| 2974 | 3300 | , |
| 2975 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3301 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2976 | 3302 | ); |
| 2977 | 3303 | |
| 2978 | 3304 | cases.add( |
| ... | ... | @@ -2982,7 +3308,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2982 | 3308 | \\ _ = a | a; |
| 2983 | 3309 | \\} |
| 2984 | 3310 | , |
| 2985 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3311 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 2986 | 3312 | ); |
| 2987 | 3313 | |
| 2988 | 3314 | cases.add( |
| ... | ... | @@ -2992,7 +3318,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2992 | 3318 | \\ a |= a; |
| 2993 | 3319 | \\} |
| 2994 | 3320 | , |
| 2995 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3321 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 2996 | 3322 | ); |
| 2997 | 3323 | |
| 2998 | 3324 | cases.add( |
| ... | ... | @@ -3002,7 +3328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3002 | 3328 | \\ _ = a ^ a; |
| 3003 | 3329 | \\} |
| 3004 | 3330 | , |
| 3005 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3331 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3006 | 3332 | ); |
| 3007 | 3333 | |
| 3008 | 3334 | cases.add( |
| ... | ... | @@ -3012,7 +3338,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3012 | 3338 | \\ a ^= a; |
| 3013 | 3339 | \\} |
| 3014 | 3340 | , |
| 3015 | ".tmp_source.zig:3:5: error: use of undefined value", | |
| 3341 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", | |
| 3016 | 3342 | ); |
| 3017 | 3343 | |
| 3018 | 3344 | cases.add( |
| ... | ... | @@ -3022,7 +3348,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3022 | 3348 | \\ _ = a == a; |
| 3023 | 3349 | \\} |
| 3024 | 3350 | , |
| 3025 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3351 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3026 | 3352 | ); |
| 3027 | 3353 | |
| 3028 | 3354 | cases.add( |
| ... | ... | @@ -3032,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3032 | 3358 | \\ _ = a != a; |
| 3033 | 3359 | \\} |
| 3034 | 3360 | , |
| 3035 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3361 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3036 | 3362 | ); |
| 3037 | 3363 | |
| 3038 | 3364 | cases.add( |
| ... | ... | @@ -3042,7 +3368,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3042 | 3368 | \\ _ = a > a; |
| 3043 | 3369 | \\} |
| 3044 | 3370 | , |
| 3045 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3371 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3046 | 3372 | ); |
| 3047 | 3373 | |
| 3048 | 3374 | cases.add( |
| ... | ... | @@ -3052,7 +3378,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3052 | 3378 | \\ _ = a >= a; |
| 3053 | 3379 | \\} |
| 3054 | 3380 | , |
| 3055 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3381 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3056 | 3382 | ); |
| 3057 | 3383 | |
| 3058 | 3384 | cases.add( |
| ... | ... | @@ -3062,7 +3388,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3062 | 3388 | \\ _ = a < a; |
| 3063 | 3389 | \\} |
| 3064 | 3390 | , |
| 3065 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3391 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3066 | 3392 | ); |
| 3067 | 3393 | |
| 3068 | 3394 | cases.add( |
| ... | ... | @@ -3072,7 +3398,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3072 | 3398 | \\ _ = a <= a; |
| 3073 | 3399 | \\} |
| 3074 | 3400 | , |
| 3075 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3401 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3076 | 3402 | ); |
| 3077 | 3403 | |
| 3078 | 3404 | cases.add( |
| ... | ... | @@ -3082,7 +3408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3082 | 3408 | \\ _ = a and a; |
| 3083 | 3409 | \\} |
| 3084 | 3410 | , |
| 3085 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3411 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3086 | 3412 | ); |
| 3087 | 3413 | |
| 3088 | 3414 | cases.add( |
| ... | ... | @@ -3092,7 +3418,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3092 | 3418 | \\ _ = a or a; |
| 3093 | 3419 | \\} |
| 3094 | 3420 | , |
| 3095 | ".tmp_source.zig:3:9: error: use of undefined value", | |
| 3421 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", | |
| 3096 | 3422 | ); |
| 3097 | 3423 | |
| 3098 | 3424 | cases.add( |
| ... | ... | @@ -3102,7 +3428,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3102 | 3428 | \\ _ = -a; |
| 3103 | 3429 | \\} |
| 3104 | 3430 | , |
| 3105 | ".tmp_source.zig:3:10: error: use of undefined value", | |
| 3431 | ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior", | |
| 3106 | 3432 | ); |
| 3107 | 3433 | |
| 3108 | 3434 | cases.add( |
| ... | ... | @@ -3112,7 +3438,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3112 | 3438 | \\ _ = -%a; |
| 3113 | 3439 | \\} |
| 3114 | 3440 | , |
| 3115 | ".tmp_source.zig:3:11: error: use of undefined value", | |
| 3441 | ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior", | |
| 3116 | 3442 | ); |
| 3117 | 3443 | |
| 3118 | 3444 | cases.add( |
| ... | ... | @@ -3122,7 +3448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3122 | 3448 | \\ _ = ~a; |
| 3123 | 3449 | \\} |
| 3124 | 3450 | , |
| 3125 | ".tmp_source.zig:3:10: error: use of undefined value", | |
| 3451 | ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior", | |
| 3126 | 3452 | ); |
| 3127 | 3453 | |
| 3128 | 3454 | cases.add( |
| ... | ... | @@ -3132,7 +3458,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3132 | 3458 | \\ _ = !a; |
| 3133 | 3459 | \\} |
| 3134 | 3460 | , |
| 3135 | ".tmp_source.zig:3:10: error: use of undefined value", | |
| 3461 | ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior", | |
| 3136 | 3462 | ); |
| 3137 | 3463 | |
| 3138 | 3464 | cases.add( |
| ... | ... | @@ -3142,7 +3468,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3142 | 3468 | \\ _ = a orelse false; |
| 3143 | 3469 | \\} |
| 3144 | 3470 | , |
| 3145 | ".tmp_source.zig:3:11: error: use of undefined value", | |
| 3471 | ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior", | |
| 3146 | 3472 | ); |
| 3147 | 3473 | |
| 3148 | 3474 | cases.add( |
| ... | ... | @@ -3152,7 +3478,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3152 | 3478 | \\ _ = a catch |err| false; |
| 3153 | 3479 | \\} |
| 3154 | 3480 | , |
| 3155 | ".tmp_source.zig:3:11: error: use of undefined value", | |
| 3481 | ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior", | |
| 3156 | 3482 | ); |
| 3157 | 3483 | |
| 3158 | 3484 | cases.add( |
| ... | ... | @@ -3854,7 +4180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3854 | 4180 | \\ |
| 3855 | 4181 | \\export fn entry() usize { return @sizeOf(@typeOf(pass)); } |
| 3856 | 4182 | , |
| 3857 | ".tmp_source.zig:4:10: error: attempt to dereference non pointer type '[10]u8'", | |
| 4183 | ".tmp_source.zig:4:10: error: attempt to dereference non-pointer type '[10]u8'", | |
| 3858 | 4184 | ); |
| 3859 | 4185 | |
| 3860 | 4186 | cases.add( |
| ... | ... | @@ -4554,20 +4880,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4554 | 4880 | ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal", |
| 4555 | 4881 | ); |
| 4556 | 4882 | |
| 4557 | cases.add( | |
| 4558 | "@setEvalBranchQuota in non-root comptime execution context", | |
| 4559 | \\comptime { | |
| 4560 | \\ foo(); | |
| 4561 | \\} | |
| 4562 | \\fn foo() void { | |
| 4563 | \\ @setEvalBranchQuota(1001); | |
| 4564 | \\} | |
| 4565 | , | |
| 4566 | ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack", | |
| 4567 | ".tmp_source.zig:2:8: note: called from here", | |
| 4568 | ".tmp_source.zig:1:10: note: called from here", | |
| 4569 | ); | |
| 4570 | ||
| 4571 | 4883 | cases.add( |
| 4572 | 4884 | "wrong pointer implicitly casted to pointer to @OpaqueType()", |
| 4573 | 4885 | \\const Derp = @OpaqueType(); |
| ... | ... | @@ -4788,7 +5100,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4788 | 5100 | |
| 4789 | 5101 | cases.add( |
| 4790 | 5102 | "non-printable invalid character", |
| 4791 | "\xff\xfe" ++ | |
| 5103 | "\xff\xfe" ++ | |
| 4792 | 5104 | \\fn test() bool {\r |
| 4793 | 5105 | \\ true\r |
| 4794 | 5106 | \\} |
| ... | ... | @@ -5348,7 +5660,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5348 | 5660 | \\ Baz: void, |
| 5349 | 5661 | \\}; |
| 5350 | 5662 | \\comptime { |
| 5351 | \\ var foo = Foo {.Baz = {}}; | |
| 5663 | \\ var foo = Foo {.Baz = {}}; | |
| 5352 | 5664 | \\ const bar_val = foo.Bar; |
| 5353 | 5665 | \\} |
| 5354 | 5666 | , |
| ... | ... | @@ -5430,4 +5742,28 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5430 | 5742 | , |
| 5431 | 5743 | ".tmp_source.zig:7:30: error: unable to evaluate constant expression", |
| 5432 | 5744 | ); |
| 5745 | ||
| 5746 | cases.addTest( | |
| 5747 | "nested vectors", | |
| 5748 | \\export fn entry() void { | |
| 5749 | \\ const V = @Vector(4, @Vector(4, u8)); | |
| 5750 | \\ var v: V = undefined; | |
| 5751 | \\} | |
| 5752 | , | |
| 5753 | ".tmp_source.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid", | |
| 5754 | ); | |
| 5755 | ||
| 5756 | cases.add("compileLog of tagged enum doesn't crash the compiler", | |
| 5757 | \\const Bar = union(enum(u32)) { | |
| 5758 | \\ X: i32 = 1 | |
| 5759 | \\}; | |
| 5760 | \\ | |
| 5761 | \\fn testCompileLog(x: Bar) void { | |
| 5762 | \\ @compileLog(x); | |
| 5763 | \\} | |
| 5764 | \\ | |
| 5765 | \\pub fn main () void { | |
| 5766 | \\ comptime testCompileLog(Bar{.X = 123}); | |
| 5767 | \\} | |
| 5768 | , ".tmp_source.zig:6:5: error: found compile log statement"); | |
| 5433 | 5769 | } |
test/runtime_safety.zig+51| ... | ... | @@ -1,6 +1,16 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 4 | cases.addRuntimeSafety("pointer casting null to non-optional 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 c_ptr: [*c]u8 = 0; | |
| 10 | \\ var zig_ptr: *u8 = c_ptr; | |
| 11 | \\} | |
| 12 | ); | |
| 13 | ||
| 4 | 14 | cases.addRuntimeSafety("@intToEnum - no matching tag value", |
| 5 | 15 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 6 | 16 | \\ @import("std").os.exit(126); |
| ... | ... | @@ -108,6 +118,47 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 108 | 118 | \\} |
| 109 | 119 | ); |
| 110 | 120 | |
| 121 | cases.addRuntimeSafety("vector integer subtraction overflow", | |
| 122 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 123 | \\ @import("std").os.exit(126); | |
| 124 | \\} | |
| 125 | \\pub fn main() void { | |
| 126 | \\ var a: @Vector(4, u32) = []u32{ 1, 2, 8, 4 }; | |
| 127 | \\ var b: @Vector(4, u32) = []u32{ 5, 6, 7, 8 }; | |
| 128 | \\ const x = sub(b, a); | |
| 129 | \\} | |
| 130 | \\fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { | |
| 131 | \\ return a - b; | |
| 132 | \\} | |
| 133 | ); | |
| 134 | ||
| 135 | cases.addRuntimeSafety("vector integer multiplication overflow", | |
| 136 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 137 | \\ @import("std").os.exit(126); | |
| 138 | \\} | |
| 139 | \\pub fn main() void { | |
| 140 | \\ var a: @Vector(4, u8) = []u8{ 1, 2, 200, 4 }; | |
| 141 | \\ var b: @Vector(4, u8) = []u8{ 5, 6, 2, 8 }; | |
| 142 | \\ const x = mul(b, a); | |
| 143 | \\} | |
| 144 | \\fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { | |
| 145 | \\ return a * b; | |
| 146 | \\} | |
| 147 | ); | |
| 148 | ||
| 149 | cases.addRuntimeSafety("vector integer negation overflow", | |
| 150 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 151 | \\ @import("std").os.exit(126); | |
| 152 | \\} | |
| 153 | \\pub fn main() void { | |
| 154 | \\ var a: @Vector(4, i16) = []i16{ 1, -32768, 200, 4 }; | |
| 155 | \\ const x = neg(a); | |
| 156 | \\} | |
| 157 | \\fn neg(a: @Vector(4, i16)) @Vector(4, i16) { | |
| 158 | \\ return -a; | |
| 159 | \\} | |
| 160 | ); | |
| 161 | ||
| 111 | 162 | cases.addRuntimeSafety("integer subtraction overflow", |
| 112 | 163 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 113 | 164 | \\ @import("std").os.exit(126); |
test/stage1/behavior.zig+8| ... | ... | @@ -11,15 +11,22 @@ comptime { |
| 11 | 11 | _ = @import("behavior/bswap.zig"); |
| 12 | 12 | _ = @import("behavior/bugs/1076.zig"); |
| 13 | 13 | _ = @import("behavior/bugs/1111.zig"); |
| 14 | _ = @import("behavior/bugs/1120.zig"); | |
| 14 | 15 | _ = @import("behavior/bugs/1277.zig"); |
| 15 | 16 | _ = @import("behavior/bugs/1322.zig"); |
| 16 | 17 | _ = @import("behavior/bugs/1381.zig"); |
| 17 | 18 | _ = @import("behavior/bugs/1421.zig"); |
| 18 | 19 | _ = @import("behavior/bugs/1442.zig"); |
| 19 | 20 | _ = @import("behavior/bugs/1486.zig"); |
| 21 | _ = @import("behavior/bugs/1851.zig"); | |
| 22 | _ = @import("behavior/bugs/2006.zig"); | |
| 20 | 23 | _ = @import("behavior/bugs/394.zig"); |
| 24 | _ = @import("behavior/bugs/421.zig"); | |
| 25 | _ = @import("behavior/bugs/529.zig"); | |
| 21 | 26 | _ = @import("behavior/bugs/655.zig"); |
| 22 | 27 | _ = @import("behavior/bugs/656.zig"); |
| 28 | _ = @import("behavior/bugs/704.zig"); | |
| 29 | _ = @import("behavior/bugs/718.zig"); | |
| 23 | 30 | _ = @import("behavior/bugs/726.zig"); |
| 24 | 31 | _ = @import("behavior/bugs/828.zig"); |
| 25 | 32 | _ = @import("behavior/bugs/920.zig"); |
| ... | ... | @@ -59,6 +66,7 @@ comptime { |
| 59 | 66 | _ = @import("behavior/reflection.zig"); |
| 60 | 67 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 61 | 68 | _ = @import("behavior/slice.zig"); |
| 69 | _ = @import("behavior/slicetobytes.zig"); | |
| 62 | 70 | _ = @import("behavior/struct.zig"); |
| 63 | 71 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| 64 | 72 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); |
test/stage1/behavior/bitcast.zig+78| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const expect = std.testing.expect; |
| 3 | 4 | const maxInt = std.math.maxInt; |
| 4 | 5 | |
| ... | ... | @@ -34,3 +35,80 @@ test "@bitCast extern enum to its integer type" { |
| 34 | 35 | SOCK.testBitCastExternEnum(); |
| 35 | 36 | comptime SOCK.testBitCastExternEnum(); |
| 36 | 37 | } |
| 38 | ||
| 39 | test "@bitCast packed structs at runtime and comptime" { | |
| 40 | const Full = packed struct { | |
| 41 | number: u16, | |
| 42 | }; | |
| 43 | const Divided = packed struct { | |
| 44 | half1: u8, | |
| 45 | quarter3: u4, | |
| 46 | quarter4: u4, | |
| 47 | }; | |
| 48 | const S = struct { | |
| 49 | fn doTheTest() void { | |
| 50 | var full = Full{ .number = 0x1234 }; | |
| 51 | var two_halves = @bitCast(Divided, full); | |
| 52 | switch (builtin.endian) { | |
| 53 | builtin.Endian.Big => { | |
| 54 | expect(two_halves.half1 == 0x12); | |
| 55 | expect(two_halves.quarter3 == 0x3); | |
| 56 | expect(two_halves.quarter4 == 0x4); | |
| 57 | }, | |
| 58 | builtin.Endian.Little => { | |
| 59 | expect(two_halves.half1 == 0x34); | |
| 60 | expect(two_halves.quarter3 == 0x2); | |
| 61 | expect(two_halves.quarter4 == 0x1); | |
| 62 | }, | |
| 63 | } | |
| 64 | } | |
| 65 | }; | |
| 66 | S.doTheTest(); | |
| 67 | comptime S.doTheTest(); | |
| 68 | } | |
| 69 | ||
| 70 | test "@bitCast extern structs at runtime and comptime" { | |
| 71 | const Full = extern struct { | |
| 72 | number: u16, | |
| 73 | }; | |
| 74 | const TwoHalves = extern struct { | |
| 75 | half1: u8, | |
| 76 | half2: u8, | |
| 77 | }; | |
| 78 | const S = struct { | |
| 79 | fn doTheTest() void { | |
| 80 | var full = Full{ .number = 0x1234 }; | |
| 81 | var two_halves = @bitCast(TwoHalves, full); | |
| 82 | switch (builtin.endian) { | |
| 83 | builtin.Endian.Big => { | |
| 84 | expect(two_halves.half1 == 0x12); | |
| 85 | expect(two_halves.half2 == 0x34); | |
| 86 | }, | |
| 87 | builtin.Endian.Little => { | |
| 88 | expect(two_halves.half1 == 0x34); | |
| 89 | expect(two_halves.half2 == 0x12); | |
| 90 | }, | |
| 91 | } | |
| 92 | } | |
| 93 | }; | |
| 94 | S.doTheTest(); | |
| 95 | comptime S.doTheTest(); | |
| 96 | } | |
| 97 | ||
| 98 | test "bitcast packed struct to integer and back" { | |
| 99 | const LevelUpMove = packed struct { | |
| 100 | move_id: u9, | |
| 101 | level: u7, | |
| 102 | }; | |
| 103 | const S = struct { | |
| 104 | fn doTheTest() void { | |
| 105 | var move = LevelUpMove{ .move_id = 1, .level = 2 }; | |
| 106 | var v = @bitCast(u16, move); | |
| 107 | var back_to_a_move = @bitCast(LevelUpMove, v); | |
| 108 | expect(back_to_a_move.move_id == 1); | |
| 109 | expect(back_to_a_move.level == 2); | |
| 110 | } | |
| 111 | }; | |
| 112 | S.doTheTest(); | |
| 113 | comptime S.doTheTest(); | |
| 114 | } |
test/stage1/behavior/bugs/1120.zig created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | ||
| 4 | const A = packed struct { | |
| 5 | a: u2, | |
| 6 | b: u6, | |
| 7 | }; | |
| 8 | const B = packed struct { | |
| 9 | q: u8, | |
| 10 | a: u2, | |
| 11 | b: u6, | |
| 12 | }; | |
| 13 | test "bug 1120" { | |
| 14 | var a = A{ .a = 2, .b = 2 }; | |
| 15 | var b = B{ .q = 22, .a = 3, .b = 2 }; | |
| 16 | var t: usize = 0; | |
| 17 | const ptr = switch (t) { | |
| 18 | 0 => &a.a, | |
| 19 | 1 => &b.a, | |
| 20 | else => unreachable, | |
| 21 | }; | |
| 22 | expect(ptr.* == 2); | |
| 23 | } |
test/stage1/behavior/bugs/1851.zig created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | ||
| 4 | test "allocation and looping over 3-byte integer" { | |
| 5 | expect(@sizeOf(u24) == 4); | |
| 6 | expect(@sizeOf([1]u24) == 4); | |
| 7 | expect(@alignOf(u24) == 4); | |
| 8 | expect(@alignOf([1]u24) == 4); | |
| 9 | var buffer: [100]u8 = undefined; | |
| 10 | const a = &std.heap.FixedBufferAllocator.init(&buffer).allocator; | |
| 11 | ||
| 12 | var x = a.alloc(u24, 2) catch unreachable; | |
| 13 | expect(x.len == 2); | |
| 14 | x[0] = 0xFFFFFF; | |
| 15 | x[1] = 0xFFFFFF; | |
| 16 | ||
| 17 | const bytes = @sliceToBytes(x); | |
| 18 | expect(@typeOf(bytes) == []align(4) u8); | |
| 19 | expect(bytes.len == 8); | |
| 20 | ||
| 21 | for (bytes) |*b| { | |
| 22 | b.* = 0x00; | |
| 23 | } | |
| 24 | ||
| 25 | expect(x[0] == 0x00); | |
| 26 | expect(x[1] == 0x00); | |
| 27 | } |
test/stage1/behavior/bugs/2006.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | ||
| 4 | const S = struct { | |
| 5 | p: *S, | |
| 6 | }; | |
| 7 | test "bug 2006" { | |
| 8 | var a: S = undefined; | |
| 9 | a = S{ .p = undefined }; | |
| 10 | expect(@sizeOf(S) != 0); | |
| 11 | expect(@sizeOf(*void) == 0); | |
| 12 | } |
test/stage1/behavior/bugs/421.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "bitCast to array" { | |
| 4 | comptime testBitCastArray(); | |
| 5 | testBitCastArray(); | |
| 6 | } | |
| 7 | ||
| 8 | fn testBitCastArray() void { | |
| 9 | assert(extractOne64(0x0123456789abcdef0123456789abcdef) == 0x0123456789abcdef); | |
| 10 | } | |
| 11 | ||
| 12 | fn extractOne64(a: u128) u64 { | |
| 13 | const x = @bitCast([2]u64, a); | |
| 14 | return x[1]; | |
| 15 | } | |
| 16 |
test/stage1/behavior/bugs/529.zig created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | const A = extern struct { | |
| 2 | field: c_int, | |
| 3 | }; | |
| 4 | ||
| 5 | extern fn issue529(?*A) void; | |
| 6 | ||
| 7 | comptime { | |
| 8 | _ = @import("529_other_file_2.zig"); | |
| 9 | } | |
| 10 | ||
| 11 | test "issue 529 fixed" { | |
| 12 | @import("529_other_file.zig").issue529(null); | |
| 13 | issue529(null); | |
| 14 | } | |
| 15 |
test/stage1/behavior/bugs/529_other_file.zig created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | pub const A = extern struct { | |
| 2 | field: c_int, | |
| 3 | }; | |
| 4 | ||
| 5 | pub extern fn issue529(?*A) void; |
test/stage1/behavior/bugs/529_other_file_2.zig created+4| ... | ... | @@ -0,0 +1,4 @@ |
| 1 | pub const A = extern struct { | |
| 2 | field: c_int, | |
| 3 | }; | |
| 4 | export fn issue529(a: ?*A) void {} |
test/stage1/behavior/bugs/704.zig created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | const xxx = struct { | |
| 2 | pub fn bar(self: *xxx) void {} | |
| 3 | }; | |
| 4 | test "bug 704" { | |
| 5 | var x: xxx = undefined; | |
| 6 | x.bar(); | |
| 7 | } |
test/stage1/behavior/bugs/718.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | const std = @import("std"); | |
| 2 | const mem = std.mem; | |
| 3 | const expect = std.testing.expect; | |
| 4 | const Keys = struct { | |
| 5 | up: bool, | |
| 6 | down: bool, | |
| 7 | left: bool, | |
| 8 | right: bool, | |
| 9 | }; | |
| 10 | var keys: Keys = undefined; | |
| 11 | test "zero keys with @memset" { | |
| 12 | @memset(@ptrCast([*]u8, &keys), 0, @sizeOf(@typeOf(keys))); | |
| 13 | expect(!keys.up); | |
| 14 | expect(!keys.down); | |
| 15 | expect(!keys.left); | |
| 16 | expect(!keys.right); | |
| 17 | } |
test/stage1/behavior/pointers.zig+82| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | const expectError = std.testing.expectError; | |
| 3 | 4 | |
| 4 | 5 | test "dereference pointer" { |
| 5 | 6 | comptime testDerefPtr(); |
| ... | ... | @@ -42,3 +43,84 @@ test "double pointer parsing" { |
| 42 | 43 | fn PtrOf(comptime T: type) type { |
| 43 | 44 | return *T; |
| 44 | 45 | } |
| 46 | ||
| 47 | test "assigning integer to C pointer" { | |
| 48 | var x: i32 = 0; | |
| 49 | var ptr: [*c]u8 = 0; | |
| 50 | var ptr2: [*c]u8 = x; | |
| 51 | } | |
| 52 | ||
| 53 | test "implicit cast single item pointer to C pointer and back" { | |
| 54 | var y: u8 = 11; | |
| 55 | var x: [*c]u8 = &y; | |
| 56 | var z: *u8 = x; | |
| 57 | z.* += 1; | |
| 58 | expect(y == 12); | |
| 59 | } | |
| 60 | ||
| 61 | test "C pointer comparison and arithmetic" { | |
| 62 | const S = struct { | |
| 63 | fn doTheTest() void { | |
| 64 | var one: usize = 1; | |
| 65 | var ptr1: [*c]u32 = 0; | |
| 66 | var ptr2 = ptr1 + 10; | |
| 67 | expect(ptr1 == 0); | |
| 68 | expect(ptr1 >= 0); | |
| 69 | expect(ptr1 <= 0); | |
| 70 | expect(ptr1 < 1); | |
| 71 | expect(ptr1 < one); | |
| 72 | expect(1 > ptr1); | |
| 73 | expect(one > ptr1); | |
| 74 | expect(ptr1 < ptr2); | |
| 75 | expect(ptr2 > ptr1); | |
| 76 | expect(ptr2 >= 40); | |
| 77 | expect(ptr2 == 40); | |
| 78 | expect(ptr2 <= 40); | |
| 79 | ptr2 -= 10; | |
| 80 | expect(ptr1 == ptr2); | |
| 81 | } | |
| 82 | }; | |
| 83 | S.doTheTest(); | |
| 84 | comptime S.doTheTest(); | |
| 85 | } | |
| 86 | ||
| 87 | test "peer type resolution with C pointers" { | |
| 88 | var ptr_one: *u8 = undefined; | |
| 89 | var ptr_many: [*]u8 = undefined; | |
| 90 | var ptr_c: [*c]u8 = undefined; | |
| 91 | var t = true; | |
| 92 | var x1 = if (t) ptr_one else ptr_c; | |
| 93 | var x2 = if (t) ptr_many else ptr_c; | |
| 94 | var x3 = if (t) ptr_c else ptr_one; | |
| 95 | var x4 = if (t) ptr_c else ptr_many; | |
| 96 | expect(@typeOf(x1) == [*c]u8); | |
| 97 | expect(@typeOf(x2) == [*c]u8); | |
| 98 | expect(@typeOf(x3) == [*c]u8); | |
| 99 | expect(@typeOf(x4) == [*c]u8); | |
| 100 | } | |
| 101 | ||
| 102 | test "implicit casting between C pointer and optional non-C pointer" { | |
| 103 | var slice: []const u8 = "aoeu"; | |
| 104 | const opt_many_ptr: ?[*]const u8 = slice.ptr; | |
| 105 | var ptr_opt_many_ptr = &opt_many_ptr; | |
| 106 | var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr; | |
| 107 | expect(c_ptr.*.* == 'a'); | |
| 108 | ptr_opt_many_ptr = c_ptr; | |
| 109 | expect(ptr_opt_many_ptr.*.?[1] == 'o'); | |
| 110 | } | |
| 111 | ||
| 112 | test "implicit cast error unions with non-optional to optional pointer" { | |
| 113 | const S = struct { | |
| 114 | fn doTheTest() void { | |
| 115 | expectError(error.Fail, foo()); | |
| 116 | } | |
| 117 | fn foo() anyerror!?*u8 { | |
| 118 | return bar() orelse error.Fail; | |
| 119 | } | |
| 120 | fn bar() ?*u8 { | |
| 121 | return null; | |
| 122 | } | |
| 123 | }; | |
| 124 | S.doTheTest(); | |
| 125 | comptime S.doTheTest(); | |
| 126 | } |
test/stage1/behavior/ptrcast.zig+8| ... | ... | @@ -50,3 +50,11 @@ const Bytes = struct { |
| 50 | 50 | return res; |
| 51 | 51 | } |
| 52 | 52 | }; |
| 53 | ||
| 54 | test "comptime ptrcast keeps larger alignment" { | |
| 55 | comptime { | |
| 56 | const a: u32 = 1234; | |
| 57 | const p = @ptrCast([*]const u8, &a); | |
| 58 | std.debug.assert(@typeOf(p) == [*]align(@alignOf(u32)) const u8); | |
| 59 | } | |
| 60 | } |
test/stage1/behavior/slicetobytes.zig created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const expect = std.testing.expect; | |
| 4 | ||
| 5 | test "@sliceToBytes packed struct at runtime and comptime" { | |
| 6 | const Foo = packed struct { | |
| 7 | a: u4, | |
| 8 | b: u4, | |
| 9 | }; | |
| 10 | const S = struct { | |
| 11 | fn doTheTest() void { | |
| 12 | var foo: Foo = undefined; | |
| 13 | var slice = @sliceToBytes(((*[1]Foo)(&foo))[0..1]); | |
| 14 | slice[0] = 0x13; | |
| 15 | switch (builtin.endian) { | |
| 16 | builtin.Endian.Big => { | |
| 17 | expect(foo.a == 0x1); | |
| 18 | expect(foo.b == 0x3); | |
| 19 | }, | |
| 20 | builtin.Endian.Little => { | |
| 21 | expect(foo.a == 0x3); | |
| 22 | expect(foo.b == 0x1); | |
| 23 | }, | |
| 24 | } | |
| 25 | } | |
| 26 | }; | |
| 27 | S.doTheTest(); | |
| 28 | comptime S.doTheTest(); | |
| 29 | } |
test/stage1/behavior/struct.zig+42-11| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | const expectEqualSlices = std.testing.expectEqualSlices; | |
| 3 | 4 | const builtin = @import("builtin"); |
| 4 | 5 | const maxInt = std.math.maxInt; |
| 5 | 6 | |
| ... | ... | @@ -103,19 +104,20 @@ fn structInitializer() void { |
| 103 | 104 | } |
| 104 | 105 | |
| 105 | 106 | test "fn call of struct field" { |
| 106 | expect(callStructField(Foo{ .ptr = aFunc }) == 13); | |
| 107 | } | |
| 108 | ||
| 109 | const Foo = struct { | |
| 110 | ptr: fn () i32, | |
| 111 | }; | |
| 107 | const Foo = struct { | |
| 108 | ptr: fn () i32, | |
| 109 | }; | |
| 110 | const S = struct { | |
| 111 | fn aFunc() i32 { | |
| 112 | return 13; | |
| 113 | } | |
| 112 | 114 | |
| 113 | fn aFunc() i32 { | |
| 114 | return 13; | |
| 115 | } | |
| 115 | fn callStructField(foo: Foo) i32 { | |
| 116 | return foo.ptr(); | |
| 117 | } | |
| 118 | }; | |
| 116 | 119 | |
| 117 | fn callStructField(foo: Foo) i32 { | |
| 118 | return foo.ptr(); | |
| 120 | expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13); | |
| 119 | 121 | } |
| 120 | 122 | |
| 121 | 123 | test "store member function in variable" { |
| ... | ... | @@ -468,3 +470,32 @@ test "pointer to packed struct member in a stack variable" { |
| 468 | 470 | b_ptr.* = 2; |
| 469 | 471 | expect(s.b == 2); |
| 470 | 472 | } |
| 473 | ||
| 474 | test "non-byte-aligned array inside packed struct" { | |
| 475 | const Foo = packed struct { | |
| 476 | a: bool, | |
| 477 | b: [0x16]u8, | |
| 478 | }; | |
| 479 | const S = struct { | |
| 480 | fn bar(slice: []const u8) void { | |
| 481 | expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu"); | |
| 482 | } | |
| 483 | fn doTheTest() void { | |
| 484 | var foo = Foo{ | |
| 485 | .a = true, | |
| 486 | .b = "abcdefghijklmnopqurstu", | |
| 487 | }; | |
| 488 | bar(foo.b); | |
| 489 | } | |
| 490 | }; | |
| 491 | S.doTheTest(); | |
| 492 | comptime S.doTheTest(); | |
| 493 | } | |
| 494 | ||
| 495 | test "packed struct with u0 field access" { | |
| 496 | const S = packed struct { | |
| 497 | f0: u0, | |
| 498 | }; | |
| 499 | var s = S{ .f0 = 0 }; | |
| 500 | comptime expect(s.f0 == 0); | |
| 501 | } |
test/stage1/behavior/truncate.zig+5| ... | ... | @@ -29,3 +29,8 @@ test "truncate sign mismatch but comptime known so it works anyway" { |
| 29 | 29 | var result = @truncate(i8, x); |
| 30 | 30 | expect(result == 10); |
| 31 | 31 | } |
| 32 | ||
| 33 | test "truncate on comptime integer" { | |
| 34 | var x = @truncate(u16, 9999); | |
| 35 | expect(x == 9999); | |
| 36 | } |
test/stage1/behavior/type_info.zig+15| ... | ... | @@ -61,6 +61,21 @@ fn testUnknownLenPtr() void { |
| 61 | 61 | expect(u32_ptr_info.Pointer.child == f64); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | test "type info: C pointer type info" { | |
| 65 | testCPtr(); | |
| 66 | comptime testCPtr(); | |
| 67 | } | |
| 68 | ||
| 69 | fn testCPtr() void { | |
| 70 | const ptr_info = @typeInfo([*c]align(4) const i8); | |
| 71 | expect(TypeId(ptr_info) == TypeId.Pointer); | |
| 72 | expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C); | |
| 73 | expect(ptr_info.Pointer.is_const); | |
| 74 | expect(!ptr_info.Pointer.is_volatile); | |
| 75 | expect(ptr_info.Pointer.alignment == 4); | |
| 76 | expect(ptr_info.Pointer.child == i8); | |
| 77 | } | |
| 78 | ||
| 64 | 79 | test "type info: slice type info" { |
| 65 | 80 | testSlice(); |
| 66 | 81 | comptime testSlice(); |
test/stage1/behavior/union.zig+15| ... | ... | @@ -350,3 +350,18 @@ test "union with only 1 field casted to its enum type which has enum value speci |
| 350 | 350 | expect(@enumToInt(t) == 33); |
| 351 | 351 | comptime expect(@enumToInt(t) == 33); |
| 352 | 352 | } |
| 353 | ||
| 354 | test "@enumToInt works on unions" { | |
| 355 | const Bar = union(enum) { | |
| 356 | A: bool, | |
| 357 | B: u8, | |
| 358 | C, | |
| 359 | }; | |
| 360 | ||
| 361 | const a = Bar{ .A = true }; | |
| 362 | var b = Bar{ .B = undefined }; | |
| 363 | var c = Bar.C; | |
| 364 | expect(@enumToInt(a) == 0); | |
| 365 | expect(@enumToInt(b) == 1); | |
| 366 | expect(@enumToInt(c) == 2); | |
| 367 | } |
test/stage1/behavior/vector.zig+51-5| ... | ... | @@ -5,11 +5,57 @@ const expect = std.testing.expect; |
| 5 | 5 | test "vector wrap operators" { |
| 6 | 6 | const S = struct { |
| 7 | 7 | fn doTheTest() void { |
| 8 | const v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 }; | |
| 9 | const x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 }; | |
| 10 | expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ 11, 22, 33, 44 })); | |
| 11 | expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 9, 18, 27, 36 })); | |
| 12 | expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 10, 40, 90, 160 })); | |
| 8 | var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 }; | |
| 9 | var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 }; | |
| 10 | expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ -2147483648, 2147483645, 33, 44 })); | |
| 11 | expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 2147483646, 2147483647, 27, 36 })); | |
| 12 | expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 2147483647, 2, 90, 160 })); | |
| 13 | var z: @Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 }; | |
| 14 | expect(mem.eql(i32, ([4]i32)(-%z), [4]i32{ -1, -2, -3, -2147483648 })); | |
| 15 | } | |
| 16 | }; | |
| 17 | S.doTheTest(); | |
| 18 | comptime S.doTheTest(); | |
| 19 | } | |
| 20 | ||
| 21 | test "vector int operators" { | |
| 22 | const S = struct { | |
| 23 | fn doTheTest() void { | |
| 24 | var v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 }; | |
| 25 | var x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 }; | |
| 26 | expect(mem.eql(i32, ([4]i32)(v + x), [4]i32{ 11, 22, 33, 44 })); | |
| 27 | expect(mem.eql(i32, ([4]i32)(v - x), [4]i32{ 9, 18, 27, 36 })); | |
| 28 | expect(mem.eql(i32, ([4]i32)(v * x), [4]i32{ 10, 40, 90, 160 })); | |
| 29 | expect(mem.eql(i32, ([4]i32)(-v), [4]i32{ -10, -20, -30, -40 })); | |
| 30 | } | |
| 31 | }; | |
| 32 | S.doTheTest(); | |
| 33 | comptime S.doTheTest(); | |
| 34 | } | |
| 35 | ||
| 36 | test "vector float operators" { | |
| 37 | const S = struct { | |
| 38 | fn doTheTest() void { | |
| 39 | var v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 }; | |
| 40 | var x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 }; | |
| 41 | expect(mem.eql(f32, ([4]f32)(v + x), [4]f32{ 11, 22, 33, 44 })); | |
| 42 | expect(mem.eql(f32, ([4]f32)(v - x), [4]f32{ 9, 18, 27, 36 })); | |
| 43 | expect(mem.eql(f32, ([4]f32)(v * x), [4]f32{ 10, 40, 90, 160 })); | |
| 44 | expect(mem.eql(f32, ([4]f32)(-x), [4]f32{ -1, -2, -3, -4 })); | |
| 45 | } | |
| 46 | }; | |
| 47 | S.doTheTest(); | |
| 48 | comptime S.doTheTest(); | |
| 49 | } | |
| 50 | ||
| 51 | test "vector bit operators" { | |
| 52 | const S = struct { | |
| 53 | fn doTheTest() void { | |
| 54 | var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 }; | |
| 55 | var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 }; | |
| 56 | expect(mem.eql(u8, ([4]u8)(v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 })); | |
| 57 | expect(mem.eql(u8, ([4]u8)(v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 })); | |
| 58 | expect(mem.eql(u8, ([4]u8)(v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 })); | |
| 13 | 59 | } |
| 14 | 60 | }; |
| 15 | 61 | S.doTheTest(); |
test/stage1/c_abi/build.zig+3-2| ... | ... | @@ -3,9 +3,10 @@ const Builder = @import("std").build.Builder; |
| 3 | 3 | pub fn build(b: *Builder) void { |
| 4 | 4 | const rel_opts = b.standardReleaseOptions(); |
| 5 | 5 | |
| 6 | const c_obj = b.addCObject("cfuncs", "cfuncs.c"); | |
| 6 | const c_obj = b.addObject("cfuncs", null); | |
| 7 | c_obj.addCSourceFile("cfuncs.c", [][]const u8{"-std=c99"}); | |
| 7 | 8 | c_obj.setBuildMode(rel_opts); |
| 8 | c_obj.setNoStdLib(true); | |
| 9 | c_obj.linkSystemLibrary("c"); | |
| 9 | 10 | |
| 10 | 11 | const main = b.addTest("main.zig"); |
| 11 | 12 | main.setBuildMode(rel_opts); |
test/tests.zig+66-16| ... | ... | @@ -24,24 +24,24 @@ const gen_h = @import("gen_h.zig"); |
| 24 | 24 | const TestTarget = struct { |
| 25 | 25 | os: builtin.Os, |
| 26 | 26 | arch: builtin.Arch, |
| 27 | environ: builtin.Environ, | |
| 27 | abi: builtin.Abi, | |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | 30 | const test_targets = []TestTarget{ |
| 31 | 31 | TestTarget{ |
| 32 | 32 | .os = builtin.Os.linux, |
| 33 | 33 | .arch = builtin.Arch.x86_64, |
| 34 | .environ = builtin.Environ.gnu, | |
| 34 | .abi = builtin.Abi.gnu, | |
| 35 | 35 | }, |
| 36 | 36 | TestTarget{ |
| 37 | 37 | .os = builtin.Os.macosx, |
| 38 | 38 | .arch = builtin.Arch.x86_64, |
| 39 | .environ = builtin.Environ.unknown, | |
| 39 | .abi = builtin.Abi.gnu, | |
| 40 | 40 | }, |
| 41 | 41 | TestTarget{ |
| 42 | 42 | .os = builtin.Os.windows, |
| 43 | 43 | .arch = builtin.Arch.x86_64, |
| 44 | .environ = builtin.Environ.msvc, | |
| 44 | .abi = builtin.Abi.msvc, | |
| 45 | 45 | }, |
| 46 | 46 | }; |
| 47 | 47 | |
| ... | ... | @@ -189,7 +189,7 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons |
| 189 | 189 | these_tests.setFilter(test_filter); |
| 190 | 190 | these_tests.setBuildMode(mode); |
| 191 | 191 | if (!is_native) { |
| 192 | these_tests.setTarget(test_target.arch, test_target.os, test_target.environ); | |
| 192 | these_tests.setTarget(test_target.arch, test_target.os, test_target.abi); | |
| 193 | 193 | } |
| 194 | 194 | if (link_libc) { |
| 195 | 195 | these_tests.linkSystemLibrary("c"); |
| ... | ... | @@ -536,6 +536,7 @@ pub const CompileErrorContext = struct { |
| 536 | 536 | name: []const u8, |
| 537 | 537 | sources: ArrayList(SourceFile), |
| 538 | 538 | expected_errors: ArrayList([]const u8), |
| 539 | expect_exact: bool, | |
| 539 | 540 | link_libc: bool, |
| 540 | 541 | is_exe: bool, |
| 541 | 542 | is_test: bool, |
| ... | ... | @@ -565,6 +566,24 @@ pub const CompileErrorContext = struct { |
| 565 | 566 | case: *const TestCase, |
| 566 | 567 | build_mode: Mode, |
| 567 | 568 | |
| 569 | const ErrLineIter = struct { | |
| 570 | lines: mem.SplitIterator, | |
| 571 | ||
| 572 | const source_file = ".tmp_source.zig"; | |
| 573 | ||
| 574 | fn init(input: []const u8) ErrLineIter { | |
| 575 | return ErrLineIter{ .lines = mem.separate(input, "\n") }; | |
| 576 | } | |
| 577 | ||
| 578 | fn next(self: *ErrLineIter) ?[]const u8 { | |
| 579 | while (self.lines.next()) |line| { | |
| 580 | if (mem.indexOf(u8, line, source_file) != null) | |
| 581 | return line; | |
| 582 | } | |
| 583 | return null; | |
| 584 | } | |
| 585 | }; | |
| 586 | ||
| 568 | 587 | pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep { |
| 569 | 588 | const allocator = context.b.allocator; |
| 570 | 589 | const ptr = allocator.create(CompileCmpOutputStep) catch unreachable; |
| ... | ... | @@ -674,19 +693,49 @@ pub const CompileErrorContext = struct { |
| 674 | 693 | return error.TestFailed; |
| 675 | 694 | } |
| 676 | 695 | |
| 677 | for (self.case.expected_errors.toSliceConst()) |expected_error| { | |
| 678 | if (mem.indexOf(u8, stderr, expected_error) == null) { | |
| 679 | warn( | |
| 680 | \\ | |
| 681 | \\========= Expected this compile error: ========= | |
| 682 | \\{} | |
| 683 | \\================================================ | |
| 684 | \\{} | |
| 685 | \\ | |
| 686 | , expected_error, stderr); | |
| 687 | return error.TestFailed; | |
| 696 | var ok = true; | |
| 697 | if (self.case.expect_exact) { | |
| 698 | var err_iter = ErrLineIter.init(stderr); | |
| 699 | var i: usize = 0; | |
| 700 | ok = while (err_iter.next()) |line| : (i += 1) { | |
| 701 | if (i >= self.case.expected_errors.len) break false; | |
| 702 | const expected = self.case.expected_errors.at(i); | |
| 703 | if (mem.indexOf(u8, line, expected) == null) break false; | |
| 704 | continue; | |
| 705 | } else true; | |
| 706 | ||
| 707 | ok = ok and i == self.case.expected_errors.len; | |
| 708 | ||
| 709 | if (!ok) { | |
| 710 | warn("\n======== Expected these compile errors: ========\n"); | |
| 711 | for (self.case.expected_errors.toSliceConst()) |expected| { | |
| 712 | warn("{}\n", expected); | |
| 713 | } | |
| 714 | } | |
| 715 | } else { | |
| 716 | for (self.case.expected_errors.toSliceConst()) |expected| { | |
| 717 | if (mem.indexOf(u8, stderr, expected) == null) { | |
| 718 | warn( | |
| 719 | \\ | |
| 720 | \\=========== Expected compile error: ============ | |
| 721 | \\{} | |
| 722 | \\ | |
| 723 | , expected); | |
| 724 | ok = false; | |
| 725 | break; | |
| 726 | } | |
| 688 | 727 | } |
| 689 | 728 | } |
| 729 | ||
| 730 | if (!ok) { | |
| 731 | warn( | |
| 732 | \\================= Full output: ================= | |
| 733 | \\{} | |
| 734 | \\ | |
| 735 | , stderr); | |
| 736 | return error.TestFailed; | |
| 737 | } | |
| 738 | ||
| 690 | 739 | warn("OK\n"); |
| 691 | 740 | } |
| 692 | 741 | }; |
| ... | ... | @@ -704,6 +753,7 @@ pub const CompileErrorContext = struct { |
| 704 | 753 | .name = name, |
| 705 | 754 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 706 | 755 | .expected_errors = ArrayList([]const u8).init(self.b.allocator), |
| 756 | .expect_exact = false, | |
| 707 | 757 | .link_libc = false, |
| 708 | 758 | .is_exe = false, |
| 709 | 759 | .is_test = false, |
test/translate_c.zig+69-31| ... | ... | @@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 117 | 117 | \\}; |
| 118 | 118 | , |
| 119 | 119 | \\pub const struct_Foo = extern struct { |
| 120 | \\ a: ?[*]Foo, | |
| 120 | \\ a: [*c]Foo, | |
| 121 | 121 | \\}; |
| 122 | 122 | \\pub const Foo = struct_Foo; |
| 123 | 123 | \\pub const struct_Bar = extern struct { |
| 124 | \\ a: ?[*]Foo, | |
| 124 | \\ a: [*c]Foo, | |
| 125 | 125 | \\}; |
| 126 | 126 | ); |
| 127 | 127 | |
| ... | ... | @@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 213 | 213 | , |
| 214 | 214 | \\const struct_Foo = extern struct { |
| 215 | 215 | \\ x: c_int, |
| 216 | \\ y: ?[*]u8, | |
| 216 | \\ y: [*c]u8, | |
| 217 | 217 | \\}; |
| 218 | 218 | , |
| 219 | 219 | \\pub const Foo = struct_Foo; |
| ... | ... | @@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 244 | 244 | , |
| 245 | 245 | \\pub const BarB = enum_Bar.B; |
| 246 | 246 | , |
| 247 | \\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void; | |
| 247 | \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void; | |
| 248 | 248 | , |
| 249 | 249 | \\pub const Foo = struct_Foo; |
| 250 | 250 | , |
| ... | ... | @@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 254 | 254 | cases.add("constant size array", |
| 255 | 255 | \\void func(int array[20]); |
| 256 | 256 | , |
| 257 | \\pub extern fn func(array: ?[*]c_int) void; | |
| 257 | \\pub extern fn func(array: [*c]c_int) void; | |
| 258 | 258 | ); |
| 259 | 259 | |
| 260 | 260 | cases.add("self referential struct with function pointer", |
| ... | ... | @@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 263 | 263 | \\}; |
| 264 | 264 | , |
| 265 | 265 | \\pub const struct_Foo = extern struct { |
| 266 | \\ derp: ?extern fn(?[*]struct_Foo) void, | |
| 266 | \\ derp: ?extern fn([*c]struct_Foo) void, | |
| 267 | 267 | \\}; |
| 268 | 268 | , |
| 269 | 269 | \\pub const Foo = struct_Foo; |
| ... | ... | @@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 322 | 322 | \\}; |
| 323 | 323 | , |
| 324 | 324 | \\pub const struct_Bar = extern struct { |
| 325 | \\ next: ?[*]struct_Foo, | |
| 325 | \\ next: [*c]struct_Foo, | |
| 326 | 326 | \\}; |
| 327 | 327 | , |
| 328 | 328 | \\pub const struct_Foo = extern struct { |
| 329 | \\ next: ?[*]struct_Bar, | |
| 329 | \\ next: [*c]struct_Bar, | |
| 330 | 330 | \\}; |
| 331 | 331 | ); |
| 332 | 332 | |
| ... | ... | @@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 610 | 610 | , |
| 611 | 611 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 612 | 612 | \\ if ((a != 0) and (b != 0)) return 0; |
| 613 | \\ if ((b != 0) and (c != null)) return 1; | |
| 614 | \\ if ((a != 0) and (c != null)) return 2; | |
| 613 | \\ if ((b != 0) and (c != 0)) return 1; | |
| 614 | \\ if ((a != 0) and (c != 0)) return 2; | |
| 615 | 615 | \\ if ((a != 0) or (b != 0)) return 3; |
| 616 | \\ if ((b != 0) or (c != null)) return 4; | |
| 617 | \\ if ((a != 0) or (c != null)) return 5; | |
| 616 | \\ if ((b != 0) or (c != 0)) return 4; | |
| 617 | \\ if ((a != 0) or (c != 0)) return 5; | |
| 618 | 618 | \\ return 6; |
| 619 | 619 | \\} |
| 620 | 620 | ); |
| ... | ... | @@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 710 | 710 | \\pub const struct_Foo = extern struct { |
| 711 | 711 | \\ field: c_int, |
| 712 | 712 | \\}; |
| 713 | \\pub export fn read_field(foo: ?[*]struct_Foo) c_int { | |
| 713 | \\pub export fn read_field(foo: [*c]struct_Foo) c_int { | |
| 714 | 714 | \\ return foo.?.field; |
| 715 | 715 | \\} |
| 716 | 716 | ); |
| ... | ... | @@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 756 | 756 | \\ return x; |
| 757 | 757 | \\} |
| 758 | 758 | , |
| 759 | \\pub export fn foo(x: ?[*]c_ushort) ?*c_void { | |
| 759 | \\pub export fn foo(x: [*c]c_ushort) ?*c_void { | |
| 760 | 760 | \\ return @ptrCast(?*c_void, x); |
| 761 | 761 | \\} |
| 762 | 762 | ); |
| ... | ... | @@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 777 | 777 | \\ return 0; |
| 778 | 778 | \\} |
| 779 | 779 | , |
| 780 | \\pub export fn foo() ?[*]c_int { | |
| 781 | \\ return null; | |
| 780 | \\pub export fn foo() [*c]c_int { | |
| 781 | \\ return 0; | |
| 782 | 782 | \\} |
| 783 | 783 | ); |
| 784 | 784 | |
| ... | ... | @@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1086 | 1086 | \\ *x = 1; |
| 1087 | 1087 | \\} |
| 1088 | 1088 | , |
| 1089 | \\pub export fn foo(x: ?[*]c_int) void { | |
| 1089 | \\pub export fn foo(x: [*c]c_int) void { | |
| 1090 | 1090 | \\ x.?.* = 1; |
| 1091 | 1091 | \\} |
| 1092 | 1092 | ); |
| ... | ... | @@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1114 | 1114 | , |
| 1115 | 1115 | \\pub fn foo() c_int { |
| 1116 | 1116 | \\ var x: c_int = 1234; |
| 1117 | \\ var ptr: ?[*]c_int = &x; | |
| 1117 | \\ var ptr: [*c]c_int = &x; | |
| 1118 | 1118 | \\ return ptr.?.*; |
| 1119 | 1119 | \\} |
| 1120 | 1120 | ); |
| ... | ... | @@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1124 | 1124 | \\ return "bar"; |
| 1125 | 1125 | \\} |
| 1126 | 1126 | , |
| 1127 | \\pub fn foo() ?[*]const u8 { | |
| 1127 | \\pub fn foo() [*c]const u8 { | |
| 1128 | 1128 | \\ return c"bar"; |
| 1129 | 1129 | \\} |
| 1130 | 1130 | ); |
| ... | ... | @@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1253 | 1253 | \\ return (float *)a; |
| 1254 | 1254 | \\} |
| 1255 | 1255 | , |
| 1256 | \\fn ptrcast(a: ?[*]c_int) ?[*]f32 { | |
| 1257 | \\ return @ptrCast(?[*]f32, a); | |
| 1256 | \\fn ptrcast(a: [*c]c_int) [*c]f32 { | |
| 1257 | \\ return @ptrCast([*c]f32, a); | |
| 1258 | 1258 | \\} |
| 1259 | 1259 | ); |
| 1260 | 1260 | |
| ... | ... | @@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1280 | 1280 | \\ return !(a == 0); |
| 1281 | 1281 | \\ return !(a != 0); |
| 1282 | 1282 | \\ return !(b != 0); |
| 1283 | \\ return !(c != null); | |
| 1283 | \\ return !(c != 0); | |
| 1284 | 1284 | \\} |
| 1285 | 1285 | ); |
| 1286 | 1286 | |
| ... | ... | @@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1297 | 1297 | cases.add("const ptr initializer", |
| 1298 | 1298 | \\static const char *v0 = "0.0.0"; |
| 1299 | 1299 | , |
| 1300 | \\pub var v0: ?[*]const u8 = c"0.0.0"; | |
| 1300 | \\pub var v0: [*c]const u8 = c"0.0.0"; | |
| 1301 | 1301 | ); |
| 1302 | 1302 | |
| 1303 | 1303 | cases.add("static incomplete array inside function", |
| ... | ... | @@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1306 | 1306 | \\} |
| 1307 | 1307 | , |
| 1308 | 1308 | \\pub fn foo() void { |
| 1309 | \\ const v2: [*]const u8 = c"2.2.2"; | |
| 1309 | \\ const v2: [*c]const u8 = c"2.2.2"; | |
| 1310 | 1310 | \\} |
| 1311 | 1311 | ); |
| 1312 | 1312 | |
| 1313 | 1313 | cases.add("macro pointer cast", |
| 1314 | 1314 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) |
| 1315 | 1315 | , |
| 1316 | \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE); | |
| 1316 | \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*c]NRF_GPIO_Type)(NRF_GPIO_BASE); | |
| 1317 | 1317 | ); |
| 1318 | 1318 | |
| 1319 | cases.add("if on none bool", | |
| 1319 | cases.add("if on non-bool", | |
| 1320 | 1320 | \\enum SomeEnum { A, B, C }; |
| 1321 | 1321 | \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) { |
| 1322 | 1322 | \\ if (a) return 0; |
| ... | ... | @@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1337 | 1337 | \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { |
| 1338 | 1338 | \\ if (a != 0) return 0; |
| 1339 | 1339 | \\ if (b != 0) return 1; |
| 1340 | \\ if (c != null) return 2; | |
| 1340 | \\ if (c != 0) return 2; | |
| 1341 | 1341 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; |
| 1342 | 1342 | \\ return 4; |
| 1343 | 1343 | \\} |
| 1344 | 1344 | ); |
| 1345 | 1345 | |
| 1346 | cases.add("while on none bool", | |
| 1346 | cases.add("while on non-bool", | |
| 1347 | 1347 | \\int while_none_bool(int a, float b, void *c) { |
| 1348 | 1348 | \\ while (a) return 0; |
| 1349 | 1349 | \\ while (b) return 1; |
| ... | ... | @@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1354 | 1354 | \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 1355 | 1355 | \\ while (a != 0) return 0; |
| 1356 | 1356 | \\ while (b != 0) return 1; |
| 1357 | \\ while (c != null) return 2; | |
| 1357 | \\ while (c != 0) return 2; | |
| 1358 | 1358 | \\ return 3; |
| 1359 | 1359 | \\} |
| 1360 | 1360 | ); |
| 1361 | 1361 | |
| 1362 | cases.add("for on none bool", | |
| 1362 | cases.add("for on non-bool", | |
| 1363 | 1363 | \\int for_none_bool(int a, float b, void *c) { |
| 1364 | 1364 | \\ for (;a;) return 0; |
| 1365 | 1365 | \\ for (;b;) return 1; |
| ... | ... | @@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1370 | 1370 | \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 1371 | 1371 | \\ while (a != 0) return 0; |
| 1372 | 1372 | \\ while (b != 0) return 1; |
| 1373 | \\ while (c != null) return 2; | |
| 1373 | \\ while (c != 0) return 2; | |
| 1374 | 1374 | \\ return 3; |
| 1375 | 1375 | \\} |
| 1376 | 1376 | ); |
| ... | ... | @@ -1416,4 +1416,42 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1416 | 1416 | \\ } |
| 1417 | 1417 | \\} |
| 1418 | 1418 | ); |
| 1419 | ||
| 1420 | cases.addC("Parameterless function prototypes", | |
| 1421 | \\void foo() {} | |
| 1422 | \\void bar(void) {} | |
| 1423 | , | |
| 1424 | \\pub export fn foo() void {} | |
| 1425 | \\pub export fn bar() void {} | |
| 1426 | ); | |
| 1427 | ||
| 1428 | // cases.add("empty array with initializer", | |
| 1429 | // "int a[4] = {};" | |
| 1430 | // , | |
| 1431 | // "pub var a: [4]c_int = [1]c_int{0} ** 4;" | |
| 1432 | // ); | |
| 1433 | ||
| 1434 | // cases.add("array with initialization", | |
| 1435 | // "int a[4] = {1, 2, 3, 4};" | |
| 1436 | // , | |
| 1437 | // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};" | |
| 1438 | // ); | |
| 1439 | ||
| 1440 | // cases.add("array with incomplete initialization", | |
| 1441 | // "int a[4] = {3, 4};" | |
| 1442 | // , | |
| 1443 | // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);" | |
| 1444 | // ); | |
| 1445 | ||
| 1446 | // cases.add("2D array with initialization", | |
| 1447 | // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };" | |
| 1448 | // , | |
| 1449 | // "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}};" | |
| 1450 | // ); | |
| 1451 | ||
| 1452 | // cases.add("2D array with incomplete initialization", | |
| 1453 | // "int a[3][3] = { {1, 2}, {4, 5, 6} };" | |
| 1454 | // , | |
| 1455 | // "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};" | |
| 1456 | // ); | |
| 1419 | 1457 | } |