authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-28 09:19:18-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-28 09:19:18-05:00
log2dcf1a239250e60ec9d8865e16528049074ec4b0
treeb4aa4cc4c5e087ef72bf6e74dfd1a0c272a255c1
parent7a8f391b0fa397eea4a9602a0132e0247d0f67b7
parent9753e875453ceeb6f3683b434a7492e20b639d36
signature Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm8


133 files changed, 11458 insertions(+), 4956 deletions(-)

.builds/freebsd.yml+1-1
...@@ -4,7 +4,7 @@ packages:...@@ -4,7 +4,7 @@ packages:
4 - ninja4 - ninja
5 - llvm705 - llvm70
6sources:6sources:
7 - https://github.com/ziglang/zig.git7 - https://github.com/ziglang/zig
8tasks:8tasks:
9 - build: |9 - build: |
10 cd zig && mkdir build && cd build10 cd zig && mkdir build && cd build
.gitignore+3-3
...@@ -10,6 +10,6 @@...@@ -10,6 +10,6 @@
10# -andrewrk10# -andrewrk
1111
12zig-cache/12zig-cache/
13build/13/build/
14build-*/14/build-*/
15docgen_tmp/15/docgen_tmp/
CMakeLists.txt+17
...@@ -417,6 +417,7 @@ set(ZIG_SOURCES...@@ -417,6 +417,7 @@ set(ZIG_SOURCES
417 "${CMAKE_SOURCE_DIR}/src/error.cpp"417 "${CMAKE_SOURCE_DIR}/src/error.cpp"
418 "${CMAKE_SOURCE_DIR}/src/ir.cpp"418 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
419 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"419 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
420 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
420 "${CMAKE_SOURCE_DIR}/src/link.cpp"421 "${CMAKE_SOURCE_DIR}/src/link.cpp"
421 "${CMAKE_SOURCE_DIR}/src/main.cpp"422 "${CMAKE_SOURCE_DIR}/src/main.cpp"
422 "${CMAKE_SOURCE_DIR}/src/os.cpp"423 "${CMAKE_SOURCE_DIR}/src/os.cpp"
...@@ -432,6 +433,10 @@ set(BLAKE_SOURCES...@@ -432,6 +433,10 @@ set(BLAKE_SOURCES
432)433)
433set(ZIG_CPP_SOURCES434set(ZIG_CPP_SOURCES
434 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"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 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"440 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
436)441)
437442
...@@ -446,10 +451,12 @@ set(ZIG_STD_FILES...@@ -446,10 +451,12 @@ set(ZIG_STD_FILES
446 "buf_set.zig"451 "buf_set.zig"
447 "buffer.zig"452 "buffer.zig"
448 "build.zig"453 "build.zig"
454 "build/fmt.zig"
449 "c/darwin.zig"455 "c/darwin.zig"
450 "c/freebsd.zig"456 "c/freebsd.zig"
451 "c/index.zig"457 "c/index.zig"
452 "c/linux.zig"458 "c/linux.zig"
459 "c/netbsd.zig"
453 "c/windows.zig"460 "c/windows.zig"
454 "coff.zig"461 "coff.zig"
455 "crypto/blake2.zig"462 "crypto/blake2.zig"
...@@ -485,6 +492,7 @@ set(ZIG_STD_FILES...@@ -485,6 +492,7 @@ set(ZIG_STD_FILES
485 "fmt/errol/index.zig"492 "fmt/errol/index.zig"
486 "fmt/errol/lookup.zig"493 "fmt/errol/lookup.zig"
487 "fmt/index.zig"494 "fmt/index.zig"
495 "fmt/parse_float.zig"
488 "hash/adler.zig"496 "hash/adler.zig"
489 "hash/crc.zig"497 "hash/crc.zig"
490 "hash/fnv.zig"498 "hash/fnv.zig"
...@@ -589,6 +597,8 @@ set(ZIG_STD_FILES...@@ -589,6 +597,8 @@ set(ZIG_STD_FILES
589 "os/linux/index.zig"597 "os/linux/index.zig"
590 "os/linux/vdso.zig"598 "os/linux/vdso.zig"
591 "os/linux/x86_64.zig"599 "os/linux/x86_64.zig"
600 "os/netbsd/errno.zig"
601 "os/netbsd/index.zig"
592 "os/path.zig"602 "os/path.zig"
593 "os/time.zig"603 "os/time.zig"
594 "os/uefi.zig"604 "os/uefi.zig"
...@@ -603,6 +613,7 @@ set(ZIG_STD_FILES...@@ -603,6 +613,7 @@ set(ZIG_STD_FILES
603 "os/windows/util.zig"613 "os/windows/util.zig"
604 "os/zen.zig"614 "os/zen.zig"
605 "pdb.zig"615 "pdb.zig"
616 "priority_queue.zig"
606 "rand/index.zig"617 "rand/index.zig"
607 "rand/ziggurat.zig"618 "rand/ziggurat.zig"
608 "segmented_list.zig"619 "segmented_list.zig"
...@@ -611,6 +622,7 @@ set(ZIG_STD_FILES...@@ -611,6 +622,7 @@ set(ZIG_STD_FILES
611 "special/bootstrap_lib.zig"622 "special/bootstrap_lib.zig"
612 "special/build_runner.zig"623 "special/build_runner.zig"
613 "special/builtin.zig"624 "special/builtin.zig"
625 "special/compiler_rt/addXf3.zig"
614 "special/compiler_rt/aulldiv.zig"626 "special/compiler_rt/aulldiv.zig"
615 "special/compiler_rt/aullrem.zig"627 "special/compiler_rt/aullrem.zig"
616 "special/compiler_rt/comparetf2.zig"628 "special/compiler_rt/comparetf2.zig"
...@@ -653,6 +665,7 @@ set(ZIG_STD_FILES...@@ -653,6 +665,7 @@ set(ZIG_STD_FILES
653 "special/compiler_rt/udivmodti4.zig"665 "special/compiler_rt/udivmodti4.zig"
654 "special/compiler_rt/udivti3.zig"666 "special/compiler_rt/udivti3.zig"
655 "special/compiler_rt/umodti3.zig"667 "special/compiler_rt/umodti3.zig"
668 "special/fmt_runner.zig"
656 "special/init-exe/build.zig"669 "special/init-exe/build.zig"
657 "special/init-exe/src/main.zig"670 "special/init-exe/src/main.zig"
658 "special/init-lib/build.zig"671 "special/init-lib/build.zig"
...@@ -906,3 +919,7 @@ foreach(file ${ZIG_STD_FILES})...@@ -906,3 +919,7 @@ foreach(file ${ZIG_STD_FILES})
906 get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)919 get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)
907 install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")920 install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")
908endforeach()921endforeach()
922
923install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
924install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
925install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
README.md+40-22
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3A programming language designed for robustness, optimality, and3A programming language designed for robustness, optimality, and
4clarity.4clarity.
55
6[ziglang.org](https://ziglang.org)6[Download & Documentation](https://ziglang.org/download/)
77
8## Feature Highlights8## Feature Highlights
99
...@@ -77,36 +77,54 @@ clarity....@@ -77,36 +77,54 @@ clarity.
77 - what sizes are the C integer types77 - what sizes are the C integer types
78 - C ABI calling convention for this target78 - C ABI calling convention for this target
79 - bootstrap code and default panic handler79 - bootstrap code and default panic handler
80 * `zig targets` is guaranteed to include this target.
8081
81#### Tier 4 Support82#### Tier 4 Support
8283
83 * Support for these targets is entirely experimental.84 * Support for these targets is entirely experimental.
84 * LLVM may have the target as an experimental target, which means that you85 * LLVM may have the target as an experimental target, which means that you
85 need to use Zig-provided binaries for the target to be available, or86 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.
8793
88#### Support Table94#### Support Table
8995
90| | freestanding | linux | macosx | windows | freebsd | UEFI | other |96| | freestanding | linux | macosx | windows | freebsd | netbsd | UEFI | other |
91|--------|--------------|--------|--------|---------|---------|--------|--------|97|-------------|--------------|--------|--------|---------|---------|------- | -------|--------|
92|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 |98|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 2 | Tier 3 |
93|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 |99|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
94|arm | Tier 2 | Tier 3 | Tier 3 | 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 |
95|arm64 | Tier 2 | Tier 2 | 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 |
96|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |102|avr | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
97|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |103|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
98|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |104|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
99|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |105|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
100|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |106|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
101|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |107|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
102|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |108|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
103|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |109|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
104|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |110|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
105|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |111|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
106|wasm32 | Tier 4 | 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 |
107|wasm64 | Tier 4 | 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 |
108|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |114|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
109|riscv64 | Tier 4 | Tier 4 | N/A | N/A | 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 |
110128
111## Community129## Community
112130
build.zig+7-4
...@@ -49,13 +49,14 @@ pub fn build(b: *Builder) !void {...@@ -49,13 +49,14 @@ pub fn build(b: *Builder) !void {
49 .c_header_files = nextValue(&index, build_info),49 .c_header_files = nextValue(&index, build_info),
50 .dia_guids_lib = nextValue(&index, build_info),50 .dia_guids_lib = nextValue(&index, build_info),
51 .llvm = undefined,51 .llvm = undefined,
52 .no_rosegment = b.option(bool, "no-rosegment", "Workaround to enable valgrind builds") orelse false,
53 };52 };
54 ctx.llvm = try findLLVM(b, ctx.llvm_config_exe);53 ctx.llvm = try findLLVM(b, ctx.llvm_config_exe);
5554
56 var test_stage2 = b.addTest("src-self-hosted/test.zig");55 var test_stage2 = b.addTest("src-self-hosted/test.zig");
57 test_stage2.setBuildMode(builtin.Mode.Debug);56 test_stage2.setBuildMode(builtin.Mode.Debug);
5857
58 const fmt_build_zig = b.addFmt([][]const u8{"build.zig"});
59
59 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");60 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
60 exe.setBuildMode(mode);61 exe.setBuildMode(mode);
6162
...@@ -107,6 +108,11 @@ pub fn build(b: *Builder) !void {...@@ -107,6 +108,11 @@ pub fn build(b: *Builder) !void {
107 }108 }
108 const modes = chosen_modes[0..chosen_mode_index];109 const modes = chosen_modes[0..chosen_mode_index];
109110
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 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));116 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
111117
112 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));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,8 +295,6 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 {
289}295}
290296
291fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {297fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
292 exe.setNoRoSegment(ctx.no_rosegment);
293
294 exe.addIncludeDir("src");298 exe.addIncludeDir("src");
295 exe.addIncludeDir(ctx.cmake_binary_dir);299 exe.addIncludeDir(ctx.cmake_binary_dir);
296 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");300 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
...@@ -375,5 +379,4 @@ const Context = struct {...@@ -375,5 +379,4 @@ const Context = struct {
375 c_header_files: []const u8,379 c_header_files: []const u8,
376 dia_guids_lib: []const u8,380 dia_guids_lib: []const u8,
377 llvm: LibraryDep,381 llvm: LibraryDep,
378 no_rosegment: bool,
379};382};
cmake/Findclang.cmake+22
...@@ -11,17 +11,28 @@ if(MSVC)...@@ -11,17 +11,28 @@ if(MSVC)
11 find_package(CLANG REQUIRED CONFIG)11 find_package(CLANG REQUIRED CONFIG)
1212
13 set(CLANG_LIBRARIES13 set(CLANG_LIBRARIES
14 clangFrontendTool
15 clangCodeGen
14 clangFrontend16 clangFrontend
15 clangDriver17 clangDriver
16 clangSerialization18 clangSerialization
17 clangSema19 clangSema
20 clangStaticAnalyzerFrontend
21 clangStaticAnalyzerCheckers
22 clangStaticAnalyzerCore
18 clangAnalysis23 clangAnalysis
24 clangASTMatchers
19 clangAST25 clangAST
20 clangParse26 clangParse
21 clangSema27 clangSema
22 clangBasic28 clangBasic
23 clangEdit29 clangEdit
24 clangLex30 clangLex
31 clangARCMigrate
32 clangRewriteFrontend
33 clangRewrite
34 clangCrossTU
35 clangIndex
25 )36 )
2637
27else()38else()
...@@ -50,17 +61,28 @@ else()...@@ -50,17 +61,28 @@ else()
50 endif()61 endif()
51 endmacro(FIND_AND_ADD_CLANG_LIB)62 endmacro(FIND_AND_ADD_CLANG_LIB)
5263
64 FIND_AND_ADD_CLANG_LIB(clangFrontendTool)
65 FIND_AND_ADD_CLANG_LIB(clangCodeGen)
53 FIND_AND_ADD_CLANG_LIB(clangFrontend)66 FIND_AND_ADD_CLANG_LIB(clangFrontend)
54 FIND_AND_ADD_CLANG_LIB(clangDriver)67 FIND_AND_ADD_CLANG_LIB(clangDriver)
55 FIND_AND_ADD_CLANG_LIB(clangSerialization)68 FIND_AND_ADD_CLANG_LIB(clangSerialization)
56 FIND_AND_ADD_CLANG_LIB(clangSema)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 FIND_AND_ADD_CLANG_LIB(clangAnalysis)73 FIND_AND_ADD_CLANG_LIB(clangAnalysis)
74 FIND_AND_ADD_CLANG_LIB(clangASTMatchers)
58 FIND_AND_ADD_CLANG_LIB(clangAST)75 FIND_AND_ADD_CLANG_LIB(clangAST)
59 FIND_AND_ADD_CLANG_LIB(clangParse)76 FIND_AND_ADD_CLANG_LIB(clangParse)
60 FIND_AND_ADD_CLANG_LIB(clangSema)77 FIND_AND_ADD_CLANG_LIB(clangSema)
61 FIND_AND_ADD_CLANG_LIB(clangBasic)78 FIND_AND_ADD_CLANG_LIB(clangBasic)
62 FIND_AND_ADD_CLANG_LIB(clangEdit)79 FIND_AND_ADD_CLANG_LIB(clangEdit)
63 FIND_AND_ADD_CLANG_LIB(clangLex)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)
64endif()86endif()
6587
66include(FindPackageHandleStandardArgs)88include(FindPackageHandleStandardArgs)
doc/docgen.zig+2-8
...@@ -916,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -916,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
917 std.zig.Token.Id.Tilde,917 std.zig.Token.Id.Tilde,
918 std.zig.Token.Id.BracketStarBracket,918 std.zig.Token.Id.BracketStarBracket,
919 std.zig.Token.Id.BracketStarCBracket,
919 => try writeEscaped(out, src[token.start..token.end]),920 => try writeEscaped(out, src[token.start..token.end]),
920921
921 std.zig.Token.Id.Invalid => return parseError(922 std.zig.Token.Id.Invalid => return parseError(
...@@ -1104,14 +1105,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1104,14 +1105,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1104 },1105 },
1105 }1106 }
1106 if (code.target_windows) {1107 if (code.target_windows) {
1107 try test_args.appendSlice([][]const u8{1108 try test_args.appendSlice([][]const u8{ "-target", "x86_64-windows" });
1108 "--target-os",
1109 "windows",
1110 "--target-arch",
1111 "x86_64",
1112 "--target-environ",
1113 "msvc",
1114 });
1115 }1109 }
1116 const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");1110 const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
1117 const escaped_stderr = try escapeHtml(allocator, result.stderr);1111 const escaped_stderr = try escapeHtml(allocator, result.stderr);
doc/langref.html.in+541-142
...@@ -8,13 +8,7 @@...@@ -8,13 +8,7 @@
8 body{8 body{
9 background-color:#111;9 background-color:#111;
10 color: #bbb;10 color: #bbb;
11 font-family: system-ui,11 font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
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;
18 }12 }
19 a {13 a {
20 color: #88f;14 color: #88f;
...@@ -243,8 +237,9 @@ const Timestamp = struct {...@@ -243,8 +237,9 @@ const Timestamp = struct {
243 {#header_close#}237 {#header_close#}
244 {#header_open|Values#}238 {#header_open|Values#}
245 {#code_begin|exe|values#}239 {#code_begin|exe|values#}
246const std = @import("std");240// Top-level declarations are order-independent:
247const warn = std.debug.warn;241const warn = std.debug.warn;
242const std = @import("std");
248const os = std.os;243const os = std.os;
249const assert = std.debug.assert;244const assert = std.debug.assert;
250245
...@@ -262,7 +257,7 @@ pub fn main() void {...@@ -262,7 +257,7 @@ pub fn main() void {
262 true and false,257 true and false,
263 true or false,258 true or false,
264 !true);259 !true);
265 260
266 // optional261 // optional
267 var optional_value: ?[]const u8 = null;262 var optional_value: ?[]const u8 = null;
268 assert(optional_value == null);263 assert(optional_value == null);
...@@ -281,7 +276,7 @@ pub fn main() void {...@@ -281,7 +276,7 @@ pub fn main() void {
281276
282 warn("\nerror union 1\ntype: {}\nvalue: {}\n",277 warn("\nerror union 1\ntype: {}\nvalue: {}\n",
283 @typeName(@typeOf(number_or_error)), number_or_error);278 @typeName(@typeOf(number_or_error)), number_or_error);
284 279
285 number_or_error = 1234;280 number_or_error = 1234;
286281
287 warn("\nerror union 2\ntype: {}\nvalue: {}\n",282 warn("\nerror union 2\ntype: {}\nvalue: {}\n",
...@@ -706,15 +701,21 @@ fn divide(a: i32, b: i32) i32 {...@@ -706,15 +701,21 @@ fn divide(a: i32, b: i32) i32 {
706 {#code_end#}701 {#code_end#}
707 <p>702 <p>
708 In this function, values {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are known only at runtime,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 and704 and thus this division operation is vulnerable to both {#link|Integer Overflow#} and
710 division by zero.705 {#link|Division by Zero#}.
711 </p>706 </p>
712 <p>707 <p>
713 Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on708 Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
714 integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and709 integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and
715 {#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.710 {#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.
716 </p>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 {#header_close#}719 {#header_close#}
719 {#header_close#}720 {#header_close#}
720 {#header_open|Floats#}721 {#header_open|Floats#}
...@@ -1651,7 +1652,7 @@ test "pointer slicing" {...@@ -1651,7 +1652,7 @@ test "pointer slicing" {
1651 assert(array[3] == 5);1652 assert(array[3] == 5);
1652}1653}
1653 {#code_end#}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 an undefined memory layout:</p>1656 an undefined memory layout:</p>
1656 {#code_begin|test#}1657 {#code_begin|test#}
1657const assert = @import("std").debug.assert;1658const assert = @import("std").debug.assert;
...@@ -1694,7 +1695,7 @@ test "comptime @intToPtr" {...@@ -1694,7 +1695,7 @@ test "comptime @intToPtr" {
1694 }1695 }
1695}1696}
1696 {#code_end#}1697 {#code_end#}
1697 {#see_also|Optional Pointers#}1698 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
1698 {#header_open|volatile#}1699 {#header_open|volatile#}
1699 <p>Loads and stores are assumed to not have side effects. If a given load or store1700 <p>Loads and stores are assumed to not have side effects. If a given load or store
1700 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.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,7 +1824,9 @@ fn foo(bytes: []u8) u32 {
1823}1824}
1824 {#code_end#}1825 {#code_end#}
1825 {#header_close#}1826 {#header_close#}
1827 {#see_also|C Pointers|Pointers to Zero Bit Types#}
1826 {#header_close#}1828 {#header_close#}
1829
1827 {#header_open|Slices#}1830 {#header_open|Slices#}
1828 {#code_begin|test_safety|index out of bounds#}1831 {#code_begin|test_safety|index out of bounds#}
1829const assert = @import("std").debug.assert;1832const assert = @import("std").debug.assert;
...@@ -2043,14 +2046,211 @@ test "linked list" {...@@ -2043,14 +2046,211 @@ test "linked list" {
2043 assert(list2.first.?.data == 1234);2046 assert(list2.first.?.data == 1234);
2044}2047}
2045 {#code_end#}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 {#header_open|packed struct#}2056 {#header_open|packed struct#}
2047 <p>{#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout.</p>2057 <p>
2048 <p>TODO bit fields</p>2058 Unlike normal structs, {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout:
2049 <p>TODO alignment</p>2059 </p>
2050 <p>TODO endianness</p>2060 <ul>
2051 <p>TODO @bitOffsetOf and @byteOffsetOf</p>2061 <li>Fields remain in the order declared.</li>
2052 <p>TODO mention how volatile loads and stores of bit packed fields could be more efficient when2062 <li>There is no padding between fields.</li>
2053 done by hand instead of with packed struct</p>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#}
2081const std = @import("std");
2082const builtin = @import("builtin");
2083const assert = std.debug.assert;
2084
2085const Full = packed struct {
2086 number: u16,
2087};
2088const Divided = packed struct {
2089 half1: u8,
2090 quarter3: u4,
2091 quarter4: u4,
2092};
2093
2094test "@bitCast between packed structs" {
2095 doTheTest();
2096 comptime doTheTest();
2097}
2098
2099fn 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#}
2122const std = @import("std");
2123const assert = std.debug.assert;
2124
2125const BitField = packed struct {
2126 a: u3,
2127 b: u3,
2128 c: u2,
2129};
2130
2131var foo = BitField{
2132 .a = 1,
2133 .b = 2,
2134 .c = 3,
2135};
2136
2137test "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#}
2147const std = @import("std");
2148const assert = std.debug.assert;
2149
2150const BitField = packed struct {
2151 a: u3,
2152 b: u3,
2153 c: u2,
2154};
2155
2156var bit_field = BitField{
2157 .a = 1,
2158 .b = 2,
2159 .c = 3,
2160};
2161
2162test "pointer to non-bit-aligned field" {
2163 assert(bar(&bit_field.b) == 2);
2164}
2165
2166fn 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#}
2178const std = @import("std");
2179const assert = std.debug.assert;
2180
2181const BitField = packed struct {
2182 a: u3,
2183 b: u3,
2184 c: u2,
2185};
2186
2187var bit_field = BitField{
2188 .a = 1,
2189 .b = 2,
2190 .c = 3,
2191};
2192
2193test "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#}
2202const std = @import("std");
2203const assert = std.debug.assert;
2204
2205const BitField = packed struct {
2206 a: u3,
2207 b: u3,
2208 c: u2,
2209};
2210
2211test "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#}
2229const S = packed struct {
2230 a: u32,
2231 b: u32,
2232};
2233test "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 {#header_close#}2254 {#header_close#}
2055 {#header_open|struct Naming#}2255 {#header_open|struct Naming#}
2056 <p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p>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,8 +2400,8 @@ export fn entry(foo: Foo) void { }
2200 {#header_close#}2400 {#header_close#}
2201 {#header_open|packed enum#}2401 {#header_open|packed enum#}
2202 <p>By default, the size of enums is not guaranteed.</p>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 type2403 <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the
2204 of the enum:</p>2404 integer tag type of the enum:</p>
2205 {#code_begin|test#}2405 {#code_begin|test#}
2206const std = @import("std");2406const std = @import("std");
22072407
...@@ -2214,131 +2414,179 @@ test "packed enum" {...@@ -2214,131 +2414,179 @@ test "packed enum" {
2214 std.debug.assert(@sizeOf(Number) == @sizeOf(u8));2414 std.debug.assert(@sizeOf(Number) == @sizeOf(u8));
2215}2415}
2216 {#code_end#}2416 {#code_end#}
2417 <p>This makes the enum eligible to be in a {#link|packed struct#}.</p>
2217 {#header_close#}2418 {#header_close#}
2218 {#see_also|@memberName|@memberCount|@tagName|@sizeOf#}2419 {#see_also|@memberName|@memberCount|@tagName|@sizeOf#}
2219 {#header_close#}2420 {#header_close#}
2220 {#header_open|union#}2421 {#header_open|union#}
2221 {#code_begin|test|union#}2422 <p>
2222const assert = @import("std").debug.assert;2423 A bare {#syntax#}union{#endsyntax#} defines a set of possible types that a value
2223const mem = @import("std").mem;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#}
2433const Payload = union {
2434 Int: i64,
2435 Float: f64,
2436 Bool: bool,
2437};
2438test "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#}
2445const std = @import("std");
2446const assert = std.debug.assert;
22242447
2225// A union has only 1 active field at a time.
2226const Payload = union {2448const Payload = union {
2227 Int: i64,2449 Int: i64,
2228 Float: f64,2450 Float: f64,
2229 Bool: bool,2451 Bool: bool,
2230};2452};
2231test "simple union" {2453test "simple union" {
2232 var payload = Payload {.Int = 1234};2454 var payload = Payload{ .Int = 1234 };
2233 // payload.Float = 12.34; // ERROR! field not active
2234 assert(payload.Int == 1234);2455 assert(payload.Int == 1234);
2235 // You can activate another field by assigning the entire union.2456 payload = Payload{ .Float = 12.34 };
2236 payload = Payload {.Float = 12.34};
2237 assert(payload.Float == 12.34);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#}
2471const std = @import("std");
2472const assert = std.debug.assert;
22392473
2240// Unions can be given an enum tag type:2474const ComplexTypeTag = enum {
2241const ComplexTypeTag = enum { Ok, NotOk }; 2475 Ok,
2476 NotOk,
2477};
2242const ComplexType = union(ComplexTypeTag) {2478const ComplexType = union(ComplexTypeTag) {
2243 Ok: u8,2479 Ok: u8,
2244 NotOk: void,2480 NotOk: void,
2245};2481};
22462482
2247// Declare a specific instance of the union variant.2483test "switch on tagged union" {
2248test "declare union value" {2484 const c = ComplexType{ .Ok = 42 };
2249 const c = ComplexType { .Ok = 0 };
2250 assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);2485 assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
2486
2487 switch (c) {
2488 ComplexTypeTag.Ok => |value| assert(value == 42),
2489 ComplexTypeTag.NotOk => unreachable,
2490 }
2251}2491}
22522492
2253// @TagType can be used to access the enum tag type of a union.
2254test "@TagType" {2493test "@TagType" {
2255 assert(@TagType(ComplexType) == ComplexTypeTag);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#}
2501const std = @import("std");
2502const assert = std.debug.assert;
22572503
2258// Unions can be made to infer the enum tag type.2504const ComplexTypeTag = enum {
2259const Foo = union(enum) {2505 Ok,
2260 String: []const u8,2506 NotOk,
2261 Number: u64,2507};
22622508const ComplexType = union(ComplexTypeTag) {
2263 // void can be omitted when inferring enum tag type.2509 Ok: u8,
2264 None,2510 NotOk: void,
2265};2511};
2266test "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 },
22732512
2274 // Capture by value2513test "modify tagged union in switch" {
2275 Foo.Number => |x| blk: {2514 var c = ComplexType{ .Ok = 42 };
2276 assert(x == 54);2515 assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
2277 break :blk "this is a number";
2278 },
22792516
2280 Foo.None => blk: {2517 switch (c) {
2281 break :blk "this is a none";2518 ComplexTypeTag.Ok => |*value| value.* += 1,
2282 },2519 ComplexTypeTag.NotOk => unreachable,
2283 };2520 }
2284 assert(mem.eql(u8, what_is_it, "this is a number"));
2285}
22862521
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#}
2530const std = @import("std");
2531const assert = std.debug.assert;
22882532
2289const Variant = union(enum) {2533const Variant = union(enum) {
2290 Int: i32,2534 Int: i32,
2291 Bool: bool,2535 Bool: bool,
22922536
2537 // void can be omitted when inferring enum tag type.
2538 None,
2539
2293 fn truthy(self: Variant) bool {2540 fn truthy(self: Variant) bool {
2294 return switch (self) {2541 return switch (self) {
2295 Variant.Int => |x_int| x_int != 0,2542 Variant.Int => |x_int| x_int != 0,
2296 Variant.Bool => |x_bool| x_bool,2543 Variant.Bool => |x_bool| x_bool,
2544 Variant.None => false,
2297 };2545 };
2298 }2546 }
2299};2547};
23002548
2301test "union method" {2549test "union method" {
2302 var v1 = Variant { .Int = 1 };2550 var v1 = Variant{ .Int = 1 };
2303 var v2 = Variant { .Bool = false };2551 var v2 = Variant{ .Bool = false };
23042552
2305 assert(v1.truthy());2553 assert(v1.truthy());
2306 assert(!v2.truthy());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#}
2562const std = @import("std");
2563const assert = std.debug.assert;
23082564
2309
2310const Small = union {
2311 A: i32,
2312 B: bool,
2313 C: u8,
2314};
2315
2316// @memberCount tells how many fields a union has:
2317test "@memberCount" {
2318 assert(@memberCount(Small) == 3);
2319}
2320
2321// @memberName tells the name of a field in an enum:
2322test "@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.
2328const Small2 = union(enum) {2565const Small2 = union(enum) {
2329 A: i32,2566 A: i32,
2330 B: bool,2567 B: bool,
2331 C: u8,2568 C: u8,
2332};2569};
2333test "@tagName" {2570test "@tagName" {
2334 assert(mem.eql(u8, @tagName(Small2.C), "C"));2571 assert(std.mem.eql(u8, @tagName(Small2.C), "C"));
2335}2572}
2336 {#code_end#}2573 {#code_end#}
2574 {#header_close#}
2575
2576 {#header_open|extern union#}
2337 <p>2577 <p>
2338 Unions with an enum tag are generated as a struct with a tag field and union field. Zig2578 An {#syntax#}extern union{#endsyntax#} has memory layout guaranteed to be compatible with
2339 sorts the order of the tag and union field by the largest alignment.2579 the target C ABI.
2340 </p>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 {#header_close#}2588 {#header_close#}
2589
2342 {#header_open|blocks#}2590 {#header_open|blocks#}
2343 <p>2591 <p>
2344 Blocks are used to limit the scope of variable declarations:2592 Blocks are used to limit the scope of variable declarations:
...@@ -2371,7 +2619,36 @@ test "labeled break from labeled block expression" {...@@ -2371,7 +2619,36 @@ test "labeled break from labeled block expression" {
2371 {#code_end#}2619 {#code_end#}
2372 <p>Here, {#syntax#}blk{#endsyntax#} can be any name.</p>2620 <p>Here, {#syntax#}blk{#endsyntax#} can be any name.</p>
2373 {#see_also|Labeled while|Labeled for#}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#}
2626const pi = 3.14;
2627
2628test "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#}
2640test "separate scopes" {
2641 {
2642 const pi = 3.14;
2643 }
2644 {
2645 var pi: bool = true;
2646 }
2647}
2648 {#code_end#}
2649 {#header_close#}
2374 {#header_close#}2650 {#header_close#}
2651
2375 {#header_open|switch#}2652 {#header_open|switch#}
2376 {#code_begin|test|switch#}2653 {#code_begin|test|switch#}
2377const assert = @import("std").debug.assert;2654const assert = @import("std").debug.assert;
...@@ -2392,7 +2669,7 @@ test "switch simple" {...@@ -2392,7 +2669,7 @@ test "switch simple" {
23922669
2393 // Ranges can be specified using the ... syntax. These are inclusive2670 // Ranges can be specified using the ... syntax. These are inclusive
2394 // both ends.2671 // both ends.
2395 5 ... 100 => 1,2672 5...100 => 1,
23962673
2397 // Branches can be arbitrarily complex.2674 // Branches can be arbitrarily complex.
2398 101 => blk: {2675 101 => blk: {
...@@ -2418,14 +2695,47 @@ test "switch simple" {...@@ -2418,14 +2695,47 @@ test "switch simple" {
2418 assert(b == 1);2695 assert(b == 1);
2419}2696}
24202697
2421test "switch enum" {2698// Switch expressions can be used outside a function:
2699const 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.
2706test "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#}
2725const assert = @import("std").debug.assert;
2726
2727test "switch on tagged union" {
2728 const Point = struct {
2729 x: u8,
2730 y: u8,
2731 };
2422 const Item = union(enum) {2732 const Item = union(enum) {
2423 A: u32,2733 A: u32,
2424 C: struct { x: u8, y: u8 },2734 C: Point,
2425 D,2735 D,
2426 };2736 };
24272737
2428 var a = Item { .A = 3 };2738 var a = Item{ .C = Point{ .x = 1, .y = 2 } };
24292739
2430 // Switching on more complex enums is allowed.2740 // Switching on more complex enums is allowed.
2431 const b = switch (a) {2741 const b = switch (a) {
...@@ -2443,27 +2753,8 @@ test "switch enum" {...@@ -2443,27 +2753,8 @@ test "switch enum" {
2443 Item.D => 8,2753 Item.D => 8,
2444 };2754 };
24452755
2446 assert(b == 3);2756 assert(b == 6);
2447}2757 assert(a.C.x == 2);
2448
2449// Switch expressions can be used outside a function:
2450const 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.
2457test "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 }
2467}2758}
2468 {#code_end#}2759 {#code_end#}
2469 {#see_also|comptime|enum|@compileError|Compile Variables#}2760 {#see_also|comptime|enum|@compileError|Compile Variables#}
...@@ -3134,7 +3425,6 @@ const assert = @import("std").debug.assert;...@@ -3134,7 +3425,6 @@ const assert = @import("std").debug.assert;
3134// Functions are declared like this3425// Functions are declared like this
3135fn add(a: i8, b: i8) i8 {3426fn add(a: i8, b: i8) i8 {
3136 if (a == 0) {3427 if (a == 0) {
3137 // You can still return manually if needed.
3138 return b;3428 return b;
3139 }3429 }
31403430
...@@ -3158,12 +3448,18 @@ fn abort() noreturn {...@@ -3158,12 +3448,18 @@ fn abort() noreturn {
3158 while (true) {}3448 while (true) {}
3159}3449}
31603450
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// This can be useful when integrating with assembly.3452// This can be useful when integrating with assembly.
3163nakedcc fn _start() noreturn {3453nakedcc fn _start() noreturn {
3164 abort();3454 abort();
3165}3455}
31663456
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.
3459inline fn shiftLeftOne(a: u32) u32 {
3460 return a << 1;
3461}
3462
3167// The pub specifier allows the function to be visible when importing.3463// The pub specifier allows the function to be visible when importing.
3168// Another file can use @import and call sub23464// Another file can use @import and call sub2
3169pub fn sub2(a: i8, b: i8) i8 { return a - b; }3465pub fn sub2(a: i8, b: i8) i8 { return a - b; }
...@@ -3731,7 +4027,7 @@ fn bang2() void {...@@ -3731,7 +4027,7 @@ fn bang2() void {
3731 Here, the stack trace does not explain how the control4027 Here, the stack trace does not explain how the control
3732 flow in {#syntax#}bar{#endsyntax#} got to the {#syntax#}hello(){#endsyntax#} call.4028 flow in {#syntax#}bar{#endsyntax#} got to the {#syntax#}hello(){#endsyntax#} call.
3733 One would have to open a debugger or further instrument the application4029 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 shows exactly how the error bubbled up.4031 shows exactly how the error bubbled up.
3736 </p>4032 </p>
3737 <p>4033 <p>
...@@ -3923,7 +4219,7 @@ test "optional type" {...@@ -3923,7 +4219,7 @@ test "optional type" {
3923 cast it to a different type:4219 cast it to a different type:
3924 </p>4220 </p>
3925 {#code_begin|syntax#}4221 {#code_begin|syntax#}
3926const optional_value: ?i32 = null; 4222const optional_value: ?i32 = null;
3927 {#code_end#}4223 {#code_end#}
3928 {#header_close#}4224 {#header_close#}
3929 {#header_open|Optional Pointers#}4225 {#header_open|Optional Pointers#}
...@@ -3981,7 +4277,7 @@ test "implicit cast - invoke a type as a function" {...@@ -3981,7 +4277,7 @@ test "implicit cast - invoke a type as a function" {
3981 {#code_end#}4277 {#code_end#}
3982 <p>4278 <p>
3983 Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,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 </p>4281 </p>
3986 {#header_open|Implicit Cast: Stricter Qualification#}4282 {#header_open|Implicit Cast: Stricter Qualification#}
3987 <p>4283 <p>
...@@ -4228,9 +4524,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {...@@ -4228,9 +4524,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
4228 {#header_close#}4524 {#header_close#}
4229 {#header_close#}4525 {#header_close#}
42304526
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 <p>4538 <p>
4233 {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is4539 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 not included in the final generated code:4541 not included in the final generated code:
4235 </p>4542 </p>
4236 {#code_begin|syntax#}4543 {#code_begin|syntax#}
...@@ -4240,8 +4547,8 @@ export fn entry() void {...@@ -4240,8 +4547,8 @@ export fn entry() void {
4240 x = y;4547 x = y;
4241}4548}
4242 {#code_end#}4549 {#code_end#}
4243 <p>When this turns into LLVM IR, there is no code generated in the body of {#syntax#}entry{#endsyntax#},4550 <p>When this turns into machine code, there is no code generated in the
4244 even in debug mode. For example, on x86_64:</p>4551 body of {#syntax#}entry{#endsyntax#}, even in {#link|Debug#} mode. For example, on x86_64:</p>
4245 <pre><code>0000000000000010 &lt;entry&gt;:4552 <pre><code>0000000000000010 &lt;entry&gt;:
4246 10: 55 push %rbp4553 10: 55 push %rbp
4247 11: 48 89 e5 mov %rsp,%rbp4554 11: 48 89 e5 mov %rsp,%rbp
...@@ -4249,6 +4556,8 @@ export fn entry() void {...@@ -4249,6 +4556,8 @@ export fn entry() void {
4249 15: c3 retq </code></pre>4556 15: c3 retq </code></pre>
4250 <p>These assembly instructions do not have any code associated with the void values -4557 <p>These assembly instructions do not have any code associated with the void values -
4251 they only perform the function call prologue and epilog.</p>4558 they only perform the function call prologue and epilog.</p>
4559
4560 {#header_open|void#}
4252 <p>4561 <p>
4253 {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a4562 {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a
4254 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}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,6 +4629,38 @@ fn foo() i32 {
4320 {#code_end#}4629 {#code_end#}
4321 {#header_close#}4630 {#header_close#}
43224631
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#}
4635const std = @import("std");
4636const assert = std.debug.assert;
4637
4638test "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#}
4650const Empty = struct {};
4651
4652test "@ptrToInt for pointer to zero bit type" {
4653 var a = Empty{};
4654 _ = @ptrToInt(&a);
4655}
4656
4657test "@intToPtr for pointer to zero bit type" {
4658 _ = @intToPtr(*Empty, 0x1);
4659}
4660 {#code_end#}
4661 {#header_close#}
4662 {#header_close#}
4663
4323 {#header_open|comptime#}4664 {#header_open|comptime#}
4324 <p>4665 <p>
4325 Zig places importance on the concept of whether an expression is known at compile-time.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,7 +5442,7 @@ async fn testResumeFromSuspend(my_result: *i32) void {
5101 <p>5442 <p>
5102 {#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes5443 {#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes
5103 as an operand a promise handle.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 then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value.5446 then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value.
5106 Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its5447 Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its
5107 promise handle with the target coroutine. It becomes the target coroutine's responsibility5448 promise handle with the target coroutine. It becomes the target coroutine's responsibility
...@@ -5185,7 +5526,7 @@ fn seq(c: u8) void {...@@ -5185,7 +5526,7 @@ fn seq(c: u8) void {
5185 </li>5526 </li>
5186 </ul>5527 </ul>
5187 {#header_close#}5528 {#header_close#}
5188 5529
5189 {#header_close#}5530 {#header_close#}
5190 {#header_open|Builtin Functions#}5531 {#header_open|Builtin Functions#}
5191 <p>5532 <p>
...@@ -5540,13 +5881,13 @@ const warn = @import("std").debug.warn;...@@ -5540,13 +5881,13 @@ const warn = @import("std").debug.warn;
55405881
5541const num1 = blk: {5882const num1 = blk: {
5542 var val1: i32 = 99;5883 var val1: i32 = 99;
5543 @compileLog("comptime val1 = ", val1); 5884 @compileLog("comptime val1 = ", val1);
5544 val1 = val1 + 1;5885 val1 = val1 + 1;
5545 break :blk val1;5886 break :blk val1;
5546};5887};
55475888
5548test "main" {5889test "main" {
5549 @compileLog("comptime in main"); 5890 @compileLog("comptime in main");
55505891
5551 warn("Runtime in main, num1 = {}.\n", num1);5892 warn("Runtime in main, num1 = {}.\n", num1);
5552}5893}
...@@ -5556,10 +5897,10 @@ test "main" {...@@ -5556,10 +5897,10 @@ test "main" {
5556 will ouput:5897 will ouput:
5557 </p>5898 </p>
5558 <p>5899 <p>
5559 If all {#syntax#}@compileLog{#endsyntax#} calls are removed or 5900 If all {#syntax#}@compileLog{#endsyntax#} calls are removed or
5560 not encountered by analysis, the5901 not encountered by analysis, the
5561 program compiles successfully and the generated executable prints:5902 program compiles successfully and the generated executable prints:
5562 </p> 5903 </p>
5563 {#code_begin|test#}5904 {#code_begin|test#}
5564const warn = @import("std").debug.warn;5905const warn = @import("std").debug.warn;
55655906
...@@ -5658,12 +5999,13 @@ test "main" {...@@ -5658,12 +5999,13 @@ test "main" {
5658 {#header_close#}5999 {#header_close#}
56596000
5660 {#header_open|@enumToInt#}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 <p>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 </p>6006 </p>
5665 <p>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 known at {#link|comptime#}.6009 known at {#link|comptime#}.
5668 </p>6010 </p>
5669 {#see_also|@intToEnum#}6011 {#see_also|@intToEnum#}
...@@ -6104,6 +6446,10 @@ test "call foo" {...@@ -6104,6 +6446,10 @@ test "call foo" {
6104 <p>6446 <p>
6105 Converts a pointer of one type to a pointer of another type.6447 Converts a pointer of one type to a pointer of another type.
6106 </p>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 {#header_close#}6453 {#header_close#}
61086454
6109 {#header_open|@ptrToInt#}6455 {#header_open|@ptrToInt#}
...@@ -6293,10 +6639,15 @@ pub const FloatMode = enum {...@@ -6293,10 +6639,15 @@ pub const FloatMode = enum {
6293 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>6639 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
6294 <p>6640 <p>
6295 This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory.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 </p>6643 </p>
6297 <p>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 </p>6649 </p>
6650 {#see_also|@typeInfo#}
6300 {#header_close#}6651 {#header_close#}
63016652
6302 {#header_open|@sliceToBytes#}6653 {#header_open|@sliceToBytes#}
...@@ -6375,7 +6726,7 @@ fn List(comptime T: type) type {...@@ -6375,7 +6726,7 @@ fn List(comptime T: type) type {
6375 <p>6726 <p>
6376 When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the6727 When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the
6377 current import. There is a proposal to remove the import type and use an empty struct6728 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 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.6730 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
6380 </p>6731 </p>
6381 {#header_close#}6732 {#header_close#}
...@@ -6730,11 +7081,7 @@ pub fn build(b: *Builder) void {...@@ -6730,11 +7081,7 @@ pub fn build(b: *Builder) void {
6730 {#header_open|Single Threaded Builds#}7081 {#header_open|Single Threaded Builds#}
6731 <p>Zig has a compile option <code>--single-threaded</code> which has the following effects:7082 <p>Zig has a compile option <code>--single-threaded</code> which has the following effects:
6732 <ul>7083 <ul>
6733 <li>{#link|@atomicLoad#} is emitted as a normal load.</li>7084 <li>Variables which have Thread Local Storage instead become globals.</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>
6738 <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.7085 <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.
6739 TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li>7086 TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li>
6740 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}7087 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
...@@ -7343,12 +7690,30 @@ fn bar(f: *Foo) void {...@@ -7343,12 +7690,30 @@ fn bar(f: *Foo) void {
7343 f.float = 12.34;7690 f.float = 12.34;
7344}7691}
7345 {#code_end#}7692 {#code_end#}
7693 {#see_also|union|extern union#}
7346 {#header_close#}7694 {#header_close#}
73477695
7348 {#header_open|Out of Bounds Float To Integer Cast#}7696 {#header_open|Out of Bounds Float to Integer Cast#}
7349 <p>TODO</p>7697 <p>TODO</p>
7350 {#header_close#}7698 {#header_close#}
73517699
7700 {#header_open|Pointer Cast Invalid Null#}
7701 <p>At compile-time:</p>
7702 {#code_begin|test_err|null pointer casted to type#}
7703comptime {
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#}
7710pub 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 {#header_close#}7717 {#header_close#}
7353 {#header_open|Memory#}7718 {#header_open|Memory#}
7354 <p>TODO: explain no default allocator in zig</p>7719 <p>TODO: explain no default allocator in zig</p>
...@@ -7439,6 +7804,7 @@ pub fn main() void {...@@ -7439,6 +7804,7 @@ pub fn main() void {
7439 {#code_end#}7804 {#code_end#}
7440 {#see_also|String Literals#}7805 {#see_also|String Literals#}
7441 {#header_close#}7806 {#header_close#}
7807
7442 {#header_open|Import from C Header File#}7808 {#header_open|Import from C Header File#}
7443 <p>7809 <p>
7444 The {#syntax#}@cImport{#endsyntax#} builtin function can be used7810 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
...@@ -7477,6 +7843,36 @@ const c = @cImport({...@@ -7477,6 +7843,36 @@ const c = @cImport({
7477 {#code_end#}7843 {#code_end#}
7478 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}7844 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
7479 {#header_close#}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 {#header_open|Exporting a C Library#}7876 {#header_open|Exporting a C Library#}
7481 <p>7877 <p>
7482 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages7878 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,7 +8125,7 @@ Environments:
7729 coreclr8125 coreclr
7730 opencl</code></pre>8126 opencl</code></pre>
7731 <p>8127 <p>
7732 The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem8128 The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system
7733 abstractions, and thus takes additional work to support more platforms.8129 abstractions, and thus takes additional work to support more platforms.
7734 Not all standard library code requires operating system abstractions, however,8130 Not all standard library code requires operating system abstractions, however,
7735 so things such as generic data structures work an all above platforms.8131 so things such as generic data structures work an all above platforms.
...@@ -8164,7 +8560,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET...@@ -8164,7 +8560,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
8164PtrTypeStart8560PtrTypeStart
8165 &lt;- ASTERISK8561 &lt;- ASTERISK
8166 / ASTERISK28562 / ASTERISK2
8167 / LBRACKET ASTERISK RBRACKET8563 / PTRUNKNOWN
8564 / PTRC
81688565
8169# ContainerDecl specific8566# ContainerDecl specific
8170ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE8567ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
...@@ -8262,7 +8659,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip...@@ -8262,7 +8659,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip
8262LARROW2EQUAL &lt;- '&lt;&lt;=' skip8659LARROW2EQUAL &lt;- '&lt;&lt;=' skip
8263LARROWEQUAL &lt;- '&lt;=' skip8660LARROWEQUAL &lt;- '&lt;=' skip
8264LBRACE &lt;- '{' skip8661LBRACE &lt;- '{' skip
8265LBRACKET &lt;- '[' skip8662LBRACKET &lt;- '[' ![*] skip
8266LPAREN &lt;- '(' skip8663LPAREN &lt;- '(' skip
8267MINUS &lt;- '-' ![%=&gt;] skip8664MINUS &lt;- '-' ![%=&gt;] skip
8268MINUSEQUAL &lt;- '-=' skip8665MINUSEQUAL &lt;- '-=' skip
...@@ -8279,6 +8676,8 @@ PLUS2 &lt;- '++' skip...@@ -8279,6 +8676,8 @@ PLUS2 &lt;- '++' skip
8279PLUSEQUAL &lt;- '+=' skip8676PLUSEQUAL &lt;- '+=' skip
8280PLUSPERCENT &lt;- '+%' ![=] skip8677PLUSPERCENT &lt;- '+%' ![=] skip
8281PLUSPERCENTEQUAL &lt;- '+%=' skip8678PLUSPERCENTEQUAL &lt;- '+%=' skip
8679PTRC &lt;- '[*c]' skip
8680PTRUNKNOWN &lt;- '[*]' skip
8282QUESTIONMARK &lt;- '?' skip8681QUESTIONMARK &lt;- '?' skip
8283RARROW &lt;- '&gt;' ![&gt;=] skip8682RARROW &lt;- '&gt;' ![&gt;=] skip
8284RARROW2 &lt;- '&gt;&gt;' ![=] skip8683RARROW2 &lt;- '&gt;&gt;' ![=] skip
example/mix_o_files/build.zig+3-3
...@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;...@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;
3pub fn build(b: *Builder) void {3pub fn build(b: *Builder) void {
4 const obj = b.addObject("base64", "base64.zig");4 const obj = b.addObject("base64", "base64.zig");
55
6 const exe = b.addCExecutable("test");6 const exe = b.addExecutable("test", null);
7 exe.addCompileFlags([][]const u8{"-std=c99"});7 exe.addCSourceFile("test.c",[][]const u8{"-std=c99"});
8 exe.addSourceFile("test.c");
9 exe.addObject(obj);8 exe.addObject(obj);
9 exe.linkSystemLibrary("c");
1010
11 b.default_step.dependOn(&exe.step);11 b.default_step.dependOn(&exe.step);
1212
example/shared_library/build.zig+3-3
...@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;...@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;
3pub fn build(b: *Builder) void {3pub fn build(b: *Builder) void {
4 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));4 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
55
6 const exe = b.addCExecutable("test");6 const exe = b.addExecutable("test", null);
7 exe.addCompileFlags([][]const u8{"-std=c99"});7 exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
8 exe.addSourceFile("test.c");
9 exe.linkLibrary(lib);8 exe.linkLibrary(lib);
9 exe.linkSystemLibrary("c");
1010
11 b.default_step.dependOn(&exe.step);11 b.default_step.dependOn(&exe.step);
1212
example/shared_library/mathtest.zig-9
...@@ -1,12 +1,3 @@...@@ -1,12 +1,3 @@
1// TODO Remove this workaround
2comptime {
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}
8var _mh_execute_header = extern struct {x: usize}{.x = 0};
9
10export fn add(a: i32, b: i32) i32 {1export fn add(a: i32, b: i32) i32 {
11 return a + b;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,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
137137
138pub const ObjectFile = struct {138pub const ObjectFile = struct {
139 comp: *Compilation,139 comp: *Compilation,
140 module: llvm.ModuleRef,140 module: *llvm.Module,
141 builder: llvm.BuilderRef,141 builder: *llvm.Builder,
142 dibuilder: *llvm.DIBuilder,142 dibuilder: *llvm.DIBuilder,
143 context: llvm.ContextRef,143 context: *llvm.Context,
144 lock: event.Lock,144 lock: event.Lock,
145 arena: *std.mem.Allocator,145 arena: *std.mem.Allocator,
146146
...@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)...@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
323323
324fn addLLVMAttr(324fn addLLVMAttr(
325 ofile: *ObjectFile,325 ofile: *ObjectFile,
326 val: llvm.ValueRef,326 val: *llvm.Value,
327 attr_index: llvm.AttributeIndex,327 attr_index: llvm.AttributeIndex,
328 attr_name: []const u8,328 attr_name: []const u8,
329) !void {329) !void {
...@@ -335,7 +335,7 @@ fn addLLVMAttr(...@@ -335,7 +335,7 @@ fn addLLVMAttr(
335335
336fn addLLVMAttrStr(336fn addLLVMAttrStr(
337 ofile: *ObjectFile,337 ofile: *ObjectFile,
338 val: llvm.ValueRef,338 val: *llvm.Value,
339 attr_index: llvm.AttributeIndex,339 attr_index: llvm.AttributeIndex,
340 attr_name: []const u8,340 attr_name: []const u8,
341 attr_val: []const u8,341 attr_val: []const u8,
...@@ -351,7 +351,7 @@ fn addLLVMAttrStr(...@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
351}351}
352352
353fn addLLVMAttrInt(353fn addLLVMAttrInt(
354 val: llvm.ValueRef,354 val: *llvm.Value,
355 attr_index: llvm.AttributeIndex,355 attr_index: llvm.AttributeIndex,
356 attr_name: []const u8,356 attr_name: []const u8,
357 attr_val: u64,357 attr_val: u64,
...@@ -362,25 +362,25 @@ fn addLLVMAttrInt(...@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
363}363}
364364
365fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {365fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void {
366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
367}367}
368368
369fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void {369fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void {
370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
371}371}
372372
373fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void {373fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void {
374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
375}375}
376376
377fn renderLoadUntyped(377fn renderLoadUntyped(
378 ofile: *ObjectFile,378 ofile: *ObjectFile,
379 ptr: llvm.ValueRef,379 ptr: *llvm.Value,
380 alignment: Type.Pointer.Align,380 alignment: Type.Pointer.Align,
381 vol: Type.Pointer.Vol,381 vol: Type.Pointer.Vol,
382 name: [*]const u8,382 name: [*]const u8,
383) !llvm.ValueRef {383) !*llvm.Value {
384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385 switch (vol) {385 switch (vol) {
386 Type.Pointer.Vol.Non => {},386 Type.Pointer.Vol.Non => {},
...@@ -390,11 +390,11 @@ fn renderLoadUntyped(...@@ -390,11 +390,11 @@ fn renderLoadUntyped(
390 return result;390 return result;
391}391}
392392
393fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef {393fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395}395}
396396
397pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef {397pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value {
398 const child_type = ptr_type.key.child_type;398 const child_type = ptr_type.key.child_type;
399 if (!child_type.hasBits()) {399 if (!child_type.hasBits()) {
400 return null;400 return null;
...@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po...@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
407407
408pub fn renderStoreUntyped(408pub fn renderStoreUntyped(
409 ofile: *ObjectFile,409 ofile: *ObjectFile,
410 value: llvm.ValueRef,410 value: *llvm.Value,
411 ptr: llvm.ValueRef,411 ptr: *llvm.Value,
412 alignment: Type.Pointer.Align,412 alignment: Type.Pointer.Align,
413 vol: Type.Pointer.Vol,413 vol: Type.Pointer.Vol,
414) !llvm.ValueRef {414) !*llvm.Value {
415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416 switch (vol) {416 switch (vol) {
417 Type.Pointer.Vol.Non => {},417 Type.Pointer.Vol.Non => {},
...@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(...@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
423423
424pub fn renderStore(424pub fn renderStore(
425 ofile: *ObjectFile,425 ofile: *ObjectFile,
426 value: llvm.ValueRef,426 value: *llvm.Value,
427 ptr: llvm.ValueRef,427 ptr: *llvm.Value,
428 ptr_type: *Type.Pointer,428 ptr_type: *Type.Pointer,
429) !llvm.ValueRef {429) !*llvm.Value {
430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
431}431}
432432
...@@ -435,7 +435,7 @@ pub fn renderAlloca(...@@ -435,7 +435,7 @@ pub fn renderAlloca(
435 var_type: *Type,435 var_type: *Type,
436 name: []const u8,436 name: []const u8,
437 alignment: Type.Pointer.Align,437 alignment: Type.Pointer.Align,
438) !llvm.ValueRef {438) !*llvm.Value {
439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;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,7 +443,7 @@ pub fn renderAlloca(
443 return result;443 return result;
444}444}
445445
446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 {446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
447 return switch (alignment) {447 return switch (alignment) {
448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449 Type.Pointer.Align.Override => |a| a,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,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
37/// Data that is local to the event loop.37/// Data that is local to the event loop.
38pub const ZigCompiler = struct {38pub const ZigCompiler = struct {
39 loop: *event.Loop,39 loop: *event.Loop,
40 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),40 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
41 lld_lock: event.Lock,41 lld_lock: event.Lock,
4242
43 /// TODO pool these so that it doesn't have to lock43 /// TODO pool these so that it doesn't have to lock
...@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {...@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {
60 return ZigCompiler{60 return ZigCompiler{
61 .loop = loop,61 .loop = loop,
62 .lld_lock = event.Lock.init(loop),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 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),64 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
65 .native_libc = event.Future(LibCInstallation).init(loop),65 .native_libc = event.Future(LibCInstallation).init(loop),
66 };66 };
...@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {...@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
70 fn deinit(self: *ZigCompiler) void {70 fn deinit(self: *ZigCompiler) void {
71 self.lld_lock.deinit();71 self.lld_lock.deinit();
72 while (self.llvm_handle_pool.pop()) |node| {72 while (self.llvm_handle_pool.pop()) |node| {
73 c.LLVMContextDispose(node.data);73 llvm.ContextDispose(node.data);
74 self.loop.allocator.destroy(node);74 self.loop.allocator.destroy(node);
75 }75 }
76 }76 }
...@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {...@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {
80 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {80 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
81 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };81 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
8282
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);84 errdefer llvm.ContextDispose(context_ref);
8585
86 const node = try self.loop.allocator.create(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.ContextRef).Node{87 node.* = std.atomic.Stack(*llvm.Context).Node{
88 .next = undefined,88 .next = undefined,
89 .data = context_ref,89 .data = context_ref,
90 };90 };
...@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {...@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {
114};114};
115115
116pub const LlvmHandle = struct {116pub const LlvmHandle = struct {
117 node: *std.atomic.Stack(llvm.ContextRef).Node,117 node: *std.atomic.Stack(*llvm.Context).Node,
118118
119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
120 zig_compiler.llvm_handle_pool.push(self.node);120 zig_compiler.llvm_handle_pool.push(self.node);
...@@ -128,7 +128,7 @@ pub const Compilation = struct {...@@ -128,7 +128,7 @@ pub const Compilation = struct {
128 llvm_triple: Buffer,128 llvm_triple: Buffer,
129 root_src_path: ?[]const u8,129 root_src_path: ?[]const u8,
130 target: Target,130 target: Target,
131 llvm_target: llvm.TargetRef,131 llvm_target: *llvm.Target,
132 build_mode: builtin.Mode,132 build_mode: builtin.Mode,
133 zig_lib_dir: []const u8,133 zig_lib_dir: []const u8,
134 zig_std_dir: []const u8,134 zig_std_dir: []const u8,
...@@ -212,8 +212,8 @@ pub const Compilation = struct {...@@ -212,8 +212,8 @@ pub const Compilation = struct {
212 false_value: *Value.Bool,212 false_value: *Value.Bool,
213 noreturn_value: *Value.NoReturn,213 noreturn_value: *Value.NoReturn,
214214
215 target_machine: llvm.TargetMachineRef,215 target_machine: *llvm.TargetMachine,
216 target_data_ref: llvm.TargetDataRef,216 target_data_ref: *llvm.TargetData,
217 target_layout_str: [*]u8,217 target_layout_str: [*]u8,
218 target_ptr_bits: u32,218 target_ptr_bits: u32,
219219
src-self-hosted/ir.zig+10-10
...@@ -67,7 +67,7 @@ pub const Inst = struct {...@@ -67,7 +67,7 @@ pub const Inst = struct {
67 parent: ?*Inst,67 parent: ?*Inst,
6868
69 /// populated durign codegen69 /// populated durign codegen
70 llvm_value: ?llvm.ValueRef,70 llvm_value: ?*llvm.Value,
7171
72 pub fn cast(base: *Inst, comptime T: type) ?*T {72 pub fn cast(base: *Inst, comptime T: type) ?*T {
73 if (base.id == comptime typeToId(T)) {73 if (base.id == comptime typeToId(T)) {
...@@ -129,7 +129,7 @@ pub const Inst = struct {...@@ -129,7 +129,7 @@ pub const Inst = struct {
129 }129 }
130 }130 }
131131
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 switch (base.id) {133 switch (base.id) {
134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
...@@ -313,10 +313,10 @@ pub const Inst = struct {...@@ -313,10 +313,10 @@ pub const Inst = struct {
313 return new_inst;313 return new_inst;
314 }314 }
315315
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 const fn_ref = self.params.fn_ref.llvm_value.?;317 const fn_ref = self.params.fn_ref.llvm_value.?;
318318
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 for (self.params.args) |arg, i| {320 for (self.params.args) |arg, i| {
321 args[i] = arg.llvm_value.?;321 args[i] = arg.llvm_value.?;
322 }322 }
...@@ -360,7 +360,7 @@ pub const Inst = struct {...@@ -360,7 +360,7 @@ pub const Inst = struct {
360 return new_inst;360 return new_inst;
361 }361 }
362362
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 return self.base.val.KnownValue.getLlvmConst(ofile);364 return self.base.val.KnownValue.getLlvmConst(ofile);
365 }365 }
366 };366 };
...@@ -392,7 +392,7 @@ pub const Inst = struct {...@@ -392,7 +392,7 @@ pub const Inst = struct {
392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
393 }393 }
394394
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 const value = self.params.return_value.llvm_value;396 const value = self.params.return_value.llvm_value;
397 const return_type = self.params.return_value.getKnownType();397 const return_type = self.params.return_value.getKnownType();
398398
...@@ -540,7 +540,7 @@ pub const Inst = struct {...@@ -540,7 +540,7 @@ pub const Inst = struct {
540 }540 }
541 }541 }
542542
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 switch (self.params.var_scope.data) {544 switch (self.params.var_scope.data) {
545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546 Scope.Var.Data.Param => |param| return param.llvm_value,546 Scope.Var.Data.Param => |param| return param.llvm_value,
...@@ -596,7 +596,7 @@ pub const Inst = struct {...@@ -596,7 +596,7 @@ pub const Inst = struct {
596 return new_inst;596 return new_inst;
597 }597 }
598598
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 const child_type = self.base.getKnownType();600 const child_type = self.base.getKnownType();
601 if (!child_type.hasBits()) {601 if (!child_type.hasBits()) {
602 return null;602 return null;
...@@ -935,8 +935,8 @@ pub const BasicBlock = struct {...@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
935 ref_instruction: ?*Inst,935 ref_instruction: ?*Inst,
936936
937 /// for codegen937 /// for codegen
938 llvm_block: llvm.BasicBlockRef,938 llvm_block: *llvm.BasicBlock,
939 llvm_exit_block: llvm.BasicBlockRef,939 llvm_exit_block: *llvm.BasicBlock,
940940
941 /// the basic block that is derived from this one in analysis941 /// the basic block that is derived from this one in analysis
942 child: ?*BasicBlock,942 child: ?*BasicBlock,
src-self-hosted/libc_installation.zig+13-13
...@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {...@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
154 c.ZigFindWindowsSdkError.None => {154 c.ZigFindWindowsSdkError.None => {
155 windows_sdk = sdk;155 windows_sdk = sdk;
156156
157 if (sdk.msvc_lib_dir_ptr) |ptr| {157 if (sdk.msvc_lib_dir_ptr != 0) {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);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 try group.call(findNativeKernel32LibDir, self, loop, sdk);160 try group.call(findNativeKernel32LibDir, self, loop, sdk);
161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
...@@ -172,7 +172,7 @@ pub const LibCInstallation = struct {...@@ -172,7 +172,7 @@ pub const LibCInstallation = struct {
172 try group.call(findNativeStaticLibDir, self, loop);172 try group.call(findNativeStaticLibDir, self, loop);
173 try group.call(findNativeDynamicLinker, self, loop);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 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");176 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
177 },177 },
178 else => @compileError("unimplemented: find libc for this OS"),178 else => @compileError("unimplemented: find libc for this OS"),
...@@ -283,7 +283,7 @@ pub const LibCInstallation = struct {...@@ -283,7 +283,7 @@ pub const LibCInstallation = struct {
283 switch (builtin.arch) {283 switch (builtin.arch) {
284 builtin.Arch.i386 => try stream.write("x86"),284 builtin.Arch.i386 => try stream.write("x86"),
285 builtin.Arch.x86_64 => try stream.write("x64"),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 else => return error.UnsupportedArchitecture,287 else => return error.UnsupportedArchitecture,
288 }288 }
289 const ucrt_lib_path = try std.os.path.join(289 const ucrt_lib_path = try std.os.path.join(
...@@ -361,7 +361,7 @@ pub const LibCInstallation = struct {...@@ -361,7 +361,7 @@ pub const LibCInstallation = struct {
361 switch (builtin.arch) {361 switch (builtin.arch) {
362 builtin.Arch.i386 => try stream.write("x86\\"),362 builtin.Arch.i386 => try stream.write("x86\\"),
363 builtin.Arch.x86_64 => try stream.write("x64\\"),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 else => return error.UnsupportedArchitecture,365 else => return error.UnsupportedArchitecture,
366 }366 }
367 const kernel32_path = try std.os.path.join(367 const kernel32_path = try std.os.path.join(
...@@ -437,20 +437,20 @@ const Search = struct {...@@ -437,20 +437,20 @@ const Search = struct {
437437
438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
439 var search_end: usize = 0;439 var search_end: usize = 0;
440 if (sdk.path10_ptr) |path10_ptr| {440 if (sdk.path10_ptr != 0) {
441 if (sdk.version10_ptr) |ver10_ptr| {441 if (sdk.version10_ptr != 0) {
442 search_buf[search_end] = Search{442 search_buf[search_end] = Search{
443 .path = path10_ptr[0..sdk.path10_len],443 .path = sdk.path10_ptr[0..sdk.path10_len],
444 .version = ver10_ptr[0..sdk.version10_len],444 .version = sdk.version10_ptr[0..sdk.version10_len],
445 };445 };
446 search_end += 1;446 search_end += 1;
447 }447 }
448 }448 }
449 if (sdk.path81_ptr) |path81_ptr| {449 if (sdk.path81_ptr != 0) {
450 if (sdk.version81_ptr) |ver81_ptr| {450 if (sdk.version81_ptr != 0) {
451 search_buf[search_end] = Search{451 search_buf[search_end] = Search{
452 .path = path81_ptr[0..sdk.path81_len],452 .path = sdk.path81_ptr[0..sdk.path81_len],
453 .version = ver81_ptr[0..sdk.version81_len],453 .version = sdk.version81_ptr[0..sdk.version81_len],
454 };454 };
455 search_end += 1;455 search_end += 1;
456 }456 }
src-self-hosted/link.zig+2-6
...@@ -145,10 +145,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -145,10 +145,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
145 // lj->args.append("-T");145 // lj->args.append("-T");
146 // lj->args.append(g->linker_script);146 // lj->args.append(g->linker_script);
147 //}147 //}
148
149 //if (g->no_rosegment_workaround) {
150 // lj->args.append("--no-rosegment");
151 //}
152 try ctx.args.append(c"--gc-sections");148 try ctx.args.append(c"--gc-sections");
153149
154 //lj->args.append("-m");150 //lj->args.append("-m");
...@@ -330,7 +326,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -330,7 +326,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
330 switch (ctx.comp.target.getArch()) {326 switch (ctx.comp.target.getArch()) {
331 builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),327 builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),
332 builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"),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 else => return error.UnsupportedLinkArchitecture,330 else => return error.UnsupportedLinkArchitecture,
335 }331 }
336332
...@@ -556,7 +552,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -556,7 +552,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
556 }552 }
557 },553 },
558 DarwinPlatform.Kind.IPhoneOS => {554 DarwinPlatform.Kind.IPhoneOS => {
559 if (ctx.comp.target.getArch() == builtin.Arch.aarch64v8) {555 if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
560 // iOS does not need any crt1 files for arm64556 // iOS does not need any crt1 files for arm64
561 } else if (platform.versionLessThan(3, 1)) {557 } else if (platform.versionLessThan(3, 1)) {
562 try ctx.args.append(c"-lcrt1.o");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,45 +11,31 @@ const assert = @import("std").debug.assert;
11pub const AttributeIndex = c_uint;11pub const AttributeIndex = c_uint;
12pub const Bool = c_int;12pub const Bool = c_int;
1313
14pub const BuilderRef = removeNullability(c.LLVMBuilderRef);14pub const Builder = c.LLVMBuilderRef.Child.Child;
15pub const ContextRef = removeNullability(c.LLVMContextRef);15pub const Context = c.LLVMContextRef.Child.Child;
16pub const ModuleRef = removeNullability(c.LLVMModuleRef);16pub const Module = c.LLVMModuleRef.Child.Child;
17pub const ValueRef = removeNullability(c.LLVMValueRef);17pub const Value = c.LLVMValueRef.Child.Child;
18pub const TypeRef = removeNullability(c.LLVMTypeRef);18pub const Type = c.LLVMTypeRef.Child.Child;
19pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);19pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
20pub const AttributeRef = removeNullability(c.LLVMAttributeRef);20pub const Attribute = c.LLVMAttributeRef.Child.Child;
21pub const TargetRef = removeNullability(c.LLVMTargetRef);21pub const Target = c.LLVMTargetRef.Child.Child;
22pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);22pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
23pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);23pub const TargetData = c.LLVMTargetDataRef.Child.Child;
24pub const DIBuilder = c.ZigLLVMDIBuilder;24pub const DIBuilder = c.ZigLLVMDIBuilder;
25pub const DIFile = c.ZigLLVMDIFile;
26pub const DICompileUnit = c.ZigLLVMDICompileUnit;
2527
26pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;28pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
27pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;29pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
28pub const AddFunction = c.LLVMAddFunction;
29pub const AddGlobal = c.LLVMAddGlobal;
30pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;30pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
31pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;31pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
32pub const ArrayType = c.LLVMArrayType;
33pub const BuildLoad = c.LLVMBuildLoad;
34pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;32pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
35pub const ConstAllOnes = c.LLVMConstAllOnes;33pub const ConstAllOnes = c.LLVMConstAllOnes;
36pub const ConstArray = c.LLVMConstArray;34pub const ConstArray = c.LLVMConstArray;
37pub const ConstBitCast = c.LLVMConstBitCast;35pub const ConstBitCast = c.LLVMConstBitCast;
38pub const ConstInt = c.LLVMConstInt;
39pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;36pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
40pub const ConstNeg = c.LLVMConstNeg;37pub const ConstNeg = c.LLVMConstNeg;
41pub const ConstNull = c.LLVMConstNull;
42pub const ConstStringInContext = c.LLVMConstStringInContext;
43pub const ConstStructInContext = c.LLVMConstStructInContext;38pub const ConstStructInContext = c.LLVMConstStructInContext;
44pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData;
45pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;
46pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit;
47pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder;
48pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute;
49pub const CreateFile = c.ZigLLVMCreateFile;
50pub const CreateStringAttribute = c.LLVMCreateStringAttribute;
51pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout;
52pub const CreateTargetMachine = c.LLVMCreateTargetMachine;
53pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;39pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
54pub const DisposeBuilder = c.LLVMDisposeBuilder;40pub const DisposeBuilder = c.LLVMDisposeBuilder;
55pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;41pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
...@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;...@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
62pub const FP128TypeInContext = c.LLVMFP128TypeInContext;48pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
63pub const FloatTypeInContext = c.LLVMFloatTypeInContext;49pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
64pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;50pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
65pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
66pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;51pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
67pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
68pub const GetUndef = c.LLVMGetUndef;52pub const GetUndef = c.LLVMGetUndef;
69pub const HalfTypeInContext = c.LLVMHalfTypeInContext;53pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
70pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;54pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
...@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;...@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
81pub const Int8TypeInContext = c.LLVMInt8TypeInContext;65pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
82pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;66pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
83pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;67pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
84pub const IntTypeInContext = c.LLVMIntTypeInContext;
85pub const LabelTypeInContext = c.LLVMLabelTypeInContext;68pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
86pub const MDNodeInContext = c.LLVMMDNodeInContext;69pub const MDNodeInContext = c.LLVMMDNodeInContext;
87pub const MDStringInContext = c.LLVMMDStringInContext;70pub const MDStringInContext = c.LLVMMDStringInContext;
88pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;71pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
89pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
90pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;72pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
91pub const PointerType = c.LLVMPointerType;
92pub const SetAlignment = c.LLVMSetAlignment;73pub const SetAlignment = c.LLVMSetAlignment;
93pub const SetDataLayout = c.LLVMSetDataLayout;74pub const SetDataLayout = c.LLVMSetDataLayout;
94pub const SetGlobalConstant = c.LLVMSetGlobalConstant;75pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
...@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;...@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
99pub const SetVolatile = c.LLVMSetVolatile;80pub const SetVolatile = c.LLVMSetVolatile;
100pub const StructTypeInContext = c.LLVMStructTypeInContext;81pub const StructTypeInContext = c.LLVMStructTypeInContext;
101pub const TokenTypeInContext = c.LLVMTokenTypeInContext;82pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
102pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
103pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;83pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
104pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;84pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
10585
86pub const AddGlobal = LLVMAddGlobal;
87extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value;
88
89pub const ConstStringInContext = LLVMConstStringInContext;
90extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
91
92pub const ConstInt = LLVMConstInt;
93extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
94
95pub const BuildLoad = LLVMBuildLoad;
96extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value;
97
98pub const ConstNull = LLVMConstNull;
99extern fn LLVMConstNull(Ty: *Type) ?*Value;
100
101pub const CreateStringAttribute = LLVMCreateStringAttribute;
102extern fn LLVMCreateStringAttribute(
103 C: *Context,
104 K: [*]const u8,
105 KLength: c_uint,
106 V: [*]const u8,
107 VLength: c_uint,
108) ?*Attribute;
109
110pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
111extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
112
113pub const AddFunction = LLVMAddFunction;
114extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value;
115
116pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
117extern 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
130pub const CreateFile = ZigLLVMCreateFile;
131extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile;
132
133pub const ArrayType = LLVMArrayType;
134extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
135
136pub const CreateDIBuilder = ZigLLVMCreateDIBuilder;
137extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder;
138
139pub const PointerType = LLVMPointerType;
140extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type;
141
142pub const CreateBuilderInContext = LLVMCreateBuilderInContext;
143extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder;
144
145pub const IntTypeInContext = LLVMIntTypeInContext;
146extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
147
148pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
149extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;
150
151pub const VoidTypeInContext = LLVMVoidTypeInContext;
152extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
153
154pub const ContextCreate = LLVMContextCreate;
155extern fn LLVMContextCreate() ?*Context;
156
157pub const ContextDispose = LLVMContextDispose;
158extern fn LLVMContextDispose(C: *Context) void;
159
160pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
161extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;
162
163pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
164extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
165
166pub const CreateTargetMachine = LLVMCreateTargetMachine;
167extern 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
177pub const GetHostCPUName = LLVMGetHostCPUName;
178extern fn LLVMGetHostCPUName() ?[*]u8;
179
180pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
181extern fn ZigLLVMGetNativeFeatures() ?[*]u8;
182
106pub const GetElementType = LLVMGetElementType;183pub const GetElementType = LLVMGetElementType;
107extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;184extern fn LLVMGetElementType(Ty: *Type) *Type;
108185
109pub const TypeOf = LLVMTypeOf;186pub const TypeOf = LLVMTypeOf;
110extern fn LLVMTypeOf(Val: ValueRef) TypeRef;187extern fn LLVMTypeOf(Val: *Value) *Type;
111188
112pub const BuildStore = LLVMBuildStore;189pub const BuildStore = LLVMBuildStore;
113extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
114191
115pub const BuildAlloca = LLVMBuildAlloca;192pub const BuildAlloca = LLVMBuildAlloca;
116extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef;193extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value;
117194
118pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;195pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
119pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef;196pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
120197
121pub const GetTargetFromTriple = LLVMGetTargetFromTriple;198pub const GetTargetFromTriple = LLVMGetTargetFromTriple;
122extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool;199extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool;
123200
124pub const VerifyModule = LLVMVerifyModule;201pub const VerifyModule = LLVMVerifyModule;
125extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
126203
127pub const GetInsertBlock = LLVMGetInsertBlock;204pub const GetInsertBlock = LLVMGetInsertBlock;
128extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
129206
130pub const FunctionType = LLVMFunctionType;207pub const FunctionType = LLVMFunctionType;
131extern fn LLVMFunctionType(208extern fn LLVMFunctionType(
132 ReturnType: TypeRef,209 ReturnType: *Type,
133 ParamTypes: [*]TypeRef,210 ParamTypes: [*]*Type,
134 ParamCount: c_uint,211 ParamCount: c_uint,
135 IsVarArg: Bool,212 IsVarArg: Bool,
136) ?TypeRef;213) ?*Type;
137214
138pub const GetParam = LLVMGetParam;215pub const GetParam = LLVMGetParam;
139extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
140217
141pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;218pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
142extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef;219extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock;
143220
144pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
145extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
146223
147pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;224pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
148pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;225pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
...@@ -190,17 +267,17 @@ pub const FnInline = extern enum {...@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
190};267};
191268
192fn removeNullability(comptime T: type) type {269fn removeNullability(comptime T: type) type {
193 comptime assert(@typeId(T) == builtin.TypeId.Optional);270 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
194 return T.Child;271 return *T.Child;
195}272}
196273
197pub const BuildRet = LLVMBuildRet;274pub const BuildRet = LLVMBuildRet;
198extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;275extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
199276
200pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;277pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
201extern fn ZigLLVMTargetMachineEmitToFile(278extern fn ZigLLVMTargetMachineEmitToFile(
202 targ_machine_ref: TargetMachineRef,279 targ_machine_ref: *TargetMachine,
203 module_ref: ModuleRef,280 module_ref: *Module,
204 filename: [*]const u8,281 filename: [*]const u8,
205 output_type: EmitOutputType,282 output_type: EmitOutputType,
206 error_message: *[*]u8,283 error_message: *[*]u8,
...@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(...@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
209) bool;286) bool;
210287
211pub const BuildCall = ZigLLVMBuildCall;288pub const BuildCall = ZigLLVMBuildCall;
212extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef;289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value;
213290
214pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/main.zig+10-14
...@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;...@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
24var stderr: *io.OutStream(os.File.WriteError) = undefined;24var stderr: *io.OutStream(os.File.WriteError) = undefined;
25var stdout: *io.OutStream(os.File.WriteError) = undefined;25var stdout: *io.OutStream(os.File.WriteError) = undefined;
2626
27const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB27pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
2828
29const usage =29const usage =
30 \\usage: zig [command] [options]30 \\usage: zig [command] [options]
...@@ -154,9 +154,7 @@ const usage_build_generic =...@@ -154,9 +154,7 @@ const usage_build_generic =
154 \\ release-small optimize for small binary, safety off154 \\ release-small optimize for small binary, safety off
155 \\ --static Output will be statically linked155 \\ --static Output will be statically linked
156 \\ --strip Exclude debug symbols156 \\ --strip Exclude debug symbols
157 \\ --target-arch [name] Specify target architecture157 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
158 \\ --target-environ [name] Specify target environment
159 \\ --target-os [name] Specify target operating system
160 \\ --verbose-tokenize Turn on compiler debug output for tokenization158 \\ --verbose-tokenize Turn on compiler debug output for tokenization
161 \\ --verbose-ast-tree Turn on compiler debug output for parsing into an AST (tree view)159 \\ --verbose-ast-tree Turn on compiler debug output for parsing into an AST (tree view)
162 \\ --verbose-ast-fmt Turn on compiler debug output for parsing into an AST (render source)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,9 +218,7 @@ const args_build_generic = []Flag{
220 Flag.Bool("--pkg-end"),218 Flag.Bool("--pkg-end"),
221 Flag.Bool("--static"),219 Flag.Bool("--static"),
222 Flag.Bool("--strip"),220 Flag.Bool("--strip"),
223 Flag.Arg1("--target-arch"),221 Flag.Arg1("-target"),
224 Flag.Arg1("--target-environ"),
225 Flag.Arg1("--target-os"),
226 Flag.Bool("--verbose-tokenize"),222 Flag.Bool("--verbose-tokenize"),
227 Flag.Bool("--verbose-ast-tree"),223 Flag.Bool("--verbose-ast-tree"),
228 Flag.Bool("--verbose-ast-fmt"),224 Flag.Bool("--verbose-ast-fmt"),
...@@ -510,7 +506,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {...@@ -510,7 +506,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
510 return buildOutputType(allocator, args, Compilation.Kind.Obj);506 return buildOutputType(allocator, args, Compilation.Kind.Obj);
511}507}
512508
513const usage_fmt =509pub const usage_fmt =
514 \\usage: zig fmt [file]...510 \\usage: zig fmt [file]...
515 \\511 \\
516 \\ Formats the input files and modifies them in-place.512 \\ Formats the input files and modifies them in-place.
...@@ -527,7 +523,7 @@ const usage_fmt =...@@ -527,7 +523,7 @@ const usage_fmt =
527 \\523 \\
528;524;
529525
530const args_fmt_spec = []Flag{526pub const args_fmt_spec = []Flag{
531 Flag.Bool("--help"),527 Flag.Bool("--help"),
532 Flag.Bool("--check"),528 Flag.Bool("--check"),
533 Flag.Option("--color", []const []const u8{529 Flag.Option("--color", []const []const u8{
...@@ -839,15 +835,15 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {...@@ -839,15 +835,15 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
839 }835 }
840 try stdout.write("\n");836 try stdout.write("\n");
841837
842 try stdout.write("Environments:\n");838 try stdout.write("C ABIs:\n");
843 {839 {
844 comptime var i: usize = 0;840 comptime var i: usize = 0;
845 inline while (i < @memberCount(builtin.Environ)) : (i += 1) {841 inline while (i < @memberCount(builtin.Abi)) : (i += 1) {
846 comptime const environ_tag = @memberName(builtin.Environ, i);842 comptime const abi_tag = @memberName(builtin.Abi, i);
847 // NOTE: Cannot use empty string, see #918.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";
849845
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,7 +362,7 @@ pub const Scope = struct {
362 pub const Param = struct {362 pub const Param = struct {
363 index: usize,363 index: usize,
364 typ: *Type,364 typ: *Type,
365 llvm_value: llvm.ValueRef,365 llvm_value: *llvm.Value,
366 };366 };
367367
368 pub fn createParam(368 pub fn createParam(
src-self-hosted/target.zig+47-234
...@@ -16,7 +16,7 @@ pub const Target = union(enum) {...@@ -16,7 +16,7 @@ pub const Target = union(enum) {
16 pub const Cross = struct {16 pub const Cross = struct {
17 arch: builtin.Arch,17 arch: builtin.Arch,
18 os: builtin.Os,18 os: builtin.Os,
19 environ: builtin.Environ,19 abi: builtin.Abi,
20 object_format: builtin.ObjectFormat,20 object_format: builtin.ObjectFormat,
21 };21 };
2222
...@@ -49,16 +49,16 @@ pub const Target = union(enum) {...@@ -49,16 +49,16 @@ pub const Target = union(enum) {
49 }49 }
5050
51 pub fn getArch(self: Target) builtin.Arch {51 pub fn getArch(self: Target) builtin.Arch {
52 return switch (self) {52 switch (self) {
53 Target.Native => builtin.arch,53 Target.Native => return builtin.arch,
54 @TagType(Target).Cross => |t| t.arch,54 @TagType(Target).Cross => |t| return t.arch,
55 };55 }
56 }56 }
5757
58 pub fn getEnviron(self: Target) builtin.Environ {58 pub fn getAbi(self: Target) builtin.Abi {
59 return switch (self) {59 return switch (self) {
60 Target.Native => builtin.environ,60 Target.Native => builtin.abi,
61 @TagType(Target).Cross => |t| t.environ,61 @TagType(Target).Cross => |t| t.abi,
62 };62 };
63 }63 }
6464
...@@ -93,50 +93,10 @@ pub const Target = union(enum) {...@@ -93,50 +93,10 @@ pub const Target = union(enum) {
93 /// TODO expose the arch and subarch separately93 /// TODO expose the arch and subarch separately
94 pub fn isArmOrThumb(self: Target) bool {94 pub fn isArmOrThumb(self: Target) bool {
95 return switch (self.getArch()) {95 return switch (self.getArch()) {
96 builtin.Arch.armv8_5a,96 builtin.Arch.arm,
97 builtin.Arch.armv8_4a,97 builtin.Arch.armeb,
98 builtin.Arch.armv8_3a,98 builtin.Arch.aarch64,
99 builtin.Arch.armv8_2a,99 builtin.Arch.aarch64_be,
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,
140 builtin.Arch.thumb,100 builtin.Arch.thumb,
141 builtin.Arch.thumbeb,101 builtin.Arch.thumbeb,
142 => true,102 => true,
...@@ -159,14 +119,14 @@ pub const Target = union(enum) {...@@ -159,14 +119,14 @@ pub const Target = union(enum) {
159 // LLVM WebAssembly output support requires the target to be activated at119 // LLVM WebAssembly output support requires the target to be activated at
160 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.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 // defaulting to an object based on the architecture. The default format in123 // defaulting to an object based on the architecture. The default format in
164 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to124 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
165 // explicitly set this ourself in order for it to work.125 // explicitly set this ourself in order for it to work.
166 //126 //
167 // This is fixed in LLVM 7 and you will be able to get wasm output by127 // This is fixed in LLVM 7 and you will be able to get wasm output by
168 // using the target triple `wasm32-unknown-unknown-unknown`.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());
170130
171 var out = &std.io.BufferOutStream.init(&result).stream;131 var out = &std.io.BufferOutStream.init(&result).stream;
172 try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name);132 try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name);
...@@ -185,50 +145,8 @@ pub const Target = union(enum) {...@@ -185,50 +145,8 @@ pub const Target = union(enum) {
185 => return 16,145 => return 16,
186146
187 builtin.Arch.arc,147 builtin.Arch.arc,
188 builtin.Arch.armv8_5a,148 builtin.Arch.arm,
189 builtin.Arch.armv8_4a,149 builtin.Arch.armeb,
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,
232 builtin.Arch.hexagon,150 builtin.Arch.hexagon,
233 builtin.Arch.le32,151 builtin.Arch.le32,
234 builtin.Arch.mipsr6,152 builtin.Arch.mipsr6,
...@@ -248,35 +166,17 @@ pub const Target = union(enum) {...@@ -248,35 +166,17 @@ pub const Target = union(enum) {
248 builtin.Arch.amdil,166 builtin.Arch.amdil,
249 builtin.Arch.hsail,167 builtin.Arch.hsail,
250 builtin.Arch.spir,168 builtin.Arch.spir,
251 builtin.Arch.kalimbav3,169 builtin.Arch.kalimba,
252 builtin.Arch.kalimbav4,
253 builtin.Arch.kalimbav5,
254 builtin.Arch.shave,170 builtin.Arch.shave,
255 builtin.Arch.lanai,171 builtin.Arch.lanai,
256 builtin.Arch.wasm32,172 builtin.Arch.wasm32,
257 builtin.Arch.renderscript32,173 builtin.Arch.renderscript32,
258 => return 32,174 => return 32,
259175
260 builtin.Arch.aarch64v8_5a,176 builtin.Arch.aarch64,
261 builtin.Arch.aarch64v8_4a,177 builtin.Arch.aarch64_be,
262 builtin.Arch.aarch64v8_3a,178 builtin.Arch.mips64,
263 builtin.Arch.aarch64v8_2a,179 builtin.Arch.mips64el,
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,
280 builtin.Arch.powerpc64,180 builtin.Arch.powerpc64,
281 builtin.Arch.powerpc64le,181 builtin.Arch.powerpc64le,
282 builtin.Arch.riscv64,182 builtin.Arch.riscv64,
...@@ -298,17 +198,17 @@ pub const Target = union(enum) {...@@ -298,17 +198,17 @@ pub const Target = union(enum) {
298 }198 }
299199
300 pub fn getFloatAbi(self: Target) FloatAbi {200 pub fn getFloatAbi(self: Target) FloatAbi {
301 return switch (self.getEnviron()) {201 return switch (self.getAbi()) {
302 builtin.Environ.gnueabihf,202 builtin.Abi.gnueabihf,
303 builtin.Environ.eabihf,203 builtin.Abi.eabihf,
304 builtin.Environ.musleabihf,204 builtin.Abi.musleabihf,
305 => FloatAbi.Hard,205 => FloatAbi.Hard,
306 else => FloatAbi.Soft,206 else => FloatAbi.Soft,
307 };207 };
308 }208 }
309209
310 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {210 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
311 const env = self.getEnviron();211 const env = self.getAbi();
312 const arch = self.getArch();212 const arch = self.getArch();
313 const os = self.getOs();213 const os = self.getOs();
314 switch (os) {214 switch (os) {
...@@ -317,21 +217,21 @@ pub const Target = union(enum) {...@@ -317,21 +217,21 @@ pub const Target = union(enum) {
317 },217 },
318 builtin.Os.linux => {218 builtin.Os.linux => {
319 switch (env) {219 switch (env) {
320 builtin.Environ.android => {220 builtin.Abi.android => {
321 if (self.is64bit()) {221 if (self.is64bit()) {
322 return "/system/bin/linker64";222 return "/system/bin/linker64";
323 } else {223 } else {
324 return "/system/bin/linker";224 return "/system/bin/linker";
325 }225 }
326 },226 },
327 builtin.Environ.gnux32 => {227 builtin.Abi.gnux32 => {
328 if (arch == builtin.Arch.x86_64) {228 if (arch == builtin.Arch.x86_64) {
329 return "/libx32/ld-linux-x32.so.2";229 return "/libx32/ld-linux-x32.so.2";
330 }230 }
331 },231 },
332 builtin.Environ.musl,232 builtin.Abi.musl,
333 builtin.Environ.musleabi,233 builtin.Abi.musleabi,
334 builtin.Environ.musleabihf,234 builtin.Abi.musleabihf,
335 => {235 => {
336 if (arch == builtin.Arch.x86_64) {236 if (arch == builtin.Arch.x86_64) {
337 return "/lib/ld-musl-x86_64.so.1";237 return "/lib/ld-musl-x86_64.so.1";
...@@ -345,73 +245,18 @@ pub const Target = union(enum) {...@@ -345,73 +245,18 @@ pub const Target = union(enum) {
345 builtin.Arch.sparcel,245 builtin.Arch.sparcel,
346 => return "/lib/ld-linux.so.2",246 => return "/lib/ld-linux.so.2",
347247
348 builtin.Arch.aarch64v8_5a,248 builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
349 builtin.Arch.aarch64v8_4a,249
350 builtin.Arch.aarch64v8_3a,250 builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
351 builtin.Arch.aarch64v8_2a,251
352 builtin.Arch.aarch64v8_1a,252 builtin.Arch.arm,
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,
392 builtin.Arch.thumb,253 builtin.Arch.thumb,
393 builtin.Arch.armebv8_5a,254 => return switch (self.getFloatAbi()) {
394 builtin.Arch.armebv8_4a,255 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
395 builtin.Arch.armebv8_3a,256 else => return "/lib/ld-linux.so.3",
396 builtin.Arch.armebv8_2a,257 },
397 builtin.Arch.armebv8_1a,258
398 builtin.Arch.armebv8,259 builtin.Arch.armeb,
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,
415 builtin.Arch.thumbeb,260 builtin.Arch.thumbeb,
416 => return switch (self.getFloatAbi()) {261 => return switch (self.getFloatAbi()) {
417 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",262 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
...@@ -454,9 +299,7 @@ pub const Target = union(enum) {...@@ -454,9 +299,7 @@ pub const Target = union(enum) {
454 builtin.Arch.hsail64,299 builtin.Arch.hsail64,
455 builtin.Arch.spir,300 builtin.Arch.spir,
456 builtin.Arch.spir64,301 builtin.Arch.spir64,
457 builtin.Arch.kalimbav3,302 builtin.Arch.kalimba,
458 builtin.Arch.kalimbav4,
459 builtin.Arch.kalimbav5,
460 builtin.Arch.shave,303 builtin.Arch.shave,
461 builtin.Arch.lanai,304 builtin.Arch.lanai,
462 builtin.Arch.wasm32,305 builtin.Arch.wasm32,
...@@ -470,8 +313,8 @@ pub const Target = union(enum) {...@@ -470,8 +313,8 @@ pub const Target = union(enum) {
470 }313 }
471 }314 }
472315
473 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {316 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
474 var result: llvm.TargetRef = undefined;317 var result: *llvm.Target = undefined;
475 var err_msg: [*]u8 = undefined;318 var err_msg: [*]u8 = undefined;
476 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {319 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
477 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);320 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
...@@ -582,39 +425,9 @@ pub const Target = union(enum) {...@@ -582,39 +425,9 @@ pub const Target = union(enum) {
582 pub fn getDarwinArchString(self: Target) []const u8 {425 pub fn getDarwinArchString(self: Target) []const u8 {
583 const arch = self.getArch();426 const arch = self.getArch();
584 switch (arch) {427 switch (arch) {
585 builtin.Arch.aarch64v8_5a,428 builtin.Arch.aarch64 => return "arm64",
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",
595 builtin.Arch.thumb,429 builtin.Arch.thumb,
596 builtin.Arch.armv8_5a,430 builtin.Arch.arm,
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,
618 => return "arm",431 => return "arm",
619 builtin.Arch.powerpc => return "ppc",432 builtin.Arch.powerpc => return "ppc",
620 builtin.Arch.powerpc64 => return "ppc64",433 builtin.Arch.powerpc64 => return "ppc64",
src-self-hosted/type.zig+23-21
...@@ -51,8 +51,8 @@ pub const Type = struct {...@@ -51,8 +51,8 @@ pub const Type = struct {
51 pub fn getLlvmType(51 pub fn getLlvmType(
52 base: *Type,52 base: *Type,
53 allocator: *Allocator,53 allocator: *Allocator,
54 llvm_context: llvm.ContextRef,54 llvm_context: *llvm.Context,
55 ) (error{OutOfMemory}!llvm.TypeRef) {55 ) (error{OutOfMemory}!*llvm.Type) {
56 switch (base.id) {56 switch (base.id) {
57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
...@@ -196,7 +196,7 @@ pub const Type = struct {...@@ -196,7 +196,7 @@ pub const Type = struct {
196 }196 }
197197
198 /// If you have an llvm conext handy, you can use it here.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 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
201201
202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
...@@ -205,7 +205,7 @@ pub const Type = struct {...@@ -205,7 +205,7 @@ pub const Type = struct {
205 }205 }
206206
207 /// Lower level function that does the work. See getAbiAlignment.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 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
211 }211 }
...@@ -218,7 +218,7 @@ pub const Type = struct {...@@ -218,7 +218,7 @@ pub const Type = struct {
218 comp.gpa().destroy(self);218 comp.gpa().destroy(self);
219 }219 }
220220
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 @panic("TODO");222 @panic("TODO");
223 }223 }
224 };224 };
...@@ -496,13 +496,13 @@ pub const Type = struct {...@@ -496,13 +496,13 @@ pub const Type = struct {
496 comp.gpa().destroy(self);496 comp.gpa().destroy(self);
497 }497 }
498498
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 const normal = &self.key.data.Normal;500 const normal = &self.key.data.Normal;
501 const llvm_return_type = switch (normal.return_type.id) {501 const llvm_return_type = switch (normal.return_type.id) {
502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
503 else => try normal.return_type.getLlvmType(allocator, llvm_context),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 defer allocator.free(llvm_param_types);506 defer allocator.free(llvm_param_types);
507 for (llvm_param_types) |*llvm_param_type, i| {507 for (llvm_param_types) |*llvm_param_type, i| {
508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
...@@ -559,7 +559,7 @@ pub const Type = struct {...@@ -559,7 +559,7 @@ pub const Type = struct {
559 comp.gpa().destroy(self);559 comp.gpa().destroy(self);
560 }560 }
561561
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 @panic("TODO");563 @panic("TODO");
564 }564 }
565 };565 };
...@@ -658,7 +658,7 @@ pub const Type = struct {...@@ -658,7 +658,7 @@ pub const Type = struct {
658 comp.gpa().destroy(self);658 comp.gpa().destroy(self);
659 }659 }
660660
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 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;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,7 +670,7 @@ pub const Type = struct {
670 comp.gpa().destroy(self);670 comp.gpa().destroy(self);
671 }671 }
672672
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 @panic("TODO");674 @panic("TODO");
675 }675 }
676 };676 };
...@@ -794,6 +794,7 @@ pub const Type = struct {...@@ -794,6 +794,7 @@ pub const Type = struct {
794 Size.One => "*",794 Size.One => "*",
795 Size.Many => "[*]",795 Size.Many => "[*]",
796 Size.Slice => "[]",796 Size.Slice => "[]",
797 Size.C => "[*c]",
797 };798 };
798 const mut_str = switch (self.key.mut) {799 const mut_str = switch (self.key.mut) {
799 Mut.Const => "const ",800 Mut.Const => "const ",
...@@ -835,7 +836,7 @@ pub const Type = struct {...@@ -835,7 +836,7 @@ pub const Type = struct {
835 return self;836 return self;
836 }837 }
837838
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 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);840 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
840 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;841 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
841 }842 }
...@@ -903,7 +904,7 @@ pub const Type = struct {...@@ -903,7 +904,7 @@ pub const Type = struct {
903 return self;904 return self;
904 }905 }
905906
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 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);908 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
908 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;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,7 +917,7 @@ pub const Type = struct {
916 comp.gpa().destroy(self);917 comp.gpa().destroy(self);
917 }918 }
918919
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 @panic("TODO");921 @panic("TODO");
921 }922 }
922 };923 };
...@@ -966,7 +967,7 @@ pub const Type = struct {...@@ -966,7 +967,7 @@ pub const Type = struct {
966 comp.gpa().destroy(self);967 comp.gpa().destroy(self);
967 }968 }
968969
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 @panic("TODO");971 @panic("TODO");
971 }972 }
972 };973 };
...@@ -978,7 +979,7 @@ pub const Type = struct {...@@ -978,7 +979,7 @@ pub const Type = struct {
978 comp.gpa().destroy(self);979 comp.gpa().destroy(self);
979 }980 }
980981
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 @panic("TODO");983 @panic("TODO");
983 }984 }
984 };985 };
...@@ -990,7 +991,7 @@ pub const Type = struct {...@@ -990,7 +991,7 @@ pub const Type = struct {
990 comp.gpa().destroy(self);991 comp.gpa().destroy(self);
991 }992 }
992993
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 @panic("TODO");995 @panic("TODO");
995 }996 }
996 };997 };
...@@ -1002,7 +1003,7 @@ pub const Type = struct {...@@ -1002,7 +1003,7 @@ pub const Type = struct {
1002 comp.gpa().destroy(self);1003 comp.gpa().destroy(self);
1003 }1004 }
10041005
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 @panic("TODO");1007 @panic("TODO");
1007 }1008 }
1008 };1009 };
...@@ -1014,7 +1015,7 @@ pub const Type = struct {...@@ -1014,7 +1015,7 @@ pub const Type = struct {
1014 comp.gpa().destroy(self);1015 comp.gpa().destroy(self);
1015 }1016 }
10161017
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 @panic("TODO");1019 @panic("TODO");
1019 }1020 }
1020 };1021 };
...@@ -1034,7 +1035,7 @@ pub const Type = struct {...@@ -1034,7 +1035,7 @@ pub const Type = struct {
1034 comp.gpa().destroy(self);1035 comp.gpa().destroy(self);
1035 }1036 }
10361037
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 @panic("TODO");1039 @panic("TODO");
1039 }1040 }
1040 };1041 };
...@@ -1054,7 +1055,7 @@ pub const Type = struct {...@@ -1054,7 +1055,7 @@ pub const Type = struct {
1054 comp.gpa().destroy(self);1055 comp.gpa().destroy(self);
1055 }1056 }
10561057
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 @panic("TODO");1059 @panic("TODO");
1059 }1060 }
1060 };1061 };
...@@ -1066,7 +1067,7 @@ pub const Type = struct {...@@ -1066,7 +1067,7 @@ pub const Type = struct {
1066 comp.gpa().destroy(self);1067 comp.gpa().destroy(self);
1067 }1068 }
10681069
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 @panic("TODO");1071 @panic("TODO");
1071 }1072 }
1072 };1073 };
...@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {...@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
1088 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),1089 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
1089 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),1090 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
1090 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),1091 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1092 builtin.TypeInfo.Pointer.Size.C => unreachable,
1091 }1093 }
1092 },1094 },
1093 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),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,7 +57,7 @@ pub const Value = struct {
57 std.debug.warn("{}", @tagName(base.id));57 std.debug.warn("{}", @tagName(base.id));
58 }58 }
5959
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 switch (base.id) {61 switch (base.id) {
62 Id.Type => unreachable,62 Id.Type => unreachable,
63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
...@@ -153,7 +153,7 @@ pub const Value = struct {...@@ -153,7 +153,7 @@ pub const Value = struct {
153 comp.gpa().destroy(self);153 comp.gpa().destroy(self);
154 }154 }
155155
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
158 const llvm_fn = llvm.AddFunction(158 const llvm_fn = llvm.AddFunction(
159 ofile.module,159 ofile.module,
...@@ -238,7 +238,7 @@ pub const Value = struct {...@@ -238,7 +238,7 @@ pub const Value = struct {
238 /// We know that the function definition will end up in an .o file somewhere.238 /// We know that the function definition will end up in an .o file somewhere.
239 /// Here, all we have to do is generate a global prototype.239 /// Here, all we have to do is generate a global prototype.
240 /// TODO cache the prototype per ObjectFile240 /// 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 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
243 const llvm_fn = llvm.AddFunction(243 const llvm_fn = llvm.AddFunction(
244 ofile.module,244 ofile.module,
...@@ -283,8 +283,8 @@ pub const Value = struct {...@@ -283,8 +283,8 @@ pub const Value = struct {
283 comp.gpa().destroy(self);283 comp.gpa().destroy(self);
284 }284 }
285285
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context);287 const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
288 if (self.x) {288 if (self.x) {
289 return llvm.ConstAllOnes(llvm_type);289 return llvm.ConstAllOnes(llvm_type);
290 } else {290 } else {
...@@ -381,7 +381,7 @@ pub const Value = struct {...@@ -381,7 +381,7 @@ pub const Value = struct {
381 comp.gpa().destroy(self);381 comp.gpa().destroy(self);
382 }382 }
383383
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
387 switch (self.special) {387 switch (self.special) {
...@@ -391,7 +391,7 @@ pub const Value = struct {...@@ -391,7 +391,7 @@ pub const Value = struct {
391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
392 const ptr_bit_count = ofile.comp.target_ptr_bits;392 const ptr_bit_count = ofile.comp.target_ptr_bits;
393 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;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 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,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,7 +459,7 @@ pub const Value = struct {
459 comp.gpa().destroy(self);459 comp.gpa().destroy(self);
460 }460 }
461461
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
463 switch (self.special) {463 switch (self.special) {
464 Special.Undefined => {464 Special.Undefined => {
465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
...@@ -534,7 +534,7 @@ pub const Value = struct {...@@ -534,7 +534,7 @@ pub const Value = struct {
534 return self;534 return self;
535 }535 }
536536
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
538 switch (self.base.typ.id) {538 switch (self.base.typ.id) {
539 Type.Id.Int => {539 Type.Id.Int => {
540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
src/all_types.hpp+112-50
...@@ -18,6 +18,7 @@...@@ -18,6 +18,7 @@
18#include "bigfloat.hpp"18#include "bigfloat.hpp"
19#include "target.hpp"19#include "target.hpp"
20#include "tokenizer.hpp"20#include "tokenizer.hpp"
21#include "libc_installation.hpp"
2122
22struct AstNode;23struct AstNode;
23struct ImportTableEntry;24struct ImportTableEntry;
...@@ -630,24 +631,12 @@ struct AstNodeUnwrapOptional {...@@ -630,24 +631,12 @@ struct AstNodeUnwrapOptional {
630 AstNode *expr;631 AstNode *expr;
631};632};
632633
633enum 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
646struct AstNodeFnCallExpr {634struct AstNodeFnCallExpr {
647 AstNode *fn_ref_expr;635 AstNode *fn_ref_expr;
648 ZigList<AstNode *> params;636 ZigList<AstNode *> params;
649 bool is_builtin;637 bool is_builtin;
650 bool is_async;638 bool is_async;
639 bool seen; // used by @compileLog
651 AstNode *async_allocator;640 AstNode *async_allocator;
652};641};
653642
...@@ -691,15 +680,17 @@ struct AstNodePointerType {...@@ -691,15 +680,17 @@ struct AstNodePointerType {
691 AstNode *align_expr;680 AstNode *align_expr;
692 BigInt *bit_offset_start;681 BigInt *bit_offset_start;
693 BigInt *host_int_bytes;682 BigInt *host_int_bytes;
683 AstNode *op_expr;
684 Token *allow_zero_token;
694 bool is_const;685 bool is_const;
695 bool is_volatile;686 bool is_volatile;
696 AstNode *op_expr;
697};687};
698688
699struct AstNodeArrayType {689struct AstNodeArrayType {
700 AstNode *size;690 AstNode *size;
701 AstNode *child_type;691 AstNode *child_type;
702 AstNode *align_expr;692 AstNode *align_expr;
693 Token *allow_zero_token;
703 bool is_const;694 bool is_const;
704 bool is_volatile;695 bool is_volatile;
705};696};
...@@ -1038,6 +1029,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);...@@ -1038,6 +1029,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
1038enum PtrLen {1029enum PtrLen {
1039 PtrLenUnknown,1030 PtrLenUnknown,
1040 PtrLenSingle,1031 PtrLenSingle,
1032 PtrLenC,
1041};1033};
10421034
1043struct ZigTypePointer {1035struct ZigTypePointer {
...@@ -1049,6 +1041,7 @@ struct ZigTypePointer {...@@ -1049,6 +1041,7 @@ struct ZigTypePointer {
1049 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned1041 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
1050 bool is_const;1042 bool is_const;
1051 bool is_volatile;1043 bool is_volatile;
1044 bool allow_zero;
1052};1045};
10531046
1054struct ZigTypeInt {1047struct ZigTypeInt {
...@@ -1247,6 +1240,12 @@ enum ZigTypeId {...@@ -1247,6 +1240,12 @@ enum ZigTypeId {
1247 ZigTypeIdVector,1240 ZigTypeIdVector,
1248};1241};
12491242
1243enum OnePossibleValue {
1244 OnePossibleValueInvalid,
1245 OnePossibleValueNo,
1246 OnePossibleValueYes,
1247};
1248
1250struct ZigType {1249struct ZigType {
1251 ZigTypeId id;1250 ZigTypeId id;
1252 Buf name;1251 Buf name;
...@@ -1254,9 +1253,6 @@ struct ZigType {...@@ -1254,9 +1253,6 @@ struct ZigType {
1254 LLVMTypeRef type_ref;1253 LLVMTypeRef type_ref;
1255 ZigLLVMDIType *di_type;1254 ZigLLVMDIType *di_type;
12561255
1257 bool zero_bits; // this is denormalized data
1258 bool gen_h_loop_flag;
1259
1260 union {1256 union {
1261 ZigTypePointer pointer;1257 ZigTypePointer pointer;
1262 ZigTypeInt integral;1258 ZigTypeInt integral;
...@@ -1282,6 +1278,11 @@ struct ZigType {...@@ -1282,6 +1278,11 @@ struct ZigType {
1282 // If we generate a constant name value for this type, we memoize it here.1278 // If we generate a constant name value for this type, we memoize it here.
1283 // The type of this is array1279 // The type of this is array
1284 ConstExprValue *cached_const_name_val;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};
12861287
1287struct PackageTableEntry {1288struct PackageTableEntry {
...@@ -1340,15 +1341,11 @@ struct ZigFn {...@@ -1340,15 +1341,11 @@ struct ZigFn {
1340 // in the case of async functions this is the implicit return type according to the1341 // in the case of async functions this is the implicit return type according to the
1341 // zig source code, not according to zig ir1342 // zig source code, not according to zig ir
1342 ZigType *src_implicit_return_type;1343 ZigType *src_implicit_return_type;
1343 bool is_test;
1344 FnInline fn_inline;
1345 FnAnalState anal_state;
1346 IrExecutable ir_executable;1344 IrExecutable ir_executable;
1347 IrExecutable analyzed_executable;1345 IrExecutable analyzed_executable;
1348 size_t prealloc_bbc;1346 size_t prealloc_bbc;
1349 AstNode **param_source_nodes;1347 AstNode **param_source_nodes;
1350 Buf **param_names;1348 Buf **param_names;
1351 uint32_t align_bytes;
13521349
1353 AstNode *fn_no_inline_set_node;1350 AstNode *fn_no_inline_set_node;
1354 AstNode *fn_static_eval_set_node;1351 AstNode *fn_static_eval_set_node;
...@@ -1358,13 +1355,22 @@ struct ZigFn {...@@ -1358,13 +1355,22 @@ struct ZigFn {
13581355
1359 Buf *section_name;1356 Buf *section_name;
1360 AstNode *set_alignstack_node;1357 AstNode *set_alignstack_node;
1361 uint32_t alignstack_value;
13621358
1363 AstNode *set_cold_node;1359 AstNode *set_cold_node;
1364 bool is_cold;
13651360
1366 ZigList<FnExport> export_list;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 bool calls_or_awaits_errorable_fn;1371 bool calls_or_awaits_errorable_fn;
1372 bool is_cold;
1373 bool is_test;
1368};1374};
13691375
1370uint32_t fn_table_entry_hash(ZigFn*);1376uint32_t fn_table_entry_hash(ZigFn*);
...@@ -1484,6 +1490,7 @@ enum PanicMsgId {...@@ -1484,6 +1490,7 @@ enum PanicMsgId {
1484 PanicMsgIdBadUnionField,1490 PanicMsgIdBadUnionField,
1485 PanicMsgIdBadEnumValue,1491 PanicMsgIdBadEnumValue,
1486 PanicMsgIdFloatToInt,1492 PanicMsgIdFloatToInt,
1493 PanicMsgIdPtrCastNull,
14871494
1488 PanicMsgIdCount,1495 PanicMsgIdCount,
1489};1496};
...@@ -1498,11 +1505,12 @@ struct TypeId {...@@ -1498,11 +1505,12 @@ struct TypeId {
1498 struct {1505 struct {
1499 ZigType *child_type;1506 ZigType *child_type;
1500 PtrLen ptr_len;1507 PtrLen ptr_len;
1501 bool is_const;
1502 bool is_volatile;
1503 uint32_t alignment;1508 uint32_t alignment;
1504 uint32_t bit_offset_in_host;1509 uint32_t bit_offset_in_host;
1505 uint32_t host_int_bytes;1510 uint32_t host_int_bytes;
1511 bool is_const;
1512 bool is_volatile;
1513 bool allow_zero;
1506 } pointer;1514 } pointer;
1507 struct {1515 struct {
1508 ZigType *child_type;1516 ZigType *child_type;
...@@ -1605,6 +1613,17 @@ struct LinkLib {...@@ -1605,6 +1613,17 @@ struct LinkLib {
1605 bool provided_explicitly;1613 bool provided_explicitly;
1606};1614};
16071615
1616enum ValgrindSupport {
1617 ValgrindSupportAuto,
1618 ValgrindSupportDisabled,
1619 ValgrindSupportEnabled,
1620};
1621
1622struct CFile {
1623 ZigList<const char *> args;
1624 const char *source_path;
1625};
1626
1608// When adding fields, check if they should be added to the hash computation in build_with_cache1627// When adding fields, check if they should be added to the hash computation in build_with_cache
1609struct CodeGen {1628struct CodeGen {
1610 //////////////////////////// Runtime State1629 //////////////////////////// Runtime State
...@@ -1660,7 +1679,7 @@ struct CodeGen {...@@ -1660,7 +1679,7 @@ struct CodeGen {
1660 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;1679 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
1661 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;1680 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
1662 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;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 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;1683 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
1665 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;1684 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
1666 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;1685 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
...@@ -1732,12 +1751,16 @@ struct CodeGen {...@@ -1732,12 +1751,16 @@ struct CodeGen {
1732 Buf triple_str;1751 Buf triple_str;
1733 Buf global_asm;1752 Buf global_asm;
1734 Buf *out_h_path;1753 Buf *out_h_path;
1754 Buf *out_lib_path;
1735 Buf artifact_dir;1755 Buf artifact_dir;
1736 Buf output_file_path;1756 Buf output_file_path;
1737 Buf o_file_output_path;1757 Buf o_file_output_path;
1738 Buf *wanted_output_file_path;1758 Buf *wanted_output_file_path;
1739 Buf cache_dir;1759 Buf cache_dir;
17401760
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 IrInstruction *invalid_instruction;1764 IrInstruction *invalid_instruction;
1742 IrInstruction *unreach_instruction;1765 IrInstruction *unreach_instruction;
17431766
...@@ -1752,6 +1775,7 @@ struct CodeGen {...@@ -1752,6 +1775,7 @@ struct CodeGen {
1752 ZigFn *cur_fn;1775 ZigFn *cur_fn;
1753 ZigFn *main_fn;1776 ZigFn *main_fn;
1754 ZigFn *panic_fn;1777 ZigFn *panic_fn;
1778 TldFn *panic_tld_fn;
1755 AstNode *root_export_decl;1779 AstNode *root_export_decl;
17561780
1757 CacheHash cache_hash;1781 CacheHash cache_hash;
...@@ -1760,7 +1784,8 @@ struct CodeGen {...@@ -1760,7 +1784,8 @@ struct CodeGen {
1760 unsigned pointer_size_bytes;1784 unsigned pointer_size_bytes;
1761 uint32_t target_os_index;1785 uint32_t target_os_index;
1762 uint32_t target_arch_index;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 uint32_t target_oformat_index;1789 uint32_t target_oformat_index;
1765 bool is_big_endian;1790 bool is_big_endian;
1766 bool have_pub_main;1791 bool have_pub_main;
...@@ -1778,13 +1803,17 @@ struct CodeGen {...@@ -1778,13 +1803,17 @@ struct CodeGen {
1778 bool verbose_ir;1803 bool verbose_ir;
1779 bool verbose_llvm_ir;1804 bool verbose_llvm_ir;
1780 bool verbose_cimport;1805 bool verbose_cimport;
1806 bool verbose_cc;
1781 bool error_during_imports;1807 bool error_during_imports;
1782 bool generate_error_name_table;1808 bool generate_error_name_table;
1783 bool enable_cache;1809 bool enable_cache;
1784 bool enable_time_report;1810 bool enable_time_report;
1785 bool system_linker_hack;1811 bool system_linker_hack;
1812 bool reported_bad_link_libc_error;
17861813
1787 //////////////////////////// Participates in Input Parameter Cache Hash1814 //////////////////////////// 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 ZigList<LinkLib *> link_libs_list;1817 ZigList<LinkLib *> link_libs_list;
1789 // add -framework [name] args to linker1818 // add -framework [name] args to linker
1790 ZigList<Buf *> darwin_frameworks;1819 ZigList<Buf *> darwin_frameworks;
...@@ -1793,8 +1822,11 @@ struct CodeGen {...@@ -1793,8 +1822,11 @@ struct CodeGen {
1793 ZigList<Buf *> forbidden_libs;1822 ZigList<Buf *> forbidden_libs;
1794 ZigList<Buf *> link_objects;1823 ZigList<Buf *> link_objects;
1795 ZigList<Buf *> assembly_files;1824 ZigList<Buf *> assembly_files;
1825 ZigList<CFile *> c_source_files;
1796 ZigList<const char *> lib_dirs;1826 ZigList<const char *> lib_dirs;
17971827
1828 ZigLibCInstallation *libc;
1829
1798 size_t version_major;1830 size_t version_major;
1799 size_t version_minor;1831 size_t version_minor;
1800 size_t version_patch;1832 size_t version_patch;
...@@ -1803,15 +1835,14 @@ struct CodeGen {...@@ -1803,15 +1835,14 @@ struct CodeGen {
1803 EmitFileType emit_file_type;1835 EmitFileType emit_file_type;
1804 BuildMode build_mode;1836 BuildMode build_mode;
1805 OutType out_type;1837 OutType out_type;
1806 ZigTarget zig_target;1838 const ZigTarget *zig_target;
1807 TargetSubsystem subsystem;1839 TargetSubsystem subsystem;
1840 ValgrindSupport valgrind_support;
1808 bool is_static;1841 bool is_static;
1809 bool strip_debug_symbols;1842 bool strip_debug_symbols;
1810 bool is_test_build;1843 bool is_test_build;
1811 bool is_single_threaded;1844 bool is_single_threaded;
1812 bool is_native_target;
1813 bool linker_rdynamic;1845 bool linker_rdynamic;
1814 bool no_rosegment_workaround;
1815 bool each_lib_rpath;1846 bool each_lib_rpath;
1816 bool disable_pic;1847 bool disable_pic;
18171848
...@@ -1821,31 +1852,21 @@ struct CodeGen {...@@ -1821,31 +1852,21 @@ struct CodeGen {
1821 Buf *test_filter;1852 Buf *test_filter;
1822 Buf *test_name_prefix;1853 Buf *test_name_prefix;
1823 PackageTableEntry *root_package;1854 PackageTableEntry *root_package;
1855 Buf *zig_lib_dir;
1856 Buf *zig_std_dir;
18241857
1825 const char **llvm_argv;1858 const char **llvm_argv;
1826 size_t llvm_argv_len;1859 size_t llvm_argv_len;
18271860
1828 const char **clang_argv;1861 const char **clang_argv;
1829 size_t clang_argv_len;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};
18451864
1846enum VarLinkage {1865enum VarLinkage {
1847 VarLinkageInternal,1866 VarLinkageInternal,
1848 VarLinkageExport,1867 VarLinkageExportStrong,
1868 VarLinkageExportWeak,
1869 VarLinkageExportLinkOnce,
1849 VarLinkageExternal,1870 VarLinkageExternal,
1850};1871};
18511872
...@@ -2084,6 +2105,11 @@ struct IrBasicBlock {...@@ -2084,6 +2105,11 @@ struct IrBasicBlock {
2084 IrInstruction *must_be_comptime_source_instr;2105 IrInstruction *must_be_comptime_source_instr;
2085};2106};
20862107
2108enum LVal {
2109 LValNone,
2110 LValPtr,
2111};
2112
2087// These instructions are in transition to having "pass 1" instructions2113// These instructions are in transition to having "pass 1" instructions
2088// and "pass 2" instructions. The pass 1 instructions are suffixed with Src2114// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
2089// and pass 2 are suffixed with Gen.2115// and pass 2 are suffixed with Gen.
...@@ -2106,6 +2132,7 @@ enum IrInstructionId {...@@ -2106,6 +2132,7 @@ enum IrInstructionId {
2106 IrInstructionIdUnOp,2132 IrInstructionIdUnOp,
2107 IrInstructionIdBinOp,2133 IrInstructionIdBinOp,
2108 IrInstructionIdLoadPtr,2134 IrInstructionIdLoadPtr,
2135 IrInstructionIdLoadPtrGen,
2109 IrInstructionIdStorePtr,2136 IrInstructionIdStorePtr,
2110 IrInstructionIdFieldPtr,2137 IrInstructionIdFieldPtr,
2111 IrInstructionIdStructFieldPtr,2138 IrInstructionIdStructFieldPtr,
...@@ -2116,6 +2143,7 @@ enum IrInstructionId {...@@ -2116,6 +2143,7 @@ enum IrInstructionId {
2116 IrInstructionIdConst,2143 IrInstructionIdConst,
2117 IrInstructionIdReturn,2144 IrInstructionIdReturn,
2118 IrInstructionIdCast,2145 IrInstructionIdCast,
2146 IrInstructionIdResizeSlice,
2119 IrInstructionIdContainerInitList,2147 IrInstructionIdContainerInitList,
2120 IrInstructionIdContainerInitFields,2148 IrInstructionIdContainerInitFields,
2121 IrInstructionIdStructInit,2149 IrInstructionIdStructInit,
...@@ -2183,6 +2211,7 @@ enum IrInstructionId {...@@ -2183,6 +2211,7 @@ enum IrInstructionId {
2183 IrInstructionIdPtrCastSrc,2211 IrInstructionIdPtrCastSrc,
2184 IrInstructionIdPtrCastGen,2212 IrInstructionIdPtrCastGen,
2185 IrInstructionIdBitCast,2213 IrInstructionIdBitCast,
2214 IrInstructionIdBitCastGen,
2186 IrInstructionIdWidenOrShorten,2215 IrInstructionIdWidenOrShorten,
2187 IrInstructionIdIntToPtr,2216 IrInstructionIdIntToPtr,
2188 IrInstructionIdPtrToInt,2217 IrInstructionIdPtrToInt,
...@@ -2347,6 +2376,7 @@ struct IrInstructionUnOp {...@@ -2347,6 +2376,7 @@ struct IrInstructionUnOp {
23472376
2348 IrUnOp op_id;2377 IrUnOp op_id;
2349 IrInstruction *value;2378 IrInstruction *value;
2379 LVal lval;
2350};2380};
23512381
2352enum IrBinOp {2382enum IrBinOp {
...@@ -2399,6 +2429,13 @@ struct IrInstructionLoadPtr {...@@ -2399,6 +2429,13 @@ struct IrInstructionLoadPtr {
2399 IrInstruction *ptr;2429 IrInstruction *ptr;
2400};2430};
24012431
2432struct IrInstructionLoadPtrGen {
2433 IrInstruction base;
2434
2435 IrInstruction *ptr;
2436 LLVMValueRef tmp_ptr;
2437};
2438
2402struct IrInstructionStorePtr {2439struct IrInstructionStorePtr {
2403 IrInstruction base;2440 IrInstruction base;
24042441
...@@ -2476,6 +2513,18 @@ struct IrInstructionReturn {...@@ -2476,6 +2513,18 @@ struct IrInstructionReturn {
2476 IrInstruction *value;2513 IrInstruction *value;
2477};2514};
24782515
2516enum 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// TODO get rid of this instruction, replace with instructions for each op code2528// TODO get rid of this instruction, replace with instructions for each op code
2480struct IrInstructionCast {2529struct IrInstructionCast {
2481 IrInstruction base;2530 IrInstruction base;
...@@ -2486,6 +2535,13 @@ struct IrInstructionCast {...@@ -2486,6 +2535,13 @@ struct IrInstructionCast {
2486 LLVMValueRef tmp_ptr;2535 LLVMValueRef tmp_ptr;
2487};2536};
24882537
2538struct IrInstructionResizeSlice {
2539 IrInstruction base;
2540
2541 IrInstruction *operand;
2542 LLVMValueRef tmp_ptr;
2543};
2544
2489struct IrInstructionContainerInitList {2545struct IrInstructionContainerInitList {
2490 IrInstruction base;2546 IrInstruction base;
24912547
...@@ -2591,6 +2647,7 @@ struct IrInstructionPtrType {...@@ -2591,6 +2647,7 @@ struct IrInstructionPtrType {
2591 PtrLen ptr_len;2647 PtrLen ptr_len;
2592 bool is_const;2648 bool is_const;
2593 bool is_volatile;2649 bool is_volatile;
2650 bool allow_zero;
2594};2651};
25952652
2596struct IrInstructionPromiseType {2653struct IrInstructionPromiseType {
...@@ -2606,6 +2663,7 @@ struct IrInstructionSliceType {...@@ -2606,6 +2663,7 @@ struct IrInstructionSliceType {
2606 IrInstruction *child_type;2663 IrInstruction *child_type;
2607 bool is_const;2664 bool is_const;
2608 bool is_volatile;2665 bool is_volatile;
2666 bool allow_zero;
2609};2667};
26102668
2611struct IrInstructionAsm {2669struct IrInstructionAsm {
...@@ -2994,12 +3052,14 @@ struct IrInstructionPtrCastSrc {...@@ -2994,12 +3052,14 @@ struct IrInstructionPtrCastSrc {
29943052
2995 IrInstruction *dest_type;3053 IrInstruction *dest_type;
2996 IrInstruction *ptr;3054 IrInstruction *ptr;
3055 bool safety_check_on;
2997};3056};
29983057
2999struct IrInstructionPtrCastGen {3058struct IrInstructionPtrCastGen {
3000 IrInstruction base;3059 IrInstruction base;
30013060
3002 IrInstruction *ptr;3061 IrInstruction *ptr;
3062 bool safety_check_on;
3003};3063};
30043064
3005struct IrInstructionBitCast {3065struct IrInstructionBitCast {
...@@ -3009,6 +3069,13 @@ struct IrInstructionBitCast {...@@ -3009,6 +3069,13 @@ struct IrInstructionBitCast {
3009 IrInstruction *value;3069 IrInstruction *value;
3010};3070};
30113071
3072struct IrInstructionBitCastGen {
3073 IrInstruction base;
3074
3075 IrInstruction *operand;
3076 LLVMValueRef tmp_ptr;
3077};
3078
3012struct IrInstructionWidenOrShorten {3079struct IrInstructionWidenOrShorten {
3013 IrInstruction base;3080 IrInstruction base;
30143081
...@@ -3079,11 +3146,6 @@ struct IrInstructionTypeName {...@@ -3079,11 +3146,6 @@ struct IrInstructionTypeName {
3079 IrInstruction *type_value;3146 IrInstruction *type_value;
3080};3147};
30813148
3082enum LVal {
3083 LValNone,
3084 LValPtr,
3085};
3086
3087struct IrInstructionDeclRef {3149struct IrInstructionDeclRef {
3088 IrInstruction base;3150 IrInstruction base;
30893151
src/analyze.cpp+246-294
...@@ -356,7 +356,7 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {...@@ -356,7 +356,7 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
356 }356 }
357 }357 }
358358
359 return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);359 return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
360}360}
361361
362uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {362uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
...@@ -365,19 +365,19 @@ 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 if (!type_has_bits(type_entry))365 if (!type_has_bits(type_entry))
366 return 0;366 return 0;
367367
368 if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {368 if (type_entry->id == ZigTypeIdStruct) {
369 uint64_t result = 0;369 if (type_entry->data.structure.layout == ContainerLayoutPacked) {
370 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {370 uint64_t result = 0;
371 result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry);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 } else if (type_entry->id == ZigTypeIdArray) {378 } else if (type_entry->id == ZigTypeIdArray) {
375 ZigType *child_type = type_entry->data.array.child_type;379 ZigType *child_type = type_entry->data.array.child_type;
376 if (child_type->id == ZigTypeIdStruct &&380 return type_entry->data.array.len * type_size_bits(g, child_type);
377 child_type->data.structure.layout == ContainerLayoutPacked)
378 {
379 return type_entry->data.array.len * type_size_bits(g, child_type);
380 }
381 }381 }
382382
383 return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref);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,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
417 return entry;417 return entry;
418}418}
419419
420static 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
420ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,432ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
421 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,433 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
422 uint32_t bit_offset_in_host, uint32_t host_int_bytes)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 assert(!type_is_invalid(child_type));439 assert(!type_is_invalid(child_type));
425 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);440 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
426441
...@@ -440,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -440,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
440455
441 TypeId type_id = {};456 TypeId type_id = {};
442 ZigType **parent_pointer = nullptr;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 type_id.id = ZigTypeIdPointer;459 type_id.id = ZigTypeIdPointer;
445 type_id.data.pointer.child_type = child_type;460 type_id.data.pointer.child_type = child_type;
446 type_id.data.pointer.is_const = is_const;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,6 +464,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
449 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;464 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
450 type_id.data.pointer.host_int_bytes = host_int_bytes;465 type_id.data.pointer.host_int_bytes = host_int_bytes;
451 type_id.data.pointer.ptr_len = ptr_len;466 type_id.data.pointer.ptr_len = ptr_len;
467 type_id.data.pointer.allow_zero = allow_zero;
452468
453 auto existing_entry = g->type_table.maybe_get(type_id);469 auto existing_entry = g->type_table.maybe_get(type_id);
454 if (existing_entry)470 if (existing_entry)
...@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
466482
467 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);483 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
468484
469 const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";485 const char *star_str = ptr_len_to_star_str(ptr_len);
470 const char *const_str = is_const ? "const " : "";486 const char *const_str = is_const ? "const " : "";
471 const char *volatile_str = is_volatile ? "volatile " : "";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 buf_resize(&entry->name, 0);495 buf_resize(&entry->name, 0);
473 if (host_int_bytes == 0 && byte_alignment == 0) {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 } else if (host_int_bytes == 0) {499 } else if (host_int_bytes == 0) {
476 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,500 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
477 const_str, volatile_str, buf_ptr(&child_type->name));501 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
478 } else if (byte_alignment == 0) {502 } else if (byte_alignment == 0) {
479 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,503 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
480 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));504 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
505 buf_ptr(&child_type->name));
481 } else {506 } else {
482 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,507 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
483 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));508 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
509 buf_ptr(&child_type->name));
484 }510 }
485511
486 assert(child_type->id != ZigTypeIdInvalid);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,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
488 entry->zero_bits = !type_has_bits(child_type);514 entry->zero_bits = !type_has_bits(child_type);
489515
490 if (!entry->zero_bits) {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 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,520 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
493 PtrLenSingle, 0, 0, host_int_bytes);521 PtrLenSingle, 0, 0, host_int_bytes);
494 entry->type_ref = peer_type->type_ref;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,6 +550,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
522 entry->data.pointer.explicit_alignment = byte_alignment;550 entry->data.pointer.explicit_alignment = byte_alignment;
523 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;551 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
524 entry->data.pointer.host_int_bytes = host_int_bytes;552 entry->data.pointer.host_int_bytes = host_int_bytes;
553 entry->data.pointer.allow_zero = allow_zero;
525554
526 if (parent_pointer) {555 if (parent_pointer) {
527 *parent_pointer = entry;556 *parent_pointer = entry;
...@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
838867
839 ZigType *child_type = ptr_type->data.pointer.child_type;868 ZigType *child_type = ptr_type->data.pointer.child_type;
840 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||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 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,872 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
844 PtrLenUnknown, 0, 0, 0);873 PtrLenUnknown, 0, 0, 0);
...@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
861 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;890 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
862 assert(child_ptr_type->id == ZigTypeIdPointer);891 assert(child_ptr_type->id == ZigTypeIdPointer);
863 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||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 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;895 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
867 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,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,10 +1102,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
1073 if (type_is_c_abi_int(g, fn_type_id->return_type)) {1102 if (type_is_c_abi_int(g, fn_type_id->return_type)) {
1074 return false;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 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);1106 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1078 return abi_class == X64CABIClass_MEMORY;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 return type_size(g, fn_type_id->return_type) > 16;1109 return type_size(g, fn_type_id->return_type) > 16;
1081 }1110 }
1082 zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");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,7 +1329,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no
1300 size_t backward_branch_count = 0;1329 size_t backward_branch_count = 0;
1301 return ir_eval_const_value(g, scope, node, type_entry,1330 return ir_eval_const_value(g, scope, node, type_entry,
1302 &backward_branch_count, default_backward_branch_quota,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}
13051334
1306ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {1335ZigType *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,7 +1444,10 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1415 return true;1444 return true;
1416}1445}
14171446
1418static bool type_allowed_in_packed_struct(ZigType *type_entry) {1447static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType *type_entry,
1448 AstNode *source_node)
1449{
1450 Error err;
1419 switch (type_entry->id) {1451 switch (type_entry->id) {
1420 case ZigTypeIdInvalid:1452 case ZigTypeIdInvalid:
1421 zig_unreachable();1453 zig_unreachable();
...@@ -1432,32 +1464,79 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {...@@ -1432,32 +1464,79 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
1432 case ZigTypeIdArgTuple:1464 case ZigTypeIdArgTuple:
1433 case ZigTypeIdOpaque:1465 case ZigTypeIdOpaque:
1434 case ZigTypeIdPromise: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 case ZigTypeIdVoid:1471 case ZigTypeIdVoid:
1437 case ZigTypeIdBool:1472 case ZigTypeIdBool:
1438 case ZigTypeIdInt:1473 case ZigTypeIdInt:
1439 case ZigTypeIdFloat:1474 case ZigTypeIdFloat:
1440 case ZigTypeIdPointer:1475 case ZigTypeIdPointer:
1441 case ZigTypeIdArray:
1442 case ZigTypeIdFn:1476 case ZigTypeIdFn:
1443 case ZigTypeIdVector: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 case ZigTypeIdStruct: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 case ZigTypeIdUnion: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 case ZigTypeIdOptional:1514 case ZigTypeIdOptional:
1450 {1515 if (get_codegen_ptr_type(type_entry) != nullptr) {
1451 ZigType *child_type = type_entry->data.maybe.child_type;1516 return ErrorNone;
1452 return type_is_codegen_pointer(child_type);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:1523 case ZigTypeIdEnum: {
1455 return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;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 zig_unreachable();1536 zig_unreachable();
1458}1537}
14591538
1460static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {1539bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1461 switch (type_entry->id) {1540 switch (type_entry->id) {
1462 case ZigTypeIdInvalid:1541 case ZigTypeIdInvalid:
1463 zig_unreachable();1542 zig_unreachable();
...@@ -1583,7 +1662,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1583,7 +1662,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1583 }1662 }
1584 } else if (param_node->data.param_decl.var_token != nullptr) {1663 } else if (param_node->data.param_decl.var_token != nullptr) {
1585 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {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 buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",1666 buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
1588 calling_convention_name(fn_type_id.cc)));1667 calling_convention_name(fn_type_id.cc)));
1589 return g->builtin_types.entry_invalid;1668 return g->builtin_types.entry_invalid;
...@@ -2022,11 +2101,8 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2022,11 +2101,8 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
2022 type_struct_field->gen_index = gen_field_index;2101 type_struct_field->gen_index = gen_field_index;
20232102
2024 if (packed) {2103 if (packed) {
2025 if (!type_allowed_in_packed_struct(field_type)) {2104 AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
2026 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))) {
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)));
2030 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2106 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2031 break;2107 break;
2032 }2108 }
...@@ -2650,6 +2726,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2650,6 +2726,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2650 buf_sprintf("enums, not structs, support field assignment"));2726 buf_sprintf("enums, not structs, support field assignment"));
2651 }2727 }
26522728
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 switch (type_requires_comptime(g, field_type)) {2736 switch (type_requires_comptime(g, field_type)) {
2654 case ReqCompTimeYes:2737 case ReqCompTimeYes:
2655 struct_type->data.structure.requires_comptime = true;2738 struct_type->data.structure.requires_comptime = true;
...@@ -2828,7 +2911,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2828,7 +2911,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2828 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||2911 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
2829 enum_type_node != nullptr;2912 enum_type_node != nullptr;
2830 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);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 ZigType *tag_type;2915 ZigType *tag_type;
2833 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);2916 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
2834 bool *covered_enum_fields;2917 bool *covered_enum_fields;
...@@ -2934,6 +3017,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2934,6 +3017,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2934 }3017 }
2935 union_field->type_entry = field_type;3018 union_field->type_entry = field_type;
29363019
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 switch (type_requires_comptime(g, field_type)) {3027 switch (type_requires_comptime(g, field_type)) {
2938 case ReqCompTimeInvalid:3028 case ReqCompTimeInvalid:
2939 union_type->data.unionation.is_invalid = true;3029 union_type->data.unionation.is_invalid = true;
...@@ -3182,36 +3272,19 @@ static bool scope_is_root_decls(Scope *scope) {...@@ -3182,36 +3272,19 @@ static bool scope_is_root_decls(Scope *scope) {
3182 zig_unreachable();3272 zig_unreachable();
3183}3273}
31843274
3185static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {3275void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
3186 add_node_error(g, proto_node,3276 ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
3187 buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",3277 assert(panic_fn_type_val != nullptr);
3188 buf_ptr(&fn_type->name)));3278 assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
3189}3279 ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
3190
3191static 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 }
32053280
3206 ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));3281 AstNode *fake_decl = allocate<AstNode>(1);
3207 if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {3282 *fake_decl = *panic_fn->proto_node;
3208 return wrong_panic_prototype(g, proto_node, fn_type);3283 fake_decl->type = NodeTypeSymbol;
3209 }3284 fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
32103285
3211 ZigType *actual_return_type = fn_type_id->return_type;3286 // call this for the side effects of casting to panic_fn_type
3212 if (actual_return_type != g->builtin_types.entry_unreachable) {3287 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
3213 return wrong_panic_prototype(g, proto_node, fn_type);
3214 }
3215}3288}
32163289
3217ZigType *get_test_fn_type(CodeGen *g) {3290ZigType *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,16 +3304,16 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
3231 g->have_c_main = true;3304 g->have_c_main = true;
3232 g->subsystem = TargetSubsystemConsole;3305 g->subsystem = TargetSubsystemConsole;
3233 } else if (buf_eql_str(symbol_name, "WinMain") &&3306 } else if (buf_eql_str(symbol_name, "WinMain") &&
3234 g->zig_target.os == OsWindows)3307 g->zig_target->os == OsWindows)
3235 {3308 {
3236 g->have_winmain = true;3309 g->have_winmain = true;
3237 g->subsystem = TargetSubsystemWindows;3310 g->subsystem = TargetSubsystemWindows;
3238 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&3311 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
3239 g->zig_target.os == OsWindows)3312 g->zig_target->os == OsWindows)
3240 {3313 {
3241 g->have_winmain_crt_startup = true;3314 g->have_winmain_crt_startup = true;
3242 } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") &&3315 } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") &&
3243 g->zig_target.os == OsWindows)3316 g->zig_target->os == OsWindows)
3244 {3317 {
3245 g->have_dllmain_crt_startup = true;3318 g->have_dllmain_crt_startup = true;
3246 }3319 }
...@@ -3306,18 +3379,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -3306,18 +3379,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
3306 if (!fn_table_entry->type_entry->data.fn.is_generic) {3379 if (!fn_table_entry->type_entry->data.fn.is_generic) {
3307 if (fn_def_node)3380 if (fn_def_node)
3308 g->fn_defs.append(fn_table_entry);3381 g->fn_defs.append(fn_table_entry);
3382 }
33093383
3310 if (scope_is_root_decls(tld_fn->base.parent_scope) &&3384 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
3311 (import == g->root_import || import->package == g->panic_package))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")) {3392 g->panic_fn = fn_table_entry;
3314 g->main_fn = fn_table_entry;3393 g->panic_tld_fn = tld_fn;
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 }
3321 }3394 }
3322 }3395 }
3323 } else if (source_node->type == NodeTypeTestDecl) {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,9 +3439,9 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
3366 if (is_export) {3439 if (is_export) {
3367 g->resolve_queue.append(tld);3440 g->resolve_queue.append(tld);
33683441
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 if (entry) {3443 if (entry) {
3371 AstNode *other_source_node = entry->value;3444 AstNode *other_source_node = entry->value->source_node;
3372 ErrorMsg *msg = add_node_error(g, tld->source_node,3445 ErrorMsg *msg = add_node_error(g, tld->source_node,
3373 buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name)));3446 buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name)));
3374 add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here"));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,7 +3771,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36983771
3699 VarLinkage linkage;3772 VarLinkage linkage;
3700 if (is_export) {3773 if (is_export) {
3701 linkage = VarLinkageExport;3774 linkage = VarLinkageExportStrong;
3702 } else if (is_extern) {3775 } else if (is_extern) {
3703 linkage = VarLinkageExternal;3776 linkage = VarLinkageExternal;
3704 } else {3777 } else {
...@@ -4041,7 +4114,9 @@ ZigType *get_src_ptr_type(ZigType *type) {...@@ -4041,7 +4114,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
4041 if (type->id == ZigTypeIdFn) return type;4114 if (type->id == ZigTypeIdFn) return type;
4042 if (type->id == ZigTypeIdPromise) return type;4115 if (type->id == ZigTypeIdPromise) return type;
4043 if (type->id == ZigTypeIdOptional) {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 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;4120 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
4046 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;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,6 +4130,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
4055 return ty;4130 return ty;
4056}4131}
40574132
4133bool type_is_nonnull_ptr(ZigType *type) {
4134 return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
4135}
4136
4058bool type_is_codegen_pointer(ZigType *type) {4137bool type_is_codegen_pointer(ZigType *type) {
4059 return get_codegen_ptr_type(type) == type;4138 return get_codegen_ptr_type(type) == type;
4060}4139}
...@@ -4572,185 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4572,185 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) {
4572 zig_unreachable();4651 zig_unreachable();
4573}4652}
45744653
4575static 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
4587static 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
4613static 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
4666void 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
4694void 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
4754static uint32_t hash_ptr(void *ptr) {4654static uint32_t hash_ptr(void *ptr) {
4755 return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX);4655 return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX);
4756}4656}
...@@ -5229,6 +5129,10 @@ bool type_has_bits(ZigType *type_entry) {...@@ -5229,6 +5129,10 @@ bool type_has_bits(ZigType *type_entry) {
5229// Whether you can infer the value based solely on the type.5129// Whether you can infer the value based solely on the type.
5230OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {5130OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5231 assert(type_entry != nullptr);5131 assert(type_entry != nullptr);
5132
5133 if (type_entry->one_possible_value != OnePossibleValueInvalid)
5134 return type_entry->one_possible_value;
5135
5232 Error err;5136 Error err;
5233 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))5137 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5234 return OnePossibleValueInvalid;5138 return OnePossibleValueInvalid;
...@@ -5276,8 +5180,14 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5276,8 +5180,14 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5276 case ZigTypeIdInt:5180 case ZigTypeIdInt:
5277 case ZigTypeIdVector:5181 case ZigTypeIdVector:
5278 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;5182 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
5279 case ZigTypeIdPointer:5183 case ZigTypeIdPointer: {
5280 return type_has_one_possible_value(g, type_entry->data.pointer.child_type);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 case ZigTypeIdUnion:5191 case ZigTypeIdUnion:
5282 if (type_entry->data.unionation.src_field_count > 1)5192 if (type_entry->data.unionation.src_field_count > 1)
5283 return OnePossibleValueNo;5193 return OnePossibleValueNo;
...@@ -6010,16 +5920,20 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const...@@ -6010,16 +5920,20 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const
6010 }5920 }
6011}5921}
60125922
6013static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) {5923static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) {
6014 switch (const_val->data.x_array.special) {5924 ConstArrayValue *array = &const_val->data.x_array;
5925 switch (array->special) {
6015 case ConstArraySpecialUndef:5926 case ConstArraySpecialUndef:
6016 buf_append_str(buf, "undefined");5927 buf_append_str(buf, "undefined");
6017 return;5928 return;
6018 case ConstArraySpecialBuf: {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 buf_append_char(buf, '"');5934 buf_append_char(buf, '"');
6021 for (size_t i = 0; i < buf_len(array_buf); i += 1) {5935 for (size_t i = 0; i < len; i += 1) {
6022 uint8_t c = buf_ptr(array_buf)[i];5936 uint8_t c = base[i];
6023 if (c == '"') {5937 if (c == '"') {
6024 buf_append_str(buf, "\\\"");5938 buf_append_str(buf, "\\\"");
6025 } else {5939 } else {
...@@ -6030,12 +5944,13 @@ static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_v...@@ -6030,12 +5944,13 @@ static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_v
6030 return;5944 return;
6031 }5945 }
6032 case ConstArraySpecialNone: {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 for (uint64_t i = 0; i < len; i += 1) {5951 for (uint64_t i = 0; i < len; i += 1) {
6035 if (i != 0)5952 if (i != 0) buf_appendf(buf, ",");
6036 buf_appendf(buf, ",");5953 render_const_value(g, buf, &base[i]);
6037 ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
6038 render_const_value(g, buf, child_value);
6039 }5954 }
6040 buf_appendf(buf, "}");5955 buf_appendf(buf, "}");
6041 return;5956 return;
...@@ -6124,10 +6039,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -6124,10 +6039,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
6124 }6039 }
6125 case ZigTypeIdPointer:6040 case ZigTypeIdPointer:
6126 return render_const_val_ptr(g, buf, const_val, type_entry);6041 return render_const_val_ptr(g, buf, const_val, type_entry);
6127 case ZigTypeIdVector:6042 case ZigTypeIdArray: {
6128 return render_const_val_array(g, buf, const_val, type_entry->data.vector.len);6043 uint64_t len = type_entry->data.array.len;
6129 case ZigTypeIdArray:6044 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
6130 return render_const_val_array(g, buf, const_val, type_entry->data.array.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 case ZigTypeIdNull:6052 case ZigTypeIdNull:
6132 {6053 {
6133 buf_appendf(buf, "null");6054 buf_appendf(buf, "null");
...@@ -6169,7 +6090,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -6169,7 +6090,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
6169 }6090 }
6170 case ZigTypeIdStruct: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 return;6111 return;
6174 }6112 }
6175 case ZigTypeIdEnum:6113 case ZigTypeIdEnum:
...@@ -6193,8 +6131,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -6193,8 +6131,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
6193 }6131 }
6194 case ZigTypeIdUnion:6132 case ZigTypeIdUnion:
6195 {6133 {
6196 uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag);6134 const BigInt *tag = &const_val->data.x_union.tag;
6197 TypeUnionField *field = &type_entry->data.unionation.fields[tag];6135 TypeUnionField *field = find_union_field_by_tag(type_entry, tag);
6198 buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));6136 buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
6199 render_const_value(g, buf, const_val->data.x_union.payload);6137 render_const_value(g, buf, const_val->data.x_union.payload);
6200 buf_append_str(buf, "}");6138 buf_append_str(buf, "}");
...@@ -6277,6 +6215,7 @@ uint32_t type_id_hash(TypeId x) {...@@ -6277,6 +6215,7 @@ uint32_t type_id_hash(TypeId x) {
6277 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +6215 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
6278 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +6216 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
6279 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +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 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +6219 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
6281 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +6220 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
6282 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);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,6 +6266,7 @@ bool type_id_eql(TypeId a, TypeId b) {
6327 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&6266 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
6328 a.data.pointer.is_const == b.data.pointer.is_const &&6267 a.data.pointer.is_const == b.data.pointer.is_const &&
6329 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&6268 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
6269 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
6330 a.data.pointer.alignment == b.data.pointer.alignment &&6270 a.data.pointer.alignment == b.data.pointer.alignment &&
6331 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&6271 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
6332 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;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,12 +6566,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
6626 if (is_libc && g->libc_link_lib != nullptr)6566 if (is_libc && g->libc_link_lib != nullptr)
6627 return g->libc_link_lib;6567 return g->libc_link_lib;
66286568
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 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {6569 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
6636 LinkLib *existing_lib = g->link_libs_list.at(i);6570 LinkLib *existing_lib = g->link_libs_list.at(i);
6637 if (buf_eql_buf(existing_lib->name, name)) {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,3 +6794,21 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
68606794
6861 return ErrorNone;6795 return ErrorNone;
6862}6796}
6797
6798const 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
6807bool 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,11 +40,11 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type);
40ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);40ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);
41ZigType *get_test_fn_type(CodeGen *g);41ZigType *get_test_fn_type(CodeGen *g);
42bool handle_is_ptr(ZigType *type_entry);42bool handle_is_ptr(ZigType *type_entry);
43void find_libc_include_path(CodeGen *g);
44void find_libc_lib_path(CodeGen *g);
4543
46bool type_has_bits(ZigType *type_entry);44bool type_has_bits(ZigType *type_entry);
4745bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
46bool ptr_allows_addr_zero(ZigType *ptr_type);
47bool type_is_nonnull_ptr(ZigType *type);
4848
49ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);49ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
5050
...@@ -215,6 +215,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);...@@ -215,6 +215,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
215X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);215X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
216bool type_is_c_abi_int(CodeGen *g, ZigType *ty);216bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
217bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);217bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
218const char *container_string(ContainerKind kind);
218219
219uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);220uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
220221
...@@ -225,14 +226,10 @@ enum ReqCompTime {...@@ -225,14 +226,10 @@ enum ReqCompTime {
225};226};
226ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);227ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
227228
228enum OnePossibleValue {
229 OnePossibleValueInvalid,
230 OnePossibleValueNo,
231 OnePossibleValueYes,
232};
233OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);229OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
234230
235Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,231Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
236 ConstExprValue *const_val, ZigType *wanted_type);232 ConstExprValue *const_val, ZigType *wanted_type);
237233
234void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
238#endif235#endif
src/ast_render.cpp+14-13
...@@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) {...@@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) {
136 return (tok == nullptr) ? "" : "threadlocal ";136 return (tok == nullptr) ? "" : "threadlocal ";
137}137}
138138
139const char *container_string(ContainerKind kind) {139static const char *token_to_ptr_len_str(Token *tok) {
140 switch (kind) {140 assert(tok != nullptr);
141 case ContainerKindEnum: return "enum";141 switch (tok->id) {
142 case ContainerKindStruct: return "struct";142 case TokenIdStar:
143 case ContainerKindUnion: return "union";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}
147153
148static const char *node_type_str(NodeType node_type) {154static const char *node_type_str(NodeType node_type) {
...@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
644 case NodeTypePointerType:650 case NodeTypePointerType:
645 {651 {
646 if (!grouped) fprintf(ar->f, "(");652 if (!grouped) fprintf(ar->f, "(");
647 const char *star = "[*]";653 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
648 if (node->data.pointer_type.star_token != nullptr &&654 fprintf(ar->f, "%s", ptr_len_str);
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);
654 if (node->data.pointer_type.align_expr != nullptr) {655 if (node->data.pointer_type.align_expr != nullptr) {
655 fprintf(ar->f, "align(");656 fprintf(ar->f, "align(");
656 render_node_grouped(ar, node->data.pointer_type.align_expr);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,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);
1717
18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
1919
20const char *container_string(ContainerKind kind);
21
22#endif20#endif
23
src/bigint.cpp-1
...@@ -1665,7 +1665,6 @@ int64_t bigint_as_signed(const BigInt *bigint) {...@@ -1665,7 +1665,6 @@ int64_t bigint_as_signed(const BigInt *bigint) {
1665 return 0;1665 return 0;
1666 } else if (bigint->digit_count == 1) {1666 } else if (bigint->digit_count == 1) {
1667 if (bigint->is_negative) {1667 if (bigint->is_negative) {
1668 // TODO this code path is untested
1669 if (bigint->data.digit <= 9223372036854775808ULL) {1668 if (bigint->data.digit <= 9223372036854775808ULL) {
1670 return (-((int64_t)(bigint->data.digit - 1))) - 1;1669 return (-((int64_t)(bigint->data.digit - 1))) - 1;
1671 } else {1670 } else {
src/buffer.hpp+1-3
...@@ -132,9 +132,7 @@ void buf_appendf(Buf *buf, const char *format, ...)...@@ -132,9 +132,7 @@ void buf_appendf(Buf *buf, const char *format, ...)
132132
133static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {133static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
134 assert(buf->list.length);134 assert(buf->list.length);
135 if (buf_len(buf) != mem_len)135 return mem_eql_mem(buf_ptr(buf), buf_len(buf), mem, mem_len);
136 return false;
137 return memcmp(buf_ptr(buf), mem, mem_len) == 0;
138}136}
139137
140static inline bool buf_eql_str(Buf *buf, const char *str) {138static 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,6 +414,39 @@ Error cache_add_file(CacheHash *ch, Buf *path) {
414 return cache_add_file_fetch(ch, resolved_path, nullptr);414 return cache_add_file_fetch(ch, resolved_path, nullptr);
415}415}
416416
417Error 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
417static Error write_manifest_file(CacheHash *ch) {450static Error write_manifest_file(CacheHash *ch) {
418 Error err;451 Error err;
419 Buf contents = BUF_INIT;452 Buf contents = BUF_INIT;
...@@ -464,3 +497,4 @@ void cache_release(CacheHash *ch) {...@@ -464,3 +497,4 @@ void cache_release(CacheHash *ch) {
464497
465 os_file_close(ch->manifest_file);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,6 +56,8 @@ Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
56// If you did not get a cache hit, call this function for every file56// If you did not get a cache hit, call this function for every file
57// that is depended on, and then finish with cache_final.57// that is depended on, and then finish with cache_final.
58Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path);58Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path);
59// This opens a file created by -MD -MF args to Clang
60Error ATTRIBUTE_MUST_USE cache_add_dep_file(CacheHash *ch, Buf *path, bool verbose);
5961
60// This variant of cache_add_file returns the file contents.62// This variant of cache_add_file returns the file contents.
61// Also the file path argument must be already resolved.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,9 +29,9 @@ static void init_darwin_native(CodeGen *g) {
2929
30 // Allow conflicts among OSX and iOS, but choose the default platform.30 // Allow conflicts among OSX and iOS, but choose the default platform.
31 if (osx_target && ios_target) {31 if (osx_target && ios_target) {
32 if (g->zig_target.arch.arch == ZigLLVM_arm ||32 if (g->zig_target->arch == ZigLLVM_arm ||
33 g->zig_target.arch.arch == ZigLLVM_aarch64 ||33 g->zig_target->arch == ZigLLVM_aarch64 ||
34 g->zig_target.arch.arch == ZigLLVM_thumb)34 g->zig_target->arch == ZigLLVM_thumb)
35 {35 {
36 osx_target = nullptr;36 osx_target = nullptr;
37 } else {37 } else {
...@@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) {...@@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) {
43 g->mmacosx_version_min = buf_create_from_str(osx_target);43 g->mmacosx_version_min = buf_create_from_str(osx_target);
44 } else if (ios_target) {44 } else if (ios_target) {
45 g->mios_version_min = buf_create_from_str(ios_target);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 g->mmacosx_version_min = buf_create_from_str("10.10");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,13 +88,15 @@ static const char *symbols_that_llvm_depends_on[] = {
88};88};
8989
90CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,90CodeGen *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 CodeGen *g = allocate<CodeGen>(1);93 CodeGen *g = allocate<CodeGen>(1);
9494
95 codegen_add_time_event(g, "Initialize");95 codegen_add_time_event(g, "Initialize");
9696
97 g->libc = libc;
97 g->zig_lib_dir = zig_lib_dir;98 g->zig_lib_dir = zig_lib_dir;
99 g->zig_target = target;
98100
99 if (override_std_dir == nullptr) {101 if (override_std_dir == nullptr) {
100 g->zig_std_dir = buf_alloc();102 g->zig_std_dir = buf_alloc();
...@@ -149,43 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -149,43 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
149 g->zig_std_special_dir = buf_alloc();151 g->zig_std_special_dir = buf_alloc();
150 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);152 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
151153
152 if (target) {154 assert(target != nullptr);
153 // cross compiling, so we can't rely on all the configured stuff since155 if (!target->is_native) {
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;
163 g->each_lib_rpath = false;156 g->each_lib_rpath = false;
164 } else {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 g->each_lib_rpath = true;158 g->each_lib_rpath = true;
175159
176 if (g->zig_target.os == OsMacOSX ||160 if (target_is_darwin(g->zig_target)) {
177 g->zig_target.os == OsIOS)
178 {
179 init_darwin_native(g);161 init_darwin_native(g);
180 }162 }
181163
182 }164 }
183165
184 // On Darwin/MacOS/iOS, we always link libSystem which contains libc.166 if (target_requires_libc(g->zig_target)) {
185 if (g->zig_target.os == OsMacOSX ||
186 g->zig_target.os == OsIOS ||
187 g->zig_target.os == OsFreeBSD)
188 {
189 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));167 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
190 g->link_libs_list.append(g->libc_link_lib);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,6 +175,10 @@ void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
197 g->out_h_path = h_path;175 g->out_h_path = h_path;
198}176}
199177
178void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path) {
179 g->out_lib_path = lib_path;
180}
181
200void codegen_set_output_path(CodeGen *g, Buf *path) {182void codegen_set_output_path(CodeGen *g, Buf *path) {
201 g->wanted_output_file_path = path;183 g->wanted_output_file_path = path;
202}184}
...@@ -253,30 +235,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {...@@ -253,30 +235,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
253 g->root_out_name = out_name;235 g->root_out_name = out_name;
254}236}
255237
256void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
257 g->libc_lib_dir = libc_lib_dir;
258}
259
260void 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
264void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {
265 g->libc_include_dir = libc_include_dir;
266}
267
268void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) {
269 g->msvc_lib_dir = msvc_lib_dir;
270}
271
272void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) {
273 g->kernel32_lib_dir = kernel32_lib_dir;
274}
275
276void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) {
277 g->dynamic_linker = dynamic_linker;
278}
279
280void codegen_add_lib_dir(CodeGen *g, const char *dir) {238void codegen_add_lib_dir(CodeGen *g, const char *dir) {
281 g->lib_dirs.append(dir);239 g->lib_dirs.append(dir);
282}240}
...@@ -389,11 +347,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {...@@ -389,11 +347,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
389 case CallingConventionC: return LLVMCCallConv;347 case CallingConventionC: return LLVMCCallConv;
390 case CallingConventionCold:348 case CallingConventionCold:
391 // cold calling convention only works on x86.349 // cold calling convention only works on x86.
392 if (g->zig_target.arch.arch == ZigLLVM_x86 ||350 if (g->zig_target->arch == ZigLLVM_x86 ||
393 g->zig_target.arch.arch == ZigLLVM_x86_64)351 g->zig_target->arch == ZigLLVM_x86_64)
394 {352 {
395 // cold calling convention is not supported on windows353 // cold calling convention is not supported on windows
396 if (g->zig_target.os == OsWindows) {354 if (g->zig_target->os == OsWindows) {
397 return LLVMCCallConv;355 return LLVMCCallConv;
398 } else {356 } else {
399 return LLVMColdCallConv;357 return LLVMColdCallConv;
...@@ -406,7 +364,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {...@@ -406,7 +364,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
406 zig_unreachable();364 zig_unreachable();
407 case CallingConventionStdcall:365 case CallingConventionStdcall:
408 // stdcall calling convention only works on x86.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 return LLVMX86StdcallCallConv;368 return LLVMX86StdcallCallConv;
411 } else {369 } else {
412 return LLVMCCallConv;370 return LLVMCCallConv;
...@@ -418,7 +376,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {...@@ -418,7 +376,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
418}376}
419377
420static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {378static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
421 if (g->zig_target.os == OsWindows) {379 if (g->zig_target->os == OsWindows) {
422 addLLVMFnAttr(fn_val, "uwtable");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,13 +412,13 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
454}412}
455413
456static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {414static 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 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);416 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
459 }417 }
460}418}
461419
462static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {420static 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 // TODO come up with a good explanation/understanding for why we never do422 // TODO come up with a good explanation/understanding for why we never do
465 // DLLImportStorageClass. Empirically it only causes problems. But let's have423 // DLLImportStorageClass. Empirically it only causes problems. But let's have
466 // this documented and then clean up the code accordingly.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,7 +463,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
505 bool external_linkage = linkage != GlobalLinkageIdInternal;463 bool external_linkage = linkage != GlobalLinkageIdInternal;
506 CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;464 CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
507 if (cc == CallingConventionStdcall && external_linkage &&465 if (cc == CallingConventionStdcall && external_linkage &&
508 g->zig_target.arch.arch == ZigLLVM_x86)466 g->zig_target->arch == ZigLLVM_x86)
509 {467 {
510 // prevent llvm name mangling468 // prevent llvm name mangling
511 symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name));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,10 +478,23 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
520 fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));478 fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));
521 return fn_table_entry->llvm_value;479 return fn_table_entry->llvm_value;
522 } else {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 } else {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 }
527498
528 for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {499 for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
529 FnExport *fn_export = &fn_table_entry->export_list.items[i];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,9 +588,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
617 unsigned init_gen_i = 0;588 unsigned init_gen_i = 0;
618 if (!type_has_bits(return_type)) {589 if (!type_has_bits(return_type)) {
619 // nothing to do590 // nothing to do
620 } else if (type_is_codegen_pointer(return_type)) {591 } else if (type_is_nonnull_ptr(return_type)) {
621 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");592 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
622 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {593 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
594 // Sret pointers must not be address 0
623 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");595 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
624 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");596 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
625 if (cc_want_sret_attr(cc)) {597 if (cc_want_sret_attr(cc)) {
...@@ -637,6 +609,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -637,6 +609,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
637609
638 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);610 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
639 if (err_ret_trace_arg_index != UINT32_MAX) {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 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");614 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
641 }615 }
642616
...@@ -950,6 +924,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -950,6 +924,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
950 return buf_create_from_str("invalid enum value");924 return buf_create_from_str("invalid enum value");
951 case PanicMsgIdFloatToInt:925 case PanicMsgIdFloatToInt:
952 return buf_create_from_str("integer part of floating point value out of bounds");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 zig_unreachable();930 zig_unreachable();
955}931}
...@@ -1244,6 +1220,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {...@@ -1244,6 +1220,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
1244 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1220 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1245 addLLVMFnAttr(fn_val, "nounwind");1221 addLLVMFnAttr(fn_val, "nounwind");
1246 add_uwtable_attr(g, fn_val);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 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1225 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1248 if (g->build_mode == BuildModeDebug) {1226 if (g->build_mode == BuildModeDebug) {
1249 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");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,9 +1296,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
1318 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1296 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1319 addLLVMFnAttr(fn_val, "nounwind");1297 addLLVMFnAttr(fn_val, "nounwind");
1320 add_uwtable_attr(g, fn_val);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 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1301 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1322 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");1302 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
1323 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");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 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");1306 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
1325 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");1307 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
1326 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");1308 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
...@@ -1448,6 +1430,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1448,6 +1430,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
1448 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1430 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1449 addLLVMFnAttr(fn_val, "nounwind");1431 addLLVMFnAttr(fn_val, "nounwind");
1450 add_uwtable_attr(g, fn_val);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 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1435 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1452 if (g->build_mode == BuildModeDebug) {1436 if (g->build_mode == BuildModeDebug) {
1453 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");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,7 +2033,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2049 case FnWalkIdAttrs: {2033 case FnWalkIdAttrs: {
2050 ZigType *ptr_type = get_codegen_ptr_type(ty);2034 ZigType *ptr_type = get_codegen_ptr_type(ty);
2051 if (ptr_type != nullptr) {2035 if (ptr_type != nullptr) {
2052 if (ty->id != ZigTypeIdOptional) {2036 if (type_is_nonnull_ptr(ty)) {
2053 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2037 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2054 }2038 }
2055 if (ptr_type->data.pointer.is_const) {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,6 +2077,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2093 assert(handle_is_ptr(ty));2077 assert(handle_is_ptr(ty));
2094 switch (fn_walk->id) {2078 switch (fn_walk->id) {
2095 case FnWalkIdAttrs:2079 case FnWalkIdAttrs:
2080 // arrays passed to C ABI functions may not be at address 0
2096 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2081 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2097 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));2082 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2098 fn_walk->data.attrs.gen_i += 1;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,7 +2108,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2123 return true;2108 return true;
2124 }2109 }
21252110
2126 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {2111 if (g->zig_target->arch == ZigLLVM_x86_64) {
2127 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);2112 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
2128 size_t ty_size = type_size(g, ty);2113 size_t ty_size = type_size(g, ty);
2129 if (abi_class == X64CABIClass_MEMORY) {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,6 +2117,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2132 case FnWalkIdAttrs:2117 case FnWalkIdAttrs:
2133 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");2118 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
2134 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));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 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2121 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2136 fn_walk->data.attrs.gen_i += 1;2122 fn_walk->data.attrs.gen_i += 1;
2137 break;2123 break;
...@@ -2264,7 +2250,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2264,7 +2250,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2264 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {2250 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
2265 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");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 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");2257 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
2269 }2258 }
2270 break;2259 break;
...@@ -2657,7 +2646,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2657,7 +2646,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2657 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||2646 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
2658 (op1->value.type->id == ZigTypeIdPointer &&2647 (op1->value.type->id == ZigTypeIdPointer &&
2659 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&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 ZigType *operand_type = op1->value.type;2651 ZigType *operand_type = op1->value.type;
2663 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;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,7 +2705,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2716 AddSubMulMul;2705 AddSubMulMul;
27172706
2718 if (scalar_type->id == ZigTypeIdPointer) {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 LLVMValueRef subscript_value;2709 LLVMValueRef subscript_value;
2721 if (operand_type->id == ZigTypeIdVector)2710 if (operand_type->id == ZigTypeIdVector)
2722 zig_panic("TODO: Implement vector operations on pointers.");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,6 +2852,76 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in
2863 }2852 }
2864}2853}
28652854
2855static 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
2866static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,2925static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2867 IrInstructionCast *cast_instruction)2926 IrInstructionCast *cast_instruction)
2868{2927{
...@@ -2877,69 +2936,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2877,69 +2936,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2877 zig_unreachable();2936 zig_unreachable();
2878 case CastOpNoop:2937 case CastOpNoop:
2879 return expr_val;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 case CastOpIntToFloat:2939 case CastOpIntToFloat:
2944 assert(actual_type->id == ZigTypeIdInt);2940 assert(actual_type->id == ZigTypeIdInt);
2945 if (actual_type->data.integral.is_signed) {2941 if (actual_type->data.integral.is_signed) {
...@@ -3028,15 +3024,51 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,...@@ -3028,15 +3024,51 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
3028 return nullptr;3024 return nullptr;
3029 }3025 }
3030 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);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}
30333044
3034static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,3045static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
3035 IrInstructionBitCast *instruction)3046 IrInstructionBitCastGen *instruction)
3036{3047{
3037 ZigType *wanted_type = instruction->base.value.type;3048 ZigType *wanted_type = instruction->base.value.type;
3038 LLVMValueRef value = ir_llvm_value(g, instruction->value);3049 ZigType *actual_type = instruction->operand->value.type;
3039 return LLVMBuildBitCast(g->builder, value, wanted_type->type_ref, "");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}
30413073
3042static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,3074static 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,7 +3199,8 @@ static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstruc
3167static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {3199static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {
3168 IrUnOp op_id = un_op_instruction->op_id;3200 IrUnOp op_id = un_op_instruction->op_id;
3169 LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value);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;
31713204
3172 switch (op_id) {3205 switch (op_id) {
3173 case IrUnOpInvalid:3206 case IrUnOpInvalid:
...@@ -3177,16 +3210,16 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst...@@ -3177,16 +3210,16 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
3177 case IrUnOpNegation:3210 case IrUnOpNegation:
3178 case IrUnOpNegationWrap:3211 case IrUnOpNegationWrap:
3179 {3212 {
3180 if (expr_type->id == ZigTypeIdFloat) {3213 if (scalar_type->id == ZigTypeIdFloat) {
3181 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base));3214 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base));
3182 return LLVMBuildFNeg(g->builder, expr, "");3215 return LLVMBuildFNeg(g->builder, expr, "");
3183 } else if (expr_type->id == ZigTypeIdInt) {3216 } else if (scalar_type->id == ZigTypeIdInt) {
3184 if (op_id == IrUnOpNegationWrap) {3217 if (op_id == IrUnOpNegationWrap) {
3185 return LLVMBuildNeg(g->builder, expr, "");3218 return LLVMBuildNeg(g->builder, expr, "");
3186 } else if (ir_want_runtime_safety(g, &un_op_instruction->base)) {3219 } else if (ir_want_runtime_safety(g, &un_op_instruction->base)) {
3187 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));3220 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
3188 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);3221 return gen_overflow_op(g, operand_type, AddSubMulSub, zero, expr);
3189 } else if (expr_type->data.integral.is_signed) {3222 } else if (scalar_type->data.integral.is_signed) {
3190 return LLVMBuildNSWNeg(g->builder, expr, "");3223 return LLVMBuildNSWNeg(g->builder, expr, "");
3191 } else {3224 } else {
3192 return LLVMBuildNUWNeg(g->builder, expr, "");3225 return LLVMBuildNUWNeg(g->builder, expr, "");
...@@ -3237,7 +3270,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -3237,7 +3270,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3237 return nullptr;3270 return nullptr;
3238}3271}
32393272
3240static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {3273static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) {
3241 ZigType *child_type = instruction->base.value.type;3274 ZigType *child_type = instruction->base.value.type;
3242 if (!type_has_bits(child_type))3275 if (!type_has_bits(child_type))
3243 return nullptr;3276 return nullptr;
...@@ -3252,7 +3285,6 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3252,7 +3285,6 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32523285
3253 bool big_endian = g->is_big_endian;3286 bool big_endian = g->is_big_endian;
32543287
3255 assert(!handle_is_ptr(child_type));
3256 LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");3288 LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
3257 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));3289 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
3258 assert(host_bit_count == host_int_bytes * 8);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,7 +3296,16 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
3264 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);3296 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
3265 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");3297 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
32663298
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}
32693310
3270static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {3311static 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,6 +3348,77 @@ static bool value_is_all_undef(ConstExprValue *const_val) {
3307 zig_unreachable();3348 zig_unreachable();
3308}3349}
33093350
3351static 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
3408static 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
3310static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {3422static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3311 assert(type_has_bits(value_type));3423 assert(type_has_bits(value_type));
3312 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);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,6 +3431,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_
3319 ZigType *usize = g->builtin_types.entry_usize;3431 ZigType *usize = g->builtin_types.entry_usize;
3320 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);3432 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3321 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);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}
33233443
3324static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {3444static 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,7 +3599,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) {
3479 LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);3599 LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);
34803600
3481 if (g->sp_md_node == nullptr) {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 LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);3603 LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);
3484 g->sp_md_node = LLVMMDNode(&str_node, 1);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,6 +5457,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5337 case IrInstructionIdDeclVarSrc:5457 case IrInstructionIdDeclVarSrc:
5338 case IrInstructionIdPtrCastSrc:5458 case IrInstructionIdPtrCastSrc:
5339 case IrInstructionIdCmpxchgSrc:5459 case IrInstructionIdCmpxchgSrc:
5460 case IrInstructionIdLoadPtr:
5461 case IrInstructionIdBitCast:
5340 zig_unreachable();5462 zig_unreachable();
53415463
5342 case IrInstructionIdDeclVarGen:5464 case IrInstructionIdDeclVarGen:
...@@ -5355,8 +5477,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5355,8 +5477,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5355 return ir_render_br(g, executable, (IrInstructionBr *)instruction);5477 return ir_render_br(g, executable, (IrInstructionBr *)instruction);
5356 case IrInstructionIdUnOp:5478 case IrInstructionIdUnOp:
5357 return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);5479 return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
5358 case IrInstructionIdLoadPtr:5480 case IrInstructionIdLoadPtrGen:
5359 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);5481 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);
5360 case IrInstructionIdStorePtr:5482 case IrInstructionIdStorePtr:
5361 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);5483 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
5362 case IrInstructionIdVarPtr:5484 case IrInstructionIdVarPtr:
...@@ -5433,8 +5555,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5433,8 +5555,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5433 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);5555 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5434 case IrInstructionIdPtrCastGen:5556 case IrInstructionIdPtrCastGen:
5435 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);5557 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
5436 case IrInstructionIdBitCast:5558 case IrInstructionIdBitCastGen:
5437 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);5559 return ir_render_bit_cast(g, executable, (IrInstructionBitCastGen *)instruction);
5438 case IrInstructionIdWidenOrShorten:5560 case IrInstructionIdWidenOrShorten:
5439 return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);5561 return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
5440 case IrInstructionIdPtrToInt:5562 case IrInstructionIdPtrToInt:
...@@ -5509,6 +5631,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5509,6 +5631,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5509 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);5631 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
5510 case IrInstructionIdAssertZero:5632 case IrInstructionIdAssertZero:
5511 return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);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 zig_unreachable();5637 zig_unreachable();
5514}5638}
...@@ -5711,8 +5835,32 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -5711,8 +5835,32 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
5711 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);5835 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
5712 return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);5836 return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);
5713 }5837 }
5714 case ZigTypeIdArray:5838 case ZigTypeIdArray: {
5715 zig_panic("TODO bit pack an array");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 case ZigTypeIdVector:5864 case ZigTypeIdVector:
5717 zig_panic("TODO bit pack a vector");5865 zig_panic("TODO bit pack a vector");
5718 case ZigTypeIdUnion:5866 case ZigTypeIdUnion:
...@@ -6387,6 +6535,22 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {...@@ -6387,6 +6535,22 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
6387 }6535 }
6388}6536}
63896537
6538static 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
6390static void do_code_gen(CodeGen *g) {6554static void do_code_gen(CodeGen *g) {
6391 assert(!g->errors.length);6555 assert(!g->errors.length);
63926556
...@@ -6467,21 +6631,21 @@ static void do_code_gen(CodeGen *g) {...@@ -6467,21 +6631,21 @@ static void do_code_gen(CodeGen *g) {
6467 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));6631 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
6468 // TODO debug info for the extern variable6632 // TODO debug info for the extern variable
64696633
6470 LLVMSetLinkage(global_value, LLVMExternalLinkage);6634 LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
6471 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);6635 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
6472 LLVMSetAlignment(global_value, var->align_bytes);6636 LLVMSetAlignment(global_value, var->align_bytes);
6473 LLVMSetGlobalConstant(global_value, var->gen_is_const);6637 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6474 set_global_tls(g, var, global_value);6638 set_global_tls(g, var, global_value);
6475 }6639 }
6476 } else {6640 } else {
6477 bool exported = (var->linkage == VarLinkageExport);6641 bool exported = (var->linkage != VarLinkageInternal);
6478 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));6642 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6479 render_const_val(g, var->const_value, mangled_name);6643 render_const_val(g, var->const_value, mangled_name);
6480 render_const_val_global(g, var->const_value, mangled_name);6644 render_const_val_global(g, var->const_value, mangled_name);
6481 global_value = var->const_value->global_refs->llvm_global;6645 global_value = var->const_value->global_refs->llvm_global;
64826646
6483 if (exported) {6647 if (exported) {
6484 LLVMSetLinkage(global_value, LLVMExternalLinkage);6648 LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
6485 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);6649 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
6486 }6650 }
6487 if (tld_var->section_name) {6651 if (tld_var->section_name) {
...@@ -6584,6 +6748,15 @@ static void do_code_gen(CodeGen *g) {...@@ -6584,6 +6748,15 @@ static void do_code_gen(CodeGen *g) {
6584 } else if (instruction->id == IrInstructionIdCmpxchgGen) {6748 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6585 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;6749 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
6586 slot = &cmpxchg_instruction->tmp_ptr;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 } else if (instruction->id == IrInstructionIdVectorToArray) {6760 } else if (instruction->id == IrInstructionIdVectorToArray) {
6588 IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;6761 IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
6589 alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);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,7 +7012,7 @@ static void define_builtin_types(CodeGen *g) {
68397012
6840 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {7013 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
6841 const CIntTypeInfo *info = &c_int_type_infos[i];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 bool is_signed = info->is_signed;7016 bool is_signed = info->is_signed;
68447017
6845 ZigType *entry = new_type_table_entry(ZigTypeIdInt);7018 ZigType *entry = new_type_table_entry(ZigTypeIdInt);
...@@ -7106,6 +7279,9 @@ static const char *build_mode_to_str(BuildMode build_mode) {...@@ -7106,6 +7279,9 @@ static const char *build_mode_to_str(BuildMode build_mode) {
7106Buf *codegen_generate_builtin_source(CodeGen *g) {7279Buf *codegen_generate_builtin_source(CodeGen *g) {
7107 Buf *contents = buf_alloc();7280 Buf *contents = buf_alloc();
71087281
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 // Modifications to this struct must be coordinated with code that does anything with7285 // Modifications to this struct must be coordinated with code that does anything with
7110 // g->stack_trace_type. There are hard-coded references to the field indexes.7286 // g->stack_trace_type. There are hard-coded references to the field indexes.
7111 buf_append_str(contents,7287 buf_append_str(contents,
...@@ -7114,16 +7290,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7114,16 +7290,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7114 " instruction_addresses: []usize,\n"7290 " instruction_addresses: []usize,\n"
7115 "};\n\n");7291 "};\n\n");
71167292
7293 buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
7294
7117 const char *cur_os = nullptr;7295 const char *cur_os = nullptr;
7118 {7296 {
7119 buf_appendf(contents, "pub const Os = enum {\n");7297 buf_appendf(contents, "pub const Os = enum {\n");
7120 uint32_t field_count = (uint32_t)target_os_count();7298 uint32_t field_count = (uint32_t)target_os_count();
7121 for (uint32_t i = 0; i < field_count; i += 1) {7299 for (uint32_t i = 0; i < field_count; i += 1) {
7122 Os os_type = get_target_os(i);7300 Os os_type = target_os_enum(i);
7123 const char *name = get_target_os_name(os_type);7301 const char *name = target_os_name(os_type);
7124 buf_appendf(contents, " %s,\n", name);7302 buf_appendf(contents, " %s,\n", name);
71257303
7126 if (os_type == g->zig_target.os) {7304 if (os_type == g->zig_target->os) {
7127 g->target_os_index = i;7305 g->target_os_index = i;
7128 cur_os = name;7306 cur_os = name;
7129 }7307 }
...@@ -7134,56 +7312,81 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7134,56 +7312,81 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
71347312
7135 const char *cur_arch = nullptr;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 uint32_t field_count = (uint32_t)target_arch_count();7316 uint32_t field_count = (uint32_t)target_arch_count();
7139 for (uint32_t i = 0; i < field_count; i += 1) {7317 for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) {
7140 const ArchType *arch_type = get_target_arch(i);7318 ZigLLVM_ArchType arch = target_arch_enum(arch_i);
7141 Buf *arch_name = buf_alloc();7319 const char *arch_name = target_arch_name(arch);
7142 buf_resize(arch_name, 50);7320 SubArchList sub_arch_list = target_subarch_list(arch);
7143 get_arch_name(buf_ptr(arch_name), arch_type);7321 if (sub_arch_list == SubArchListNone) {
7144 buf_resize(arch_name, strlen(buf_ptr(arch_name)));7322 buf_appendf(contents, " %s,\n", arch_name);
71457323 if (arch == g->zig_target->arch) {
7146 buf_appendf(contents, " %s,\n", buf_ptr(arch_name));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 }
71477343
7148 if (arch_type->arch == g->zig_target.arch.arch &&7344 uint32_t list_count = target_subarch_list_count();
7149 arch_type->sub_arch == g->zig_target.arch.sub_arch)7345 // start at index 1 to skip None
7150 {7346 for (uint32_t list_i = 1; list_i < list_count; list_i += 1) {
7151 g->target_arch_index = i;7347 SubArchList sub_arch_list = target_subarch_list_enum(list_i);
7152 cur_arch = buf_ptr(arch_name);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 buf_appendf(contents, "};\n\n");7357 buf_appendf(contents, "};\n\n");
7156 }7358 }
7157 assert(cur_arch != nullptr);7359 assert(cur_arch != nullptr);
71587360
7159 const char *cur_environ = nullptr;7361 const char *cur_abi = nullptr;
7160 {7362 {
7161 buf_appendf(contents, "pub const Environ = enum {\n");7363 buf_appendf(contents, "pub const Abi = enum {\n");
7162 uint32_t field_count = (uint32_t)target_environ_count();7364 uint32_t field_count = (uint32_t)target_abi_count();
7163 for (uint32_t i = 0; i < field_count; i += 1) {7365 for (uint32_t i = 0; i < field_count; i += 1) {
7164 ZigLLVM_EnvironmentType environ_type = get_target_environ(i);7366 ZigLLVM_EnvironmentType abi = target_abi_enum(i);
7165 const char *name = ZigLLVMGetEnvironmentTypeName(environ_type);7367 const char *name = target_abi_name(abi);
7166 buf_appendf(contents, " %s,\n", name);7368 buf_appendf(contents, " %s,\n", name);
71677369
7168 if (environ_type == g->zig_target.env_type) {7370 if (abi == g->zig_target->abi) {
7169 g->target_environ_index = i;7371 g->target_abi_index = i;
7170 cur_environ = name;7372 cur_abi = name;
7171 }7373 }
7172 }7374 }
7173 buf_appendf(contents, "};\n\n");7375 buf_appendf(contents, "};\n\n");
7174 }7376 }
7175 assert(cur_environ != nullptr);7377 assert(cur_abi != nullptr);
71767378
7177 const char *cur_obj_fmt = nullptr;7379 const char *cur_obj_fmt = nullptr;
7178 {7380 {
7179 buf_appendf(contents, "pub const ObjectFormat = enum {\n");7381 buf_appendf(contents, "pub const ObjectFormat = enum {\n");
7180 uint32_t field_count = (uint32_t)target_oformat_count();7382 uint32_t field_count = (uint32_t)target_oformat_count();
7181 for (uint32_t i = 0; i < field_count; i += 1) {7383 for (uint32_t i = 0; i < field_count; i += 1) {
7182 ZigLLVM_ObjectFormatType oformat = get_target_oformat(i);7384 ZigLLVM_ObjectFormatType oformat = target_oformat_enum(i);
7183 const char *name = get_target_oformat_name(oformat);7385 const char *name = target_oformat_name(oformat);
7184 buf_appendf(contents, " %s,\n", name);7386 buf_appendf(contents, " %s,\n", name);
71857387
7186 if (oformat == g->zig_target.oformat) {7388 ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target);
7389 if (oformat == target_oformat) {
7187 g->target_oformat_index = i;7390 g->target_oformat_index = i;
7188 cur_obj_fmt = name;7391 cur_obj_fmt = name;
7189 }7392 }
...@@ -7294,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7294,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7294 " One,\n"7497 " One,\n"
7295 " Many,\n"7498 " Many,\n"
7296 " Slice,\n"7499 " Slice,\n"
7500 " C,\n"
7297 " };\n"7501 " };\n"
7298 " };\n"7502 " };\n"
7299 "\n"7503 "\n"
...@@ -7466,12 +7670,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7466,12 +7670,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7466 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));7670 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
7467 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));7671 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
7468 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);7672 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
7469 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);7673 buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
7470 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);7674 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
7471 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);7675 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
7472 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));7676 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
7473 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));7677 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
7474 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));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)));
74757680
7476 buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n");7681 buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n");
74777682
...@@ -7500,14 +7705,15 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -7500,14 +7705,15 @@ static Error define_builtin_compile_vars(CodeGen *g) {
7500 cache_int(&cache_hash, g->build_mode);7705 cache_int(&cache_hash, g->build_mode);
7501 cache_bool(&cache_hash, g->is_test_build);7706 cache_bool(&cache_hash, g->is_test_build);
7502 cache_bool(&cache_hash, g->is_single_threaded);7707 cache_bool(&cache_hash, g->is_single_threaded);
7503 cache_int(&cache_hash, g->zig_target.arch.arch);7708 cache_int(&cache_hash, g->zig_target->is_native);
7504 cache_int(&cache_hash, g->zig_target.arch.sub_arch);7709 cache_int(&cache_hash, g->zig_target->arch);
7505 cache_int(&cache_hash, g->zig_target.vendor);7710 cache_int(&cache_hash, g->zig_target->sub_arch);
7506 cache_int(&cache_hash, g->zig_target.os);7711 cache_int(&cache_hash, g->zig_target->vendor);
7507 cache_int(&cache_hash, g->zig_target.env_type);7712 cache_int(&cache_hash, g->zig_target->os);
7508 cache_int(&cache_hash, g->zig_target.oformat);7713 cache_int(&cache_hash, g->zig_target->abi);
7509 cache_bool(&cache_hash, g->have_err_ret_tracing);7714 cache_bool(&cache_hash, g->have_err_ret_tracing);
7510 cache_bool(&cache_hash, g->libc_link_lib != nullptr);7715 cache_bool(&cache_hash, g->libc_link_lib != nullptr);
7716 cache_bool(&cache_hash, g->valgrind_support);
75117717
7512 Buf digest = BUF_INIT;7718 Buf digest = BUF_INIT;
7513 buf_resize(&digest, 0);7719 buf_resize(&digest, 0);
...@@ -7576,11 +7782,11 @@ static void init(CodeGen *g) {...@@ -7576,11 +7782,11 @@ static void init(CodeGen *g) {
7576 assert(g->root_out_name);7782 assert(g->root_out_name);
7577 g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));7783 g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
75787784
7579 get_target_triple(&g->triple_str, &g->zig_target);7785 get_target_triple(&g->triple_str, g->zig_target);
75807786
7581 LLVMSetTarget(g->module, buf_ptr(&g->triple_str));7787 LLVMSetTarget(g->module, buf_ptr(&g->triple_str));
75827788
7583 if (g->zig_target.oformat == ZigLLVM_COFF) {7789 if (target_object_format(g->zig_target) == ZigLLVM_COFF) {
7584 ZigLLVMAddModuleCodeViewFlag(g->module);7790 ZigLLVMAddModuleCodeViewFlag(g->module);
7585 } else {7791 } else {
7586 ZigLLVMAddModuleDebugInfoFlag(g->module);7792 ZigLLVMAddModuleDebugInfoFlag(g->module);
...@@ -7608,11 +7814,11 @@ static void init(CodeGen *g) {...@@ -7608,11 +7814,11 @@ static void init(CodeGen *g) {
76087814
7609 const char *target_specific_cpu_args;7815 const char *target_specific_cpu_args;
7610 const char *target_specific_features;7816 const char *target_specific_features;
7611 if (g->is_native_target) {7817 if (g->zig_target->is_native) {
7612 // LLVM creates invalid binaries on Windows sometimes.7818 // LLVM creates invalid binaries on Windows sometimes.
7613 // See https://github.com/ziglang/zig/issues/5087819 // See https://github.com/ziglang/zig/issues/508
7614 // As a workaround we do not use target native features on Windows.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 target_specific_cpu_args = "";7822 target_specific_cpu_args = "";
7617 target_specific_features = "";7823 target_specific_features = "";
7618 } else {7824 } else {
...@@ -7685,9 +7891,59 @@ static void init(CodeGen *g) {...@@ -7685,9 +7891,59 @@ static void init(CodeGen *g) {
7685 }7891 }
7686}7892}
76877893
7688void codegen_translate_c(CodeGen *g, Buf *full_path) {7894static void detect_libc(CodeGen *g) {
7689 find_libc_include_path(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}
76907945
7946void codegen_translate_c(CodeGen *g, Buf *full_path) {
7691 Buf *src_basename = buf_alloc();7947 Buf *src_basename = buf_alloc();
7692 Buf *src_dirname = buf_alloc();7948 Buf *src_dirname = buf_alloc();
7693 os_path_split(full_path, src_dirname, src_basename);7949 os_path_split(full_path, src_dirname, src_basename);
...@@ -7698,6 +7954,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {...@@ -7698,6 +7954,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
7698 g->root_import = import;7954 g->root_import = import;
7699 import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);7955 import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);
77007956
7957 detect_libc(g);
7958
7701 init(g);7959 init(g);
77027960
7703 import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));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,14 +8115,14 @@ static void gen_root_source(CodeGen *g) {
7857 }8115 }
7858 report_errors_and_maybe_exit(g);8116 report_errors_and_maybe_exit(g);
78598117
7860 if (!g->is_test_build && g->zig_target.os != OsFreestanding &&8118 if (!g->is_test_build && g->zig_target->os != OsFreestanding &&
7861 g->zig_target.os != OsUefi &&8119 g->zig_target->os != OsUefi &&
7862 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&8120 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
7863 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))8121 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
7864 {8122 {
7865 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");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 g->out_type == OutTypeLib && !g->is_static)8126 g->out_type == OutTypeLib && !g->is_static)
7869 {8127 {
7870 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");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,6 +8140,8 @@ static void gen_root_source(CodeGen *g) {
7882 }8140 }
7883 }8141 }
78848142
8143 typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
8144
7885 report_errors_and_maybe_exit(g);8145 report_errors_and_maybe_exit(g);
78868146
7887}8147}
...@@ -7904,6 +8164,168 @@ static void gen_global_asm(CodeGen *g) {...@@ -7904,6 +8164,168 @@ static void gen_global_asm(CodeGen *g) {
7904 }8164 }
7905}8165}
79068166
8167static 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
8175static 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
8311static 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
7907void codegen_add_object(CodeGen *g, Buf *object_path) {8329void codegen_add_object(CodeGen *g, Buf *object_path) {
7908 g->link_objects.append(object_path);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,31 +8832,39 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
8410 }8832 }
8411 cache_buf(ch, compiler_id);8833 cache_buf(ch, compiler_id);
8412 cache_buf(ch, g->root_out_name);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 cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);8837 cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);
8414 cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);8838 cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);
8415 cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);8839 cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);
8416 cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length);8840 cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length);
8417 cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);8841 cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
8418 cache_list_of_file(ch, g->assembly_files.items, g->assembly_files.length);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 cache_int(ch, g->emit_file_type);8850 cache_int(ch, g->emit_file_type);
8420 cache_int(ch, g->build_mode);8851 cache_int(ch, g->build_mode);
8421 cache_int(ch, g->out_type);8852 cache_int(ch, g->out_type);
8422 cache_int(ch, g->zig_target.arch.arch);8853 cache_bool(ch, g->zig_target->is_native);
8423 cache_int(ch, g->zig_target.arch.sub_arch);8854 cache_int(ch, g->zig_target->arch);
8424 cache_int(ch, g->zig_target.vendor);8855 cache_int(ch, g->zig_target->sub_arch);
8425 cache_int(ch, g->zig_target.os);8856 cache_int(ch, g->zig_target->vendor);
8426 cache_int(ch, g->zig_target.env_type);8857 cache_int(ch, g->zig_target->os);
8427 cache_int(ch, g->zig_target.oformat);8858 cache_int(ch, g->zig_target->abi);
8428 cache_int(ch, g->subsystem);8859 cache_int(ch, g->subsystem);
8429 cache_bool(ch, g->is_static);8860 cache_bool(ch, g->is_static);
8430 cache_bool(ch, g->strip_debug_symbols);8861 cache_bool(ch, g->strip_debug_symbols);
8431 cache_bool(ch, g->is_test_build);8862 cache_bool(ch, g->is_test_build);
8432 cache_bool(ch, g->is_single_threaded);8863 cache_bool(ch, g->is_single_threaded);
8433 cache_bool(ch, g->is_native_target);
8434 cache_bool(ch, g->linker_rdynamic);8864 cache_bool(ch, g->linker_rdynamic);
8435 cache_bool(ch, g->no_rosegment_workaround);
8436 cache_bool(ch, g->each_lib_rpath);8865 cache_bool(ch, g->each_lib_rpath);
8437 cache_bool(ch, g->disable_pic);8866 cache_bool(ch, g->disable_pic);
8867 cache_bool(ch, g->valgrind_support);
8438 cache_buf_opt(ch, g->mmacosx_version_min);8868 cache_buf_opt(ch, g->mmacosx_version_min);
8439 cache_buf_opt(ch, g->mios_version_min);8869 cache_buf_opt(ch, g->mios_version_min);
8440 cache_usize(ch, g->version_major);8870 cache_usize(ch, g->version_major);
...@@ -8445,6 +8875,16 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -8445,6 +8875,16 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
8445 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);8875 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
8446 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);8876 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
8447 cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);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 }
84488888
8449 buf_resize(digest, 0);8889 buf_resize(digest, 0);
8450 if ((err = cache_hit(ch, digest)))8890 if ((err = cache_hit(ch, digest)))
...@@ -8459,19 +8899,19 @@ static void resolve_out_paths(CodeGen *g) {...@@ -8459,19 +8899,19 @@ static void resolve_out_paths(CodeGen *g) {
8459 switch (g->emit_file_type) {8899 switch (g->emit_file_type) {
8460 case EmitFileTypeBinary: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 buf_append_str(o_basename, o_ext);8903 buf_append_str(o_basename, o_ext);
8464 break;8904 break;
8465 }8905 }
8466 case EmitFileTypeAssembly: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 buf_append_str(o_basename, asm_ext);8909 buf_append_str(o_basename, asm_ext);
8470 break;8910 break;
8471 }8911 }
8472 case EmitFileTypeLLVMIr: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 buf_append_str(o_basename, llvm_ir_ext);8915 buf_append_str(o_basename, llvm_ir_ext);
8476 break;8916 break;
8477 }8917 }
...@@ -8497,7 +8937,7 @@ static void resolve_out_paths(CodeGen *g) {...@@ -8497,7 +8937,7 @@ static void resolve_out_paths(CodeGen *g) {
84978937
8498 Buf basename = BUF_INIT;8938 Buf basename = BUF_INIT;
8499 buf_init_from_buf(&basename, g->root_out_name);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 if (g->enable_cache || g->is_test_build) {8941 if (g->enable_cache || g->is_test_build) {
8502 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);8942 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
8503 } else {8943 } else {
...@@ -8510,7 +8950,7 @@ static void resolve_out_paths(CodeGen *g) {...@@ -8510,7 +8950,7 @@ static void resolve_out_paths(CodeGen *g) {
8510 } else {8950 } else {
8511 Buf basename = BUF_INIT;8951 Buf basename = BUF_INIT;
8512 buf_init_from_buf(&basename, g->root_out_name);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 g->version_major, g->version_minor, g->version_patch));8954 g->version_major, g->version_minor, g->version_patch));
8515 if (g->enable_cache) {8955 if (g->enable_cache) {
8516 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);8956 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
...@@ -8523,11 +8963,12 @@ static void resolve_out_paths(CodeGen *g) {...@@ -8523,11 +8963,12 @@ static void resolve_out_paths(CodeGen *g) {
8523 }8963 }
8524}8964}
85258965
8526
8527void codegen_build_and_link(CodeGen *g) {8966void codegen_build_and_link(CodeGen *g) {
8528 Error err;8967 Error err;
8529 assert(g->out_type != OutTypeUnknown);8968 assert(g->out_type != OutTypeUnknown);
85308969
8970 detect_libc(g);
8971
8531 Buf *stage1_dir = get_stage1_cache_path();8972 Buf *stage1_dir = get_stage1_cache_path();
8532 Buf *artifact_dir = buf_alloc();8973 Buf *artifact_dir = buf_alloc();
8533 Buf digest = BUF_INIT;8974 Buf digest = BUF_INIT;
...@@ -8559,6 +9000,7 @@ void codegen_build_and_link(CodeGen *g) {...@@ -8559,6 +9000,7 @@ void codegen_build_and_link(CodeGen *g) {
85599000
8560 gen_global_asm(g);9001 gen_global_asm(g);
8561 gen_root_source(g);9002 gen_root_source(g);
9003 gen_c_objects(g);
85629004
8563 if (g->enable_cache) {9005 if (g->enable_cache) {
8564 if ((err = cache_final(&g->cache_hash, &digest))) {9006 if ((err = cache_final(&g->cache_hash, &digest))) {
...@@ -8576,16 +9018,25 @@ void codegen_build_and_link(CodeGen *g) {...@@ -8576,16 +9018,25 @@ void codegen_build_and_link(CodeGen *g) {
8576 resolve_out_paths(g);9018 resolve_out_paths(g);
85779019
8578 codegen_add_time_event(g, "Code Generation");9020 codegen_add_time_event(g, "Code Generation");
8579 do_code_gen(g);9021 if (g->out_type == OutTypeObj && g->c_source_files.length == 1) {
8580 codegen_add_time_event(g, "LLVM Emit Output");9022 assert(g->link_objects.length == 1);
8581 zig_llvm_emit_output(g);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);
85829032
8583 if (g->out_h_path != nullptr) {9033 if (g->out_h_path != nullptr) {
8584 codegen_add_time_event(g, "Generate .h");9034 codegen_add_time_event(g, "Generate .h");
8585 gen_h_file(g);9035 gen_h_file(g);
8586 }9036 }
8587 if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {9037 if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
8588 codegen_link(g);9038 codegen_link(g);
9039 }
8589 }9040 }
8590 }9041 }
85919042
src/codegen.hpp+3-7
...@@ -11,11 +11,12 @@...@@ -11,11 +11,12 @@
11#include "parser.hpp"11#include "parser.hpp"
12#include "errmsg.hpp"12#include "errmsg.hpp"
13#include "target.hpp"13#include "target.hpp"
14#include "libc_installation.hpp"
1415
15#include <stdio.h>16#include <stdio.h>
1617
17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,18CodeGen *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);
1920
20void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);21void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
21void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);22void 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,12 +28,6 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static);
27void codegen_set_strip(CodeGen *codegen, bool strip);28void codegen_set_strip(CodeGen *codegen, bool strip);
28void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);29void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
29void codegen_set_out_name(CodeGen *codegen, Buf *out_name);30void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
30void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);
31void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
32void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
33void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);
34void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
35void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
36void codegen_add_lib_dir(CodeGen *codegen, const char *dir);31void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
37void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);32void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
38LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);33LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
...@@ -46,6 +41,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter);...@@ -46,6 +41,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter);
46void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);41void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
47void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);42void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
48void codegen_set_output_h_path(CodeGen *g, Buf *h_path);43void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
44void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path);
49void codegen_set_output_path(CodeGen *g, Buf *path);45void codegen_set_output_path(CodeGen *g, Buf *path);
50void codegen_add_time_event(CodeGen *g, const char *name);46void codegen_add_time_event(CodeGen *g, const char *name);
51void codegen_print_timing_report(CodeGen *g, FILE *f);47void codegen_print_timing_report(CodeGen *g, FILE *f);
src/error.cpp+9
...@@ -34,6 +34,15 @@ const char *err_str(Error err) {...@@ -34,6 +34,15 @@ const char *err_str(Error err) {
34 case ErrorPipeBusy: return "pipe busy";34 case ErrorPipeBusy: return "pipe busy";
35 case ErrorPrimitiveTypeNotFound: return "primitive type not found";35 case ErrorPrimitiveTypeNotFound: return "primitive type not found";
36 case ErrorCacheUnavailable: return "cache unavailable";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 return "(invalid error)";47 return "(invalid error)";
39}48}
src/error.hpp+9
...@@ -36,6 +36,15 @@ enum Error {...@@ -36,6 +36,15 @@ enum Error {
36 ErrorPipeBusy,36 ErrorPipeBusy,
37 ErrorPrimitiveTypeNotFound,37 ErrorPrimitiveTypeNotFound,
38 ErrorCacheUnavailable,38 ErrorCacheUnavailable,
39 ErrorPathTooLong,
40 ErrorCCompilerCannotFindFile,
41 ErrorReadingDepFile,
42 ErrorMissingArchitecture,
43 ErrorMissingOperatingSystem,
44 ErrorUnknownArchitecture,
45 ErrorUnknownOperatingSystem,
46 ErrorUnknownABI,
47 ErrorInvalidFilename,
39};48};
4049
41const char *err_str(Error err);50const char *err_str(Error err);
src/ir.cpp+1042-367
...@@ -61,7 +61,7 @@ enum ConstCastResultId {...@@ -61,7 +61,7 @@ enum ConstCastResultId {
61 ConstCastResultIdType,61 ConstCastResultIdType,
62 ConstCastResultIdUnresolvedInferredErrSet,62 ConstCastResultIdUnresolvedInferredErrSet,
63 ConstCastResultIdAsyncAllocatorType,63 ConstCastResultIdAsyncAllocatorType,
64 ConstCastResultIdNullWrapPtr64 ConstCastResultIdBadAllowsZero,
65};65};
6666
67struct ConstCastOnly;67struct ConstCastOnly;
...@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;...@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
83struct ConstCastErrUnionPayloadMismatch;83struct ConstCastErrUnionPayloadMismatch;
84struct ConstCastErrSetMismatch;84struct ConstCastErrSetMismatch;
85struct ConstCastTypeMismatch;85struct ConstCastTypeMismatch;
86struct ConstCastBadAllowsZero;
8687
87struct ConstCastOnly {88struct ConstCastOnly {
88 ConstCastResultId id;89 ConstCastResultId id;
...@@ -99,6 +100,7 @@ struct ConstCastOnly {...@@ -99,6 +100,7 @@ struct ConstCastOnly {
99 ConstCastOnly *null_wrap_ptr_child;100 ConstCastOnly *null_wrap_ptr_child;
100 ConstCastArg fn_arg;101 ConstCastArg fn_arg;
101 ConstCastArgNoAlias arg_no_alias;102 ConstCastArgNoAlias arg_no_alias;
103 ConstCastBadAllowsZero *bad_allows_zero;
102 } data;104 } data;
103};105};
104106
...@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {...@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
141 ZigList<ErrorTableEntry *> missing_errors;143 ZigList<ErrorTableEntry *> missing_errors;
142};144};
143145
146struct ConstCastBadAllowsZero {
147 ZigType *wanted_type;
148 ZigType *actual_type;
149};
150
151
144enum UndefAllowed {152enum UndefAllowed {
145 UndefOk,153 UndefOk,
146 UndefBad,154 UndefBad,
...@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
164static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
165 ConstExprValue *out_val, ConstExprValue *ptr_val);173 ConstExprValue *out_val, ConstExprValue *ptr_val);
166static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,174static 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);
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);179static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
180static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
181 ZigType *ptr_type);
182static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
183 ZigType *dest_type);
172184
173static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {185static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
174 assert(get_src_ptr_type(const_val->type) != nullptr);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,10 +198,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
186 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];198 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
187 break;199 break;
188 }200 }
189 case ConstPtrSpecialBaseStruct:201 case ConstPtrSpecialBaseStruct: {
190 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[202 ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
191 const_val->data.x_ptr.data.base_struct.field_index];203 result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];
192 break;204 break;
205 }
193 case ConstPtrSpecialBaseErrorUnionCode:206 case ConstPtrSpecialBaseErrorUnionCode:
194 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;207 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
195 break;208 break;
...@@ -218,20 +231,55 @@ static bool is_opt_err_set(ZigType *ty) {...@@ -218,20 +231,55 @@ static bool is_opt_err_set(ZigType *ty) {
218 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);231 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
219}232}
220233
234// This function returns true when you can change the type of a ConstExprValue and the
235// value remains meaningful.
221static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {236static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
222 if (a == b)237 if (a == b)
223 return true;238 return true;
224239
225 if (a->id == b->id)
226 return true;
227
228 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)240 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
229 return true;241 return true;
230242
231 if (is_opt_err_set(a) && is_opt_err_set(b))243 if (is_opt_err_set(a) && is_opt_err_set(b))
232 return true;244 return true;
233245
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}
236284
237static bool ir_should_inline(IrExecutable *exec, Scope *scope) {285static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
...@@ -368,6 +416,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) {...@@ -368,6 +416,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) {
368 return IrInstructionIdLoadPtr;416 return IrInstructionIdLoadPtr;
369}417}
370418
419static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtrGen *) {
420 return IrInstructionIdLoadPtrGen;
421}
422
371static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {423static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
372 return IrInstructionIdStorePtr;424 return IrInstructionIdStorePtr;
373}425}
...@@ -408,6 +460,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {...@@ -408,6 +460,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
408 return IrInstructionIdCast;460 return IrInstructionIdCast;
409}461}
410462
463static constexpr IrInstructionId ir_instruction_id(IrInstructionResizeSlice *) {
464 return IrInstructionIdResizeSlice;
465}
466
411static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) {467static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) {
412 return IrInstructionIdContainerInitList;468 return IrInstructionIdContainerInitList;
413}469}
...@@ -688,6 +744,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {...@@ -688,6 +744,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
688 return IrInstructionIdBitCast;744 return IrInstructionIdBitCast;
689}745}
690746
747static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
748 return IrInstructionIdBitCastGen;
749}
750
691static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {751static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
692 return IrInstructionIdWidenOrShorten;752 return IrInstructionIdWidenOrShorten;
693}753}
...@@ -1291,14 +1351,23 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1291,14 +1351,23 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
1291 return &ptr_type_of_instruction->base;1351 return &ptr_type_of_instruction->base;
1292}1352}
12931353
1294static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {1354static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
1295 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node);1355 IrInstruction *value, LVal lval)
1296 br_instruction->op_id = op_id;1356{
1297 br_instruction->value = value;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;
12981361
1299 ir_ref_instruction(value, irb->current_basic_block);1362 ir_ref_instruction(value, irb->current_basic_block);
13001363
1301 return &br_instruction->base;1364 return &instruction->base;
1365}
1366
1367static 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}
13031372
1304static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,1373static 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,6 +1487,19 @@ static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *sourc
1418 return &decl_var_instruction->base;1487 return &decl_var_instruction->base;
1419}1488}
14201489
1490static 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
1421static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,1503static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
1422 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)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,12 +2272,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2190}2272}
21912273
2192static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,2274static 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 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(2277 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
2196 irb, scope, source_node);2278 irb, scope, source_node);
2197 instruction->dest_type = dest_type;2279 instruction->dest_type = dest_type;
2198 instruction->ptr = ptr;2280 instruction->ptr = ptr;
2281 instruction->safety_check_on = safety_check_on;
21992282
2200 ir_ref_instruction(dest_type, irb->current_basic_block);2283 ir_ref_instruction(dest_type, irb->current_basic_block);
2201 ir_ref_instruction(ptr, irb->current_basic_block);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,12 +2287,26 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod
2204}2287}
22052288
2206static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,2289static 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 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(2292 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2210 &ira->new_irb, source_instruction->scope, source_instruction->source_node);2293 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2211 instruction->base.value.type = ptr_type;2294 instruction->base.value.type = ptr_type;
2212 instruction->ptr = ptr;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
2303static 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;
22132310
2214 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);2311 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
22152312
...@@ -2224,12 +2321,25 @@ static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *s...@@ -2224,12 +2321,25 @@ static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *s
2224 instruction->dest_type = dest_type;2321 instruction->dest_type = dest_type;
2225 instruction->value = value;2322 instruction->value = value;
22262323
2227 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);2324 ir_ref_instruction(dest_type, irb->current_basic_block);
2228 ir_ref_instruction(value, irb->current_basic_block);2325 ir_ref_instruction(value, irb->current_basic_block);
22292326
2230 return &instruction->base;2327 return &instruction->base;
2231}2328}
22322329
2330static 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
2233static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,2343static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,
2234 IrInstruction *target)2344 IrInstruction *target)
2235{2345{
...@@ -2458,7 +2568,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *...@@ -2458,7 +2568,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
24582568
2459 ir_ref_instruction(type_value, irb->current_basic_block);2569 ir_ref_instruction(type_value, irb->current_basic_block);
24602570
2461 return &instruction->base; 2571 return &instruction->base;
2462}2572}
24632573
2464static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,2574static 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,6 +3761,22 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode
3651 return ir_build_const_null(irb, scope, node);3761 return ir_build_const_null(irb, scope, node);
3652}3762}
36533763
3764static 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
3654static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {3780static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
3655 Error err;3781 Error err;
3656 assert(node->type == NodeTypeSymbol);3782 assert(node->type == NodeTypeSymbol);
...@@ -3704,8 +3830,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3704,8 +3830,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3704 return irb->codegen->invalid_instruction;3830 return irb->codegen->invalid_instruction;
3705 }3831 }
37063832
3707 // TODO put a variable of same name with invalid type in global scope3833 // put a variable of same name with invalid type in global scope
3708 // so that future references to this same name will find a variable with an invalid type3834 // 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 add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));3836 add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
3710 return irb->codegen->invalid_instruction;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,7 +4620,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4493 if (arg1_value == irb->codegen->invalid_instruction)4620 if (arg1_value == irb->codegen->invalid_instruction)
4494 return arg1_value;4621 return arg1_value;
44954622
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 return ir_lval_wrap(irb, scope, ptr_cast, lval);4624 return ir_lval_wrap(irb, scope, ptr_cast, lval);
4498 }4625 }
4499 case BuiltinFnIdBitCast:4626 case BuiltinFnIdBitCast:
...@@ -5019,10 +5146,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *...@@ -5019,10 +5146,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
5019 return ir_build_ref(irb, scope, value->source_node, value, false, false);5146 return ir_build_ref(irb, scope, value->source_node, value, false, false);
5020}5147}
50215148
5149static 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
5022static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {5163static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
5023 assert(node->type == NodeTypePointerType);5164 assert(node->type == NodeTypePointerType);
5024 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||5165 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
5025 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5026 bool is_const = node->data.pointer_type.is_const;5166 bool is_const = node->data.pointer_type.is_const;
5027 bool is_volatile = node->data.pointer_type.is_volatile;5167 bool is_volatile = node->data.pointer_type.is_volatile;
5028 AstNode *expr_node = node->data.pointer_type.op_expr;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,14 +6855,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
6715 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b0106855 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
67166856
6717 // TODO relies on Zig not re-ordering fields6857 // 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 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6860 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6720 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6861 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6721 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6862 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6722 atomic_state_field_name);6863 atomic_state_field_name);
67236864
6724 // set the is_canceled bit6865 // 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 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,6867 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
6727 AtomicRmwOp_or, AtomicOrderSeqCst);6868 AtomicRmwOp_or, AtomicOrderSeqCst);
67286869
...@@ -6793,14 +6934,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6793,14 +6934,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
6793 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));6934 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
67946935
6795 // TODO relies on Zig not re-ordering fields6936 // 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 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6939 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6798 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6940 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6799 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6941 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6800 atomic_state_field_name);6942 atomic_state_field_name);
68016943
6802 // clear the is_suspended bit6944 // 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 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,6946 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
6805 AtomicRmwOp_and, AtomicOrderSeqCst);6947 AtomicRmwOp_and, AtomicOrderSeqCst);
68066948
...@@ -6916,7 +7058,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6916,7 +7058,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69167058
6917 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);7059 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
6918 IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);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 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,7062 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
6921 AtomicRmwOp_or, AtomicOrderSeqCst);7063 AtomicRmwOp_or, AtomicOrderSeqCst);
69227064
...@@ -6959,7 +7101,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6959,7 +7101,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69597101
69607102
6961 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);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 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,7105 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
6964 AtomicRmwOp_or, AtomicOrderSeqCst);7106 AtomicRmwOp_or, AtomicOrderSeqCst);
6965 IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);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,7 +7133,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69917133
6992 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);7134 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6993 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);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 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,7137 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
6996 AtomicRmwOp_or, AtomicOrderSeqCst);7138 AtomicRmwOp_or, AtomicOrderSeqCst);
6997 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);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,7 +7336,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7194 if (value == irb->codegen->invalid_instruction)7336 if (value == irb->codegen->invalid_instruction)
7195 return value;7337 return value;
71967338
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 case NodeTypeUnwrapOptional: {7344 case NodeTypeUnwrapOptional: {
7200 AstNode *expr_node = node->data.unwrap_optional.expr;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,7 +7483,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73387483
7339 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,7484 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
7340 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));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 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);7488 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7343 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7489 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7344 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);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,7 +7508,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7362 ir_build_return(irb, coro_scope, node, undef);7508 ir_build_return(irb, coro_scope, node, undef);
73637509
7364 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);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 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);7513 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
73677514
7368 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);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,9 +7587,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7440 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7587 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7441 false, false, PtrLenUnknown, 0, 0, 0));7588 false, false, PtrLenUnknown, 0, 0, 0));
7442 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);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);7590 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7444 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,7591 result_ptr, false);
7445 irb->exec->coro_result_field_ptr);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 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,7594 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
7447 fn_entry->type_entry->data.fn.fn_type_id.return_type);7595 fn_entry->type_entry->data.fn.fn_type_id.return_type);
7448 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);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,7 +7640,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7492 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7640 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7493 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7641 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7494 false, false, PtrLenUnknown, 0, 0, 0));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 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7645 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7497 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7646 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7498 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);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,7 +8768,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
8619 return err_set_type;8768 return err_set_type;
8620}8769}
86218770
8622
8623static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,8771static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
8624 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)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,53 +8780,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8632 if (wanted_type == actual_type)8780 if (wanted_type == actual_type)
8633 return result;8781 return result;
86348782
8635 // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively8783 // If pointers have the same representation in memory, they can be "const-casted".
8636 // but not if we want a mutable pointer8784 // `const` attribute can be gained
8637 // and not if the actual pointer has zero bits8785 // `volatile` attribute can be gained
8638 if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&8786 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
8639 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&8787 // but only if !wanted_is_mutable
8640 actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))8788 // alignment can be decreased
8641 {8789 // bit offset attributes must match exactly
8642 ConstCastOnly child = types_match_const_cast_only(ira,8790 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
8643 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);8791 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8644 if (child.id == ConstCastResultIdInvalid)8792 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8645 return child;8793 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
8646 if (child.id != ConstCastResultIdOk) {8794 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
8647 result.id = ConstCastResultIdNullWrapPtr;8795 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8648 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);8796 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8649 *result.data.null_wrap_ptr_child = child;8797 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
8650 }8798 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
8651 return result;8799 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
8652 }8800 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
86538801 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
8654 // pointer const8802 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8655 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {8803 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
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);
8658 if (child.id == ConstCastResultIdInvalid)8804 if (child.id == ConstCastResultIdInvalid)
8659 return child;8805 return child;
8660 if (child.id != ConstCastResultIdOk) {8806 if (child.id != ConstCastResultIdOk) {
8661 result.id = ConstCastResultIdPointerChild;8807 result.id = ConstCastResultIdPointerChild;
8662 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);8808 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
8663 result.data.pointer_mismatch->child = child;8809 result.data.pointer_mismatch->child = child;
8664 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;8810 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
8665 result.data.pointer_mismatch->actual_child = actual_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 return result;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 result.id = ConstCastResultIdInvalid;8825 result.id = ConstCastResultIdInvalid;
8670 return result;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 result.id = ConstCastResultIdInvalid;8829 result.id = ConstCastResultIdInvalid;
8674 return result;8830 return result;
8675 }8831 }
8676 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&8832 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8677 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&8833 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8678 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&8834 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
8679 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&8835 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8680 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&8836 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8681 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))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 return result;8841 return result;
8684 }8842 }
...@@ -8912,7 +9070,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *...@@ -8912,7 +9070,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
8912 *errors = reallocate(*errors, old_errors_count, *errors_count);9070 *errors = reallocate(*errors, old_errors_count, *errors_count);
8913}9071}
89149072
8915static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) {9073static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type,
9074 IrInstruction **instructions, size_t instruction_count)
9075{
8916 Error err;9076 Error err;
8917 assert(instruction_count >= 1);9077 assert(instruction_count >= 1);
8918 IrInstruction *prev_inst = instructions[0];9078 IrInstruction *prev_inst = instructions[0];
...@@ -9229,6 +9389,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9229,6 +9389,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9229 continue;9389 continue;
9230 }9390 }
92319391
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 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {9423 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
9233 continue;9424 continue;
9234 }9425 }
...@@ -9534,9 +9725,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9534,9 +9725,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9534 }9725 }
9535 const_val->type = new_type;9726 const_val->type = new_type;
9536 break;9727 break;
9537 case CastOpResizeSlice:
9538 // can't do it
9539 zig_unreachable();
9540 case CastOpIntToFloat:9728 case CastOpIntToFloat:
9541 {9729 {
9542 assert(new_type->id == ZigTypeIdFloat);9730 assert(new_type->id == ZigTypeIdFloat);
...@@ -9600,9 +9788,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z...@@ -9600,9 +9788,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
9600static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,9788static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9601 ZigType *wanted_type, CastOp cast_op, bool need_alloca)9789 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
9602{9790{
9603 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&9791 if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {
9604 cast_op != CastOpResizeSlice)
9605 {
9606 IrInstruction *result = ir_const(ira, source_instr, wanted_type);9792 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9607 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,9793 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
9608 &result->value, wanted_type))9794 &result->value, wanted_type))
...@@ -9864,7 +10050,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9864,7 +10050,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9864 if (undef_allowed == UndefOk) {10050 if (undef_allowed == UndefOk) {
9865 return &value->value;10051 return &value->value;
9866 } else {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 return nullptr;10054 return nullptr;
9869 }10055 }
9870 }10056 }
...@@ -9874,7 +10060,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9874,7 +10060,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9874ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,10060ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9875 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,10061 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
9876 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,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 if (expected_type != nullptr && type_is_invalid(expected_type))10065 if (expected_type != nullptr && type_is_invalid(expected_type))
9880 return &codegen->invalid_instruction->value;10066 return &codegen->invalid_instruction->value;
...@@ -9910,7 +10096,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -9910,7 +10096,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
9910 analyzed_executable->backward_branch_count = backward_branch_count;10096 analyzed_executable->backward_branch_count = backward_branch_count;
9911 analyzed_executable->backward_branch_quota = backward_branch_quota;10097 analyzed_executable->backward_branch_quota = backward_branch_quota;
9912 analyzed_executable->begin_scope = scope;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 if (type_is_invalid(result_type))10100 if (type_is_invalid(result_type))
9915 return &codegen->invalid_instruction->value;10101 return &codegen->invalid_instruction->value;
991610102
...@@ -10230,49 +10416,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -10230,49 +10416,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
10230 return result;10416 return result;
10231}10417}
1023210418
10233static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr,10419static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *union_type) {
10234 IrInstruction *target, ZigType *wanted_type)10420 assert(union_type->id == ZigTypeIdUnion);
10235{10421
10236 Error err;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;
1023810425
10239 ZigType *actual_type = target->value.type;10426 AstNode *decl_node = union_type->data.unionation.decl_node;
10240 if ((err = ensure_complete_type(ira->codegen, actual_type)))10427 if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
10241 return ira->codegen->invalid_instruction;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}
1024210437
10243 if (wanted_type != actual_type->data.enumeration.tag_int_type) {10438static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) {
10244 ir_add_error(ira, source_instr,10439 Error err;
10245 buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'",10440
10246 buf_ptr(&wanted_type->name),10441 IrInstruction *enum_target;
10247 buf_ptr(&actual_type->data.enumeration.tag_int_type->name)));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 return ira->codegen->invalid_instruction;10456 return ira->codegen->invalid_instruction;
10249 }10457 }
1025010458
10251 assert(actual_type->id == ZigTypeIdEnum);10459 if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown)))
10460 return ira->codegen->invalid_instruction;
1025210461
10253 if (instr_is_comptime(target)) {10462 ZigType *tag_type = enum_type->data.enumeration.tag_int_type;
10254 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);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 if (!val)10467 if (!val)
10256 return ira->codegen->invalid_instruction;10468 return ira->codegen->invalid_instruction;
10257 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10469 IrInstruction *result = ir_const(ira, source_instr, tag_type);
10258 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);10470 init_const_bigint(&result->value, tag_type, &val->data.x_enum_tag);
10259 return result;10471 return result;
10260 }10472 }
1026110473
10262 // If there is only one possible tag, then we know at comptime what it is.10474 // If there is only one possible tag, then we know at comptime what it is.
10263 if (actual_type->data.enumeration.layout == ContainerLayoutAuto &&10475 if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&
10264 actual_type->data.enumeration.src_field_count == 1)10476 enum_type->data.enumeration.src_field_count == 1)
10265 {10477 {
10266 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);10478 assert(tag_type == ira->codegen->builtin_types.entry_num_lit_int);
10267 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10479 IrInstruction *result = ir_const(ira, source_instr, tag_type);
10268 init_const_bigint(&result->value, wanted_type,10480 init_const_bigint(&result->value, tag_type,
10269 &actual_type->data.enumeration.fields[0].value);10481 &enum_type->data.enumeration.fields[0].value);
10270 return result;10482 return result;
10271 }10483 }
1027210484
10273 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,10485 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
10274 source_instr->source_node, target);10486 source_instr->source_node, enum_target);
10275 result->value.type = wanted_type;10487 result->value.type = tag_type;
10276 return result;10488 return result;
10277}10489}
1027810490
...@@ -10770,17 +10982,37 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10770,17 +10982,37 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10770 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);10982 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
10771 break;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 case ConstCastResultIdFnAlign: // TODO11007 case ConstCastResultIdFnAlign: // TODO
10774 case ConstCastResultIdFnCC: // TODO11008 case ConstCastResultIdFnCC: // TODO
10775 case ConstCastResultIdFnVarArgs: // TODO11009 case ConstCastResultIdFnVarArgs: // TODO
10776 case ConstCastResultIdFnIsGeneric: // TODO
10777 case ConstCastResultIdFnReturnType: // TODO11010 case ConstCastResultIdFnReturnType: // TODO
10778 case ConstCastResultIdFnArgCount: // TODO11011 case ConstCastResultIdFnArgCount: // TODO
10779 case ConstCastResultIdFnGenericArgCount: // TODO11012 case ConstCastResultIdFnGenericArgCount: // TODO
10780 case ConstCastResultIdFnArgNoAlias: // TODO11013 case ConstCastResultIdFnArgNoAlias: // TODO
10781 case ConstCastResultIdUnresolvedInferredErrSet: // TODO11014 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
10782 case ConstCastResultIdAsyncAllocatorType: // TODO11015 case ConstCastResultIdAsyncAllocatorType: // TODO
10783 case ConstCastResultIdNullWrapPtr: // TODO
10784 break;11016 break;
10785 }11017 }
10786}11018}
...@@ -10811,6 +11043,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *...@@ -10811,6 +11043,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
10811 return ir_build_vector_to_array(ira, source_instr, vector, array_type);11043 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
10812}11044}
1081311045
11046static 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
10814static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,11079static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
10815 ZigType *wanted_type, IrInstruction *value)11080 ZigType *wanted_type, IrInstruction *value)
10816{11081{
...@@ -11182,7 +11447,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11182,7 +11447,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11182 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&11447 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
11183 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))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 }
1118811453
...@@ -11217,6 +11482,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11217,6 +11482,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11217 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);11482 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
11218 }11483 }
1121911484
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 // cast from undefined to anything11502 // cast from undefined to anything
11221 if (actual_type->id == ZigTypeIdUndefined) {11503 if (actual_type->id == ZigTypeIdUndefined) {
11222 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);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,13 +11568,14 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11286 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);11568 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
11287 return ref_inst->value;11569 return ref_inst->value;
11288 }11570 }
11289 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,11571 IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type);
11290 source_instruction->source_node, ptr);11572 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
11291 load_ptr_instruction->value.type = child_type;11573 ir_add_alloca(ira, result, child_type);
11292 return load_ptr_instruction;11574 }
11575 return result;
11293 } else {11576 } else {
11294 ir_add_error_node(ira, source_instruction->source_node,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 buf_ptr(&type_entry->name)));11579 buf_ptr(&type_entry->name)));
11297 return ira->codegen->invalid_instruction;11580 return ira->codegen->invalid_instruction;
11298 }11581 }
...@@ -11588,28 +11871,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -11588,28 +11871,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
11588}11871}
1158911872
11590static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {11873static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
11591 if (op_id == IrBinOpCmpEq) {11874 switch (op_id) {
11592 return cmp == CmpEQ;11875 case IrBinOpCmpEq:
11593 } else if (op_id == IrBinOpCmpNotEq) {11876 return cmp == CmpEQ;
11594 return cmp != CmpEQ;11877 case IrBinOpCmpNotEq:
11595 } else if (op_id == IrBinOpCmpLessThan) {11878 return cmp != CmpEQ;
11596 return cmp == CmpLT;11879 case IrBinOpCmpLessThan:
11597 } else if (op_id == IrBinOpCmpGreaterThan) {11880 return cmp == CmpLT;
11598 return cmp == CmpGT;11881 case IrBinOpCmpGreaterThan:
11599 } else if (op_id == IrBinOpCmpLessOrEq) {11882 return cmp == CmpGT;
11600 return cmp != CmpGT;11883 case IrBinOpCmpLessOrEq:
11601 } else if (op_id == IrBinOpCmpGreaterOrEq) {11884 return cmp != CmpGT;
11602 return cmp != CmpLT;11885 case IrBinOpCmpGreaterOrEq:
11603 } else {11886 return cmp != CmpLT;
11604 zig_unreachable();11887 default:
11888 zig_unreachable();
11605 }11889 }
11606}11890}
1160711891
11608static bool optional_value_is_null(ConstExprValue *val) {11892static bool optional_value_is_null(ConstExprValue *val) {
11609 assert(val->special == ConstValSpecialStatic);11893 assert(val->special == ConstValSpecialStatic);
11610 if (get_codegen_ptr_type(val->type) != nullptr) {11894 if (get_codegen_ptr_type(val->type) != nullptr) {
11611 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&11895 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
11612 val->data.x_ptr.data.hard_coded_addr.addr == 0;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 } else if (is_opt_err_set(val->type)) {11902 } else if (is_opt_err_set(val->type)) {
11614 return val->data.x_err_set == nullptr;11903 return val->data.x_err_set == nullptr;
11615 } else {11904 } else {
...@@ -11773,7 +12062,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11773,7 +12062,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11773 case ZigTypeIdBool:12062 case ZigTypeIdBool:
11774 case ZigTypeIdMetaType:12063 case ZigTypeIdMetaType:
11775 case ZigTypeIdVoid:12064 case ZigTypeIdVoid:
11776 case ZigTypeIdPointer:
11777 case ZigTypeIdErrorSet:12065 case ZigTypeIdErrorSet:
11778 case ZigTypeIdFn:12066 case ZigTypeIdFn:
11779 case ZigTypeIdOpaque:12067 case ZigTypeIdOpaque:
...@@ -11785,6 +12073,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11785,6 +12073,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11785 operator_allowed = is_equality_cmp;12073 operator_allowed = is_equality_cmp;
11786 break;12074 break;
1178712075
12076 case ZigTypeIdPointer:
12077 operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
12078 break;
12079
11788 case ZigTypeIdUnreachable:12080 case ZigTypeIdUnreachable:
11789 case ZigTypeIdArray:12081 case ZigTypeIdArray:
11790 case ZigTypeIdStruct:12082 case ZigTypeIdStruct:
...@@ -11832,15 +12124,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11832,15 +12124,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11832 if (op2_val == nullptr)12124 if (op2_val == nullptr)
11833 return ira->codegen->invalid_instruction;12125 return ira->codegen->invalid_instruction;
1183412126
11835 bool answer;
11836 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {12127 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
11837 Cmp cmp_result = float_cmp(op1_val, op2_val);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 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {12131 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
11840 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);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 } else {12156 } else {
11843 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);12157 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
12158 bool answer;
11844 if (op_id == IrBinOpCmpEq) {12159 if (op_id == IrBinOpCmpEq) {
11845 answer = are_equal;12160 answer = are_equal;
11846 } else if (op_id == IrBinOpCmpNotEq) {12161 } else if (op_id == IrBinOpCmpNotEq) {
...@@ -11848,9 +12163,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11848,9 +12163,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11848 } else {12163 } else {
11849 zig_unreachable();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 }
1185512169
11856 // some comparisons with unsigned numbers can be evaluated12170 // some comparisons with unsigned numbers can be evaluated
...@@ -12245,7 +12559,29 @@ static bool ok_float_op(IrBinOp op) {...@@ -12245,7 +12559,29 @@ static bool ok_float_op(IrBinOp op) {
12245 zig_unreachable();12559 zig_unreachable();
12246}12560}
1224712561
12562static 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
12248static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {12582static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12583 Error err;
12584
12249 IrInstruction *op1 = instruction->op1->child;12585 IrInstruction *op1 = instruction->op1->child;
12250 if (type_is_invalid(op1->value.type))12586 if (type_is_invalid(op1->value.type))
12251 return ira->codegen->invalid_instruction;12587 return ira->codegen->invalid_instruction;
...@@ -12257,23 +12593,54 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -12257,23 +12593,54 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
12257 IrBinOp op_id = instruction->op_id;12593 IrBinOp op_id = instruction->op_id;
1225812594
12259 // look for pointer math12595 // look for pointer math
12260 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&12596 if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
12261 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
12262 {
12263 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);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 return ira->codegen->invalid_instruction;12599 return ira->codegen->invalid_instruction;
1226612600
12267 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,12601 if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
12268 instruction->base.source_node, op_id, op1, casted_op2, true);12602 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12269 result->value.type = op1->value.type;12603 result->value.special = ConstValSpecialUndef;
12270 return result;12604 return result;
12271 }12605 }
1227212606 if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&
12273 IrInstruction *instructions[] = {op1, op2};12607 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
12274 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);12608 op1->value.data.x_ptr.special == ConstPtrSpecialNull))
12275 if (type_is_invalid(resolved_type))12609 {
12276 return ira->codegen->invalid_instruction;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;
1227712644
12278 bool is_int = resolved_type->id == ZigTypeIdInt || resolved_type->id == ZigTypeIdComptimeInt;12645 bool is_int = resolved_type->id == ZigTypeIdInt || resolved_type->id == ZigTypeIdComptimeInt;
12279 bool is_float = resolved_type->id == ZigTypeIdFloat || resolved_type->id == ZigTypeIdComptimeFloat;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,6 +13245,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
12878 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);13245 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
12879}13246}
1288013247
13248static 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
12881static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {13262static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
12882 IrInstruction *name = instruction->name->child;13263 IrInstruction *name = instruction->name->child;
12883 Buf *symbol_name = ir_resolve_str(ira, name);13264 Buf *symbol_name = ir_resolve_str(ira, name);
...@@ -12898,14 +13279,24 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12898,14 +13279,24 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12898 }13279 }
12899 }13280 }
1290013281
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 if (entry) {13291 if (entry) {
12903 AstNode *other_export_node = entry->value;13292 AstNode *other_export_node = entry->value->source_node;
12904 ErrorMsg *msg = ir_add_error(ira, &instruction->base,13293 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
12905 buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name)));13294 buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name)));
12906 add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here"));13295 add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here"));
13296 return ira->codegen->invalid_instruction;
12907 }13297 }
1290813298
13299 bool want_var_export = false;
12909 switch (target->value.type->id) {13300 switch (target->value.type->id) {
12910 case ZigTypeIdInvalid:13301 case ZigTypeIdInvalid:
12911 case ZigTypeIdUnreachable:13302 case ZigTypeIdUnreachable:
...@@ -12913,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12913,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12913 case ZigTypeIdFn: {13304 case ZigTypeIdFn: {
12914 assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction);13305 assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction);
12915 ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry;13306 ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry;
13307 tld_fn->fn_entry = fn_entry;
12916 CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc;13308 CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc;
12917 switch (cc) {13309 switch (cc) {
12918 case CallingConventionUnspecified: {13310 case CallingConventionUnspecified: {
...@@ -12941,6 +13333,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12941,6 +13333,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12941 ErrorMsg *msg = ir_add_error(ira, target,13333 ErrorMsg *msg = ir_add_error(ira, target,
12942 buf_sprintf("exported struct value must be declared extern"));13334 buf_sprintf("exported struct value must be declared extern"));
12943 add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here"));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 break;13339 break;
12946 case ZigTypeIdUnion:13340 case ZigTypeIdUnion:
...@@ -12948,6 +13342,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12948,6 +13342,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12948 ErrorMsg *msg = ir_add_error(ira, target,13342 ErrorMsg *msg = ir_add_error(ira, target,
12949 buf_sprintf("exported union value must be declared extern"));13343 buf_sprintf("exported union value must be declared extern"));
12950 add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here"));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 break;13348 break;
12953 case ZigTypeIdEnum:13349 case ZigTypeIdEnum:
...@@ -12955,6 +13351,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12955,6 +13351,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12955 ErrorMsg *msg = ir_add_error(ira, target,13351 ErrorMsg *msg = ir_add_error(ira, target,
12956 buf_sprintf("exported enum value must be declared extern"));13352 buf_sprintf("exported enum value must be declared extern"));
12957 add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here"));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 break;13357 break;
12960 case ZigTypeIdMetaType: {13358 case ZigTypeIdMetaType: {
...@@ -13044,6 +13442,16 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -13044,6 +13442,16 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
13044 break;13442 break;
13045 }13443 }
1304613444
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 return ir_const_void(ira, &instruction->base);13455 return ir_const_void(ira, &instruction->base);
13048}13456}
1304913457
...@@ -13331,9 +13739,16 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13331,9 +13739,16 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13331 if (var->var_type == nullptr || type_is_invalid(var->var_type))13739 if (var->var_type == nullptr || type_is_invalid(var->var_type))
13332 return ira->codegen->invalid_instruction;13740 return ira->codegen->invalid_instruction;
1333313741
13742 ConstExprValue *mem_slot = nullptr;
13743
13334 bool comptime_var_mem = ir_get_var_is_comptime(var);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;
1333513751
13336 ConstExprValue *mem_slot = nullptr;
13337 if (var->const_value->special == ConstValSpecialStatic) {13752 if (var->const_value->special == ConstValSpecialStatic) {
13338 mem_slot = var->const_value;13753 mem_slot = var->const_value;
13339 } else {13754 } else {
...@@ -13347,8 +13762,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13347,8 +13762,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13347 }13762 }
13348 }13763 }
1334913764
13350 bool is_const = var->src_is_const;
13351 bool is_volatile = false;
13352 if (mem_slot != nullptr) {13765 if (mem_slot != nullptr) {
13353 switch (mem_slot->special) {13766 switch (mem_slot->special) {
13354 case ConstValSpecialRuntime:13767 case ConstValSpecialRuntime:
...@@ -13387,26 +13800,32 @@ no_mem_slot:...@@ -13387,26 +13800,32 @@ no_mem_slot:
13387static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,13800static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
13388 IrInstruction *ptr, IrInstruction *uncasted_value)13801 IrInstruction *ptr, IrInstruction *uncasted_value)
13389{13802{
13390 if (ptr->value.type->id != ZigTypeIdPointer) {13803 assert(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 }
1339513804
13396 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {13805 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
13397 return ir_const_void(ira, source_instr);13806 return ir_const_void(ira, source_instr);
13398 }13807 }
1339913808
13809 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13810
13400 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {13811 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
13401 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));13812 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13402 return ira->codegen->invalid_instruction;13813 return ira->codegen->invalid_instruction;
13403 }13814 }
1340413815
13405 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13406 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);13816 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13407 if (value == ira->codegen->invalid_instruction)13817 if (value == ira->codegen->invalid_instruction)
13408 return ira->codegen->invalid_instruction;13818 return ira->codegen->invalid_instruction;
1340913819
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 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {13829 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13411 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {13830 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
13412 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));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,15 +13846,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
13427 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;13846 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
13428 copy_const_val(dest_val, &value->value, same_global_refs);13847 copy_const_val(dest_val, &value->value, same_global_refs);
13429 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {13848 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13430 switch (type_has_one_possible_value(ira->codegen, child_type)) {13849 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
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 }
13439 }13850 }
13440 return ir_const_void(ira, source_instr);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,7 +14041,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13630 AstNode *body_node = fn_entry->body_node;14041 AstNode *body_node = fn_entry->body_node;
13631 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,14042 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
13632 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,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);
1363414045
13635 if (inferred_err_set_type != nullptr) {14046 if (inferred_err_set_type != nullptr) {
13636 inferred_err_set_type->data.error_set.infer_fn = nullptr;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,7 +14237,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13826 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,14237 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
13827 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),14238 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
13828 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,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 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,14241 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
13831 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);14242 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
13832 const_instruction->base.value = *align_result;14243 const_instruction->base.value = *align_result;
...@@ -14108,12 +14519,11 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -14108,12 +14519,11 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
14108 size_t src_size = type_size(codegen, pointee->type);14519 size_t src_size = type_size(codegen, pointee->type);
14109 size_t dst_size = type_size(codegen, out_val->type);14520 size_t dst_size = type_size(codegen, out_val->type);
1411014521
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 if (dst_size <= src_size) {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 Buf buf = BUF_INIT;14527 Buf buf = BUF_INIT;
14118 buf_resize(&buf, src_size);14528 buf_resize(&buf, src_size);
14119 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);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,12 +14539,12 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
14129 if (dst_size == 0)14539 if (dst_size == 0)
14130 return ErrorNone;14540 return ErrorNone;
14131 opt_ir_add_error_node(ira, codegen, source_node,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 dst_size));14543 dst_size));
14134 return ErrorSemanticAnalyzeFail;14544 return ErrorSemanticAnalyzeFail;
14135 case ConstPtrSpecialRef: {14545 case ConstPtrSpecialRef: {
14136 opt_ir_add_error_node(ira, codegen, source_node,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 dst_size, buf_ptr(&pointee->type->name), src_size));14548 dst_size, buf_ptr(&pointee->type->name), src_size));
14139 return ErrorSemanticAnalyzeFail;14549 return ErrorSemanticAnalyzeFail;
14140 }14550 }
...@@ -14148,7 +14558,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -14148,7 +14558,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
14148 src_size = elem_size * (array_val->type->data.array.len - elem_index);14558 src_size = elem_size * (array_val->type->data.array.len - elem_index);
14149 if (dst_size > src_size) {14559 if (dst_size > src_size) {
14150 opt_ir_add_error_node(ira, codegen, source_node,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 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));14562 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
14153 return ErrorSemanticAnalyzeFail;14563 return ErrorSemanticAnalyzeFail;
14154 }14564 }
...@@ -14220,6 +14630,41 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_...@@ -14220,6 +14630,41 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
14220 zig_unreachable();14630 zig_unreachable();
14221}14631}
1422214632
14633static 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
14223static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) {14668static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) {
14224 IrInstruction *value = instruction->value->child;14669 IrInstruction *value = instruction->value->child;
14225 ZigType *expr_type = value->value.type;14670 ZigType *expr_type = value->value.type;
...@@ -14228,47 +14673,50 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins...@@ -14228,47 +14673,50 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins
1422814673
14229 bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);14674 bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
1423014675
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;
1423214677
14233 if ((expr_type->id == ZigTypeIdInt && expr_type->data.integral.is_signed) ||14678 if (instr_is_comptime(value)) {
14234 expr_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op))14679 ConstExprValue *operand_val = ir_resolve_const(ira, value, UndefBad);
14235 {14680 if (!operand_val)
14236 if (instr_is_comptime(value)) {14681 return ira->codegen->invalid_instruction;
14237 ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
14238 if (!target_const_val)
14239 return ira->codegen->invalid_instruction;
1424014682
14241 IrInstruction *result = ir_const(ira, &instruction->base, expr_type);14683 IrInstruction *result_instruction = ir_const(ira, &instruction->base, expr_type);
14242 ConstExprValue *out_val = &result->value;14684 ConstExprValue *out_val = &result_instruction->value;
14243 if (is_float) {14685 if (expr_type->id == ZigTypeIdVector) {
14244 float_negate(out_val, target_const_val);14686 expand_undef_array(ira->codegen, operand_val);
14245 } else if (is_wrap_op) {14687 out_val->special = ConstValSpecialUndef;
14246 bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint,14688 expand_undef_array(ira->codegen, out_val);
14247 expr_type->data.integral.bit_count);14689 size_t len = expr_type->data.vector.len;
14248 } else {14690 for (size_t i = 0; i < len; i += 1) {
14249 bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);14691 ConstExprValue *scalar_operand_val = &operand_val->data.x_array.data.s_none.elements[i];
14250 }14692 ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
14251 if (is_wrap_op || is_float || expr_type->id == ZigTypeIdComptimeInt) {14693 assert(scalar_operand_val->type == scalar_type);
14252 return result;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 }
1425414703 out_val->type = expr_type;
14255 if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {14704 out_val->special = ConstValSpecialStatic;
14256 ir_add_error(ira, &instruction->base, buf_sprintf("negation caused overflow"));14705 } else {
14706 if (ir_eval_negation_scalar(ira, &instruction->base, scalar_type, operand_val, out_val,
14707 is_wrap_op) != nullptr)
14708 {
14257 return ira->codegen->invalid_instruction;14709 return ira->codegen->invalid_instruction;
14258 }14710 }
14259 return result;
14260 }14711 }
1426114712 return result_instruction;
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;
14267 }14713 }
1426814714
14269 const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";14715 IrInstruction *result = ir_build_un_op(&ira->new_irb,
14270 ir_add_error(ira, &instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));14716 instruction->base.scope, instruction->base.source_node,
14271 return ira->codegen->invalid_instruction;14717 instruction->op_id, value);
14718 result->value.type = expr_type;
14719 return result;
14272}14720}
1427314721
14274static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {14722static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
...@@ -14321,11 +14769,18 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction...@@ -14321,11 +14769,18 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
14321 buf_ptr(&ptr_type->name)));14769 buf_ptr(&ptr_type->name)));
14322 return ira->codegen->invalid_instruction;14770 return ira->codegen->invalid_instruction;
14323 }14771 }
14324 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit14772
14325 // one of the ptr instructions
14326 IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);14773 IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);
14327 if (result == ira->codegen->invalid_instruction)14774 if (result == ira->codegen->invalid_instruction)
14328 return ira->codegen->invalid_instruction;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 return result;14784 return result;
14330 }14785 }
14331 case IrUnOpOptional:14786 case IrUnOpOptional:
...@@ -14958,6 +15413,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -14958,6 +15413,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
14958 if (bare_type->id == ZigTypeIdStruct) {15413 if (bare_type->id == ZigTypeIdStruct) {
14959 TypeStructField *field = find_struct_type_field(bare_type, field_name);15414 TypeStructField *field = find_struct_type_field(bare_type, field_name);
14960 if (field) {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 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);15426 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
14962 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);15427 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
14963 uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;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,6 +15530,14 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
15065}15530}
1506615531
15067static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {15532static 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 LinkLib *link_lib = add_link_lib(ira->codegen, lib_name);15541 LinkLib *link_lib = add_link_lib(ira->codegen, lib_name);
15069 for (size_t i = 0; i < link_lib->symbols.length; i += 1) {15542 for (size_t i = 0; i < link_lib->symbols.length; i += 1) {
15070 Buf *existing_symbol_name = link_lib->symbols.at(i);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,12 +15624,6 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
15151 if (type_is_invalid(container_ptr->value.type))15624 if (type_is_invalid(container_ptr->value.type))
15152 return ira->codegen->invalid_instruction;15625 return ira->codegen->invalid_instruction;
1515315626
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 ZigType *container_type = container_ptr->value.type->data.pointer.child_type;15627 ZigType *container_type = container_ptr->value.type->data.pointer.child_type;
1516115628
15162 Buf *field_name = field_ptr_instruction->field_name_buffer;15629 Buf *field_name = field_ptr_instruction->field_name_buffer;
...@@ -15572,6 +16039,8 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio...@@ -15572,6 +16039,8 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
15572static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,16039static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
15573 IrInstructionToPtrType *to_ptr_type_instruction)16040 IrInstructionToPtrType *to_ptr_type_instruction)
15574{16041{
16042 Error err;
16043
15575 IrInstruction *value = to_ptr_type_instruction->value->child;16044 IrInstruction *value = to_ptr_type_instruction->value->child;
15576 ZigType *type_entry = value->value.type;16045 ZigType *type_entry = value->value.type;
15577 if (type_is_invalid(type_entry))16046 if (type_is_invalid(type_entry))
...@@ -15587,7 +16056,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,...@@ -15587,7 +16056,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
15587 ptr_type = get_pointer_to_type(ira->codegen,16056 ptr_type = get_pointer_to_type(ira->codegen,
15588 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);16057 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
15589 } else if (is_slice(type_entry)) {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 } else if (type_entry->id == ZigTypeIdArgTuple) {16070 } else if (type_entry->id == ZigTypeIdArgTuple) {
15592 ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);16071 ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
15593 if (!arg_tuple_val)16072 if (!arg_tuple_val)
...@@ -16355,18 +16834,13 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16355,18 +16834,13 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16355 return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type);16834 return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type);
16356 }16835 }
1635716836
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 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;16837 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
16364 ConstExprValue *pointee_val = nullptr;16838 ConstExprValue *pointee_val = nullptr;
16365 if (instr_is_comptime(target_value_ptr)) {16839 if (instr_is_comptime(target_value_ptr)) {
16366 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);16840 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
16367 if (pointee_val == nullptr)16841 if (pointee_val == nullptr)
16368 return ira->codegen->invalid_instruction;16842 return ira->codegen->invalid_instruction;
16369 16843
16370 if (pointee_val->special == ConstValSpecialRuntime)16844 if (pointee_val->special == ConstValSpecialRuntime)
16371 pointee_val = nullptr;16845 pointee_val = nullptr;
16372 }16846 }
...@@ -16953,9 +17427,13 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr...@@ -16953,9 +17427,13 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr
16953 }17427 }
16954 fprintf(stderr, "\n");17428 fprintf(stderr, "\n");
1695517429
16956 // Here we bypass higher level functions such as ir_add_error because we do not want17430 auto *expr = &instruction->base.source_node->data.fn_call_expr;
16957 // invalidate_exec to be called.17431 if (!expr->seen) {
16958 add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));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;
1695917437
16960 return ir_const_void(ira, &instruction->base);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,7 +17594,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
17116static TypeStructField *validate_byte_offset(IrAnalyze *ira,17594static TypeStructField *validate_byte_offset(IrAnalyze *ira,
17117 IrInstruction *type_value,17595 IrInstruction *type_value,
17118 IrInstruction *field_name_value,17596 IrInstruction *field_name_value,
17119 size_t *byte_offset) 17597 size_t *byte_offset)
17120{17598{
17121 ZigType *container_type = ir_resolve_type(ira, type_value);17599 ZigType *container_type = ir_resolve_type(ira, type_value);
17122 if (type_is_invalid(container_type))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,7 +17768,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1729017768
17291 // Loop through the definitions and generate info.17769 // Loop through the definitions and generate info.
17292 decl_it = decls_scope->decl_table.entry_iterator();17770 decl_it = decls_scope->decl_table.entry_iterator();
17293 curr_entry = nullptr; 17771 curr_entry = nullptr;
17294 int definition_index = 0;17772 int definition_index = 0;
17295 while ((curr_entry = decl_it.next()) != nullptr) {17773 while ((curr_entry = decl_it.next()) != nullptr) {
17296 // Skip comptime blocks and test functions.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,6 +17947,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17469 return ErrorNone;17947 return ErrorNone;
17470}17948}
1747117949
17950static 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
17472static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {17962static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
17473 Error err;17963 Error err;
17474 ZigType *attrs_type;17964 ZigType *attrs_type;
...@@ -17478,7 +17968,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -17478,7 +17968,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
17478 size_enum_index = 2;17968 size_enum_index = 2;
17479 } else if (ptr_type_entry->id == ZigTypeIdPointer) {17969 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
17480 attrs_type = ptr_type_entry;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 } else {17972 } else {
17483 zig_unreachable();17973 zig_unreachable();
17484 }17974 }
...@@ -18172,12 +18662,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,...@@ -18172,12 +18662,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
18172static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,18662static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
18173 IrInstructionSetEvalBranchQuota *instruction)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 uint64_t new_quota;18665 uint64_t new_quota;
18182 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))18666 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
18183 return ira->codegen->invalid_instruction;18667 return ira->codegen->invalid_instruction;
...@@ -18204,12 +18688,6 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc...@@ -18204,12 +18688,6 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc
18204}18688}
1820518689
18206static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {18690static 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 AstNode *node = instruction->base.source_node;18691 AstNode *node = instruction->base.source_node;
18214 assert(node->type == NodeTypeFnCallExpr);18692 assert(node->type == NodeTypeFnCallExpr);
18215 AstNode *block_node = node->data.fn_call_expr.params.at(0);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,12 +18698,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
18220 ZigType *void_type = ira->codegen->builtin_types.entry_void;18698 ZigType *void_type = ira->codegen->builtin_types.entry_void;
18221 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,18699 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
18222 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,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 if (type_is_invalid(cimport_result->type))18702 if (type_is_invalid(cimport_result->type))
18225 return ira->codegen->invalid_instruction;18703 return ira->codegen->invalid_instruction;
1822618704
18227 find_libc_include_path(ira->codegen);
18228
18229 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);18705 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
18230 child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);18706 child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);
18231 child_import->c_import_node = node;18707 child_import->c_import_node = node;
...@@ -18247,6 +18723,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -18247,6 +18723,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1824718723
18248 if (errors.length > 0) {18724 if (errors.length > 0) {
18249 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));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 for (size_t i = 0; i < errors.length; i += 1) {18730 for (size_t i = 0; i < errors.length; i += 1) {
18251 ErrorMsg *err_msg = errors.at(i);18731 ErrorMsg *err_msg = errors.at(i);
18252 err_msg_add_note(parent_err_msg, err_msg);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,7 +19193,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
18713 }19193 }
18714 }19194 }
1871519195
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}
1871819200
18719static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {19201static 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,7 +19222,34 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
18740 alignment, 0, 0);19222 alignment, 0, 0);
18741 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);19223 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
1874219224
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}
1874519254
18746static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {19255static 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,10 +19461,12 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
18952 if (type_is_invalid(casted_count->value.type))19461 if (type_is_invalid(casted_count->value.type))
18953 return ira->codegen->invalid_instruction;19462 return ira->codegen->invalid_instruction;
1895419463
19464 // TODO test this at comptime with u8 and non-u8 types
18955 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&19465 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
18956 casted_byte->value.special == ConstValSpecialStatic &&19466 casted_byte->value.special == ConstValSpecialStatic &&
18957 casted_count->value.special == ConstValSpecialStatic &&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 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;19471 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;
1896119472
...@@ -19074,6 +19585,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -19074,6 +19585,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
19074 if (type_is_invalid(casted_count->value.type))19585 if (type_is_invalid(casted_count->value.type))
19075 return ira->codegen->invalid_instruction;19586 return ira->codegen->invalid_instruction;
1907619587
19588 // TODO test this at comptime with u8 and non-u8 types
19589 // TODO test with dest ptr being a global runtime variable
19077 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&19590 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
19078 casted_src_ptr->value.special == ConstValSpecialStatic &&19591 casted_src_ptr->value.special == ConstValSpecialStatic &&
19079 casted_count->value.special == ConstValSpecialStatic &&19592 casted_count->value.special == ConstValSpecialStatic &&
...@@ -20242,7 +20755,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,...@@ -20242,7 +20755,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
20242 } else {20755 } else {
20243 seenFalse += 1;20756 seenFalse += 1;
20244 }20757 }
20245 20758
20246 if ((seenTrue > 1) || (seenFalse > 1)) {20759 if ((seenTrue > 1) || (seenFalse > 1)) {
20247 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));20760 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
20248 return ira->codegen->invalid_instruction;20761 return ira->codegen->invalid_instruction;
...@@ -20375,7 +20888,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -20375,7 +20888,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
20375}20888}
2037620889
20377static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,20890static 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 Error err;20893 Error err;
2038120894
...@@ -20385,12 +20898,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20385,12 +20898,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20385 // We have a check for zero bits later so we use get_src_ptr_type to20898 // We have a check for zero bits later so we use get_src_ptr_type to
20386 // validate src_type and dest_type.20899 // validate src_type and dest_type.
2038720900
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 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));20903 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
20390 return ira->codegen->invalid_instruction;20904 return ira->codegen->invalid_instruction;
20391 }20905 }
2039220906
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 ir_add_error(ira, dest_type_src,20909 ir_add_error(ira, dest_type_src,
20395 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));20910 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
20396 return ira->codegen->invalid_instruction;20911 return ira->codegen->invalid_instruction;
...@@ -20400,25 +20915,44 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20400,25 +20915,44 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20400 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));20915 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
20401 return ira->codegen->invalid_instruction;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;
2040320925
20404 if (instr_is_comptime(ptr)) {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 if (!val)20930 if (!val)
20407 return ira->codegen->invalid_instruction;20931 return ira->codegen->invalid_instruction;
2040820932
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 IrInstruction *result = ir_const(ira, source_instr, dest_type);20944 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20410 copy_const_val(&result->value, val, false);20945 copy_const_val(&result->value, val, false);
20411 result->value.type = dest_type;20946 result->value.type = dest_type;
20412 return result;
20413 }
2041420947
20415 uint32_t src_align_bytes;20948 // Keep the bigger alignment, it can only help-
20416 if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))20949 // unless the target is zero bits.
20417 return ira->codegen->invalid_instruction;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 }
2041820953
20419 uint32_t dest_align_bytes;20954 return result;
20420 if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))20955 }
20421 return ira->codegen->invalid_instruction;
2042220956
20423 if (dest_align_bytes > src_align_bytes) {20957 if (dest_align_bytes > src_align_bytes) {
20424 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));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,7 +20963,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20429 return ira->codegen->invalid_instruction;20963 return ira->codegen->invalid_instruction;
20430 }20964 }
2043120965
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);
2043320967
20434 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {20968 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
20435 ErrorMsg *msg = ir_add_error(ira, source_instr,20969 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -20466,7 +21000,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct...@@ -20466,7 +21000,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
20466 if (type_is_invalid(src_type))21000 if (type_is_invalid(src_type))
20467 return ira->codegen->invalid_instruction;21001 return ira->codegen->invalid_instruction;
2046821002
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}
2047121006
20472static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {21007static 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,7 +21064,79 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20529 case ZigTypeIdVector:21064 case ZigTypeIdVector:
20530 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);21065 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
20531 case ZigTypeIdStruct: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 case ZigTypeIdOptional:21140 case ZigTypeIdOptional:
20534 zig_panic("TODO buf_write_value_bytes maybe type");21141 zig_panic("TODO buf_write_value_bytes maybe type");
20535 case ZigTypeIdErrorUnion:21142 case ZigTypeIdErrorUnion:
...@@ -20656,8 +21263,62 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20656,8 +21263,62 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20656 }21263 }
20657 return ErrorNone;21264 return ErrorNone;
20658 }21265 }
20659 case ContainerLayoutPacked:21266 case ContainerLayoutPacked: {
20660 zig_panic("TODO buf_read_value_bytes packed struct");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 zig_unreachable();21323 zig_unreachable();
20663 case ZigTypeIdOptional:21324 case ZigTypeIdOptional:
...@@ -20674,32 +21335,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20674,32 +21335,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20674 zig_unreachable();21335 zig_unreachable();
20675}21336}
2067621337
20677static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {21338static bool type_can_bit_cast(ZigType *t) {
20678 Error err;21339 switch (t->id) {
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) {
20702 case ZigTypeIdInvalid:21340 case ZigTypeIdInvalid:
21341 zig_unreachable();
20703 case ZigTypeIdMetaType:21342 case ZigTypeIdMetaType:
20704 case ZigTypeIdOpaque:21343 case ZigTypeIdOpaque:
20705 case ZigTypeIdBoundFn:21344 case ZigTypeIdBoundFn:
...@@ -20710,42 +21349,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20710,42 +21349,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20710 case ZigTypeIdComptimeInt:21349 case ZigTypeIdComptimeInt:
20711 case ZigTypeIdUndefined:21350 case ZigTypeIdUndefined:
20712 case ZigTypeIdNull:21351 case ZigTypeIdNull:
20713 ir_add_error(ira, dest_type_value,21352 case ZigTypeIdPointer:
20714 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));21353 return false;
20715 return ira->codegen->invalid_instruction;
20716 default: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}
2071921359
20720 if (get_codegen_ptr_type(dest_type) != nullptr) {21360static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20721 ir_add_error(ira, dest_type_value,21361 ZigType *dest_type)
20722 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));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 return ira->codegen->invalid_instruction;21375 return ira->codegen->invalid_instruction;
20724 }
2072521376
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 }
2074421377
20745 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);21378 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
20746 uint64_t src_size_bytes = type_size(ira->codegen, src_type);21379 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
20747 if (dest_size_bytes != src_size_bytes) {21380 if (dest_size_bytes != src_size_bytes) {
20748 ir_add_error(ira, &instruction->base,21381 ir_add_error(ira, source_instr,
20749 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,21382 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
20750 buf_ptr(&dest_type->name), dest_size_bytes,21383 buf_ptr(&dest_type->name), dest_size_bytes,
20751 buf_ptr(&src_type->name), src_size_bytes));21384 buf_ptr(&src_type->name), src_size_bytes));
...@@ -20755,7 +21388,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20755,7 +21388,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20755 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);21388 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
20756 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);21389 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
20757 if (dest_size_bits != src_size_bits) {21390 if (dest_size_bits != src_size_bits) {
20758 ir_add_error(ira, &instruction->base,21391 ir_add_error(ira, source_instr,
20759 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",21392 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
20760 buf_ptr(&dest_type->name), dest_size_bits,21393 buf_ptr(&dest_type->name), dest_size_bits,
20761 buf_ptr(&src_type->name), src_size_bits));21394 buf_ptr(&src_type->name), src_size_bits));
...@@ -20767,44 +21400,64 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20767,44 +21400,64 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20767 if (!val)21400 if (!val)
20768 return ira->codegen->invalid_instruction;21401 return ira->codegen->invalid_instruction;
2076921402
20770 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);21403 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20771 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);21404 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
20772 buf_write_value_bytes(ira->codegen, buf, val);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 return ira->codegen->invalid_instruction;21407 return ira->codegen->invalid_instruction;
20775 return result;21408 return result;
20776 }21409 }
2077721410
20778 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,21411 IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
20779 instruction->base.source_node, nullptr, value);21412 if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) {
20780 result->value.type = dest_type;21413 ir_add_alloca(ira, result, dest_type);
21414 }
20781 return result;21415 return result;
20782}21416}
2078321417
20784static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {21418static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20785 Error err;
20786 IrInstruction *dest_type_value = instruction->dest_type->child;21419 IrInstruction *dest_type_value = instruction->dest_type->child;
20787 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);21420 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20788 if (type_is_invalid(dest_type))21421 if (type_is_invalid(dest_type))
20789 return ira->codegen->invalid_instruction;21422 return ira->codegen->invalid_instruction;
2079021423
20791 // We explicitly check for the size, so we can use get_src_ptr_type21424 IrInstruction *value = instruction->value->child;
20792 if (get_src_ptr_type(dest_type) == nullptr) {21425 ZigType *src_type = value->value.type;
20793 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));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 return ira->codegen->invalid_instruction;21432 return ira->codegen->invalid_instruction;
20795 }21433 }
2079621434
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 return ira->codegen->invalid_instruction;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 ir_add_error(ira, dest_type_value,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 return ira->codegen->invalid_instruction;21444 return ira->codegen->invalid_instruction;
20803 }21445 }
2080421446
20805 IrInstruction *target = instruction->target->child;21447 if (!type_can_bit_cast(dest_type)) {
20806 if (type_is_invalid(target->value.type))21448 ir_add_error(ira, dest_type_value,
21449 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20807 return ira->codegen->invalid_instruction;21450 return ira->codegen->invalid_instruction;
21451 }
21452
21453 return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
21454}
21455
21456static 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));
2080821461
20809 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);21462 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
20810 if (type_is_invalid(casted_int->value.type))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,19 +21468,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
20815 if (!val)21468 if (!val)
20816 return ira->codegen->invalid_instruction;21469 return ira->codegen->invalid_instruction;
2081721470
20818 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);21471 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
20819 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;21472 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
20820 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;21473 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
20821 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);21474 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
20822 return result;21475 return result;
20823 }21476 }
2082421477
20825 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,21478 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
20826 instruction->base.source_node, nullptr, casted_int);21479 source_instr->source_node, nullptr, casted_int);
20827 result->value.type = dest_type;21480 result->value.type = ptr_type;
20828 return result;21481 return result;
20829}21482}
2083021483
21484static 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
20831static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,21513static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20832 IrInstructionDeclRef *instruction)21514 IrInstructionDeclRef *instruction)
20833{21515{
...@@ -20931,6 +21613,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -20931,6 +21613,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
20931 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {21613 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
20932 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));21614 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
20933 return ira->codegen->invalid_instruction;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 }
2093521626
20936 uint32_t align_bytes;21627 uint32_t align_bytes;
...@@ -21068,20 +21759,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct...@@ -21068,20 +21759,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct
2106821759
21069 return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);21760 return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);
21070 } else if (enum_type->id == ZigTypeIdUnion) {21761 } else if (enum_type->id == ZigTypeIdUnion) {
21071 if ((err = ensure_complete_type(ira->codegen, enum_type)))21762 ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target, enum_type);
21072 return ira->codegen->invalid_instruction;21763 if (type_is_invalid(tag_type))
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"));
21083 return ira->codegen->invalid_instruction;21764 return ira->codegen->invalid_instruction;
21084 }21765 return ir_const_type(ira, &instruction->base, tag_type);
21085 } else {21766 } else {
21086 ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'",21767 ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'",
21087 buf_ptr(&enum_type->name)));21768 buf_ptr(&enum_type->name)));
...@@ -21662,23 +22343,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr...@@ -21662,23 +22343,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr
2166222343
2166322344
21664static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {22345static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
21665 Error err;
21666 IrInstruction *target = instruction->target->child;22346 IrInstruction *target = instruction->target->child;
21667 if (type_is_invalid(target->value.type))22347 if (type_is_invalid(target->value.type))
21668 return ira->codegen->invalid_instruction;22348 return ira->codegen->invalid_instruction;
2166922349
21670 if (target->value.type->id != ZigTypeIdEnum) {22350 return ir_analyze_enum_to_int(ira, &instruction->base, target);
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);
21682}22351}
2168322352
21684static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {22353static 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,6 +22419,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21750 case IrInstructionIdArrayToVector:22419 case IrInstructionIdArrayToVector:
21751 case IrInstructionIdVectorToArray:22420 case IrInstructionIdVectorToArray:
21752 case IrInstructionIdAssertZero:22421 case IrInstructionIdAssertZero:
22422 case IrInstructionIdResizeSlice:
22423 case IrInstructionIdLoadPtrGen:
22424 case IrInstructionIdBitCastGen:
21753 zig_unreachable();22425 zig_unreachable();
2175422426
21755 case IrInstructionIdReturn:22427 case IrInstructionIdReturn:
...@@ -22149,12 +22821,14 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -22149,12 +22821,14 @@ bool ir_has_side_effects(IrInstruction *instruction) {
22149 case IrInstructionIdCmpxchgGen:22821 case IrInstructionIdCmpxchgGen:
22150 case IrInstructionIdCmpxchgSrc:22822 case IrInstructionIdCmpxchgSrc:
22151 case IrInstructionIdAssertZero:22823 case IrInstructionIdAssertZero:
22824 case IrInstructionIdResizeSlice:
22152 return true;22825 return true;
2215322826
22154 case IrInstructionIdPhi:22827 case IrInstructionIdPhi:
22155 case IrInstructionIdUnOp:22828 case IrInstructionIdUnOp:
22156 case IrInstructionIdBinOp:22829 case IrInstructionIdBinOp:
22157 case IrInstructionIdLoadPtr:22830 case IrInstructionIdLoadPtr:
22831 case IrInstructionIdLoadPtrGen:
22158 case IrInstructionIdConst:22832 case IrInstructionIdConst:
22159 case IrInstructionIdCast:22833 case IrInstructionIdCast:
22160 case IrInstructionIdContainerInitList:22834 case IrInstructionIdContainerInitList:
...@@ -22205,6 +22879,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -22205,6 +22879,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
22205 case IrInstructionIdPtrCastSrc:22879 case IrInstructionIdPtrCastSrc:
22206 case IrInstructionIdPtrCastGen:22880 case IrInstructionIdPtrCastGen:
22207 case IrInstructionIdBitCast:22881 case IrInstructionIdBitCast:
22882 case IrInstructionIdBitCastGen:
22208 case IrInstructionIdWidenOrShorten:22883 case IrInstructionIdWidenOrShorten:
22209 case IrInstructionIdPtrToInt:22884 case IrInstructionIdPtrToInt:
22210 case IrInstructionIdIntToPtr:22885 case IrInstructionIdIntToPtr:
src/ir.hpp+1-1
...@@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);...@@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 IrExecutable *parent_exec);19 IrExecutable *parent_exec, AstNode *expected_type_source_node);
2020
21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
22 ZigType *expected_type, AstNode *expected_type_source_node);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,6 +336,11 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
336 fprintf(irp->f, ".*");336 fprintf(irp->f, ".*");
337}337}
338338
339static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) {
340 ir_print_other_instruction(irp, instruction->ptr);
341 fprintf(irp->f, ".*");
342}
343
339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {344static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
340 fprintf(irp->f, "*");345 fprintf(irp->f, "*");
341 ir_print_var_instruction(irp, instruction->ptr);346 ir_print_var_instruction(irp, instruction->ptr);
...@@ -915,14 +920,18 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc...@@ -915,14 +920,18 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
915920
916static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {921static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
917 fprintf(irp->f, "@bitCast(");922 fprintf(irp->f, "@bitCast(");
918 if (instruction->dest_type) {923 ir_print_other_instruction(irp, instruction->dest_type);
919 ir_print_other_instruction(irp, instruction->dest_type);
920 }
921 fprintf(irp->f, ",");924 fprintf(irp->f, ",");
922 ir_print_other_instruction(irp, instruction->value);925 ir_print_other_instruction(irp, instruction->value);
923 fprintf(irp->f, ")");926 fprintf(irp->f, ")");
924}927}
925928
929static 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
926static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {935static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
927 fprintf(irp->f, "WidenOrShorten(");936 fprintf(irp->f, "WidenOrShorten(");
928 ir_print_other_instruction(irp, instruction->target);937 ir_print_other_instruction(irp, instruction->target);
...@@ -990,6 +999,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct...@@ -990,6 +999,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct
990 fprintf(irp->f, ")");999 fprintf(irp->f, ")");
991}1000}
9921001
1002static 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
993static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {1008static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
994 fprintf(irp->f, "inttoerr ");1009 fprintf(irp->f, "inttoerr ");
995 ir_print_other_instruction(irp, instruction->target);1010 ir_print_other_instruction(irp, instruction->target);
...@@ -1462,6 +1477,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1462,6 +1477,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1462 case IrInstructionIdLoadPtr:1477 case IrInstructionIdLoadPtr:
1463 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);1478 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
1464 break;1479 break;
1480 case IrInstructionIdLoadPtrGen:
1481 ir_print_load_ptr_gen(irp, (IrInstructionLoadPtrGen *)instruction);
1482 break;
1465 case IrInstructionIdStorePtr:1483 case IrInstructionIdStorePtr:
1466 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);1484 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
1467 break;1485 break;
...@@ -1678,6 +1696,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1678,6 +1696,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1678 case IrInstructionIdBitCast:1696 case IrInstructionIdBitCast:
1679 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);1697 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
1680 break;1698 break;
1699 case IrInstructionIdBitCastGen:
1700 ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
1701 break;
1681 case IrInstructionIdWidenOrShorten:1702 case IrInstructionIdWidenOrShorten:
1682 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);1703 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
1683 break;1704 break;
...@@ -1852,6 +1873,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1852,6 +1873,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1852 case IrInstructionIdAssertZero:1873 case IrInstructionIdAssertZero:
1853 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);1874 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
1854 break;1875 break;
1876 case IrInstructionIdResizeSlice:
1877 ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
1878 break;
1855 }1879 }
1856 fprintf(irp->f, "\n");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
13static 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
24static const size_t zig_libc_keys_len = array_length(zig_libc_keys);
25
26static 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
35static 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
47Error 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)
171static 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}
181static 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}
193static 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}
205static 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}
215static 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
243static 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)
329static 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}
363static 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}
366static 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
370static 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
375static 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
402void 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
451Error 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
18struct 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
29Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file,
30 const ZigTarget *target, bool verbose);
31void zig_libc_render(ZigLibCInstallation *self, FILE *file);
32
33Error 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,32 +17,33 @@ struct LinkJob {
17 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;17 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
18};18};
1919
20static const char *get_libc_file(CodeGen *g, const char *file) {20static const char *get_libc_crt_file(CodeGen *g, const char *file) {
21 assert(g->libc != nullptr);
21 Buf *out_buf = buf_alloc();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 return buf_ptr(out_buf);24 return buf_ptr(out_buf);
24}25}
2526
26static const char *get_libc_static_file(CodeGen *g, const char *file) {27static const char *get_libc_static_file(CodeGen *g, const char *file) {
28 assert(g->libc != nullptr);
27 Buf *out_buf = buf_alloc();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 return buf_ptr(out_buf);31 return buf_ptr(out_buf);
30}32}
3133
32static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {34static 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 // The Mach-O LLD code is not well maintained, and trips an assertion35 // The Mach-O LLD code is not well maintained, and trips an assertion
36 // when we link compiler_rt and builtin as libraries rather than objects.36 // when we link compiler_rt and builtin as libraries rather than objects.
37 // Here we workaround this by having compiler_rt and builtin be objects.37 // Here we workaround this by having compiler_rt and builtin be objects.
38 // TODO write our own linker. https://github.com/ziglang/zig/issues/153538 // TODO write our own linker. https://github.com/ziglang/zig/issues/1535
39 OutType child_out_type = OutTypeLib;39 OutType child_out_type = OutTypeLib;
40 if (parent_gen->zig_target.os == OsMacOSX) {40 if (parent_gen->zig_target->os == OsMacOSX) {
41 child_out_type = OutTypeObj;41 child_out_type = OutTypeObj;
42 }42 }
4343
44 CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,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);45 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir,
46 parent_gen->libc);
4647
47 child_gen->out_h_path = nullptr;48 child_gen->out_h_path = nullptr;
48 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;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,6 +56,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
55 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);56 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
56 codegen_set_is_static(child_gen, true);57 codegen_set_is_static(child_gen, true);
57 child_gen->disable_pic = parent_gen->disable_pic;58 child_gen->disable_pic = parent_gen->disable_pic;
59 child_gen->valgrind_support = ValgrindSupportDisabled;
5860
59 codegen_set_out_name(child_gen, buf_create_from_str(aname));61 codegen_set_out_name(child_gen, buf_create_from_str(aname));
6062
...@@ -94,7 +96,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {...@@ -94,7 +96,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {
94}96}
9597
96static const char *get_darwin_arch_string(const ZigTarget *t) {98static const char *get_darwin_arch_string(const ZigTarget *t) {
97 switch (t->arch.arch) {99 switch (t->arch) {
98 case ZigLLVM_aarch64:100 case ZigLLVM_aarch64:
99 return "arm64";101 return "arm64";
100 case ZigLLVM_thumb:102 case ZigLLVM_thumb:
...@@ -107,13 +109,13 @@ static const char *get_darwin_arch_string(const ZigTarget *t) {...@@ -107,13 +109,13 @@ static const char *get_darwin_arch_string(const ZigTarget *t) {
107 case ZigLLVM_ppc64le:109 case ZigLLVM_ppc64le:
108 return "ppc64le";110 return "ppc64le";
109 default:111 default:
110 return ZigLLVMGetArchTypeName(t->arch.arch);112 return ZigLLVMGetArchTypeName(t->arch);
111 }113 }
112}114}
113115
114116
115static const char *getLDMOption(const ZigTarget *t) {117static const char *getLDMOption(const ZigTarget *t) {
116 switch (t->arch.arch) {118 switch (t->arch) {
117 case ZigLLVM_x86:119 case ZigLLVM_x86:
118 return "elf_i386";120 return "elf_i386";
119 case ZigLLVM_aarch64:121 case ZigLLVM_aarch64:
...@@ -147,7 +149,7 @@ static const char *getLDMOption(const ZigTarget *t) {...@@ -147,7 +149,7 @@ static const char *getLDMOption(const ZigTarget *t) {
147 case ZigLLVM_systemz:149 case ZigLLVM_systemz:
148 return "elf64_s390";150 return "elf64_s390";
149 case ZigLLVM_x86_64:151 case ZigLLVM_x86_64:
150 if (t->env_type == ZigLLVM_GNUX32) {152 if (t->abi == ZigLLVM_GNUX32) {
151 return "elf32_x86_64";153 return "elf32_x86_64";
152 }154 }
153 // Any target elf will use the freebsd osabi if suffixed with "_fbsd".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,78 +172,27 @@ static void add_rpath(LinkJob *lj, Buf *rpath) {
170 lj->rpath_table.put(rpath, true);172 lj->rpath_table.put(rpath, true);
171}173}
172174
173static 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
197static 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
217static void construct_linker_job_elf(LinkJob *lj) {175static void construct_linker_job_elf(LinkJob *lj) {
218 CodeGen *g = lj->codegen;176 CodeGen *g = lj->codegen;
219177
220 lj->args.append("-error-limit=0");178 lj->args.append("-error-limit=0");
221179
222 if (g->libc_link_lib != nullptr) {
223 find_libc_lib_path(g);
224 }
225
226 if (g->linker_script) {180 if (g->linker_script) {
227 lj->args.append("-T");181 lj->args.append("-T");
228 lj->args.append(g->linker_script);182 lj->args.append(g->linker_script);
229 }183 }
230184
231 if (g->no_rosegment_workaround) {
232 lj->args.append("--no-rosegment");
233 }
234 lj->args.append("--gc-sections");185 lj->args.append("--gc-sections");
235186
236 lj->args.append("-m");187 lj->args.append("-m");
237 lj->args.append(getLDMOption(&g->zig_target));188 lj->args.append(getLDMOption(g->zig_target));
238189
239 bool is_lib = g->out_type == OutTypeLib;190 bool is_lib = g->out_type == OutTypeLib;
240 bool shared = !g->is_static && is_lib;191 bool shared = !g->is_static && is_lib;
241 Buf *soname = nullptr;192 Buf *soname = nullptr;
242 if (g->is_static) {193 if (g->is_static) {
243 if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||194 if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||
244 g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)195 g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)
245 {196 {
246 lj->args.append("-Bstatic");197 lj->args.append("-Bstatic");
247 } else {198 } else {
...@@ -263,15 +214,18 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -263,15 +214,18 @@ static void construct_linker_job_elf(LinkJob *lj) {
263 if (lj->link_in_crt) {214 if (lj->link_in_crt) {
264 const char *crt1o;215 const char *crt1o;
265 const char *crtbegino;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 crt1o = "crt1.o";221 crt1o = "crt1.o";
268 crtbegino = "crtbeginT.o";222 crtbegino = "crtbeginT.o";
269 } else {223 } else {
270 crt1o = "Scrt1.o";224 crt1o = "Scrt1.o";
271 crtbegino = "crtbegin.o";225 crtbegino = "crtbegin.o";
272 }226 }
273 lj->args.append(get_libc_file(g, crt1o));227 lj->args.append(get_libc_crt_file(g, crt1o));
274 lj->args.append(get_libc_file(g, "crti.o"));228 lj->args.append(get_libc_crt_file(g, "crti.o"));
275 lj->args.append(get_libc_static_file(g, crtbegino));229 lj->args.append(get_libc_static_file(g, crtbegino));
276 }230 }
277231
...@@ -307,23 +261,24 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -307,23 +261,24 @@ static void construct_linker_job_elf(LinkJob *lj) {
307 }261 }
308262
309 if (g->libc_link_lib != nullptr) {263 if (g->libc_link_lib != nullptr) {
264 assert(g->libc != nullptr);
310 lj->args.append("-L");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 }
312272
313 lj->args.append("-L");273 lj->args.append("-L");
314 lj->args.append(buf_ptr(g->libc_static_lib_dir));274 lj->args.append(buf_ptr(&g->libc->static_lib_dir));
315 }
316275
317 if (!g->is_static) {276 if (!g->is_static) {
318 if (g->dynamic_linker != nullptr) {277 assert(buf_len(&g->libc->dynamic_linker_path) != 0);
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);
324 lj->args.append("-dynamic-linker");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 }
328283
329 if (shared) {284 if (shared) {
...@@ -390,14 +345,14 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -390,14 +345,14 @@ static void construct_linker_job_elf(LinkJob *lj) {
390 // crt end345 // crt end
391 if (lj->link_in_crt) {346 if (lj->link_in_crt) {
392 lj->args.append(get_libc_static_file(g, "crtend.o"));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 }
395350
396 if (!g->is_native_target) {351 if (!g->zig_target->is_native) {
397 lj->args.append("--allow-shlib-undefined");352 lj->args.append("--allow-shlib-undefined");
398 }353 }
399354
400 if (g->zig_target.os == OsZen) {355 if (g->zig_target->os == OsZen) {
401 lj->args.append("-e");356 lj->args.append("-e");
402 lj->args.append("_start");357 lj->args.append("_start");
403358
...@@ -420,16 +375,16 @@ static void construct_linker_job_wasm(LinkJob *lj) {...@@ -420,16 +375,16 @@ static void construct_linker_job_wasm(LinkJob *lj) {
420}375}
421376
422//static bool is_target_cyg_mingw(const ZigTarget *target) {377//static bool is_target_cyg_mingw(const ZigTarget *target) {
423// return (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_Cygnus) ||378// return (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_Cygnus) ||
424// (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_GNU);379// (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_GNU);
425//}380//}
426381
427static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {382static 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 list->append("-MACHINE:X86");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 list->append("-MACHINE:X64");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 list->append("-MACHINE:ARM");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,7 +470,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
515// lj->args.append("-Bdynamic");470// lj->args.append("-Bdynamic");
516// if (dll || shared) {471// if (dll || shared) {
517// lj->args.append("-e");472// lj->args.append("-e");
518// if (g->zig_target.arch.arch == ZigLLVM_x86) {473// if (g->zig_target.arch == ZigLLVM_x86) {
519// lj->args.append("_DllMainCRTStartup@12");474// lj->args.append("_DllMainCRTStartup@12");
520// } else {475// } else {
521// lj->args.append("DllMainCRTStartup");476// lj->args.append("DllMainCRTStartup");
...@@ -541,7 +496,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {...@@ -541,7 +496,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
541//lj->args.append("-lmingw32");496//lj->args.append("-lmingw32");
542497
543//lj->args.append("-lgcc");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//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);500//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
546//if (!g->is_static && !is_android) {501//if (!g->is_static && !is_android) {
547// if (!is_cyg_ming) {502// if (!is_cyg_ming) {
...@@ -588,10 +543,6 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -588,10 +543,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
588543
589 lj->args.append("/ERRORLIMIT:0");544 lj->args.append("/ERRORLIMIT:0");
590545
591 if (g->libc_link_lib != nullptr) {
592 find_libc_lib_path(g);
593 }
594
595 lj->args.append("/NOLOGO");546 lj->args.append("/NOLOGO");
596547
597 if (!g->strip_debug_symbols) {548 if (!g->strip_debug_symbols) {
...@@ -608,6 +559,11 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -608,6 +559,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
608 bool is_library = g->out_type == OutTypeLib;559 bool is_library = g->out_type == OutTypeLib;
609 switch (g->subsystem) {560 switch (g->subsystem) {
610 case TargetSubsystemAuto: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 break;567 break;
612 case TargetSubsystemConsole:568 case TargetSubsystemConsole:
613 lj->args.append("/SUBSYSTEM:console");569 lj->args.append("/SUBSYSTEM:console");
...@@ -646,13 +602,11 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -646,13 +602,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
646 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));602 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
647603
648 if (g->libc_link_lib != nullptr) {604 if (g->libc_link_lib != nullptr) {
649 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));605 assert(g->libc != nullptr);
650 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
651606
652 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));607 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
653 if (g->libc_static_lib_dir != nullptr) {608 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
654 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));609 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
655 }
656 }610 }
657611
658 if (is_library && !g->is_static) {612 if (is_library && !g->is_static) {
...@@ -687,7 +641,7 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -687,7 +641,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
687 continue;641 continue;
688 }642 }
689 if (link_lib->provided_explicitly) {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 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));645 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
692 lj->args.append(buf_ptr(arg));646 lj->args.append(buf_ptr(arg));
693 }647 }
...@@ -717,7 +671,8 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -717,7 +671,8 @@ static void construct_linker_job_coff(LinkJob *lj) {
717 gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));671 gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
718 gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));672 gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
719 Buf diag = BUF_INIT;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 fprintf(stderr, "%s\n", buf_ptr(&diag));676 fprintf(stderr, "%s\n", buf_ptr(&diag));
722 exit(1);677 exit(1);
723 }678 }
...@@ -786,7 +741,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {...@@ -786,7 +741,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
786 platform->kind = MacOS;741 platform->kind = MacOS;
787 } else if (g->mios_version_min) {742 } else if (g->mios_version_min) {
788 platform->kind = IPhoneOS;743 platform->kind = IPhoneOS;
789 } else if (g->zig_target.os == OsMacOSX) {744 } else if (g->zig_target->os == OsMacOSX) {
790 platform->kind = MacOS;745 platform->kind = MacOS;
791 g->mmacosx_version_min = buf_create_from_str("10.10");746 g->mmacosx_version_min = buf_create_from_str("10.10");
792 } else {747 } else {
...@@ -813,8 +768,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {...@@ -813,8 +768,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
813 }768 }
814769
815 if (platform->kind == IPhoneOS &&770 if (platform->kind == IPhoneOS &&
816 (g->zig_target.arch.arch == ZigLLVM_x86 ||771 (g->zig_target->arch == ZigLLVM_x86 ||
817 g->zig_target.arch.arch == ZigLLVM_x86_64))772 g->zig_target->arch == ZigLLVM_x86_64))
818 {773 {
819 platform->kind = IPhoneOSSimulator;774 platform->kind = IPhoneOSSimulator;
820 }775 }
...@@ -878,7 +833,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -878,7 +833,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
878 }833 }
879834
880 lj->args.append("-arch");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));
882837
883 DarwinPlatform platform;838 DarwinPlatform platform;
884 get_darwin_platform(lj, &platform);839 get_darwin_platform(lj, &platform);
...@@ -893,7 +848,11 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -893,7 +848,11 @@ static void construct_linker_job_macho(LinkJob *lj) {
893 lj->args.append("-ios_simulator_version_min");848 lj->args.append("-ios_simulator_version_min");
894 break;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));
897856
898857
899 if (g->out_type == OutTypeExe) {858 if (g->out_type == OutTypeExe) {
...@@ -914,7 +873,9 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -914,7 +873,9 @@ static void construct_linker_job_macho(LinkJob *lj) {
914 add_rpath(lj, &g->output_file_path);873 add_rpath(lj, &g->output_file_path);
915874
916 if (shared) {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 } else if (g->is_static) {879 } else if (g->is_static) {
919 lj->args.append("-lcrt0.o");880 lj->args.append("-lcrt0.o");
920 } else {881 } else {
...@@ -929,7 +890,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -929,7 +890,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
929 }890 }
930 break;891 break;
931 case IPhoneOS:892 case IPhoneOS:
932 if (g->zig_target.arch.arch == ZigLLVM_aarch64) {893 if (g->zig_target->arch == ZigLLVM_aarch64) {
933 // iOS does not need any crt1 files for arm64894 // iOS does not need any crt1 files for arm64
934 } else if (darwin_version_lt(&platform, 3, 1)) {895 } else if (darwin_version_lt(&platform, 3, 1)) {
935 lj->args.append("-lcrt1.o");896 lj->args.append("-lcrt1.o");
...@@ -959,7 +920,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -959,7 +920,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
959 lj->args.append(buf_ptr(compiler_rt_o_path));920 lj->args.append(buf_ptr(compiler_rt_o_path));
960 }921 }
961922
962 if (g->is_native_target) {923 if (g->zig_target->is_native) {
963 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {924 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
964 LinkLib *link_lib = g->link_libs_list.at(lib_i);925 LinkLib *link_lib = g->link_libs_list.at(lib_i);
965 if (buf_eql_str(link_lib->name, "c")) {926 if (buf_eql_str(link_lib->name, "c")) {
...@@ -1000,7 +961,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -1000,7 +961,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
1000}961}
1001962
1002static void construct_linker_job(LinkJob *lj) {963static void construct_linker_job(LinkJob *lj) {
1003 switch (lj->codegen->zig_target.oformat) {964 switch (target_object_format(lj->codegen->zig_target)) {
1004 case ZigLLVM_UnknownObjectFormat:965 case ZigLLVM_UnknownObjectFormat:
1005 zig_unreachable();966 zig_unreachable();
1006967
...@@ -1040,7 +1001,7 @@ void codegen_link(CodeGen *g) {...@@ -1040,7 +1001,7 @@ void codegen_link(CodeGen *g) {
1040 for (size_t i = 0; i < g->link_objects.length; i += 1) {1001 for (size_t i = 0; i < g->link_objects.length; i += 1) {
1041 file_names.append((const char *)buf_ptr(g->link_objects.at(i)));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 codegen_add_time_event(g, "LLVM Link");1005 codegen_add_time_event(g, "LLVM Link");
1045 if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {1006 if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
1046 fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));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,7 +1026,7 @@ void codegen_link(CodeGen *g) {
1065 Buf diag = BUF_INIT;1026 Buf diag = BUF_INIT;
10661027
1067 codegen_add_time_event(g, "LLVM Link");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 Termination term;1030 Termination term;
1070 ZigList<const char *> args = {};1031 ZigList<const char *> args = {};
1071 for (size_t i = 1; i < lj.args.length; i += 1) {1032 for (size_t i = 1; i < lj.args.length; i += 1) {
...@@ -1075,7 +1036,7 @@ void codegen_link(CodeGen *g) {...@@ -1075,7 +1036,7 @@ void codegen_link(CodeGen *g) {
1075 if (term.how != TerminationIdClean || term.code != 0) {1036 if (term.how != TerminationIdClean || term.code != 0) {
1076 exit(1);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 fprintf(stderr, "%s\n", buf_ptr(&diag));1040 fprintf(stderr, "%s\n", buf_ptr(&diag));
1080 exit(1);1041 exit(1);
1081 }1042 }
src/main.cpp+231-114
...@@ -13,16 +13,17 @@...@@ -13,16 +13,17 @@
13#include "error.hpp"13#include "error.hpp"
14#include "os.hpp"14#include "os.hpp"
15#include "target.hpp"15#include "target.hpp"
16#include "libc_installation.hpp"
1617
17#include <stdio.h>18#include <stdio.h>
1819
19static int print_error_usage(const char *arg0) {20static 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 return EXIT_FAILURE;22 return EXIT_FAILURE;
22}23}
2324
24static int print_full_usage(const char *arg0) {25static int print_full_usage(const char *arg0, FILE *file, int return_code) {
25 fprintf(stdout,26 fprintf(file,
26 "Usage: %s [command] [options]\n"27 "Usage: %s [command] [options]\n"
27 "\n"28 "\n"
28 "Commands:\n"29 "Commands:\n"
...@@ -31,10 +32,12 @@ static int print_full_usage(const char *arg0) {...@@ -31,10 +32,12 @@ static int print_full_usage(const char *arg0) {
31 " build-lib [source] create library from source or object files\n"32 " build-lib [source] create library from source or object files\n"
32 " build-obj [source] create object from source or assembly\n"33 " build-obj [source] create object from source or assembly\n"
33 " builtin show the source code of that @import(\"builtin\")\n"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 " id print the base64-encoded compiler id\n"37 " id print the base64-encoded compiler id\n"
36 " init-exe initialize a `zig build` application in the cwd\n"38 " init-exe initialize a `zig build` application in the cwd\n"
37 " init-lib initialize a `zig build` library in the cwd\n"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 " run [source] create executable and run immediately\n"41 " run [source] create executable and run immediately\n"
39 " translate-c [source] convert c code to zig code\n"42 " translate-c [source] convert c code to zig code\n"
40 " targets list available compilation targets\n"43 " targets list available compilation targets\n"
...@@ -44,16 +47,20 @@ static int print_full_usage(const char *arg0) {...@@ -44,16 +47,20 @@ static int print_full_usage(const char *arg0) {
44 "\n"47 "\n"
45 "Compile Options:\n"48 "Compile Options:\n"
46 " --assembly [source] add assembly file to build\n"49 " --assembly [source] add assembly file to build\n"
50 " --c-source [options] [file] compile C source code\n"
47 " --cache-dir [path] override the cache directory\n"51 " --cache-dir [path] override the cache directory\n"
48 " --cache [auto|off|on] build in global cache, print out paths to stdout\n"52 " --cache [auto|off|on] build in global cache, print out paths to stdout\n"
49 " --color [auto|off|on] enable or disable colored error messages\n"53 " --color [auto|off|on] enable or disable colored error messages\n"
50 " --disable-pic disable Position Independent Code for libraries\n"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 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"57 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
52 " -ftime-report print timing diagnostics\n"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 " --name [name] override output name\n"60 " --name [name] override output name\n"
55 " --output [file] override destination path\n"61 " --output [file] override destination path\n"
56 " --output-h [file] generate header file\n"62 " --output-h [file] generate header file\n"
63 " --output-lib [file] override import library path\n"
57 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"64 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
58 " --pkg-end pop current pkg\n"65 " --pkg-end pop current pkg\n"
59 " --release-fast build with optimizations on and safety off\n"66 " --release-fast build with optimizations on and safety off\n"
...@@ -62,15 +69,14 @@ static int print_full_usage(const char *arg0) {...@@ -62,15 +69,14 @@ static int print_full_usage(const char *arg0) {
62 " --single-threaded source may assume it is only used single-threaded\n"69 " --single-threaded source may assume it is only used single-threaded\n"
63 " --static output will be statically linked\n"70 " --static output will be statically linked\n"
64 " --strip exclude debug symbols\n"71 " --strip exclude debug symbols\n"
65 " --target-arch [name] specify target architecture\n"72 " -target [name] <arch><sub>-<os>-<abi> see the targets command\n"
66 " --target-environ [name] specify target environment\n"
67 " --target-os [name] specify target operating system\n"
68 " --verbose-tokenize enable compiler debug output for tokenization\n"73 " --verbose-tokenize enable compiler debug output for tokenization\n"
69 " --verbose-ast enable compiler debug output for AST parsing\n"74 " --verbose-ast enable compiler debug output for AST parsing\n"
70 " --verbose-link enable compiler debug output for linking\n"75 " --verbose-link enable compiler debug output for linking\n"
71 " --verbose-ir enable compiler debug output for Zig IR\n"76 " --verbose-ir enable compiler debug output for Zig IR\n"
72 " --verbose-llvm-ir enable compiler debug output for LLVM IR\n"77 " --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
73 " --verbose-cimport enable compiler debug output for C imports\n"78 " --verbose-cimport enable compiler debug output for C imports\n"
79 " --verbose-cc enable compiler debug output for C compilation\n"
74 " -dirafter [dir] same as -isystem but do it last\n"80 " -dirafter [dir] same as -isystem but do it last\n"
75 " -isystem [dir] add additional search path for other .h files\n"81 " -isystem [dir] add additional search path for other .h files\n"
76 " -mllvm [arg] forward an arg to LLVM's option processing\n"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,10 +85,6 @@ static int print_full_usage(const char *arg0) {
79 "Link Options:\n"85 "Link Options:\n"
80 " --dynamic-linker [path] set the path to ld.so\n"86 " --dynamic-linker [path] set the path to ld.so\n"
81 " --each-lib-rpath add rpath for each used dynamic library\n"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 " --library [lib] link against lib\n"88 " --library [lib] link against lib\n"
87 " --forbid-library [lib] make it an error to link against lib\n"89 " --forbid-library [lib] make it an error to link against lib\n"
88 " --library-path [dir] add a directory to the library search path\n"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,7 +93,6 @@ static int print_full_usage(const char *arg0) {
91 " -L[dir] alias for --library-path\n"93 " -L[dir] alias for --library-path\n"
92 " -rdynamic add all symbols to the dynamic symbol table\n"94 " -rdynamic add all symbols to the dynamic symbol table\n"
93 " -rpath [path] add directory to the runtime library search path\n"95 " -rpath [path] add directory to the runtime library search path\n"
94 " --no-rosegment compromise security to workaround valgrind bug\n"
95 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"96 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"
96 " -framework [name] (darwin) link against framework\n"97 " -framework [name] (darwin) link against framework\n"
97 " -mios-version-min [ver] (darwin) set iOS deployment target\n"98 " -mios-version-min [ver] (darwin) set iOS deployment target\n"
...@@ -106,7 +107,27 @@ static int print_full_usage(const char *arg0) {...@@ -106,7 +107,27 @@ static int print_full_usage(const char *arg0) {
106 " --test-cmd [arg] specify test execution command one arg at a time\n"107 " --test-cmd [arg] specify test execution command one arg at a time\n"
107 " --test-cmd-bin appends test binary path to test cmd args\n"108 " --test-cmd-bin appends test binary path to test cmd args\n"
108 , arg0);109 , arg0);
109 return EXIT_SUCCESS;110 return return_code;
111}
112
113static 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}
111132
112static const char *ZIG_ZEN = "\n"133static const char *ZIG_ZEN = "\n"
...@@ -122,6 +143,14 @@ static const char *ZIG_ZEN = "\n"...@@ -122,6 +143,14 @@ static const char *ZIG_ZEN = "\n"
122" * Minimize energy spent on coding style.\n"143" * Minimize energy spent on coding style.\n"
123" * Together we serve end users.\n";144" * Together we serve end users.\n";
124145
146static 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
125static int print_target_list(FILE *f) {154static int print_target_list(FILE *f) {
126 ZigTarget native;155 ZigTarget native;
127 get_native_target(&native);156 get_native_target(&native);
...@@ -129,28 +158,36 @@ static int print_target_list(FILE *f) {...@@ -129,28 +158,36 @@ static int print_target_list(FILE *f) {
129 fprintf(f, "Architectures:\n");158 fprintf(f, "Architectures:\n");
130 size_t arch_count = target_arch_count();159 size_t arch_count = target_arch_count();
131 for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) {160 for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) {
132 const ArchType *arch = get_target_arch(arch_i);161 ZigLLVM_ArchType arch = target_arch_enum(arch_i);
133 char arch_name[50];162 if (!arch_available_in_llvm(arch))
134 get_arch_name(arch_name, arch);163 continue;
135 const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ?164 const char *arch_name = target_arch_name(arch);
136 " (native)" : "";165 SubArchList sub_arch_list = target_subarch_list(arch);
137 fprintf(f, " %s%s\n", arch_name, native_str);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 }
139176
140 fprintf(f, "\nOperating Systems:\n");177 fprintf(f, "\nOperating Systems:\n");
141 size_t os_count = target_os_count();178 size_t os_count = target_os_count();
142 for (size_t i = 0; i < os_count; i += 1) {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 const char *native_str = (native.os == os_type) ? " (native)" : "";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 }
147184
148 fprintf(f, "\nEnvironments:\n");185 fprintf(f, "\nC ABIs:\n");
149 size_t environ_count = target_environ_count();186 size_t abi_count = target_abi_count();
150 for (size_t i = 0; i < environ_count; i += 1) {187 for (size_t i = 0; i < abi_count; i += 1) {
151 ZigLLVM_EnvironmentType environ_type = get_target_environ(i);188 ZigLLVM_EnvironmentType abi = target_abi_enum(i);
152 const char *native_str = (native.env_type == environ_type) ? " (native)" : "";189 const char *native_str = (native.abi == abi) ? " (native)" : "";
153 fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str);190 fprintf(f, " %s%s\n", target_abi_name(abi), native_str);
154 }191 }
155192
156 return EXIT_SUCCESS;193 return EXIT_SUCCESS;
...@@ -160,13 +197,13 @@ enum Cmd {...@@ -160,13 +197,13 @@ enum Cmd {
160 CmdNone,197 CmdNone,
161 CmdBuild,198 CmdBuild,
162 CmdBuiltin,199 CmdBuiltin,
163 CmdHelp,
164 CmdRun,200 CmdRun,
165 CmdTargets,201 CmdTargets,
166 CmdTest,202 CmdTest,
167 CmdTranslateC,203 CmdTranslateC,
168 CmdVersion,204 CmdVersion,
169 CmdZen,205 CmdZen,
206 CmdLibC,
170};207};
171208
172static const char *default_zig_cache_name = "zig-cache";209static const char *default_zig_cache_name = "zig-cache";
...@@ -219,6 +256,8 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {...@@ -219,6 +256,8 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
219 zig_unreachable();256 zig_unreachable();
220}257}
221258
259extern "C" int ZigClang_main(int argc, char **argv);
260
222int main(int argc, char **argv) {261int main(int argc, char **argv) {
223 char *arg0 = argv[0];262 char *arg0 = argv[0];
224 Error err;263 Error err;
...@@ -236,6 +275,12 @@ int main(int argc, char **argv) {...@@ -236,6 +275,12 @@ int main(int argc, char **argv) {
236 return 0;275 return 0;
237 }276 }
238277
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 // Must be before all os.hpp function calls.284 // Must be before all os.hpp function calls.
240 os_init();285 os_init();
241286
...@@ -345,6 +390,7 @@ int main(int argc, char **argv) {...@@ -345,6 +390,7 @@ int main(int argc, char **argv) {
345 const char *in_file = nullptr;390 const char *in_file = nullptr;
346 const char *out_file = nullptr;391 const char *out_file = nullptr;
347 const char *out_file_h = nullptr;392 const char *out_file_h = nullptr;
393 const char *out_file_lib = nullptr;
348 bool strip = false;394 bool strip = false;
349 bool is_static = false;395 bool is_static = false;
350 OutType out_type = OutTypeUnknown;396 OutType out_type = OutTypeUnknown;
...@@ -355,23 +401,17 @@ int main(int argc, char **argv) {...@@ -355,23 +401,17 @@ int main(int argc, char **argv) {
355 bool verbose_ir = false;401 bool verbose_ir = false;
356 bool verbose_llvm_ir = false;402 bool verbose_llvm_ir = false;
357 bool verbose_cimport = false;403 bool verbose_cimport = false;
404 bool verbose_cc = false;
358 ErrColor color = ErrColorAuto;405 ErrColor color = ErrColorAuto;
359 CacheOpt enable_cache = CacheOptAuto;406 CacheOpt enable_cache = CacheOptAuto;
360 const char *libc_lib_dir = nullptr;407 const char *libc_txt = 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;
366 ZigList<const char *> clang_argv = {0};408 ZigList<const char *> clang_argv = {0};
367 ZigList<const char *> llvm_argv = {0};409 ZigList<const char *> llvm_argv = {0};
368 ZigList<const char *> lib_dirs = {0};410 ZigList<const char *> lib_dirs = {0};
369 ZigList<const char *> link_libs = {0};411 ZigList<const char *> link_libs = {0};
370 ZigList<const char *> forbidden_link_libs = {0};412 ZigList<const char *> forbidden_link_libs = {0};
371 ZigList<const char *> frameworks = {0};413 ZigList<const char *> frameworks = {0};
372 const char *target_arch = nullptr;414 const char *target_string = nullptr;
373 const char *target_os = nullptr;
374 const char *target_environ = nullptr;
375 bool rdynamic = false;415 bool rdynamic = false;
376 const char *mmacosx_version_min = nullptr;416 const char *mmacosx_version_min = nullptr;
377 const char *mios_version_min = nullptr;417 const char *mios_version_min = nullptr;
...@@ -379,6 +419,7 @@ int main(int argc, char **argv) {...@@ -379,6 +419,7 @@ int main(int argc, char **argv) {
379 ZigList<const char *> rpath_list = {0};419 ZigList<const char *> rpath_list = {0};
380 bool each_lib_rpath = false;420 bool each_lib_rpath = false;
381 ZigList<const char *> objects = {0};421 ZigList<const char *> objects = {0};
422 ZigList<CFile *> c_source_files = {0};
382 ZigList<const char *> asm_files = {0};423 ZigList<const char *> asm_files = {0};
383 const char *test_filter = nullptr;424 const char *test_filter = nullptr;
384 const char *test_name_prefix = nullptr;425 const char *test_name_prefix = nullptr;
...@@ -392,11 +433,11 @@ int main(int argc, char **argv) {...@@ -392,11 +433,11 @@ int main(int argc, char **argv) {
392 BuildMode build_mode = BuildModeDebug;433 BuildMode build_mode = BuildModeDebug;
393 ZigList<const char *> test_exec_args = {0};434 ZigList<const char *> test_exec_args = {0};
394 int runtime_args_start = -1;435 int runtime_args_start = -1;
395 bool no_rosegment_workaround = false;
396 bool system_linker_hack = false;436 bool system_linker_hack = false;
397 TargetSubsystem subsystem = TargetSubsystemAuto;437 TargetSubsystem subsystem = TargetSubsystemAuto;
398 bool is_single_threaded = false;438 bool is_single_threaded = false;
399 Buf *override_std_dir = nullptr;439 Buf *override_std_dir = nullptr;
440 ValgrindSupport valgrind_support = ValgrindSupportAuto;
400441
401 if (argc >= 2 && strcmp(argv[1], "build") == 0) {442 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
402 Buf zig_exe_path_buf = BUF_INIT;443 Buf zig_exe_path_buf = BUF_INIT;
...@@ -432,8 +473,11 @@ int main(int argc, char **argv) {...@@ -432,8 +473,11 @@ int main(int argc, char **argv) {
432 Buf *build_runner_path = buf_alloc();473 Buf *build_runner_path = buf_alloc();
433 os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);474 os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
434475
435 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),476 ZigTarget target;
436 override_std_dir);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 g->enable_time_report = timing_info;481 g->enable_time_report = timing_info;
438 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);482 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
439 codegen_set_out_name(g, buf_create_from_str("build"));483 codegen_set_out_name(g, buf_create_from_str("build"));
...@@ -484,6 +528,7 @@ int main(int argc, char **argv) {...@@ -484,6 +528,7 @@ int main(int argc, char **argv) {
484 " --verbose-ir Enable compiler debug output for Zig IR\n"528 " --verbose-ir Enable compiler debug output for Zig IR\n"
485 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"529 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
486 " --verbose-cimport Enable compiler debug output for C imports\n"530 " --verbose-cimport Enable compiler debug output for C imports\n"
531 " --verbose-cc Enable compiler debug output for C compilation\n"
487 "\n"532 "\n"
488 , zig_exe_path);533 , zig_exe_path);
489 return EXIT_SUCCESS;534 return EXIT_SUCCESS;
...@@ -493,7 +538,7 @@ int main(int argc, char **argv) {...@@ -493,7 +538,7 @@ int main(int argc, char **argv) {
493 "No 'build.zig' file found.\n"538 "No 'build.zig' file found.\n"
494 "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"539 "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
495 "or build an executable directly with `zig build-exe $FILENAME.zig`.\n"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 return EXIT_FAILURE;543 return EXIT_FAILURE;
499 }544 }
...@@ -515,6 +560,37 @@ int main(int argc, char **argv) {...@@ -515,6 +560,37 @@ int main(int argc, char **argv) {
515 fprintf(stderr, "\n");560 fprintf(stderr, "\n");
516 }561 }
517 return (term.how == TerminationIdClean) ? term.code : -1;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 }
519595
520 for (int i = 1; i < argc; i += 1) {596 for (int i = 1; i < argc; i += 1) {
...@@ -527,6 +603,12 @@ int main(int argc, char **argv) {...@@ -527,6 +603,12 @@ int main(int argc, char **argv) {
527 build_mode = BuildModeSafeRelease;603 build_mode = BuildModeSafeRelease;
528 } else if (strcmp(arg, "--release-small") == 0) {604 } else if (strcmp(arg, "--release-small") == 0) {
529 build_mode = BuildModeSmallRelease;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 } else if (strcmp(arg, "--strip") == 0) {612 } else if (strcmp(arg, "--strip") == 0) {
531 strip = true;613 strip = true;
532 } else if (strcmp(arg, "--static") == 0) {614 } else if (strcmp(arg, "--static") == 0) {
...@@ -543,16 +625,20 @@ int main(int argc, char **argv) {...@@ -543,16 +625,20 @@ int main(int argc, char **argv) {
543 verbose_llvm_ir = true;625 verbose_llvm_ir = true;
544 } else if (strcmp(arg, "--verbose-cimport") == 0) {626 } else if (strcmp(arg, "--verbose-cimport") == 0) {
545 verbose_cimport = true;627 verbose_cimport = true;
628 } else if (strcmp(arg, "--verbose-cc") == 0) {
629 verbose_cc = true;
546 } else if (strcmp(arg, "-rdynamic") == 0) {630 } else if (strcmp(arg, "-rdynamic") == 0) {
547 rdynamic = true;631 rdynamic = true;
548 } else if (strcmp(arg, "--no-rosegment") == 0) {
549 no_rosegment_workaround = true;
550 } else if (strcmp(arg, "--each-lib-rpath") == 0) {632 } else if (strcmp(arg, "--each-lib-rpath") == 0) {
551 each_lib_rpath = true;633 each_lib_rpath = true;
552 } else if (strcmp(arg, "-ftime-report") == 0) {634 } else if (strcmp(arg, "-ftime-report") == 0) {
553 timing_info = true;635 timing_info = true;
554 } else if (strcmp(arg, "--disable-pic") == 0) {636 } else if (strcmp(arg, "--disable-pic") == 0) {
555 disable_pic = true;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 } else if (strcmp(arg, "--system-linker-hack") == 0) {642 } else if (strcmp(arg, "--system-linker-hack") == 0) {
557 system_linker_hack = true;643 system_linker_hack = true;
558 } else if (strcmp(arg, "--single-threaded") == 0) {644 } else if (strcmp(arg, "--single-threaded") == 0) {
...@@ -590,6 +676,8 @@ int main(int argc, char **argv) {...@@ -590,6 +676,8 @@ int main(int argc, char **argv) {
590 out_file = argv[i];676 out_file = argv[i];
591 } else if (strcmp(arg, "--output-h") == 0) {677 } else if (strcmp(arg, "--output-h") == 0) {
592 out_file_h = argv[i];678 out_file_h = argv[i];
679 } else if (strcmp(arg, "--output-lib") == 0) {
680 out_file_lib = argv[i];
593 } else if (strcmp(arg, "--color") == 0) {681 } else if (strcmp(arg, "--color") == 0) {
594 if (strcmp(argv[i], "auto") == 0) {682 if (strcmp(argv[i], "auto") == 0) {
595 color = ErrColorAuto;683 color = ErrColorAuto;
...@@ -625,18 +713,8 @@ int main(int argc, char **argv) {...@@ -625,18 +713,8 @@ int main(int argc, char **argv) {
625 }713 }
626 } else if (strcmp(arg, "--name") == 0) {714 } else if (strcmp(arg, "--name") == 0) {
627 out_name = argv[i];715 out_name = argv[i];
628 } else if (strcmp(arg, "--libc-lib-dir") == 0) {716 } else if (strcmp(arg, "--libc") == 0) {
629 libc_lib_dir = argv[i];717 libc_txt = 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];
640 } else if (strcmp(arg, "-isystem") == 0) {718 } else if (strcmp(arg, "-isystem") == 0) {
641 clang_argv.append("-isystem");719 clang_argv.append("-isystem");
642 clang_argv.append(argv[i]);720 clang_argv.append(argv[i]);
...@@ -658,16 +736,25 @@ int main(int argc, char **argv) {...@@ -658,16 +736,25 @@ int main(int argc, char **argv) {
658 forbidden_link_libs.append(argv[i]);736 forbidden_link_libs.append(argv[i]);
659 } else if (strcmp(arg, "--object") == 0) {737 } else if (strcmp(arg, "--object") == 0) {
660 objects.append(argv[i]);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 } else if (strcmp(arg, "--assembly") == 0) {752 } else if (strcmp(arg, "--assembly") == 0) {
662 asm_files.append(argv[i]);753 asm_files.append(argv[i]);
663 } else if (strcmp(arg, "--cache-dir") == 0) {754 } else if (strcmp(arg, "--cache-dir") == 0) {
664 cache_dir = argv[i];755 cache_dir = argv[i];
665 } else if (strcmp(arg, "--target-arch") == 0) {756 } else if (strcmp(arg, "-target") == 0) {
666 target_arch = argv[i];757 target_string = 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];
671 } else if (strcmp(arg, "-mmacosx-version-min") == 0) {758 } else if (strcmp(arg, "-mmacosx-version-min") == 0) {
672 mmacosx_version_min = argv[i];759 mmacosx_version_min = argv[i];
673 } else if (strcmp(arg, "-mios-version-min") == 0) {760 } else if (strcmp(arg, "-mios-version-min") == 0) {
...@@ -736,8 +823,6 @@ int main(int argc, char **argv) {...@@ -736,8 +823,6 @@ int main(int argc, char **argv) {
736 } else if (strcmp(arg, "build-lib") == 0) {823 } else if (strcmp(arg, "build-lib") == 0) {
737 cmd = CmdBuild;824 cmd = CmdBuild;
738 out_type = OutTypeLib;825 out_type = OutTypeLib;
739 } else if (strcmp(arg, "help") == 0) {
740 cmd = CmdHelp;
741 } else if (strcmp(arg, "run") == 0) {826 } else if (strcmp(arg, "run") == 0) {
742 cmd = CmdRun;827 cmd = CmdRun;
743 out_type = OutTypeExe;828 out_type = OutTypeExe;
...@@ -745,6 +830,8 @@ int main(int argc, char **argv) {...@@ -745,6 +830,8 @@ int main(int argc, char **argv) {
745 cmd = CmdVersion;830 cmd = CmdVersion;
746 } else if (strcmp(arg, "zen") == 0) {831 } else if (strcmp(arg, "zen") == 0) {
747 cmd = CmdZen;832 cmd = CmdZen;
833 } else if (strcmp(arg, "libc") == 0) {
834 cmd = CmdLibC;
748 } else if (strcmp(arg, "translate-c") == 0) {835 } else if (strcmp(arg, "translate-c") == 0) {
749 cmd = CmdTranslateC;836 cmd = CmdTranslateC;
750 } else if (strcmp(arg, "test") == 0) {837 } else if (strcmp(arg, "test") == 0) {
...@@ -764,6 +851,7 @@ int main(int argc, char **argv) {...@@ -764,6 +851,7 @@ int main(int argc, char **argv) {
764 case CmdRun:851 case CmdRun:
765 case CmdTranslateC:852 case CmdTranslateC:
766 case CmdTest:853 case CmdTest:
854 case CmdLibC:
767 if (!in_file) {855 if (!in_file) {
768 in_file = arg;856 in_file = arg;
769 if (cmd == CmdRun) {857 if (cmd == CmdRun) {
...@@ -776,7 +864,6 @@ int main(int argc, char **argv) {...@@ -776,7 +864,6 @@ int main(int argc, char **argv) {
776 }864 }
777 break;865 break;
778 case CmdBuiltin:866 case CmdBuiltin:
779 case CmdHelp:
780 case CmdVersion:867 case CmdVersion:
781 case CmdZen:868 case CmdZen:
782 case CmdTargets:869 case CmdTargets:
...@@ -795,36 +882,34 @@ int main(int argc, char **argv) {...@@ -795,36 +882,34 @@ int main(int argc, char **argv) {
795882
796 init_all_targets();883 init_all_targets();
797884
798 ZigTarget alloc_target;885 ZigTarget target;
799 ZigTarget *target;886 if (target_string == nullptr) {
800 if (!target_arch && !target_os && !target_environ) {887 get_native_target(&target);
801 target = nullptr;
802 } else {888 } else {
803 target = &alloc_target;889 if ((err = target_parse_triple(&target, target_string))) {
804 get_unknown_target(target);890 fprintf(stderr, "invalid target: %s\n", err_str(err));
805 if (target_arch) {891 return print_error_usage(arg0);
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 }
822 }892 }
823 }893 }
824894
825 switch (cmd) {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 case CmdBuiltin: {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 g->is_single_threaded = is_single_threaded;913 g->is_single_threaded = is_single_threaded;
829 Buf *builtin_source = codegen_generate_builtin_source(g);914 Buf *builtin_source = codegen_generate_builtin_source(g);
830 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {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,15 +923,43 @@ int main(int argc, char **argv) {
838 case CmdTranslateC:923 case CmdTranslateC:
839 case CmdTest:924 case CmdTest:
840 {925 {
841 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {926 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");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 return print_error_usage(arg0);935 return print_error_usage(arg0);
844 } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {936 } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
845 fprintf(stderr, "Expected source file argument.\n");937 fprintf(stderr, "Expected source file argument.\n");
846 return print_error_usage(arg0);938 return print_error_usage(arg0);
847 } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {939 } else if (cmd == CmdBuild && out_type == OutTypeObj) {
848 fprintf(stderr, "When building an object file, --object arguments are invalid.\n");940 if (objects.length != 0) {
849 return print_error_usage(arg0);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 }
851964
852 assert(cmd != CmdBuild || out_type != OutTypeUnknown);965 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
...@@ -873,6 +986,13 @@ int main(int argc, char **argv) {...@@ -873,6 +986,13 @@ int main(int argc, char **argv) {
873 }986 }
874 }987 }
875988
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 if (need_name && buf_out_name == nullptr) {996 if (need_name && buf_out_name == nullptr) {
877 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");997 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
878 return print_error_usage(arg0);998 return print_error_usage(arg0);
...@@ -883,8 +1003,17 @@ int main(int argc, char **argv) {...@@ -883,8 +1003,17 @@ int main(int argc, char **argv) {
883 if (cmd == CmdRun && buf_out_name == nullptr) {1003 if (cmd == CmdRun && buf_out_name == nullptr) {
884 buf_out_name = buf_create_from_str("run");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(),1006 ZigLibCInstallation *libc = nullptr;
887 override_std_dir);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 g->subsystem = subsystem;1017 g->subsystem = subsystem;
8891018
890 if (disable_pic) {1019 if (disable_pic) {
...@@ -909,24 +1038,13 @@ int main(int argc, char **argv) {...@@ -909,24 +1038,13 @@ int main(int argc, char **argv) {
909 codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length);1038 codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length);
910 codegen_set_strip(g, strip);1039 codegen_set_strip(g, strip);
911 codegen_set_is_static(g, is_static);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 g->verbose_tokenize = verbose_tokenize;1041 g->verbose_tokenize = verbose_tokenize;
925 g->verbose_ast = verbose_ast;1042 g->verbose_ast = verbose_ast;
926 g->verbose_link = verbose_link;1043 g->verbose_link = verbose_link;
927 g->verbose_ir = verbose_ir;1044 g->verbose_ir = verbose_ir;
928 g->verbose_llvm_ir = verbose_llvm_ir;1045 g->verbose_llvm_ir = verbose_llvm_ir;
929 g->verbose_cimport = verbose_cimport;1046 g->verbose_cimport = verbose_cimport;
1047 g->verbose_cc = verbose_cc;
930 codegen_set_errmsg_color(g, color);1048 codegen_set_errmsg_color(g, color);
931 g->system_linker_hack = system_linker_hack;1049 g->system_linker_hack = system_linker_hack;
9321050
...@@ -949,7 +1067,6 @@ int main(int argc, char **argv) {...@@ -949,7 +1067,6 @@ int main(int argc, char **argv) {
949 }1067 }
9501068
951 codegen_set_rdynamic(g, rdynamic);1069 codegen_set_rdynamic(g, rdynamic);
952 g->no_rosegment_workaround = no_rosegment_workaround;
953 if (mmacosx_version_min && mios_version_min) {1070 if (mmacosx_version_min && mios_version_min) {
954 fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");1071 fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
955 return EXIT_FAILURE;1072 return EXIT_FAILURE;
...@@ -975,11 +1092,14 @@ int main(int argc, char **argv) {...@@ -975,11 +1092,14 @@ int main(int argc, char **argv) {
975 codegen_set_output_path(g, buf_create_from_str(out_file));1092 codegen_set_output_path(g, buf_create_from_str(out_file));
976 if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib))1093 if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib))
977 codegen_set_output_h_path(g, buf_create_from_str(out_file_h));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));
9781097
9791098
980 add_package(g, cur_pkg, g->root_package);1099 add_package(g, cur_pkg, g->root_package);
9811100
982 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {1101 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
1102 g->c_source_files = c_source_files;
983 for (size_t i = 0; i < objects.length; i += 1) {1103 for (size_t i = 0; i < objects.length; i += 1) {
984 codegen_add_object(g, buf_create_from_str(objects.at(i)));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,7 +1172,7 @@ int main(int argc, char **argv) {
1052 }1172 }
1053 }1173 }
10541174
1055 if (!target_can_exec(&native, target)) {1175 if (!target_can_exec(&native, &target)) {
1056 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",1176 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
1057 buf_ptr(test_exe_path));1177 buf_ptr(test_exe_path));
1058 return 0;1178 return 0;
...@@ -1079,8 +1199,6 @@ int main(int argc, char **argv) {...@@ -1079,8 +1199,6 @@ int main(int argc, char **argv) {
1079 zig_unreachable();1199 zig_unreachable();
1080 }1200 }
1081 }1201 }
1082 case CmdHelp:
1083 return print_full_usage(arg0);
1084 case CmdVersion:1202 case CmdVersion:
1085 printf("%s\n", ZIG_VERSION_STRING);1203 printf("%s\n", ZIG_VERSION_STRING);
1086 return EXIT_SUCCESS;1204 return EXIT_SUCCESS;
...@@ -1090,7 +1208,6 @@ int main(int argc, char **argv) {...@@ -1090,7 +1208,6 @@ int main(int argc, char **argv) {
1090 case CmdTargets:1208 case CmdTargets:
1091 return print_target_list(stdout);1209 return print_target_list(stdout);
1092 case CmdNone:1210 case CmdNone:
1093 fprintf(stderr, "Zig programming language\n");1211 return print_full_usage(arg0, stderr, EXIT_FAILURE);
1094 return print_error_usage(arg0);
1095 }1212 }
1096}1213}
src/os.cpp+34-13
...@@ -50,11 +50,11 @@ typedef SSIZE_T ssize_t;...@@ -50,11 +50,11 @@ typedef SSIZE_T ssize_t;
5050
51#endif51#endif
5252
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#include <link.h>54#include <link.h>
55#endif55#endif
5656
57#if defined(ZIG_OS_FREEBSD)57#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
58#include <sys/sysctl.h>58#include <sys/sysctl.h>
59#endif59#endif
6060
...@@ -78,7 +78,7 @@ static clock_serv_t cclock;...@@ -78,7 +78,7 @@ static clock_serv_t cclock;
78#if defined(__APPLE__) && !defined(environ)78#if defined(__APPLE__) && !defined(environ)
79#include <crt_externs.h>79#include <crt_externs.h>
80#define environ (*_NSGetEnviron())80#define environ (*_NSGetEnviron())
81#elif defined(ZIG_OS_FREEBSD)81#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
82extern char **environ;82extern char **environ;
83#endif83#endif
8484
...@@ -1099,7 +1099,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {...@@ -1099,7 +1099,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
1099 case EINTR:1099 case EINTR:
1100 return ErrorInterrupted;1100 return ErrorInterrupted;
1101 case EINVAL:1101 case EINVAL:
1102 zig_unreachable();1102 return ErrorInvalidFilename;
1103 case ENFILE:1103 case ENFILE:
1104 case ENOMEM:1104 case ENOMEM:
1105 return ErrorSystemResources;1105 return ErrorSystemResources;
...@@ -1232,6 +1232,18 @@ static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_p...@@ -1232,6 +1232,18 @@ static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_p
1232}1232}
1233#endif1233#endif
12341234
1235Buf *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#if defined(ZIG_OS_WINDOWS)1247#if defined(ZIG_OS_WINDOWS)
1236static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {1248static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
1237 char tmp_dir[MAX_PATH + 1];1249 char tmp_dir[MAX_PATH + 1];
...@@ -1458,6 +1470,15 @@ Error os_self_exe_path(Buf *out_path) {...@@ -1458,6 +1470,15 @@ Error os_self_exe_path(Buf *out_path) {
1458 }1470 }
1459 buf_resize(out_path, cb - 1);1471 buf_resize(out_path, cb - 1);
1460 return ErrorNone;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#endif1482#endif
1462 return ErrorFileNotFound;1483 return ErrorFileNotFound;
1463}1484}
...@@ -1541,7 +1562,7 @@ void os_stderr_set_color(TermColor color) {...@@ -1541,7 +1562,7 @@ void os_stderr_set_color(TermColor color) {
1541#endif1562#endif
1542}1563}
15431564
1544int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {1565Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
1545#if defined(ZIG_OS_WINDOWS)1566#if defined(ZIG_OS_WINDOWS)
1546 buf_resize(output_buf, 0);1567 buf_resize(output_buf, 0);
1547 buf_appendf(output_buf, "%s\\Lib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr);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,7 +1583,7 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
1562 buf_init_from_buf(tmp_buf, output_buf);1583 buf_init_from_buf(tmp_buf, output_buf);
1563 buf_append_str(tmp_buf, "ucrt.lib");1584 buf_append_str(tmp_buf, "ucrt.lib");
1564 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {1585 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1565 return 0;1586 return ErrorNone;
1566 }1587 }
1567 else {1588 else {
1568 buf_resize(output_buf, 0);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,12 +1594,12 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
1573#endif1594#endif
1574}1595}
15751596
1576int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {1597Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
1577#if defined(ZIG_OS_WINDOWS)1598#if defined(ZIG_OS_WINDOWS)
1578 buf_resize(output_buf, 0);1599 buf_resize(output_buf, 0);
1579 buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr);1600 buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr);
1580 if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) {1601 if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) {
1581 return 0;1602 return ErrorNone;
1582 }1603 }
1583 else {1604 else {
1584 buf_resize(output_buf, 0);1605 buf_resize(output_buf, 0);
...@@ -1589,7 +1610,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {...@@ -1589,7 +1610,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
1589#endif1610#endif
1590}1611}
15911612
1592int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {1613Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
1593#if defined(ZIG_OS_WINDOWS)1614#if defined(ZIG_OS_WINDOWS)
1594 {1615 {
1595 buf_resize(output_buf, 0);1616 buf_resize(output_buf, 0);
...@@ -1611,7 +1632,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy...@@ -1611,7 +1632,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
1611 buf_init_from_buf(tmp_buf, output_buf);1632 buf_init_from_buf(tmp_buf, output_buf);
1612 buf_append_str(tmp_buf, "kernel32.lib");1633 buf_append_str(tmp_buf, "kernel32.lib");
1613 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {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,7 +1655,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
1634 buf_init_from_buf(tmp_buf, output_buf);1655 buf_init_from_buf(tmp_buf, output_buf);
1635 buf_append_str(tmp_buf, "kernel32.lib");1656 buf_append_str(tmp_buf, "kernel32.lib");
1636 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {1657 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1637 return 0;1658 return ErrorNone;
1638 }1659 }
1639 }1660 }
1640 return ErrorFileNotFound;1661 return ErrorFileNotFound;
...@@ -1776,7 +1797,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {...@@ -1776,7 +1797,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1776}1797}
17771798
17781799
1779#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)1800#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
1780static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {1801static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
1781 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);1802 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
1782 if (info->dlpi_name[0] == '/') {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,7 +1808,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size,
1787#endif1808#endif
17881809
1789Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {1810Error 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 paths.resize(0);1812 paths.resize(0);
1792 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);1813 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
1793 return ErrorNone;1814 return ErrorNone;
src/os.hpp+6-3
...@@ -25,6 +25,8 @@...@@ -25,6 +25,8 @@
25#define ZIG_OS_LINUX25#define ZIG_OS_LINUX
26#elif defined(__FreeBSD__)26#elif defined(__FreeBSD__)
27#define ZIG_OS_FREEBSD27#define ZIG_OS_FREEBSD
28#elif defined(__NetBSD__)
29#define ZIG_OS_NETBSD
28#else30#else
29#define ZIG_OS_UNKNOWN31#define ZIG_OS_UNKNOWN
30#endif32#endif
...@@ -119,6 +121,7 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);...@@ -119,6 +121,7 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
119bool os_stderr_tty(void);121bool os_stderr_tty(void);
120void os_stderr_set_color(TermColor color);122void os_stderr_set_color(TermColor color);
121123
124Buf *os_tmp_filename(Buf *prefix, Buf *suffix);
122Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);125Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
123Error os_delete_file(Buf *path);126Error os_delete_file(Buf *path);
124127
...@@ -133,9 +136,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);...@@ -133,9 +136,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
133136
134Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);137Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
135138
136int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);139Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
137int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);140Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
138int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);141Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
139142
140Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);143Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
141144
src/parser.cpp+11-1
...@@ -2739,6 +2739,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) {...@@ -2739,6 +2739,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) {
27392739
2740 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async);2740 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async);
2741 res->data.fn_call_expr.is_async = true;2741 res->data.fn_call_expr.is_async = true;
2742 res->data.fn_call_expr.seen = false;
2742 if (eat_token_if(pc, TokenIdCmpLessThan) != nullptr) {2743 if (eat_token_if(pc, TokenIdCmpLessThan) != nullptr) {
2743 AstNode *prefix_expr = ast_expect(pc, ast_parse_prefix_expr);2744 AstNode *prefix_expr = ast_expect(pc, ast_parse_prefix_expr);
2744 expect_token(pc, TokenIdCmpGreaterThan);2745 expect_token(pc, TokenIdCmpGreaterThan);
...@@ -2759,6 +2760,7 @@ static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {...@@ -2759,6 +2760,7 @@ static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
27592760
2760 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren);2761 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren);
2761 res->data.fn_call_expr.params = params;2762 res->data.fn_call_expr.params = params;
2763 res->data.fn_call_expr.seen = false;
2762 return res;2764 return res;
2763}2765}
27642766
...@@ -2778,7 +2780,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2778,7 +2780,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2778// PtrTypeStart2780// PtrTypeStart
2779// <- ASTERISK2781// <- ASTERISK
2780// / ASTERISK22782// / ASTERISK2
2781// / LBRACKET ASTERISK RBRACKET2783// / PTRUNKNOWN
2784// / PTRC
2782static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {2785static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2783 Token *asterisk = eat_token_if(pc, TokenIdStar);2786 Token *asterisk = eat_token_if(pc, TokenIdStar);
2784 if (asterisk != nullptr) {2787 if (asterisk != nullptr) {
...@@ -2804,6 +2807,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {...@@ -2804,6 +2807,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2804 return res;2807 return res;
2805 }2808 }
28062809
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 return nullptr;2817 return nullptr;
2808}2818}
28092819
src/target.cpp+599-344
...@@ -9,127 +9,116 @@...@@ -9,127 +9,116 @@
9#include "error.hpp"9#include "error.hpp"
10#include "target.hpp"10#include "target.hpp"
11#include "util.hpp"11#include "util.hpp"
12#include "os.hpp"
1213
13#include <stdio.h>14#include <stdio.h>
1415
15static const ArchType arch_list[] = {16static const SubArchList subarch_list_list[] = {
16 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_5a},17 SubArchListNone,
17 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_4a},18 SubArchListArm32,
18 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_3a},19 SubArchListArm64,
19 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_2a},20 SubArchListKalimba,
20 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a},21 SubArchListMips,
21 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8},22};
22 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8r},23
23 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_baseline},24static const ZigLLVM_SubArchType subarch_list_arm32[] = {
24 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_mainline},25 ZigLLVM_ARMSubArch_v8_5a,
25 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7},26 ZigLLVM_ARMSubArch_v8_4a,
26 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7em},27 ZigLLVM_ARMSubArch_v8_3a,
27 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7m},28 ZigLLVM_ARMSubArch_v8_2a,
28 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7s},29 ZigLLVM_ARMSubArch_v8_1a,
29 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7k},30 ZigLLVM_ARMSubArch_v8,
30 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7ve},31 ZigLLVM_ARMSubArch_v8r,
31 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6},32 ZigLLVM_ARMSubArch_v8m_baseline,
32 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6m},33 ZigLLVM_ARMSubArch_v8m_mainline,
33 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6k},34 ZigLLVM_ARMSubArch_v7,
34 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6t2},35 ZigLLVM_ARMSubArch_v7em,
35 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5},36 ZigLLVM_ARMSubArch_v7m,
36 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5te},37 ZigLLVM_ARMSubArch_v7s,
37 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v4t},38 ZigLLVM_ARMSubArch_v7k,
3839 ZigLLVM_ARMSubArch_v7ve,
39 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_5a},40 ZigLLVM_ARMSubArch_v6,
40 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_4a},41 ZigLLVM_ARMSubArch_v6m,
41 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_3a},42 ZigLLVM_ARMSubArch_v6k,
42 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_2a},43 ZigLLVM_ARMSubArch_v6t2,
43 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_1a},44 ZigLLVM_ARMSubArch_v5,
44 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8},45 ZigLLVM_ARMSubArch_v5te,
45 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8r},46 ZigLLVM_ARMSubArch_v4t,
46 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_baseline},47
47 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_mainline},48};
48 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7},49
49 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7em},50static const ZigLLVM_SubArchType subarch_list_arm64[] = {
50 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7m},51 ZigLLVM_ARMSubArch_v8_5a,
51 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7s},52 ZigLLVM_ARMSubArch_v8_4a,
52 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7k},53 ZigLLVM_ARMSubArch_v8_3a,
53 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7ve},54 ZigLLVM_ARMSubArch_v8_2a,
54 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6},55 ZigLLVM_ARMSubArch_v8_1a,
55 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6m},56 ZigLLVM_ARMSubArch_v8,
56 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6k},57 ZigLLVM_ARMSubArch_v8r,
57 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6t2},58 ZigLLVM_ARMSubArch_v8m_baseline,
58 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5},59 ZigLLVM_ARMSubArch_v8m_mainline,
59 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5te},60};
60 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v4t},61
6162static const ZigLLVM_SubArchType subarch_list_kalimba[] = {
62 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_5a},63 ZigLLVM_KalimbaSubArch_v5,
63 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_4a},64 ZigLLVM_KalimbaSubArch_v4,
64 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_3a},65 ZigLLVM_KalimbaSubArch_v3,
65 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_2a},66};
66 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_1a},67
67 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8},68static const ZigLLVM_SubArchType subarch_list_mips[] = {
68 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8r},69 ZigLLVM_MipsSubArch_r6,
69 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_baseline},70};
70 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_mainline},71
7172static const ZigLLVM_ArchType arch_list[] = {
72 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_5a},73 ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale
73 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_4a},74 ZigLLVM_armeb, // ARM (big endian): armeb
74 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_3a},75 ZigLLVM_aarch64, // AArch64 (little endian): aarch64
75 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_2a},76 ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be
76 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_1a},77 ZigLLVM_arc, // ARC: Synopsys ARC
77 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8},78 ZigLLVM_avr, // AVR: Atmel AVR microcontroller
78 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8r},79 ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
79 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_baseline},80 ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
80 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_mainline},81 ZigLLVM_hexagon, // Hexagon: hexagon
8182 ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6
82 {ZigLLVM_arc, ZigLLVM_NoSubArch},83 ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
83 {ZigLLVM_avr, ZigLLVM_NoSubArch},84 ZigLLVM_mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
84 {ZigLLVM_bpfel, ZigLLVM_NoSubArch},85 ZigLLVM_mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
85 {ZigLLVM_bpfeb, ZigLLVM_NoSubArch},86 ZigLLVM_msp430, // MSP430: msp430
86 {ZigLLVM_hexagon, ZigLLVM_NoSubArch},87 ZigLLVM_ppc, // PPC: powerpc
8788 ZigLLVM_ppc64, // PPC64: powerpc64, ppu
88 {ZigLLVM_mips, ZigLLVM_MipsSubArch_r6},89 ZigLLVM_ppc64le, // PPC64LE: powerpc64le
89 {ZigLLVM_mipsel, ZigLLVM_MipsSubArch_r6},90 ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX
90 {ZigLLVM_mips64, ZigLLVM_MipsSubArch_r6},91 ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs
91 {ZigLLVM_mips64el, ZigLLVM_MipsSubArch_r6},92 ZigLLVM_riscv32, // RISC-V (32-bit): riscv32
9293 ZigLLVM_riscv64, // RISC-V (64-bit): riscv64
93 {ZigLLVM_msp430, ZigLLVM_NoSubArch},94 ZigLLVM_sparc, // Sparc: sparc
94 {ZigLLVM_ppc, ZigLLVM_NoSubArch},95 ZigLLVM_sparcv9, // Sparcv9: Sparcv9
95 {ZigLLVM_ppc64, ZigLLVM_NoSubArch},96 ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
96 {ZigLLVM_ppc64le, ZigLLVM_NoSubArch},97 ZigLLVM_systemz, // SystemZ: s390x
97 {ZigLLVM_r600, ZigLLVM_NoSubArch},98 ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce
98 {ZigLLVM_amdgcn, ZigLLVM_NoSubArch},99 ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele
99 {ZigLLVM_riscv32, ZigLLVM_NoSubArch},100 ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.*
100 {ZigLLVM_riscv64, ZigLLVM_NoSubArch},101 ZigLLVM_thumbeb, // Thumb (big endian): thumbeb
101 {ZigLLVM_sparc, ZigLLVM_NoSubArch},102 ZigLLVM_x86, // X86: i[3-9]86
102 {ZigLLVM_sparcv9, ZigLLVM_NoSubArch},103 ZigLLVM_x86_64, // X86-64: amd64, x86_64
103 {ZigLLVM_sparcel, ZigLLVM_NoSubArch},104 ZigLLVM_xcore, // XCore: xcore
104 {ZigLLVM_systemz, ZigLLVM_NoSubArch},105 ZigLLVM_nvptx, // NVPTX: 32-bit
105 {ZigLLVM_tce, ZigLLVM_NoSubArch},106 ZigLLVM_nvptx64, // NVPTX: 64-bit
106 {ZigLLVM_tcele, ZigLLVM_NoSubArch},107 ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl)
107 {ZigLLVM_thumb, ZigLLVM_NoSubArch},108 ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl)
108 {ZigLLVM_thumbeb, ZigLLVM_NoSubArch},109 ZigLLVM_amdil, // AMDIL
109 {ZigLLVM_x86, ZigLLVM_NoSubArch},110 ZigLLVM_amdil64, // AMDIL with 64-bit pointers
110 {ZigLLVM_x86_64, ZigLLVM_NoSubArch},111 ZigLLVM_hsail, // AMD HSAIL
111 {ZigLLVM_xcore, ZigLLVM_NoSubArch},112 ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers
112 {ZigLLVM_nvptx, ZigLLVM_NoSubArch},113 ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version
113 {ZigLLVM_nvptx64, ZigLLVM_NoSubArch},114 ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version
114 {ZigLLVM_le32, ZigLLVM_NoSubArch},115 ZigLLVM_kalimba, // Kalimba: generic kalimba
115 {ZigLLVM_le64, ZigLLVM_NoSubArch},116 ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors
116 {ZigLLVM_amdil, ZigLLVM_NoSubArch},117 ZigLLVM_lanai, // Lanai: Lanai 32-bit
117 {ZigLLVM_amdil64, ZigLLVM_NoSubArch},118 ZigLLVM_wasm32, // WebAssembly with 32-bit pointers
118 {ZigLLVM_hsail, ZigLLVM_NoSubArch},119 ZigLLVM_wasm64, // WebAssembly with 64-bit pointers
119 {ZigLLVM_hsail64, ZigLLVM_NoSubArch},120 ZigLLVM_renderscript32, // 32-bit RenderScript
120 {ZigLLVM_spir, ZigLLVM_NoSubArch},121 ZigLLVM_renderscript64, // 64-bit RenderScript
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},
133};122};
134123
135static const ZigLLVM_VendorType vendor_list[] = {124static const ZigLLVM_VendorType vendor_list[] = {
...@@ -190,7 +179,7 @@ static const Os os_list[] = {...@@ -190,7 +179,7 @@ static const Os os_list[] = {
190};179};
191180
192// Coordinate with zig_llvm.h181// Coordinate with zig_llvm.h
193static const ZigLLVM_EnvironmentType environ_list[] = {182static const ZigLLVM_EnvironmentType abi_list[] = {
194 ZigLLVM_UnknownEnvironment,183 ZigLLVM_UnknownEnvironment,
195184
196 ZigLLVM_GNU,185 ZigLLVM_GNU,
...@@ -225,11 +214,12 @@ size_t target_oformat_count(void) {...@@ -225,11 +214,12 @@ size_t target_oformat_count(void) {
225 return array_length(oformat_list);214 return array_length(oformat_list);
226}215}
227216
228const ZigLLVM_ObjectFormatType get_target_oformat(size_t index) {217ZigLLVM_ObjectFormatType target_oformat_enum(size_t index) {
218 assert(index < array_length(oformat_list));
229 return oformat_list[index];219 return oformat_list[index];
230}220}
231221
232const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat) {222const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) {
233 switch (oformat) {223 switch (oformat) {
234 case ZigLLVM_UnknownObjectFormat: return "unknown";224 case ZigLLVM_UnknownObjectFormat: return "unknown";
235 case ZigLLVM_COFF: return "coff";225 case ZigLLVM_COFF: return "coff";
...@@ -244,22 +234,25 @@ size_t target_arch_count(void) {...@@ -244,22 +234,25 @@ size_t target_arch_count(void) {
244 return array_length(arch_list);234 return array_length(arch_list);
245}235}
246236
247const ArchType *get_target_arch(size_t index) {237ZigLLVM_ArchType target_arch_enum(size_t index) {
248 return &arch_list[index];238 assert(index < array_length(arch_list));
239 return arch_list[index];
249}240}
250241
251size_t target_vendor_count(void) {242size_t target_vendor_count(void) {
252 return array_length(vendor_list);243 return array_length(vendor_list);
253}244}
254245
255ZigLLVM_VendorType get_target_vendor(size_t index) {246ZigLLVM_VendorType target_vendor_enum(size_t index) {
247 assert(index < array_length(vendor_list));
256 return vendor_list[index];248 return vendor_list[index];
257}249}
258250
259size_t target_os_count(void) {251size_t target_os_count(void) {
260 return array_length(os_list);252 return array_length(os_list);
261}253}
262Os get_target_os(size_t index) {254Os target_os_enum(size_t index) {
255 assert(index < array_length(os_list));
263 return os_list[index];256 return os_list[index];
264}257}
265258
...@@ -414,7 +407,7 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) {...@@ -414,7 +407,7 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) {
414 zig_unreachable();407 zig_unreachable();
415}408}
416409
417const char *get_target_os_name(Os os_type) {410const char *target_os_name(Os os_type) {
418 switch (os_type) {411 switch (os_type) {
419 case OsFreestanding:412 case OsFreestanding:
420 return "freestanding";413 return "freestanding";
...@@ -460,78 +453,257 @@ const char *get_target_os_name(Os os_type) {...@@ -460,78 +453,257 @@ const char *get_target_os_name(Os os_type) {
460 zig_unreachable();453 zig_unreachable();
461}454}
462455
463size_t target_environ_count(void) {456size_t target_abi_count(void) {
464 return array_length(environ_list);457 return array_length(abi_list);
458}
459ZigLLVM_EnvironmentType target_abi_enum(size_t index) {
460 assert(index < array_length(abi_list));
461 return abi_list[index];
465}462}
466ZigLLVM_EnvironmentType get_target_environ(size_t index) {463const char *target_abi_name(ZigLLVM_EnvironmentType abi) {
467 return environ_list[index];464 if (abi == ZigLLVM_UnknownEnvironment)
465 return "none";
466 return ZigLLVMGetEnvironmentTypeName(abi);
468}467}
469468
470void get_native_target(ZigTarget *target) {469void get_native_target(ZigTarget *target) {
471 ZigLLVM_OSType os_type;470 ZigLLVM_OSType os_type;
471 ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
472 ZigLLVMGetNativeTarget(472 ZigLLVMGetNativeTarget(
473 &target->arch.arch,473 &target->arch,
474 &target->arch.sub_arch,474 &target->sub_arch,
475 &target->vendor,475 &target->vendor,
476 &os_type,476 &os_type,
477 &target->env_type,477 &target->abi,
478 &target->oformat);478 &oformat);
479 target->os = get_zig_os_type(os_type);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}
481485
482void get_unknown_target(ZigTarget *target) {486Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,
483 target->arch.arch = ZigLLVM_UnknownArch;487 const char *archsub_ptr, size_t archsub_len)
484 target->arch.sub_arch = ZigLLVM_NoSubArch;488{
485 target->vendor = ZigLLVM_UnknownVendor;489 for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
486 target->os = OsFreestanding;490 ZigLLVM_ArchType arch = arch_list[arch_i];
487 target->env_type = ZigLLVM_UnknownEnvironment;491 SubArchList sub_arch_list = target_subarch_list(arch);
488 target->oformat = ZigLLVM_UnknownObjectFormat;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}
490514
491static void get_arch_name_raw(char *out_str, ZigLLVM_ArchType arch, ZigLLVM_SubArchType sub_arch) {515SubArchList target_subarch_list(ZigLLVM_ArchType arch) {
492 const char *sub_str = (sub_arch == ZigLLVM_NoSubArch) ? "" : ZigLLVMGetSubArchTypeName(sub_arch);516 switch (arch) {
493 sprintf(out_str, "%s%s", ZigLLVMGetArchTypeName(arch), sub_str);517 case ZigLLVM_UnknownArch:
494}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;
495528
496void get_arch_name(char *out_str, const ArchType *arch) {529 case ZigLLVM_kalimba:
497 return get_arch_name_raw(out_str, arch->arch, arch->sub_arch);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}
499578
500int parse_target_arch(const char *str, ArchType *out_arch) {579size_t target_subarch_count(SubArchList sub_arch_list) {
501 for (size_t i = 0; i < array_length(arch_list); i += 1) {580 switch (sub_arch_list) {
502 const ArchType *arch = &arch_list[i];581 case SubArchListNone:
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;
507 return 0;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
595ZigLLVM_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
615const char *target_subarch_name(ZigLLVM_SubArchType subarch) {
616 return ZigLLVMGetSubArchTypeName(subarch);
617}
618
619size_t target_subarch_list_count(void) {
620 return array_length(subarch_list_list);
621}
622
623SubArchList target_subarch_list_enum(size_t index) {
624 assert(index < array_length(subarch_list_list));
625 return subarch_list_list[index];
626}
627
628const 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}
512643
513int parse_target_os(const char *str, Os *out_os) {644Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) {
514 for (size_t i = 0; i < array_length(os_list); i += 1) {645 for (size_t i = 0; i < array_length(os_list); i += 1) {
515 Os os = os_list[i];646 Os os = os_list[i];
516 const char *os_name = get_target_os_name(os);647 const char *os_name = target_os_name(os);
517 if (strcmp(os_name, str) == 0) {648 if (mem_eql_str(os_ptr, os_len, os_name)) {
518 *out_os = os;649 *out_os = os;
519 return 0;650 return ErrorNone;
520 }651 }
521 }652 }
522 return ErrorFileNotFound;653 return ErrorUnknownOperatingSystem;
523}654}
524655
525int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *out_environ) {656Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, size_t abi_len) {
526 for (size_t i = 0; i < array_length(environ_list); i += 1) {657 for (size_t i = 0; i < array_length(abi_list); i += 1) {
527 ZigLLVM_EnvironmentType env_type = environ_list[i];658 ZigLLVM_EnvironmentType abi = abi_list[i];
528 const char *environ_name = ZigLLVMGetEnvironmentTypeName(env_type);659 const char *abi_name = target_abi_name(abi);
529 if (strcmp(environ_name, str) == 0) {660 if (mem_eql_str(abi_ptr, abi_len, abi_name)) {
530 *out_environ = env_type;661 *out_abi = abi;
531 return 0;662 return ErrorNone;
663 }
664 }
665 return ErrorUnknownABI;
666}
667
668Error 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
705const char *target_arch_name(ZigLLVM_ArchType arch) {
706 return ZigLLVMGetArchTypeName(arch);
535}707}
536708
537void init_all_targets(void) {709void init_all_targets(void) {
...@@ -543,121 +715,39 @@ void init_all_targets(void) {...@@ -543,121 +715,39 @@ void init_all_targets(void) {
543}715}
544716
545void get_target_triple(Buf *triple, const ZigTarget *target) {717void get_target_triple(Buf *triple, const ZigTarget *target) {
546 char arch_name[50];
547 get_arch_name(arch_name, &target->arch);
548
549 buf_resize(triple, 0);718 buf_resize(triple, 0);
550719 buf_appendf(triple, "%s%s-%s-%s-%s",
551 // LLVM WebAssembly output support requires the target to be activated at720 ZigLLVMGetArchTypeName(target->arch),
552 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.721 ZigLLVMGetSubArchTypeName(target->sub_arch),
553 //722 ZigLLVMGetVendorTypeName(target->vendor),
554 // LLVM determines the output format based on the environment suffix,723 ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
555 // defaulting to an object based on the architecture. The default format in724 ZigLLVMGetEnvironmentTypeName(target->abi));
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 }
571}725}
572726
573static bool is_os_darwin(ZigTarget *target) {727bool target_is_darwin(const ZigTarget *target) {
574 switch (target->os) {728 switch (target->os) {
575 case OsMacOSX:729 case OsMacOSX:
576 case OsIOS:730 case OsIOS:
731 case OsWatchOS:
732 case OsTvOS:
577 return true;733 return true;
578 default:734 default:
579 return false;735 return false;
580 }736 }
581}737}
582738
583void resolve_target_object_format(ZigTarget *target) {739ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) {
584 if (target->oformat != ZigLLVM_UnknownObjectFormat) {740 if (target->os == OsUefi || target->os == OsWindows) {
585 return;741 return ZigLLVM_COFF;
742 } else if (target_is_darwin(target)) {
743 return ZigLLVM_MachO;
586 }744 }
587745 if (target->arch == ZigLLVM_wasm32 ||
588 switch (target->arch.arch) {746 target->arch == ZigLLVM_wasm64)
589 case ZigLLVM_UnknownArch:747 {
590 case ZigLLVM_aarch64:748 return ZigLLVM_Wasm;
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;
660 }749 }
750 return ZigLLVM_ELF;
661}751}
662752
663// See lib/Support/Triple.cpp in LLVM for the source of this data.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,7 +818,7 @@ static int get_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
728uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {818uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
729 switch (target->os) {819 switch (target->os) {
730 case OsFreestanding:820 case OsFreestanding:
731 switch (target->arch.arch) {821 switch (target->arch) {
732 case ZigLLVM_msp430:822 case ZigLLVM_msp430:
733 switch (id) {823 switch (id) {
734 case CIntTypeShort:824 case CIntTypeShort:
...@@ -756,7 +846,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -756,7 +846,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
756 return 32;846 return 32;
757 case CIntTypeLong:847 case CIntTypeLong:
758 case CIntTypeULong:848 case CIntTypeULong:
759 return get_arch_pointer_bit_width(target->arch.arch);849 return get_arch_pointer_bit_width(target->arch);
760 case CIntTypeLongLong:850 case CIntTypeLongLong:
761 case CIntTypeULongLong:851 case CIntTypeULongLong:
762 return 64;852 return 64;
...@@ -768,6 +858,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -768,6 +858,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
768 case OsMacOSX:858 case OsMacOSX:
769 case OsZen:859 case OsZen:
770 case OsFreeBSD:860 case OsFreeBSD:
861 case OsNetBSD:
771 case OsOpenBSD:862 case OsOpenBSD:
772 switch (id) {863 switch (id) {
773 case CIntTypeShort:864 case CIntTypeShort:
...@@ -778,7 +869,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -778,7 +869,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
778 return 32;869 return 32;
779 case CIntTypeLong:870 case CIntTypeLong:
780 case CIntTypeULong:871 case CIntTypeULong:
781 return get_arch_pointer_bit_width(target->arch.arch);872 return get_arch_pointer_bit_width(target->arch);
782 case CIntTypeLongLong:873 case CIntTypeLongLong:
783 case CIntTypeULongLong:874 case CIntTypeULongLong:
784 return 64;875 return 64;
...@@ -808,7 +899,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -808,7 +899,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
808 case OsIOS:899 case OsIOS:
809 case OsKFreeBSD:900 case OsKFreeBSD:
810 case OsLv2:901 case OsLv2:
811 case OsNetBSD:
812 case OsSolaris:902 case OsSolaris:
813 case OsHaiku:903 case OsHaiku:
814 case OsMinix:904 case OsMinix:
...@@ -835,23 +925,27 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -835,23 +925,27 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
835 zig_unreachable();925 zig_unreachable();
836}926}
837927
838const char *target_o_file_ext(ZigTarget *target) {928bool target_allows_addr_zero(const ZigTarget *target) {
839 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {929 return target->os == OsFreestanding;
930}
931
932const char *target_o_file_ext(const ZigTarget *target) {
933 if (target->abi == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
840 return ".obj";934 return ".obj";
841 } else {935 } else {
842 return ".o";936 return ".o";
843 }937 }
844}938}
845939
846const char *target_asm_file_ext(ZigTarget *target) {940const char *target_asm_file_ext(const ZigTarget *target) {
847 return ".s";941 return ".s";
848}942}
849943
850const char *target_llvm_ir_file_ext(ZigTarget *target) {944const char *target_llvm_ir_file_ext(const ZigTarget *target) {
851 return ".ll";945 return ".ll";
852}946}
853947
854const char *target_exe_file_ext(ZigTarget *target) {948const char *target_exe_file_ext(const ZigTarget *target) {
855 if (target->os == OsWindows) {949 if (target->os == OsWindows) {
856 return ".exe";950 return ".exe";
857 } else if (target->os == OsUefi) {951 } else if (target->os == OsUefi) {
...@@ -861,7 +955,9 @@ const char *target_exe_file_ext(ZigTarget *target) {...@@ -861,7 +955,9 @@ const char *target_exe_file_ext(ZigTarget *target) {
861 }955 }
862}956}
863957
864const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {958const 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 if (target->os == OsWindows || target->os == OsUefi) {961 if (target->os == OsWindows || target->os == OsUefi) {
866 if (is_static) {962 if (is_static) {
867 return ".lib";963 return ".lib";
...@@ -872,7 +968,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio...@@ -872,7 +968,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
872 if (is_static) {968 if (is_static) {
873 return ".a";969 return ".a";
874 } else {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,8 +979,8 @@ enum FloatAbi {
883 FloatAbiSoftFp,979 FloatAbiSoftFp,
884};980};
885981
886static FloatAbi get_float_abi(ZigTarget *target) {982static FloatAbi get_float_abi(const ZigTarget *target) {
887 const ZigLLVM_EnvironmentType env = target->env_type;983 const ZigLLVM_EnvironmentType env = target->abi;
888 if (env == ZigLLVM_GNUEABIHF ||984 if (env == ZigLLVM_GNUEABIHF ||
889 env == ZigLLVM_EABIHF ||985 env == ZigLLVM_EABIHF ||
890 env == ZigLLVM_MuslEABIHF)986 env == ZigLLVM_MuslEABIHF)
...@@ -899,64 +995,153 @@ static bool is_64_bit(ZigLLVM_ArchType arch) {...@@ -899,64 +995,153 @@ static bool is_64_bit(ZigLLVM_ArchType arch) {
899 return get_arch_pointer_bit_width(arch) == 64;995 return get_arch_pointer_bit_width(arch) == 64;
900}996}
901997
902Buf *target_dynamic_linker(ZigTarget *target) {998const char *target_dynamic_linker(const ZigTarget *target) {
903 const ZigLLVM_ArchType arch = target->arch.arch;999 switch (target->os) {
904 const ZigLLVM_EnvironmentType env = target->env_type;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 }
9051013
906 if (env == ZigLLVM_Android) {1014 switch (target->arch) {
907 if (is_64_bit(arch)) {1015 case ZigLLVM_UnknownArch:
908 return buf_create_from_str("/system/bin/linker64");1016 zig_unreachable();
909 } else {1017 case ZigLLVM_x86:
910 return buf_create_from_str("/system/bin/linker");1018 case ZigLLVM_sparc:
911 }1019 case ZigLLVM_sparcel:
912 } else if (arch == ZigLLVM_x86 ||1020 return "/lib/ld-linux.so.2";
913 arch == ZigLLVM_sparc ||1021
914 arch == ZigLLVM_sparcel)1022 case ZigLLVM_aarch64:
915 {1023 return "/lib/ld-linux-aarch64.so.1";
916 return buf_create_from_str("/lib/ld-linux.so.2");1024
917 } else if (arch == ZigLLVM_aarch64) {1025 case ZigLLVM_aarch64_be:
918 return buf_create_from_str("/lib/ld-linux-aarch64.so.1");1026 return "/lib/ld-linux-aarch64_be.so.1";
919 } else if (arch == ZigLLVM_aarch64_be) {1027
920 return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1");1028 case ZigLLVM_arm:
921 } else if (arch == ZigLLVM_arm || arch == ZigLLVM_thumb) {1029 case ZigLLVM_thumb:
922 if (get_float_abi(target) == FloatAbiHard) {1030 if (get_float_abi(target) == FloatAbiHard) {
923 return buf_create_from_str("/lib/ld-linux-armhf.so.3");1031 return "/lib/ld-linux-armhf.so.3";
924 } else {1032 } else {
925 return buf_create_from_str("/lib/ld-linux.so.3");1033 return "/lib/ld-linux.so.3";
926 }1034 }
927 } else if (arch == ZigLLVM_armeb || arch == ZigLLVM_thumbeb) {1035
928 if (get_float_abi(target) == FloatAbiHard) {1036 case ZigLLVM_armeb:
929 return buf_create_from_str("/lib/ld-linux-armhf.so.3");1037 case ZigLLVM_thumbeb:
930 } else {1038 if (get_float_abi(target) == FloatAbiHard) {
931 return buf_create_from_str("/lib/ld-linux.so.3");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 ||1110 case OsFreestanding:
934 arch == ZigLLVM_mips64 || arch == ZigLLVM_mips64el)1111 case OsIOS:
935 {1112 case OsTvOS:
936 // when you want to solve this TODO, grep clang codebase for1113 case OsWatchOS:
937 // getLinuxDynamicLinker1114 case OsMacOSX:
938 zig_panic("TODO figure out MIPS dynamic linker name");1115 return nullptr;
939 } else if (arch == ZigLLVM_ppc) {1116
940 return buf_create_from_str("/lib/ld.so.1");1117 case OsAnanas:
941 } else if (arch == ZigLLVM_ppc64) {1118 case OsCloudABI:
942 return buf_create_from_str("/lib64/ld64.so.2");1119 case OsDragonFly:
943 } else if (arch == ZigLLVM_ppc64le) {1120 case OsFuchsia:
944 return buf_create_from_str("/lib64/ld64.so.2");1121 case OsKFreeBSD:
945 } else if (arch == ZigLLVM_systemz) {1122 case OsLv2:
946 return buf_create_from_str("/lib64/ld64.so.1");1123 case OsOpenBSD:
947 } else if (arch == ZigLLVM_sparcv9) {1124 case OsSolaris:
948 return buf_create_from_str("/lib64/ld-linux.so.2");1125 case OsWindows:
949 } else if (arch == ZigLLVM_x86_64 &&1126 case OsHaiku:
950 env == ZigLLVM_GNUX32)1127 case OsMinix:
951 {1128 case OsRTEMS:
952 return buf_create_from_str("/libx32/ld-linux-x32.so.2");1129 case OsNaCl:
953 } else if (arch == ZigLLVM_x86_64 &&1130 case OsCNK:
954 (env == ZigLLVM_Musl || env == ZigLLVM_MuslEABI || env == ZigLLVM_MuslEABIHF))1131 case OsAIX:
955 {1132 case OsCUDA:
956 return buf_create_from_str("/lib/ld-musl-x86_64.so.1");1133 case OsNVCL:
957 } else {1134 case OsAMDHSA:
958 return buf_create_from_str("/lib64/ld-linux-x86-64.so.2");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}
9611146
962bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) {1147bool 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,15 +1152,15 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
967 return true;1152 return true;
968 }1153 }
9691154
970 if (guest_target->os == host_target->os && guest_target->arch.arch == host_target->arch.arch &&1155 if (guest_target->os == host_target->os && guest_target->arch == host_target->arch &&
971 guest_target->arch.sub_arch == host_target->arch.sub_arch)1156 guest_target->sub_arch == host_target->sub_arch)
972 {1157 {
973 // OS, arch, and sub-arch match1158 // OS, arch, and sub-arch match
974 return true;1159 return true;
975 }1160 }
9761161
977 if (guest_target->os == OsWindows && host_target->os == OsWindows &&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 // 64-bit windows can run 32-bit programs1165 // 64-bit windows can run 32-bit programs
981 return true;1166 return true;
...@@ -984,8 +1169,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target...@@ -984,8 +1169,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
984 return false;1169 return false;
985}1170}
9861171
987const char *arch_stack_pointer_register_name(const ArchType *arch) {1172const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
988 switch (arch->arch) {1173 switch (arch) {
989 case ZigLLVM_UnknownArch:1174 case ZigLLVM_UnknownArch:
990 zig_unreachable();1175 zig_unreachable();
991 case ZigLLVM_x86:1176 case ZigLLVM_x86:
...@@ -1047,7 +1232,7 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {...@@ -1047,7 +1232,7 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {
1047}1232}
10481233
1049bool target_is_arm(const ZigTarget *target) {1234bool target_is_arm(const ZigTarget *target) {
1050 switch (target->arch.arch) {1235 switch (target->arch) {
1051 case ZigLLVM_UnknownArch:1236 case ZigLLVM_UnknownArch:
1052 zig_unreachable();1237 zig_unreachable();
1053 case ZigLLVM_aarch64:1238 case ZigLLVM_aarch64:
...@@ -1105,3 +1290,73 @@ bool target_is_arm(const ZigTarget *target) {...@@ -1105,3 +1290,73 @@ bool target_is_arm(const ZigTarget *target) {
1105 }1290 }
1106 zig_unreachable();1291 zig_unreachable();
1107}1292}
1293
1294// Valgrind supports more, but Zig does not support them yet.
1295bool 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
1308bool 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
1315bool 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
1321ZigLLVM_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,11 +12,6 @@
1212
13struct Buf;13struct Buf;
1414
15struct ArchType {
16 ZigLLVM_ArchType arch;
17 ZigLLVM_SubArchType sub_arch;
18};
19
20// Synchronize with target.cpp::os_list15// Synchronize with target.cpp::os_list
21enum Os {16enum Os {
22 OsFreestanding,17 OsFreestanding,
...@@ -57,6 +52,15 @@ enum Os {...@@ -57,6 +52,15 @@ enum Os {
57 OsUefi,52 OsUefi,
58};53};
5954
55// Synchronize with target.cpp::subarch_list_list
56enum SubArchList {
57 SubArchListNone,
58 SubArchListArm32,
59 SubArchListArm64,
60 SubArchListKalimba,
61 SubArchListMips,
62};
63
60enum TargetSubsystem {64enum TargetSubsystem {
61 TargetSubsystemAuto, // Zig should infer the subsystem65 TargetSubsystemAuto, // Zig should infer the subsystem
62 TargetSubsystemConsole,66 TargetSubsystemConsole,
...@@ -70,11 +74,12 @@ enum TargetSubsystem {...@@ -70,11 +74,12 @@ enum TargetSubsystem {
70};74};
7175
72struct ZigTarget {76struct ZigTarget {
73 ArchType arch;77 ZigLLVM_ArchType arch;
78 ZigLLVM_SubArchType sub_arch;
74 ZigLLVM_VendorType vendor;79 ZigLLVM_VendorType vendor;
75 Os os;80 Os os;
76 ZigLLVM_EnvironmentType env_type;81 ZigLLVM_EnvironmentType abi;
77 ZigLLVM_ObjectFormatType oformat;82 bool is_native;
78};83};
7984
80enum CIntType {85enum CIntType {
...@@ -90,53 +95,71 @@ enum CIntType {...@@ -90,53 +95,71 @@ enum CIntType {
90 CIntTypeCount,95 CIntTypeCount,
91};96};
9297
98Error target_parse_triple(ZigTarget *target, const char *triple);
99Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub,
100 const char *archsub_ptr, size_t archsub_len);
101Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
102Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
103
93size_t target_arch_count(void);104size_t target_arch_count(void);
94const ArchType *get_target_arch(size_t index);105ZigLLVM_ArchType target_arch_enum(size_t index);
95void get_arch_name(char *out_str, const ArchType *arch);106const char *target_arch_name(ZigLLVM_ArchType arch);
107
108SubArchList target_subarch_list(ZigLLVM_ArchType arch);
109size_t target_subarch_count(SubArchList sub_arch_list);
110ZigLLVM_SubArchType target_subarch_enum(SubArchList subarch_list, size_t index);
111const char *target_subarch_name(ZigLLVM_SubArchType subarch);
96112
97const char *arch_stack_pointer_register_name(const ArchType *arch);113size_t target_subarch_list_count(void);
114SubArchList target_subarch_list_enum(size_t index);
115const char *target_subarch_list_name(SubArchList sub_arch_list);
116
117const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch);
98118
99size_t target_vendor_count(void);119size_t target_vendor_count(void);
100ZigLLVM_VendorType get_target_vendor(size_t index);120ZigLLVM_VendorType target_vendor_enum(size_t index);
101121
102size_t target_os_count(void);122size_t target_os_count(void);
103Os get_target_os(size_t index);123Os target_os_enum(size_t index);
104const char *get_target_os_name(Os os_type);124const char *target_os_name(Os os_type);
105125
106size_t target_environ_count(void);126size_t target_abi_count(void);
107ZigLLVM_EnvironmentType get_target_environ(size_t index);127ZigLLVM_EnvironmentType target_abi_enum(size_t index);
128const char *target_abi_name(ZigLLVM_EnvironmentType abi);
129ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os);
108130
109131
110size_t target_oformat_count(void);132size_t target_oformat_count(void);
111const ZigLLVM_ObjectFormatType get_target_oformat(size_t index);133ZigLLVM_ObjectFormatType target_oformat_enum(size_t index);
112const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat);134const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat);
135ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target);
113136
114void get_native_target(ZigTarget *target);137void get_native_target(ZigTarget *target);
115void get_unknown_target(ZigTarget *target);138void get_target_triple(Buf *triple, const ZigTarget *target);
116
117int parse_target_arch(const char *str, ArchType *arch);
118int parse_target_os(const char *str, Os *os);
119int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *env_type);
120139
121void init_all_targets(void);140void init_all_targets(void);
122141
123void get_target_triple(Buf *triple, const ZigTarget *target);
124
125void resolve_target_object_format(ZigTarget *target);142void resolve_target_object_format(ZigTarget *target);
126143
127uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);144uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
128145
129const char *target_o_file_ext(ZigTarget *target);146const char *target_o_file_ext(const ZigTarget *target);
130const char *target_asm_file_ext(ZigTarget *target);147const char *target_asm_file_ext(const ZigTarget *target);
131const char *target_llvm_ir_file_ext(ZigTarget *target);148const char *target_llvm_ir_file_ext(const ZigTarget *target);
132const char *target_exe_file_ext(ZigTarget *target);149const char *target_exe_file_ext(const ZigTarget *target);
133const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch);150const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
151 size_t version_major, size_t version_minor, size_t version_patch);
134152
135Buf *target_dynamic_linker(ZigTarget *target);153const char *target_dynamic_linker(const ZigTarget *target);
136154
137bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);155bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
138ZigLLVM_OSType get_llvm_os_type(Os os_type);156ZigLLVM_OSType get_llvm_os_type(Os os_type);
139157
140bool target_is_arm(const ZigTarget *target);158bool target_is_arm(const ZigTarget *target);
159bool target_allows_addr_zero(const ZigTarget *target);
160bool target_has_valgrind_support(const ZigTarget *target);
161bool target_is_darwin(const ZigTarget *target);
162bool target_requires_libc(const ZigTarget *target);
163bool target_supports_fpic(const ZigTarget *target);
141164
142#endif165#endif
src/tokenizer.cpp+18-1
...@@ -221,6 +221,7 @@ enum TokenizeState {...@@ -221,6 +221,7 @@ enum TokenizeState {
221 TokenizeStateError,221 TokenizeStateError,
222 TokenizeStateLBracket,222 TokenizeStateLBracket,
223 TokenizeStateLBracketStar,223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
224};225};
225226
226227
...@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
846 switch (c) {847 switch (c) {
847 case '*':848 case '*':
848 t.state = TokenizeStateLBracketStar;849 t.state = TokenizeStateLBracketStar;
849 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
850 break;850 break;
851 default:851 default:
852 // reinterpret as just an lbracket852 // reinterpret as just an lbracket
...@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
857 }857 }
858 break;858 break;
859 case TokenizeStateLBracketStar: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 switch (c) {875 switch (c) {
861 case ']':876 case ']':
862 end_token(&t);877 end_token(&t);
...@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
1491 case TokenizeStateLineStringContinue:1506 case TokenizeStateLineStringContinue:
1492 case TokenizeStateLineStringContinueC:1507 case TokenizeStateLineStringContinueC:
1493 case TokenizeStateLBracketStar:1508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
1494 tokenize_error(&t, "unexpected EOF");1510 tokenize_error(&t, "unexpected EOF");
1495 break;1511 break;
1496 case TokenizeStateLineComment:1512 case TokenizeStateLineComment:
...@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {...@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
1528 case TokenIdBitShiftRightEq: return ">>=";1544 case TokenIdBitShiftRightEq: return ">>=";
1529 case TokenIdBitXorEq: return "^=";1545 case TokenIdBitXorEq: return "^=";
1530 case TokenIdBracketStarBracket: return "[*]";1546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
1531 case TokenIdCharLiteral: return "CharLiteral";1548 case TokenIdCharLiteral: return "CharLiteral";
1532 case TokenIdCmpEq: return "==";1549 case TokenIdCmpEq: return "==";
1533 case TokenIdCmpGreaterOrEq: return ">=";1550 case TokenIdCmpGreaterOrEq: return ">=";
src/tokenizer.hpp+1
...@@ -29,6 +29,7 @@ enum TokenId {...@@ -29,6 +29,7 @@ enum TokenId {
29 TokenIdBitShiftRightEq,29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,30 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
32 TokenIdCharLiteral,33 TokenIdCharLiteral,
33 TokenIdCmpEq,34 TokenIdCmpEq,
34 TokenIdCmpGreaterOrEq,35 TokenIdCmpGreaterOrEq,
src/translate_c.cpp+945-1697
...@@ -4,7 +4,6 @@...@@ -4,7 +4,6 @@
4 * This file is part of zig, which is MIT licensed.4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT5 * See http://opensource.org/licenses/MIT
6 */6 */
7
8#include "all_types.hpp"7#include "all_types.hpp"
9#include "analyze.hpp"8#include "analyze.hpp"
10#include "c_tokenizer.hpp"9#include "c_tokenizer.hpp"
...@@ -13,7 +12,7 @@...@@ -13,7 +12,7 @@
13#include "os.hpp"12#include "os.hpp"
14#include "translate_c.hpp"13#include "translate_c.hpp"
15#include "parser.hpp"14#include "parser.hpp"
1615#include "zig_clang.h"
1716
18#if __GNUC__ >= 817#if __GNUC__ >= 8
19#pragma GCC diagnostic push18#pragma GCC diagnostic push
...@@ -30,8 +29,6 @@...@@ -30,8 +29,6 @@
3029
31#include <string.h>30#include <string.h>
3231
33using namespace clang;
34
35struct Alias {32struct Alias {
36 Buf *new_name;33 Buf *new_name;
37 Buf *canon_name;34 Buf *canon_name;
...@@ -87,13 +84,13 @@ struct Context {...@@ -87,13 +84,13 @@ struct Context {
87 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;84 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
88 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;85 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
89 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;86 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
90 SourceManager *source_manager;87 ZigClangSourceManager *source_manager;
91 ZigList<Alias> aliases;88 ZigList<Alias> aliases;
92 AstNode *source_node;89 AstNode *source_node;
93 bool warnings_on;90 bool warnings_on;
9491
95 CodeGen *codegen;92 CodeGen *codegen;
96 ASTContext *ctx;93 ZigClangASTContext *ctx;
9794
98 TransScopeRoot *global_scope;95 TransScopeRoot *global_scope;
99 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;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,22 +114,38 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
117114
118static TransScopeBlock *trans_scope_block_find(TransScope *scope);115static TransScopeBlock *trans_scope_block_find(TransScope *scope);
119116
120static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);117static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
121static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);118static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl);
122static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);119static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl);
123120
124static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,121static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
125 ResultUsed result_used, TransLRValue lrval,122 ResultUsed result_used, TransLRValue lrval,
126 AstNode **out_node, TransScope **out_child_scope,123 AstNode **out_node, TransScope **out_child_scope,
127 TransScope **out_node_scope);124 TransScope **out_node_scope);
128static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);125static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
129static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);126static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
130static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);127static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
131static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);128static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
132static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc);129static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc);
130
131static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
132 ZigClangSourceLocation dest;
133 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangSourceLocation));
134 return dest;
135}
136static ZigClangQualType bitcast(clang::QualType src) {
137 ZigClangQualType dest;
138 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
139 return dest;
140}
141static clang::QualType bitcast(ZigClangQualType src) {
142 clang::QualType dest;
143 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
144 return dest;
145}
133146
134ATTRIBUTE_PRINTF(3, 4)147ATTRIBUTE_PRINTF(3, 4)
135static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {148static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) {
136 if (!c->warnings_on) {149 if (!c->warnings_on) {
137 return;150 return;
138 }151 }
...@@ -142,16 +155,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma...@@ -142,16 +155,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
142 Buf *msg = buf_vprintf(format, ap);155 Buf *msg = buf_vprintf(format, ap);
143 va_end(ap);156 va_end(ap);
144157
145 StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl));158 ZigClangSourceLocation sl = bitcast(clang_sl);
146 const char *filename_bytes = (const char *)filename.bytes_begin();159 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
160 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
147 Buf *path;161 Buf *path;
148 if (filename_bytes) {162 if (filename_bytes) {
149 path = buf_create_from_str(filename_bytes);163 path = buf_create_from_str(filename_bytes);
150 } else {164 } else {
151 path = buf_sprintf("(no file)");165 path = buf_sprintf("(no file)");
152 }166 }
153 unsigned line = c->source_manager->getSpellingLineNumber(sl);167 unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
154 unsigned column = c->source_manager->getSpellingColumnNumber(sl);168 unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
155 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));169 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
156}170}
157171
...@@ -292,11 +306,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod...@@ -292,11 +306,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
292 node);306 node);
293}307}
294308
309static 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
295static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {321static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
296 AstNode *node = trans_create_node(c, NodeTypePointerType);322 AstNode *node = trans_create_node(c, NodeTypePointerType);
297 node->data.pointer_type.star_token = allocate<ZigToken>(1);323 node->data.pointer_type.star_token = allocate<ZigToken>(1);
298 node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;324 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
299 node->data.pointer_type.is_const = is_const;
300 node->data.pointer_type.is_const = is_const;325 node->data.pointer_type.is_const = is_const;
301 node->data.pointer_type.is_volatile = is_volatile;326 node->data.pointer_type.is_volatile = is_volatile;
302 node->data.pointer_type.op_expr = child_node;327 node->data.pointer_type.op_expr = child_node;
...@@ -461,15 +486,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {...@@ -461,15 +486,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {
461 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());486 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
462}487}
463488
464static const char *decl_name(const Decl *decl) {489static const char *decl_name(const clang::Decl *decl) {
465 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);490 const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
466 return (const char *)named_decl->getName().bytes_begin();491 return (const char *)named_decl->getName().bytes_begin();
467}492}
468493
469static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {494static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
470 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);495 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
471 node->data.int_literal.bigint = allocate<BigInt>(1);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 if (!is_negative) {498 if (!is_negative) {
474 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);499 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
475 return node;500 return node;
...@@ -480,41 +505,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)...@@ -480,41 +505,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
480505
481}506}
482507
483static const Type *qual_type_canon(QualType qt) {508static const clang::Type *qual_type_canon(clang::QualType qt) {
484 return qt.getCanonicalType().getTypePtr();509 return qt.getCanonicalType().getTypePtr();
485}510}
486511
487static QualType get_expr_qual_type(Context *c, const Expr *expr) {512static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) {
488 // String literals in C are `char *` but they should really be `const char *`.513 // String literals in C are `char *` but they should really be `const char *`.
489 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {514 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
490 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);515 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
491 if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {516 if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
492 const Expr *sub_expr = cast_expr->getSubExpr();517 const clang::Expr *sub_expr = cast_expr->getSubExpr();
493 if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {518 if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
494 QualType array_qt = sub_expr->getType();519 clang::QualType array_qt = sub_expr->getType();
495 const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr());520 const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr());
496 QualType pointee_qt = array_type->getElementType();521 clang::QualType pointee_qt = array_type->getElementType();
497 pointee_qt.addConst();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 return expr->getType();527 return expr->getType();
503}528}
504529
505static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {530static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
506 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {531 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
507 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);532 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
508 return get_expr_qual_type(c, cast_expr->getSubExpr());533 return get_expr_qual_type(c, cast_expr->getSubExpr());
509 }534 }
510 return expr->getType();535 return expr->getType();
511}536}
512537
513static AstNode *get_expr_type(Context *c, const Expr *expr) {538static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
514 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc());539 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc());
515}540}
516541
517static bool qual_types_equal(QualType t1, QualType t2) {542static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
518 if (t1.isConstQualified() != t2.isConstQualified()) {543 if (t1.isConstQualified() != t2.isConstQualified()) {
519 return false;544 return false;
520 }545 }
...@@ -531,37 +556,37 @@ static bool is_c_void_type(AstNode *node) {...@@ -531,37 +556,37 @@ static bool is_c_void_type(AstNode *node) {
531 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));556 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
532}557}
533558
534static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {559static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
535 QualType t1 = get_expr_qual_type(c, expr1);560 clang::QualType t1 = get_expr_qual_type(c, expr1);
536 QualType t2 = get_expr_qual_type(c, expr2);561 clang::QualType t2 = get_expr_qual_type(c, expr2);
537562
538 return qual_types_equal(t1, t2);563 return qual_types_equal(t1, t2);
539}564}
540565
541static bool qual_type_is_ptr(QualType qt) {566static bool qual_type_is_ptr(clang::QualType qt) {
542 const Type *ty = qual_type_canon(qt);567 const clang::Type *ty = qual_type_canon(qt);
543 return ty->getTypeClass() == Type::Pointer;568 return ty->getTypeClass() == clang::Type::Pointer;
544}569}
545570
546static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {571static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
547 const Type *ty = qual_type_canon(qt);572 const clang::Type *ty = qual_type_canon(qt);
548 *is_ptr = false;573 *is_ptr = false;
549574
550 if (ty->getTypeClass() == Type::Pointer) {575 if (ty->getTypeClass() == clang::Type::Pointer) {
551 *is_ptr = true;576 *is_ptr = true;
552 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);577 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
553 QualType child_qt = pointer_ty->getPointeeType();578 clang::QualType child_qt = pointer_ty->getPointeeType();
554 ty = child_qt.getTypePtr();579 ty = child_qt.getTypePtr();
555 }580 }
556581
557 if (ty->getTypeClass() == Type::FunctionProto) {582 if (ty->getTypeClass() == clang::Type::FunctionProto) {
558 return static_cast<const FunctionProtoType*>(ty);583 return static_cast<const clang::FunctionProtoType*>(ty);
559 }584 }
560585
561 return nullptr;586 return nullptr;
562}587}
563588
564static bool qual_type_is_fn_ptr(QualType qt) {589static bool qual_type_is_fn_ptr(clang::QualType qt) {
565 bool is_ptr;590 bool is_ptr;
566 if (qual_type_get_fn_proto(qt, &is_ptr)) {591 if (qual_type_get_fn_proto(qt, &is_ptr)) {
567 return is_ptr;592 return is_ptr;
...@@ -570,30 +595,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {...@@ -570,30 +595,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {
570 return false;595 return false;
571}596}
572597
573static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {598static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
574 const Type *ty = qt.getTypePtr();599 const clang::Type *ty = qt.getTypePtr();
575 switch (ty->getTypeClass()) {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 switch (builtin_ty->getKind()) {604 switch (builtin_ty->getKind()) {
580 case BuiltinType::Char_U:605 case clang::BuiltinType::Char_U:
581 case BuiltinType::UChar:606 case clang::BuiltinType::UChar:
582 case BuiltinType::Char_S:607 case clang::BuiltinType::Char_S:
583 case BuiltinType::SChar:608 case clang::BuiltinType::SChar:
584 return 8;609 return 8;
585 case BuiltinType::UInt128:610 case clang::BuiltinType::UInt128:
586 case BuiltinType::Int128:611 case clang::BuiltinType::Int128:
587 return 128;612 return 128;
588 default:613 default:
589 return 0;614 return 0;
590 }615 }
591 zig_unreachable();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);620 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
596 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();621 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
597 const char *type_name = decl_name(typedef_decl);622 const char *type_name = decl_name(typedef_decl);
598 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {623 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
599 return 8;624 return 8;
...@@ -614,8 +639,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So...@@ -614,8 +639,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So
614}639}
615640
616641
617static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,642static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
618 const SourceLocation &source_loc)643 const clang::SourceLocation &source_loc)
619{644{
620 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);645 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
621 if (int_bit_width != 0) {646 if (int_bit_width != 0) {
...@@ -633,7 +658,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,...@@ -633,7 +658,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
633// FieldAccess658// FieldAccess
634// FnCall (.builtin = true)659// FnCall (.builtin = true)
635// Symbol "import"660// Symbol "import"
636// StringLiteral "std"661// clang::StringLiteral "std"
637// Symbol "math"662// Symbol "math"
638// Symbol "Log2Int"663// Symbol "Log2Int"
639// zig_type_node664// zig_type_node
...@@ -647,21 +672,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,...@@ -647,21 +672,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
647 return log2int_fn_call;672 return log2int_fn_call;
648}673}
649674
650static bool qual_type_child_is_fn_proto(const QualType &qt) {675static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
651 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {676 if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
652 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());677 const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr());
653 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {678 if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
654 return true;679 return true;
655 }680 }
656 } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {681 } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
657 const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());682 const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr());
658 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());683 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
659 }684 }
660 return false;685 return false;
661}686}
662687
663static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type,688static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
664 QualType src_type, AstNode *expr)689 clang::QualType src_type, AstNode *expr)
665{690{
666 if (qual_types_equal(dest_type, src_type)) {691 if (qual_types_equal(dest_type, src_type)) {
667 return expr;692 return expr;
...@@ -678,72 +703,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,...@@ -678,72 +703,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
678 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);703 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
679}704}
680705
681static bool c_is_signed_integer(Context *c, QualType qt) {706static bool c_is_signed_integer(Context *c, clang::QualType qt) {
682 const Type *c_type = qual_type_canon(qt);707 const clang::Type *c_type = qual_type_canon(qt);
683 if (c_type->getTypeClass() != Type::Builtin)708 if (c_type->getTypeClass() != clang::Type::Builtin)
684 return false;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 switch (builtin_ty->getKind()) {711 switch (builtin_ty->getKind()) {
687 case BuiltinType::SChar:712 case clang::BuiltinType::SChar:
688 case BuiltinType::Short:713 case clang::BuiltinType::Short:
689 case BuiltinType::Int:714 case clang::BuiltinType::Int:
690 case BuiltinType::Long:715 case clang::BuiltinType::Long:
691 case BuiltinType::LongLong:716 case clang::BuiltinType::LongLong:
692 case BuiltinType::Int128:717 case clang::BuiltinType::Int128:
693 case BuiltinType::WChar_S:718 case clang::BuiltinType::WChar_S:
694 return true;719 return true;
695 default:720 default:
696 return false;721 return false;
697 }722 }
698}723}
699724
700static bool c_is_unsigned_integer(Context *c, QualType qt) {725static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
701 const Type *c_type = qual_type_canon(qt);726 const clang::Type *c_type = qual_type_canon(qt);
702 if (c_type->getTypeClass() != Type::Builtin)727 if (c_type->getTypeClass() != clang::Type::Builtin)
703 return false;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 switch (builtin_ty->getKind()) {730 switch (builtin_ty->getKind()) {
706 case BuiltinType::Char_U:731 case clang::BuiltinType::Char_U:
707 case BuiltinType::UChar:732 case clang::BuiltinType::UChar:
708 case BuiltinType::Char_S:733 case clang::BuiltinType::Char_S:
709 case BuiltinType::UShort:734 case clang::BuiltinType::UShort:
710 case BuiltinType::UInt:735 case clang::BuiltinType::UInt:
711 case BuiltinType::ULong:736 case clang::BuiltinType::ULong:
712 case BuiltinType::ULongLong:737 case clang::BuiltinType::ULongLong:
713 case BuiltinType::UInt128:738 case clang::BuiltinType::UInt128:
714 case BuiltinType::WChar_U:739 case clang::BuiltinType::WChar_U:
715 return true;740 return true;
716 default:741 default:
717 return false;742 return false;
718 }743 }
719}744}
720745
721static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {746static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
722 const Type *c_type = qual_type_canon(qt);747 const clang::Type *c_type = qual_type_canon(qt);
723 if (c_type->getTypeClass() != Type::Builtin)748 if (c_type->getTypeClass() != clang::Type::Builtin)
724 return false;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 return builtin_ty->getKind() == kind;751 return builtin_ty->getKind() == kind;
727}752}
728753
729static bool c_is_float(Context *c, QualType qt) {754static bool c_is_float(Context *c, clang::QualType qt) {
730 const Type *c_type = qt.getTypePtr();755 const clang::Type *c_type = qt.getTypePtr();
731 if (c_type->getTypeClass() != Type::Builtin)756 if (c_type->getTypeClass() != clang::Type::Builtin)
732 return false;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 switch (builtin_ty->getKind()) {759 switch (builtin_ty->getKind()) {
735 case BuiltinType::Half:760 case clang::BuiltinType::Half:
736 case BuiltinType::Float:761 case clang::BuiltinType::Float:
737 case BuiltinType::Double:762 case clang::BuiltinType::Double:
738 case BuiltinType::Float128:763 case clang::BuiltinType::Float128:
739 case BuiltinType::LongDouble:764 case clang::BuiltinType::LongDouble:
740 return true;765 return true;
741 default:766 default:
742 return false;767 return false;
743 }768 }
744}769}
745770
746static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {771static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
747 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {772 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
748 // float and signed integer overflow is undefined behavior.773 // float and signed integer overflow is undefined behavior.
749 return false;774 return false;
...@@ -753,23 +778,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {...@@ -753,23 +778,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
753 }778 }
754}779}
755780
756static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) {781static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
757 switch (ty->getTypeClass()) {782 switch (ty->getTypeClass()) {
758 case Type::Builtin: {783 case clang::Type::Builtin: {
759 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);784 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
760 return builtin_ty->getKind() == BuiltinType::Void;785 return builtin_ty->getKind() == clang::BuiltinType::Void;
761 }786 }
762 case Type::Record: {787 case clang::Type::Record: {
763 const RecordType *record_ty = static_cast<const RecordType*>(ty);788 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
764 return record_ty->getDecl()->getDefinition() == nullptr;789 return record_ty->getDecl()->getDefinition() == nullptr;
765 }790 }
766 case Type::Elaborated: {791 case clang::Type::Elaborated: {
767 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);792 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
768 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);793 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
769 }794 }
770 case Type::Typedef: {795 case clang::Type::Typedef: {
771 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);796 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
772 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();797 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
773 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);798 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
774 }799 }
775 default:800 default:
...@@ -777,136 +802,136 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou...@@ -777,136 +802,136 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou
777 }802 }
778}803}
779804
780static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {805static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
781 switch (ty->getTypeClass()) {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 switch (builtin_ty->getKind()) {810 switch (builtin_ty->getKind()) {
786 case BuiltinType::Void:811 case clang::BuiltinType::Void:
787 return trans_create_node_symbol_str(c, "c_void");812 return trans_create_node_symbol_str(c, "c_void");
788 case BuiltinType::Bool:813 case clang::BuiltinType::Bool:
789 return trans_create_node_symbol_str(c, "bool");814 return trans_create_node_symbol_str(c, "bool");
790 case BuiltinType::Char_U:815 case clang::BuiltinType::Char_U:
791 case BuiltinType::UChar:816 case clang::BuiltinType::UChar:
792 case BuiltinType::Char_S:817 case clang::BuiltinType::Char_S:
793 case BuiltinType::Char8:818 case clang::BuiltinType::Char8:
794 return trans_create_node_symbol_str(c, "u8");819 return trans_create_node_symbol_str(c, "u8");
795 case BuiltinType::SChar:820 case clang::BuiltinType::SChar:
796 return trans_create_node_symbol_str(c, "i8");821 return trans_create_node_symbol_str(c, "i8");
797 case BuiltinType::UShort:822 case clang::BuiltinType::UShort:
798 return trans_create_node_symbol_str(c, "c_ushort");823 return trans_create_node_symbol_str(c, "c_ushort");
799 case BuiltinType::UInt:824 case clang::BuiltinType::UInt:
800 return trans_create_node_symbol_str(c, "c_uint");825 return trans_create_node_symbol_str(c, "c_uint");
801 case BuiltinType::ULong:826 case clang::BuiltinType::ULong:
802 return trans_create_node_symbol_str(c, "c_ulong");827 return trans_create_node_symbol_str(c, "c_ulong");
803 case BuiltinType::ULongLong:828 case clang::BuiltinType::ULongLong:
804 return trans_create_node_symbol_str(c, "c_ulonglong");829 return trans_create_node_symbol_str(c, "c_ulonglong");
805 case BuiltinType::Short:830 case clang::BuiltinType::Short:
806 return trans_create_node_symbol_str(c, "c_short");831 return trans_create_node_symbol_str(c, "c_short");
807 case BuiltinType::Int:832 case clang::BuiltinType::Int:
808 return trans_create_node_symbol_str(c, "c_int");833 return trans_create_node_symbol_str(c, "c_int");
809 case BuiltinType::Long:834 case clang::BuiltinType::Long:
810 return trans_create_node_symbol_str(c, "c_long");835 return trans_create_node_symbol_str(c, "c_long");
811 case BuiltinType::LongLong:836 case clang::BuiltinType::LongLong:
812 return trans_create_node_symbol_str(c, "c_longlong");837 return trans_create_node_symbol_str(c, "c_longlong");
813 case BuiltinType::UInt128:838 case clang::BuiltinType::UInt128:
814 return trans_create_node_symbol_str(c, "u128");839 return trans_create_node_symbol_str(c, "u128");
815 case BuiltinType::Int128:840 case clang::BuiltinType::Int128:
816 return trans_create_node_symbol_str(c, "i128");841 return trans_create_node_symbol_str(c, "i128");
817 case BuiltinType::Float:842 case clang::BuiltinType::Float:
818 return trans_create_node_symbol_str(c, "f32");843 return trans_create_node_symbol_str(c, "f32");
819 case BuiltinType::Double:844 case clang::BuiltinType::Double:
820 return trans_create_node_symbol_str(c, "f64");845 return trans_create_node_symbol_str(c, "f64");
821 case BuiltinType::Float128:846 case clang::BuiltinType::Float128:
822 return trans_create_node_symbol_str(c, "f128");847 return trans_create_node_symbol_str(c, "f128");
823 case BuiltinType::Float16:848 case clang::BuiltinType::Float16:
824 return trans_create_node_symbol_str(c, "f16");849 return trans_create_node_symbol_str(c, "f16");
825 case BuiltinType::LongDouble:850 case clang::BuiltinType::LongDouble:
826 return trans_create_node_symbol_str(c, "c_longdouble");851 return trans_create_node_symbol_str(c, "c_longdouble");
827 case BuiltinType::WChar_U:852 case clang::BuiltinType::WChar_U:
828 case BuiltinType::Char16:853 case clang::BuiltinType::Char16:
829 case BuiltinType::Char32:854 case clang::BuiltinType::Char32:
830 case BuiltinType::WChar_S:855 case clang::BuiltinType::WChar_S:
831 case BuiltinType::Half:856 case clang::BuiltinType::Half:
832 case BuiltinType::NullPtr:857 case clang::BuiltinType::NullPtr:
833 case BuiltinType::ObjCId:858 case clang::BuiltinType::ObjCId:
834 case BuiltinType::ObjCClass:859 case clang::BuiltinType::ObjCClass:
835 case BuiltinType::ObjCSel:860 case clang::BuiltinType::ObjCSel:
836 case BuiltinType::OMPArraySection:861 case clang::BuiltinType::OMPArraySection:
837 case BuiltinType::Dependent:862 case clang::BuiltinType::Dependent:
838 case BuiltinType::Overload:863 case clang::BuiltinType::Overload:
839 case BuiltinType::BoundMember:864 case clang::BuiltinType::BoundMember:
840 case BuiltinType::PseudoObject:865 case clang::BuiltinType::PseudoObject:
841 case BuiltinType::UnknownAny:866 case clang::BuiltinType::UnknownAny:
842 case BuiltinType::BuiltinFn:867 case clang::BuiltinType::BuiltinFn:
843 case BuiltinType::ARCUnbridgedCast:868 case clang::BuiltinType::ARCUnbridgedCast:
844 case BuiltinType::ShortAccum:869 case clang::BuiltinType::ShortAccum:
845 case BuiltinType::Accum:870 case clang::BuiltinType::Accum:
846 case BuiltinType::LongAccum:871 case clang::BuiltinType::LongAccum:
847 case BuiltinType::UShortAccum:872 case clang::BuiltinType::UShortAccum:
848 case BuiltinType::UAccum:873 case clang::BuiltinType::UAccum:
849 case BuiltinType::ULongAccum:874 case clang::BuiltinType::ULongAccum:
850875
851 case BuiltinType::OCLImage1dRO:876 case clang::BuiltinType::OCLImage1dRO:
852 case BuiltinType::OCLImage1dArrayRO:877 case clang::BuiltinType::OCLImage1dArrayRO:
853 case BuiltinType::OCLImage1dBufferRO:878 case clang::BuiltinType::OCLImage1dBufferRO:
854 case BuiltinType::OCLImage2dRO:879 case clang::BuiltinType::OCLImage2dRO:
855 case BuiltinType::OCLImage2dArrayRO:880 case clang::BuiltinType::OCLImage2dArrayRO:
856 case BuiltinType::OCLImage2dDepthRO:881 case clang::BuiltinType::OCLImage2dDepthRO:
857 case BuiltinType::OCLImage2dArrayDepthRO:882 case clang::BuiltinType::OCLImage2dArrayDepthRO:
858 case BuiltinType::OCLImage2dMSAARO:883 case clang::BuiltinType::OCLImage2dMSAARO:
859 case BuiltinType::OCLImage2dArrayMSAARO:884 case clang::BuiltinType::OCLImage2dArrayMSAARO:
860 case BuiltinType::OCLImage2dMSAADepthRO:885 case clang::BuiltinType::OCLImage2dMSAADepthRO:
861 case BuiltinType::OCLImage2dArrayMSAADepthRO:886 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
862 case BuiltinType::OCLImage3dRO:887 case clang::BuiltinType::OCLImage3dRO:
863 case BuiltinType::OCLImage1dWO:888 case clang::BuiltinType::OCLImage1dWO:
864 case BuiltinType::OCLImage1dArrayWO:889 case clang::BuiltinType::OCLImage1dArrayWO:
865 case BuiltinType::OCLImage1dBufferWO:890 case clang::BuiltinType::OCLImage1dBufferWO:
866 case BuiltinType::OCLImage2dWO:891 case clang::BuiltinType::OCLImage2dWO:
867 case BuiltinType::OCLImage2dArrayWO:892 case clang::BuiltinType::OCLImage2dArrayWO:
868 case BuiltinType::OCLImage2dDepthWO:893 case clang::BuiltinType::OCLImage2dDepthWO:
869 case BuiltinType::OCLImage2dArrayDepthWO:894 case clang::BuiltinType::OCLImage2dArrayDepthWO:
870 case BuiltinType::OCLImage2dMSAAWO:895 case clang::BuiltinType::OCLImage2dMSAAWO:
871 case BuiltinType::OCLImage2dArrayMSAAWO:896 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
872 case BuiltinType::OCLImage2dMSAADepthWO:897 case clang::BuiltinType::OCLImage2dMSAADepthWO:
873 case BuiltinType::OCLImage2dArrayMSAADepthWO:898 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
874 case BuiltinType::OCLImage3dWO:899 case clang::BuiltinType::OCLImage3dWO:
875 case BuiltinType::OCLImage1dRW:900 case clang::BuiltinType::OCLImage1dRW:
876 case BuiltinType::OCLImage1dArrayRW:901 case clang::BuiltinType::OCLImage1dArrayRW:
877 case BuiltinType::OCLImage1dBufferRW:902 case clang::BuiltinType::OCLImage1dBufferRW:
878 case BuiltinType::OCLImage2dRW:903 case clang::BuiltinType::OCLImage2dRW:
879 case BuiltinType::OCLImage2dArrayRW:904 case clang::BuiltinType::OCLImage2dArrayRW:
880 case BuiltinType::OCLImage2dDepthRW:905 case clang::BuiltinType::OCLImage2dDepthRW:
881 case BuiltinType::OCLImage2dArrayDepthRW:906 case clang::BuiltinType::OCLImage2dArrayDepthRW:
882 case BuiltinType::OCLImage2dMSAARW:907 case clang::BuiltinType::OCLImage2dMSAARW:
883 case BuiltinType::OCLImage2dArrayMSAARW:908 case clang::BuiltinType::OCLImage2dArrayMSAARW:
884 case BuiltinType::OCLImage2dMSAADepthRW:909 case clang::BuiltinType::OCLImage2dMSAADepthRW:
885 case BuiltinType::OCLImage2dArrayMSAADepthRW:910 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
886 case BuiltinType::OCLImage3dRW:911 case clang::BuiltinType::OCLImage3dRW:
887 case BuiltinType::OCLSampler:912 case clang::BuiltinType::OCLSampler:
888 case BuiltinType::OCLEvent:913 case clang::BuiltinType::OCLEvent:
889 case BuiltinType::OCLClkEvent:914 case clang::BuiltinType::OCLClkEvent:
890 case BuiltinType::OCLQueue:915 case clang::BuiltinType::OCLQueue:
891 case BuiltinType::OCLReserveID:916 case clang::BuiltinType::OCLReserveID:
892 case BuiltinType::ShortFract:917 case clang::BuiltinType::ShortFract:
893 case BuiltinType::Fract:918 case clang::BuiltinType::Fract:
894 case BuiltinType::LongFract:919 case clang::BuiltinType::LongFract:
895 case BuiltinType::UShortFract:920 case clang::BuiltinType::UShortFract:
896 case BuiltinType::UFract:921 case clang::BuiltinType::UFract:
897 case BuiltinType::ULongFract:922 case clang::BuiltinType::ULongFract:
898 case BuiltinType::SatShortAccum:923 case clang::BuiltinType::SatShortAccum:
899 case BuiltinType::SatAccum:924 case clang::BuiltinType::SatAccum:
900 case BuiltinType::SatLongAccum:925 case clang::BuiltinType::SatLongAccum:
901 case BuiltinType::SatUShortAccum:926 case clang::BuiltinType::SatUShortAccum:
902 case BuiltinType::SatUAccum:927 case clang::BuiltinType::SatUAccum:
903 case BuiltinType::SatULongAccum:928 case clang::BuiltinType::SatULongAccum:
904 case BuiltinType::SatShortFract:929 case clang::BuiltinType::SatShortFract:
905 case BuiltinType::SatFract:930 case clang::BuiltinType::SatFract:
906 case BuiltinType::SatLongFract:931 case clang::BuiltinType::SatLongFract:
907 case BuiltinType::SatUShortFract:932 case clang::BuiltinType::SatUShortFract:
908 case BuiltinType::SatUFract:933 case clang::BuiltinType::SatUFract:
909 case BuiltinType::SatULongFract:934 case clang::BuiltinType::SatULongFract:
910 case BuiltinType::OCLIntelSubgroupAVCMcePayload:935 case BuiltinType::OCLIntelSubgroupAVCMcePayload:
911 case BuiltinType::OCLIntelSubgroupAVCImePayload:936 case BuiltinType::OCLIntelSubgroupAVCImePayload:
912 case BuiltinType::OCLIntelSubgroupAVCRefPayload:937 case BuiltinType::OCLIntelSubgroupAVCRefPayload:
...@@ -924,10 +949,10 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -924,10 +949,10 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
924 }949 }
925 break;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);954 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
930 QualType child_qt = pointer_ty->getPointeeType();955 clang::QualType child_qt = pointer_ty->getPointeeType();
931 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);956 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
932 if (child_node == nullptr) {957 if (child_node == nullptr) {
933 emit_warning(c, source_loc, "pointer to unsupported type");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,90 +963,94 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
938 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);963 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
939 }964 }
940965
941 PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;966 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
942967 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
943 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),968 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
944 child_qt.isVolatileQualified(), child_node, ptr_len);969 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
945 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);977 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
950 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();978 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
951 return resolve_typedef_decl(c, typedef_decl);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 switch (elaborated_ty->getKeyword()) {984 switch (elaborated_ty->getKeyword()) {
957 case ETK_Struct:985 case clang::ETK_Struct:
958 case ETK_Enum:986 case clang::ETK_Enum:
959 case ETK_Union:987 case clang::ETK_Union:
960 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);988 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
961 case ETK_Interface:989 case clang::ETK_Interface:
962 case ETK_Class:990 case clang::ETK_Class:
963 case ETK_Typename:991 case clang::ETK_Typename:
964 case ETK_None:992 case clang::ETK_None:
965 emit_warning(c, source_loc, "unsupported elaborated type");993 emit_warning(c, source_loc, "unsupported elaborated type");
966 return nullptr;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);
9721001
973 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);1002 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
974 switch (fn_proto_ty->getCallConv()) {1003 switch (fn_ty->getCallConv()) {
975 case CC_C: // __attribute__((cdecl))1004 case clang::CC_C: // __attribute__((cdecl))
976 proto_node->data.fn_proto.cc = CallingConventionC;1005 proto_node->data.fn_proto.cc = CallingConventionC;
977 proto_node->data.fn_proto.is_extern = true;1006 proto_node->data.fn_proto.is_extern = true;
978 break;1007 break;
979 case CC_X86StdCall: // __attribute__((stdcall))1008 case clang::CC_X86StdCall: // __attribute__((stdcall))
980 proto_node->data.fn_proto.cc = CallingConventionStdcall;1009 proto_node->data.fn_proto.cc = CallingConventionStdcall;
981 break;1010 break;
982 case CC_X86FastCall: // __attribute__((fastcall))1011 case clang::CC_X86FastCall: // __attribute__((fastcall))
983 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");1012 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
984 return nullptr;1013 return nullptr;
985 case CC_X86ThisCall: // __attribute__((thiscall))1014 case clang::CC_X86ThisCall: // __attribute__((thiscall))
986 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");1015 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
987 return nullptr;1016 return nullptr;
988 case CC_X86VectorCall: // __attribute__((vectorcall))1017 case clang::CC_X86VectorCall: // __attribute__((vectorcall))
989 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");1018 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
990 return nullptr;1019 return nullptr;
991 case CC_X86Pascal: // __attribute__((pascal))1020 case clang::CC_X86Pascal: // __attribute__((pascal))
992 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");1021 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
993 return nullptr;1022 return nullptr;
994 case CC_Win64: // __attribute__((ms_abi))1023 case clang::CC_Win64: // __attribute__((ms_abi))
995 emit_warning(c, source_loc, "unsupported calling convention: win64");1024 emit_warning(c, source_loc, "unsupported calling convention: win64");
996 return nullptr;1025 return nullptr;
997 case CC_X86_64SysV: // __attribute__((sysv_abi))1026 case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
998 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");1027 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
999 return nullptr;1028 return nullptr;
1000 case CC_X86RegCall:1029 case clang::CC_X86RegCall:
1001 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");1030 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
1002 return nullptr;1031 return nullptr;
1003 case CC_AAPCS: // __attribute__((pcs("aapcs")))1032 case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
1004 emit_warning(c, source_loc, "unsupported calling convention: aapcs");1033 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
1005 return nullptr;1034 return nullptr;
1006 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))1035 case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
1007 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");1036 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
1008 return nullptr;1037 return nullptr;
1009 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))1038 case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
1010 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");1039 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
1011 return nullptr;1040 return nullptr;
1012 case CC_SpirFunction: // default for OpenCL functions on SPIR target1041 case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
1013 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");1042 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
1014 return nullptr;1043 return nullptr;
1015 case CC_OpenCLKernel:1044 case clang::CC_OpenCLKernel:
1016 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");1045 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
1017 return nullptr;1046 return nullptr;
1018 case CC_Swift:1047 case clang::CC_Swift:
1019 emit_warning(c, source_loc, "unsupported calling convention: Swift");1048 emit_warning(c, source_loc, "unsupported calling convention: Swift");
1020 return nullptr;1049 return nullptr;
1021 case CC_PreserveMost:1050 case clang::CC_PreserveMost:
1022 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");1051 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
1023 return nullptr;1052 return nullptr;
1024 case CC_PreserveAll:1053 case clang::CC_PreserveAll:
1025 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");1054 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
1026 return nullptr;1055 return nullptr;
1027 case CC_AArch64VectorCall:1056 case CC_AArch64VectorCall:
...@@ -1029,20 +1058,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1029,20 +1058,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1029 return nullptr;1058 return nullptr;
1030 }1059 }
10311060
1032 proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();1061 if (fn_ty->getNoReturnAttr()) {
1033 size_t param_count = fn_proto_ty->getNumParams();
1034
1035 if (fn_proto_ty->getNoReturnAttr()) {
1036 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");1062 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
1037 } else {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 source_loc);1065 source_loc);
1040 if (proto_node->data.fn_proto.return_type == nullptr) {1066 if (proto_node->data.fn_proto.return_type == nullptr) {
1041 emit_warning(c, source_loc, "unsupported function proto return type");1067 emit_warning(c, source_loc, "unsupported function proto return type");
1042 return nullptr;1068 return nullptr;
1043 }1069 }
1044 // convert c_void to actual void (only for return type)1070 // convert c_void to actual void (only for return type)
1045 // we do want to look at the AstNode instead of QualType, because1071 // we do want to look at the AstNode instead of clang::QualType, because
1046 // if they do something like:1072 // if they do something like:
1047 // typedef Foo void;1073 // typedef Foo void;
1048 // void foo(void) -> Foo;1074 // void foo(void) -> Foo;
...@@ -1058,8 +1084,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1058,8 +1084,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1058 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);1084 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
1059 }1085 }
10601086
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 for (size_t i = 0; i < param_count; i += 1) {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 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);1098 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
10641099
1065 if (param_type_node == nullptr) {1100 if (param_type_node == nullptr) {
...@@ -1082,19 +1117,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1082,19 +1117,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10821117
1083 return proto_node;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 return resolve_record_decl(c, record_ty->getDecl());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 return resolve_enum_decl(c, enum_ty->getDecl());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 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);1133 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
1099 if (child_type_node == nullptr) {1134 if (child_type_node == nullptr) {
1100 emit_warning(c, source_loc, "unresolved array element type");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,84 +1139,83 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1104 AstNode *size_node = trans_create_node_unsigned(c, size);1139 AstNode *size_node = trans_create_node_unsigned(c, size);
1105 return trans_create_node_array_type(c, size_node, child_type_node);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 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);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 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);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 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);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);1159 const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty);
1125 QualType child_qt = incomplete_array_ty->getElementType();1160 clang::QualType child_qt = incomplete_array_ty->getElementType();
1126 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);1161 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
1127 if (child_type_node == nullptr) {1162 if (child_type_node == nullptr) {
1128 emit_warning(c, source_loc, "unresolved array element type");1163 emit_warning(c, source_loc, "unresolved array element type");
1129 return nullptr;1164 return nullptr;
1130 }1165 }
1131 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),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 return pointer_node;1168 return pointer_node;
1134 }1169 }
1135 case Type::BlockPointer:1170 case clang::Type::BlockPointer:
1136 case Type::LValueReference:1171 case clang::Type::LValueReference:
1137 case Type::RValueReference:1172 case clang::Type::RValueReference:
1138 case Type::MemberPointer:1173 case clang::Type::MemberPointer:
1139 case Type::VariableArray:1174 case clang::Type::VariableArray:
1140 case Type::DependentSizedArray:1175 case clang::Type::DependentSizedArray:
1141 case Type::DependentSizedExtVector:1176 case clang::Type::DependentSizedExtVector:
1142 case Type::Vector:1177 case clang::Type::Vector:
1143 case Type::ExtVector:1178 case clang::Type::ExtVector:
1144 case Type::FunctionNoProto:1179 case clang::Type::UnresolvedUsing:
1145 case Type::UnresolvedUsing:1180 case clang::Type::Adjusted:
1146 case Type::Adjusted:1181 case clang::Type::TypeOfExpr:
1147 case Type::TypeOfExpr:1182 case clang::Type::TypeOf:
1148 case Type::TypeOf:1183 case clang::Type::Decltype:
1149 case Type::Decltype:1184 case clang::Type::UnaryTransform:
1150 case Type::UnaryTransform:1185 case clang::Type::TemplateTypeParm:
1151 case Type::TemplateTypeParm:1186 case clang::Type::SubstTemplateTypeParm:
1152 case Type::SubstTemplateTypeParm:1187 case clang::Type::SubstTemplateTypeParmPack:
1153 case Type::SubstTemplateTypeParmPack:1188 case clang::Type::TemplateSpecialization:
1154 case Type::TemplateSpecialization:1189 case clang::Type::Auto:
1155 case Type::Auto:1190 case clang::Type::InjectedClassName:
1156 case Type::InjectedClassName:1191 case clang::Type::DependentName:
1157 case Type::DependentName:1192 case clang::Type::DependentTemplateSpecialization:
1158 case Type::DependentTemplateSpecialization:1193 case clang::Type::PackExpansion:
1159 case Type::PackExpansion:1194 case clang::Type::ObjCObject:
1160 case Type::ObjCObject:1195 case clang::Type::ObjCInterface:
1161 case Type::ObjCInterface:1196 case clang::Type::Complex:
1162 case Type::Complex:1197 case clang::Type::ObjCObjectPointer:
1163 case Type::ObjCObjectPointer:1198 case clang::Type::Atomic:
1164 case Type::Atomic:1199 case clang::Type::Pipe:
1165 case Type::Pipe:1200 case clang::Type::ObjCTypeParam:
1166 case Type::ObjCTypeParam:1201 case clang::Type::DeducedTemplateSpecialization:
1167 case Type::DeducedTemplateSpecialization:1202 case clang::Type::DependentAddressSpace:
1168 case Type::DependentAddressSpace:1203 case clang::Type::DependentVector:
1169 case Type::DependentVector:
1170 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());1204 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
1171 return nullptr;1205 return nullptr;
1172 }1206 }
1173 zig_unreachable();1207 zig_unreachable();
1174}1208}
11751209
1176static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {1210static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) {
1177 return trans_type(c, qt.getTypePtr(), source_loc);1211 return trans_type(c, qt.getTypePtr(), source_loc);
1178}1212}
11791213
1180static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt,1214static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
1181 AstNode *block_node, TransScope **out_node_scope)1215 AstNode *block_node, TransScope **out_node_scope)
1182{1216{
1183 assert(block_node->type == NodeTypeBlock);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 AstNode *child_node;1219 AstNode *child_node;
1186 scope = trans_stmt(c, scope, *it, &child_node);1220 scope = trans_stmt(c, scope, *it, &child_node);
1187 if (scope == nullptr)1221 if (scope == nullptr)
...@@ -1195,7 +1229,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo...@@ -1195,7 +1229,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo
1195 return ErrorNone;1229 return ErrorNone;
1196}1230}
11971231
1198static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt,1232static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
1199 TransScope **out_node_scope)1233 TransScope **out_node_scope)
1200{1234{
1201 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);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,8 +1238,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun
1204 return child_scope_block->node;1238 return child_scope_block->node;
1205}1239}
12061240
1207static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) {1241static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
1208 const Expr *value_expr = stmt->getRetValue();1242 const clang::Expr *value_expr = stmt->getRetValue();
1209 if (value_expr == nullptr) {1243 if (value_expr == nullptr) {
1210 return trans_create_node(c, NodeTypeReturnExpr);1244 return trans_create_node(c, NodeTypeReturnExpr);
1211 } else {1245 } else {
...@@ -1217,18 +1251,18 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm...@@ -1217,18 +1251,18 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm
1217 }1251 }
1218}1252}
12191253
1220static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {1254static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
1221 Expr::EvalResult result;1255 Expr::EvalResult result;
1222 if (!stmt->EvaluateAsInt(result, *c->ctx)) {1256 if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
1223 emit_warning(c, stmt->getBeginLoc(), "invalid integer literal");1257 emit_warning(c, stmt->getBeginLoc(), "invalid integer literal");
1224 return nullptr;1258 return nullptr;
1225 }1259 }
1226 return trans_create_node_apint(c, result.Val.getInt());1260 return trans_create_node_apint(c, result.Val.getInt());
1227}1261}
12281262
1229static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {1263static AstNode *trans_constant_expr(Context *c, const clang::ConstantExpr *expr) {
1230 Expr::EvalResult result;1264 Expr::EvalResult result;
1231 if (!expr->EvaluateAsConstantExpr(result, Expr::EvaluateForCodeGen, *c->ctx)) {1265 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, *c->ctx)) {
1232 emit_warning(c, expr->getBeginLoc(), "invalid constant expression");1266 emit_warning(c, expr->getBeginLoc(), "invalid constant expression");
1233 return nullptr;1267 return nullptr;
1234 }1268 }
...@@ -1236,13 +1270,13 @@ static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {...@@ -1236,13 +1270,13 @@ static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {
1236}1270}
12371271
1238static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,1272static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
1239 const ConditionalOperator *stmt)1273 const clang::ConditionalOperator *stmt)
1240{1274{
1241 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);1275 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
12421276
1243 Expr *cond_expr = stmt->getCond();1277 clang::Expr *cond_expr = stmt->getCond();
1244 Expr *true_expr = stmt->getTrueExpr();1278 clang::Expr *true_expr = stmt->getTrueExpr();
1245 Expr *false_expr = stmt->getFalseExpr();1279 clang::Expr *false_expr = stmt->getFalseExpr();
12461280
1247 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);1281 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
1248 if (node->data.if_bool_expr.condition == nullptr)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,7 +1293,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
1259 return maybe_suppress_result(c, result_used, node);1293 return maybe_suppress_result(c, result_used, node);
1260}1294}
12611295
1262static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {1296static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
1263 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1297 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1264 node->data.bin_op_expr.bin_op = bin_op;1298 node->data.bin_op_expr.bin_op = bin_op;
12651299
...@@ -1274,7 +1308,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi...@@ -1274,7 +1308,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
1274 return node;1308 return node;
1275}1309}
12761310
1277static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {1311static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
1278 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);1312 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
1279 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1313 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1280 node->data.bin_op_expr.bin_op = bin_op;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,7 +1324,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh
1290 return node;1324 return node;
1291}1325}
12921326
1293static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {1327static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) {
1294 if (result_used == ResultUsedNo) {1328 if (result_used == ResultUsedNo) {
1295 // common case1329 // common case
1296 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1330 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
...@@ -1341,10 +1375,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco...@@ -1341,10 +1375,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
1341 }1375 }
1342}1376}
13431377
1344static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type,1378static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
1345 Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr)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 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);1382 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
1349 // lhs >> u5(rh)1383 // lhs >> u5(rh)
13501384
...@@ -1358,22 +1392,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re...@@ -1358,22 +1392,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re
1358 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);1392 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
1359}1393}
13601394
1361static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) {1395static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {
1362 switch (stmt->getOpcode()) {1396 switch (stmt->getOpcode()) {
1363 case BO_PtrMemD:1397 case clang::BO_PtrMemD:
1364 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD");1398 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD");
1365 return nullptr;1399 return nullptr;
1366 case BO_PtrMemI:1400 case clang::BO_PtrMemI:
1367 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI");1401 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI");
1368 return nullptr;1402 return nullptr;
1369 case BO_Cmp:1403 case clang::BO_Cmp:
1370 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp");1404 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp");
1371 return nullptr;1405 return nullptr;
1372 case BO_Mul:1406 case clang::BO_Mul:
1373 return trans_create_bin_op(c, scope, stmt->getLHS(),1407 return trans_create_bin_op(c, scope, stmt->getLHS(),
1374 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,1408 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
1375 stmt->getRHS());1409 stmt->getRHS());
1376 case BO_Div:1410 case clang::BO_Div:
1377 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {1411 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1378 // unsigned/float division uses the operator1412 // unsigned/float division uses the operator
1379 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());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,7 +1422,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1388 fn_call->data.fn_call_expr.params.append(rhs);1422 fn_call->data.fn_call_expr.params.append(rhs);
1389 return fn_call;1423 return fn_call;
1390 }1424 }
1391 case BO_Rem:1425 case clang::BO_Rem:
1392 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {1426 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1393 // unsigned/float division uses the operator1427 // unsigned/float division uses the operator
1394 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());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,43 +1437,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1403 fn_call->data.fn_call_expr.params.append(rhs);1437 fn_call->data.fn_call_expr.params.append(rhs);
1404 return fn_call;1438 return fn_call;
1405 }1439 }
1406 case BO_Add:1440 case clang::BO_Add:
1407 return trans_create_bin_op(c, scope, stmt->getLHS(),1441 return trans_create_bin_op(c, scope, stmt->getLHS(),
1408 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,1442 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
1409 stmt->getRHS());1443 stmt->getRHS());
1410 case BO_Sub:1444 case clang::BO_Sub:
1411 return trans_create_bin_op(c, scope, stmt->getLHS(),1445 return trans_create_bin_op(c, scope, stmt->getLHS(),
1412 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,1446 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
1413 stmt->getRHS());1447 stmt->getRHS());
1414 case BO_Shl:1448 case clang::BO_Shl:
1415 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());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 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());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 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());1453 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
1420 case BO_GT:1454 case clang::BO_GT:
1421 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());1455 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
1422 case BO_LE:1456 case clang::BO_LE:
1423 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());1457 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
1424 case BO_GE:1458 case clang::BO_GE:
1425 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());1459 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
1426 case BO_EQ:1460 case clang::BO_EQ:
1427 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());1461 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
1428 case BO_NE:1462 case clang::BO_NE:
1429 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());1463 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
1430 case BO_And:1464 case clang::BO_And:
1431 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());1465 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
1432 case BO_Xor:1466 case clang::BO_Xor:
1433 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());1467 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
1434 case BO_Or:1468 case clang::BO_Or:
1435 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());1469 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1436 case BO_LAnd:1470 case clang::BO_LAnd:
1437 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());1471 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1438 case BO_LOr:1472 case clang::BO_LOr:
1439 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());1473 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1440 case BO_Assign:1474 case clang::BO_Assign:
1441 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());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 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);1478 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
1445 Buf *label_name = buf_create_from_str("x");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,16 +1490,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1456 scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));1490 scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
1457 return scope_block->node;1491 return scope_block->node;
1458 }1492 }
1459 case BO_MulAssign:1493 case clang::BO_MulAssign:
1460 case BO_DivAssign:1494 case clang::BO_DivAssign:
1461 case BO_RemAssign:1495 case clang::BO_RemAssign:
1462 case BO_AddAssign:1496 case clang::BO_AddAssign:
1463 case BO_SubAssign:1497 case clang::BO_SubAssign:
1464 case BO_ShlAssign:1498 case clang::BO_ShlAssign:
1465 case BO_ShrAssign:1499 case clang::BO_ShrAssign:
1466 case BO_AndAssign:1500 case clang::BO_AndAssign:
1467 case BO_XorAssign:1501 case clang::BO_XorAssign:
1468 case BO_OrAssign:1502 case clang::BO_OrAssign:
1469 zig_unreachable();1503 zig_unreachable();
1470 }1504 }
14711505
...@@ -1473,9 +1507,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1473,9 +1507,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1473}1507}
14741508
1475static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,1509static 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 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);1513 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
14801514
1481 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();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,7 +1589,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
1555}1589}
15561590
1557static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope,1591static 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 if (result_used == ResultUsedNo) {1594 if (result_used == ResultUsedNo) {
1561 // simple common case, where the C and Zig are identical: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,76 +1649,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
16151649
16161650
1617static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,1651static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
1618 const CompoundAssignOperator *stmt)1652 const clang::CompoundAssignOperator *stmt)
1619{1653{
1620 switch (stmt->getOpcode()) {1654 switch (stmt->getOpcode()) {
1621 case BO_MulAssign:1655 case clang::BO_MulAssign:
1622 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1656 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1623 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);1657 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
1624 else1658 else
1625 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);1659 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1626 case BO_DivAssign:1660 case clang::BO_DivAssign:
1627 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign");1661 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign");
1628 return nullptr;1662 return nullptr;
1629 case BO_RemAssign:1663 case clang::BO_RemAssign:
1630 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign");1664 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign");
1631 return nullptr;1665 return nullptr;
1632 case BO_Cmp:1666 case clang::BO_Cmp:
1633 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp");1667 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp");
1634 return nullptr;1668 return nullptr;
1635 case BO_AddAssign:1669 case clang::BO_AddAssign:
1636 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1670 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1637 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);1671 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
1638 else1672 else
1639 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);1673 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1640 case BO_SubAssign:1674 case clang::BO_SubAssign:
1641 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1675 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1642 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);1676 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
1643 else1677 else
1644 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);1678 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1645 case BO_ShlAssign:1679 case clang::BO_ShlAssign:
1646 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);1680 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1647 case BO_ShrAssign:1681 case clang::BO_ShrAssign:
1648 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);1682 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1649 case BO_AndAssign:1683 case clang::BO_AndAssign:
1650 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);1684 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1651 case BO_XorAssign:1685 case clang::BO_XorAssign:
1652 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);1686 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1653 case BO_OrAssign:1687 case clang::BO_OrAssign:
1654 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);1688 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1655 case BO_PtrMemD:1689 case clang::BO_PtrMemD:
1656 case BO_PtrMemI:1690 case clang::BO_PtrMemI:
1657 case BO_Assign:1691 case clang::BO_Assign:
1658 case BO_Mul:1692 case clang::BO_Mul:
1659 case BO_Div:1693 case clang::BO_Div:
1660 case BO_Rem:1694 case clang::BO_Rem:
1661 case BO_Add:1695 case clang::BO_Add:
1662 case BO_Sub:1696 case clang::BO_Sub:
1663 case BO_Shl:1697 case clang::BO_Shl:
1664 case BO_Shr:1698 case clang::BO_Shr:
1665 case BO_LT:1699 case clang::BO_LT:
1666 case BO_GT:1700 case clang::BO_GT:
1667 case BO_LE:1701 case clang::BO_LE:
1668 case BO_GE:1702 case clang::BO_GE:
1669 case BO_EQ:1703 case clang::BO_EQ:
1670 case BO_NE:1704 case clang::BO_NE:
1671 case BO_And:1705 case clang::BO_And:
1672 case BO_Xor:1706 case clang::BO_Xor:
1673 case BO_Or:1707 case clang::BO_Or:
1674 case BO_LAnd:1708 case clang::BO_LAnd:
1675 case BO_LOr:1709 case clang::BO_LOr:
1676 case BO_Comma:1710 case clang::BO_Comma:
1677 zig_unreachable();1711 zig_unreachable();
1678 }1712 }
16791713
1680 zig_unreachable();1714 zig_unreachable();
1681}1715}
16821716
1683static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) {1717static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
1684 switch (stmt->getCastKind()) {1718 switch (stmt->getCastKind()) {
1685 case CK_LValueToRValue:1719 case clang::CK_LValueToRValue:
1686 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1720 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1687 case CK_IntegralCast:1721 case clang::CK_IntegralCast:
1688 {1722 {
1689 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1723 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1690 if (target_node == nullptr)1724 if (target_node == nullptr)
...@@ -1692,15 +1726,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im...@@ -1692,15 +1726,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
1692 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),1726 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
1693 stmt->getSubExpr()->getType(), target_node);1727 stmt->getSubExpr()->getType(), target_node);
1694 }1728 }
1695 case CK_FunctionToPointerDecay:1729 case clang::CK_FunctionToPointerDecay:
1696 case CK_ArrayToPointerDecay:1730 case clang::CK_ArrayToPointerDecay:
1697 {1731 {
1698 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1732 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1699 if (target_node == nullptr)1733 if (target_node == nullptr)
1700 return nullptr;1734 return nullptr;
1701 return target_node;1735 return target_node;
1702 }1736 }
1703 case CK_BitCast:1737 case clang::CK_BitCast:
1704 {1738 {
1705 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1739 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1706 if (target_node == nullptr)1740 if (target_node == nullptr)
...@@ -1717,172 +1751,55 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im...@@ -1717,172 +1751,55 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
1717 node->data.fn_call_expr.params.append(target_node);1751 node->data.fn_call_expr.params.append(target_node);
1718 return node;1752 return node;
1719 }1753 }
1720 case CK_NullToPointer:1754 case clang::CK_NullToPointer:
1721 return trans_create_node(c, NodeTypeNullLiteral);1755 return trans_create_node_unsigned(c, 0);
1722 case CK_Dependent:1756 case clang::CK_NoOp:
1757 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1758 case clang::CK_Dependent:
1723 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent");1759 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent");
1724 return nullptr;1760 return nullptr;
1725 case CK_LValueBitCast:1761 case clang::CK_LValueBitCast:
1726 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast");1762 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast");
1727 return nullptr;1763 return nullptr;
1728 case CK_NoOp:1764 case clang::CK_BaseToDerived:
1729 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1730 case CK_BaseToDerived:
1731 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived");1765 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived");
1732 return nullptr;1766 return nullptr;
1733 case CK_DerivedToBase:1767 case clang::CK_DerivedToBase:
1734 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase");1768 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase");
1735 return nullptr;1769 return nullptr;
1736 case CK_UncheckedDerivedToBase:1770 case clang::CK_UncheckedDerivedToBase:
1737 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase");1771 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1738 return nullptr;1772 return nullptr;
1739 case CK_Dynamic:1773 case clang::CK_Dynamic:
1740 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic");1774 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic");
1741 return nullptr;1775 return nullptr;
1742 case CK_ToUnion:1776 case clang::CK_ToUnion:
1743 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion");1777 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion");
1744 return nullptr;1778 return nullptr;
1745 case CK_NullToMemberPointer:1779 case clang::CK_NullToMemberPointer:
1746 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer");1780 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer");
1747 return nullptr;1781 return nullptr;
1748 case CK_BaseToDerivedMemberPointer:1782 case clang::CK_BaseToDerivedMemberPointer:
1749 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");1783 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
1750 return nullptr;1784 return nullptr;
1751 case CK_DerivedToBaseMemberPointer:1785 case clang::CK_DerivedToBaseMemberPointer:
1752 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");1786 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
1753 return nullptr;1787 return nullptr;
1754 case CK_MemberPointerToBoolean:1788 case clang::CK_MemberPointerToBoolean:
1755 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean");1789 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean");
1756 return nullptr;1790 return nullptr;
1757 case CK_ReinterpretMemberPointer:1791 case clang::CK_ReinterpretMemberPointer:
1758 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer");1792 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
1759 return nullptr;1793 return nullptr;
1760 case CK_UserDefinedConversion:1794 case clang::CK_UserDefinedConversion:
1761 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion");1795 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion");
1762 return nullptr;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 zig_unreachable();1798 zig_unreachable();
1882}1799}
18831800
1884static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) {1801static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
1885 const ValueDecl *value_decl = stmt->getDecl();1802 const clang::ValueDecl *value_decl = stmt->getDecl();
1886 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));1803 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
1887 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);1804 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
1888 if (lrval == TransLValue) {1805 if (lrval == TransLValue) {
...@@ -1892,9 +1809,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef...@@ -1892,9 +1809,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef
1892}1809}
18931810
1894static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,1811static 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();
18981815
1899 if (result_used == ResultUsedNo) {1816 if (result_used == ResultUsedNo) {
1900 // common case1817 // common case
...@@ -1948,9 +1865,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr...@@ -1948,9 +1865,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
1948}1865}
19491866
1950static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,1867static 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();
19541871
1955 if (result_used == ResultUsedNo) {1872 if (result_used == ResultUsedNo) {
1956 // common case1873 // common case
...@@ -1997,36 +1914,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra...@@ -1997,36 +1914,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
1997 return child_scope->node;1914 return child_scope->node;
1998}1915}
19991916
2000static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) {1917static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {
2001 switch (stmt->getOpcode()) {1918 switch (stmt->getOpcode()) {
2002 case UO_PostInc:1919 case clang::UO_PostInc:
2003 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1920 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
2004 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);1921 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
2005 else1922 else
2006 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);1923 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2007 case UO_PostDec:1924 case clang::UO_PostDec:
2008 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1925 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
2009 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);1926 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
2010 else1927 else
2011 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);1928 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2012 case UO_PreInc:1929 case clang::UO_PreInc:
2013 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1930 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
2014 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);1931 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
2015 else1932 else
2016 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);1933 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2017 case UO_PreDec:1934 case clang::UO_PreDec:
2018 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1935 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
2019 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);1936 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
2020 else1937 else
2021 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);1938 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2022 case UO_AddrOf:1939 case clang::UO_AddrOf:
2023 {1940 {
2024 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);1941 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
2025 if (value_node == nullptr)1942 if (value_node == nullptr)
2026 return value_node;1943 return value_node;
2027 return trans_create_node_addr_of(c, value_node);1944 return trans_create_node_addr_of(c, value_node);
2028 }1945 }
2029 case UO_Deref:1946 case clang::UO_Deref:
2030 {1947 {
2031 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);1948 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
2032 if (value_node == nullptr)1949 if (value_node == nullptr)
...@@ -2037,12 +1954,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -2037,12 +1954,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2037 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);1954 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
2038 return trans_create_node_ptr_deref(c, unwrapped);1955 return trans_create_node_ptr_deref(c, unwrapped);
2039 }1956 }
2040 case UO_Plus:1957 case clang::UO_Plus:
2041 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus");1958 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus");
2042 return nullptr;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 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {1963 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
2047 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);1964 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
2048 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;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,41 +1985,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2068 return nullptr;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 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);1991 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2075 if (sub_node == nullptr)1992 if (sub_node == nullptr)
2076 return nullptr;1993 return nullptr;
20771994
2078 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);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 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);2000 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2084 if (sub_node == nullptr)2001 if (sub_node == nullptr)
2085 return nullptr;2002 return nullptr;
20862003
2087 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);2004 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
2088 }2005 }
2089 case UO_Real:2006 case clang::UO_Real:
2090 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real");2007 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real");
2091 return nullptr;2008 return nullptr;
2092 case UO_Imag:2009 case clang::UO_Imag:
2093 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag");2010 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag");
2094 return nullptr;2011 return nullptr;
2095 case UO_Extension:2012 case clang::UO_Extension:
2096 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Extension");2013 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Extension");
2097 return nullptr;2014 return nullptr;
2098 case UO_Coawait:2015 case clang::UO_Coawait:
2099 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait");2016 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait");
2100 return nullptr;2017 return nullptr;
2101 }2018 }
2102 zig_unreachable();2019 zig_unreachable();
2103}2020}
21042021
2105static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt,2022static int trans_local_declaration(Context *c, TransScope *scope, const clang::DeclStmt *stmt,
2106 AstNode **out_node, TransScope **out_scope)2023 AstNode **out_node, TransScope **out_scope)
2107{2024{
2108 // declarations are added via the scope2025 // declarations are added via the scope
...@@ -2112,11 +2029,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt...@@ -2112,11 +2029,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2112 assert(scope_block != nullptr);2029 assert(scope_block != nullptr);
21132030
2114 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {2031 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
2115 Decl *decl = *iter;2032 clang::Decl *decl = *iter;
2116 switch (decl->getKind()) {2033 switch (decl->getKind()) {
2117 case Decl::Var: {2034 case clang::Decl::Var: {
2118 VarDecl *var_decl = (VarDecl *)decl;2035 clang::VarDecl *var_decl = (clang::VarDecl *)decl;
2119 QualType qual_type = var_decl->getTypeSourceInfo()->getType();2036 clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
2120 AstNode *init_node = nullptr;2037 AstNode *init_node = nullptr;
2121 if (var_decl->hasInit()) {2038 if (var_decl->hasInit()) {
2122 init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);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,225 +2058,9 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2141 scope_block->node->data.block.statements.append(node);2058 scope_block->node->data.block.statements.append(node);
2142 continue;2059 continue;
2143 }2060 }
2144 case Decl::AccessSpec:2061 case clang::Decl::AccessSpec:
2145 emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec");2062 emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec");
2146 return ErrorUnexpected;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 zig_unreachable();2065 zig_unreachable();
2365 }2066 }
...@@ -2384,7 +2085,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)...@@ -2384,7 +2085,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
2384 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);2085 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
2385}2086}
23862087
2387static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) {2088static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) {
2388 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);2089 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
2389 if (res == nullptr)2090 if (res == nullptr)
2390 return nullptr;2091 return nullptr;
...@@ -2421,143 +2122,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2421,143 +2122,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2421 }2122 }
24222123
24232124
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 auto classs = ty->getTypeClass();2126 auto classs = ty->getTypeClass();
2426 switch (classs) {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 switch (builtin_ty->getKind()) {2131 switch (builtin_ty->getKind()) {
2431 case BuiltinType::Bool:2132 case clang::BuiltinType::Bool:
2432 case BuiltinType::Char_U:2133 case clang::BuiltinType::Char_U:
2433 case BuiltinType::UChar:2134 case clang::BuiltinType::UChar:
2434 case BuiltinType::Char_S:2135 case clang::BuiltinType::Char_S:
2435 case BuiltinType::SChar:2136 case clang::BuiltinType::SChar:
2436 case BuiltinType::UShort:2137 case clang::BuiltinType::UShort:
2437 case BuiltinType::UInt:2138 case clang::BuiltinType::UInt:
2438 case BuiltinType::ULong:2139 case clang::BuiltinType::ULong:
2439 case BuiltinType::ULongLong:2140 case clang::BuiltinType::ULongLong:
2440 case BuiltinType::Short:2141 case clang::BuiltinType::Short:
2441 case BuiltinType::Int:2142 case clang::BuiltinType::Int:
2442 case BuiltinType::Long:2143 case clang::BuiltinType::Long:
2443 case BuiltinType::LongLong:2144 case clang::BuiltinType::LongLong:
2444 case BuiltinType::UInt128:2145 case clang::BuiltinType::UInt128:
2445 case BuiltinType::Int128:2146 case clang::BuiltinType::Int128:
2446 case BuiltinType::Float:2147 case clang::BuiltinType::Float:
2447 case BuiltinType::Double:2148 case clang::BuiltinType::Double:
2448 case BuiltinType::Float128:2149 case clang::BuiltinType::Float128:
2449 case BuiltinType::LongDouble:2150 case clang::BuiltinType::LongDouble:
2450 case BuiltinType::WChar_U:2151 case clang::BuiltinType::WChar_U:
2451 case BuiltinType::Char8:2152 case clang::BuiltinType::Char8:
2452 case BuiltinType::Char16:2153 case clang::BuiltinType::Char16:
2453 case BuiltinType::Char32:2154 case clang::BuiltinType::Char32:
2454 case BuiltinType::WChar_S:2155 case clang::BuiltinType::WChar_S:
2455 case BuiltinType::Float16:2156 case clang::BuiltinType::Float16:
2456 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));2157 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2457 case BuiltinType::NullPtr:2158 case clang::BuiltinType::NullPtr:
2458 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));2159 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
24592160 trans_create_node_unsigned(c, 0));
2460 case BuiltinType::Void:2161
2461 case BuiltinType::Half:2162 case clang::BuiltinType::Void:
2462 case BuiltinType::ObjCId:2163 case clang::BuiltinType::Half:
2463 case BuiltinType::ObjCClass:2164 case clang::BuiltinType::ObjCId:
2464 case BuiltinType::ObjCSel:2165 case clang::BuiltinType::ObjCClass:
2465 case BuiltinType::OMPArraySection:2166 case clang::BuiltinType::ObjCSel:
2466 case BuiltinType::Dependent:2167 case clang::BuiltinType::OMPArraySection:
2467 case BuiltinType::Overload:2168 case clang::BuiltinType::Dependent:
2468 case BuiltinType::BoundMember:2169 case clang::BuiltinType::Overload:
2469 case BuiltinType::PseudoObject:2170 case clang::BuiltinType::BoundMember:
2470 case BuiltinType::UnknownAny:2171 case clang::BuiltinType::PseudoObject:
2471 case BuiltinType::BuiltinFn:2172 case clang::BuiltinType::UnknownAny:
2472 case BuiltinType::ARCUnbridgedCast:2173 case clang::BuiltinType::BuiltinFn:
2473 case BuiltinType::OCLImage1dRO:2174 case clang::BuiltinType::ARCUnbridgedCast:
2474 case BuiltinType::OCLImage1dArrayRO:2175 case clang::BuiltinType::OCLImage1dRO:
2475 case BuiltinType::OCLImage1dBufferRO:2176 case clang::BuiltinType::OCLImage1dArrayRO:
2476 case BuiltinType::OCLImage2dRO:2177 case clang::BuiltinType::OCLImage1dBufferRO:
2477 case BuiltinType::OCLImage2dArrayRO:2178 case clang::BuiltinType::OCLImage2dRO:
2478 case BuiltinType::OCLImage2dDepthRO:2179 case clang::BuiltinType::OCLImage2dArrayRO:
2479 case BuiltinType::OCLImage2dArrayDepthRO:2180 case clang::BuiltinType::OCLImage2dDepthRO:
2480 case BuiltinType::OCLImage2dMSAARO:2181 case clang::BuiltinType::OCLImage2dArrayDepthRO:
2481 case BuiltinType::OCLImage2dArrayMSAARO:2182 case clang::BuiltinType::OCLImage2dMSAARO:
2482 case BuiltinType::OCLImage2dMSAADepthRO:2183 case clang::BuiltinType::OCLImage2dArrayMSAARO:
2483 case BuiltinType::OCLImage2dArrayMSAADepthRO:2184 case clang::BuiltinType::OCLImage2dMSAADepthRO:
2484 case BuiltinType::OCLImage3dRO:2185 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
2485 case BuiltinType::OCLImage1dWO:2186 case clang::BuiltinType::OCLImage3dRO:
2486 case BuiltinType::OCLImage1dArrayWO:2187 case clang::BuiltinType::OCLImage1dWO:
2487 case BuiltinType::OCLImage1dBufferWO:2188 case clang::BuiltinType::OCLImage1dArrayWO:
2488 case BuiltinType::OCLImage2dWO:2189 case clang::BuiltinType::OCLImage1dBufferWO:
2489 case BuiltinType::OCLImage2dArrayWO:2190 case clang::BuiltinType::OCLImage2dWO:
2490 case BuiltinType::OCLImage2dDepthWO:2191 case clang::BuiltinType::OCLImage2dArrayWO:
2491 case BuiltinType::OCLImage2dArrayDepthWO:2192 case clang::BuiltinType::OCLImage2dDepthWO:
2492 case BuiltinType::OCLImage2dMSAAWO:2193 case clang::BuiltinType::OCLImage2dArrayDepthWO:
2493 case BuiltinType::OCLImage2dArrayMSAAWO:2194 case clang::BuiltinType::OCLImage2dMSAAWO:
2494 case BuiltinType::OCLImage2dMSAADepthWO:2195 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
2495 case BuiltinType::OCLImage2dArrayMSAADepthWO:2196 case clang::BuiltinType::OCLImage2dMSAADepthWO:
2496 case BuiltinType::OCLImage3dWO:2197 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
2497 case BuiltinType::OCLImage1dRW:2198 case clang::BuiltinType::OCLImage3dWO:
2498 case BuiltinType::OCLImage1dArrayRW:2199 case clang::BuiltinType::OCLImage1dRW:
2499 case BuiltinType::OCLImage1dBufferRW:2200 case clang::BuiltinType::OCLImage1dArrayRW:
2500 case BuiltinType::OCLImage2dRW:2201 case clang::BuiltinType::OCLImage1dBufferRW:
2501 case BuiltinType::OCLImage2dArrayRW:2202 case clang::BuiltinType::OCLImage2dRW:
2502 case BuiltinType::OCLImage2dDepthRW:2203 case clang::BuiltinType::OCLImage2dArrayRW:
2503 case BuiltinType::OCLImage2dArrayDepthRW:2204 case clang::BuiltinType::OCLImage2dDepthRW:
2504 case BuiltinType::OCLImage2dMSAARW:2205 case clang::BuiltinType::OCLImage2dArrayDepthRW:
2505 case BuiltinType::OCLImage2dArrayMSAARW:2206 case clang::BuiltinType::OCLImage2dMSAARW:
2506 case BuiltinType::OCLImage2dMSAADepthRW:2207 case clang::BuiltinType::OCLImage2dArrayMSAARW:
2507 case BuiltinType::OCLImage2dArrayMSAADepthRW:2208 case clang::BuiltinType::OCLImage2dMSAADepthRW:
2508 case BuiltinType::OCLImage3dRW:2209 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
2509 case BuiltinType::OCLSampler:2210 case clang::BuiltinType::OCLImage3dRW:
2510 case BuiltinType::OCLEvent:2211 case clang::BuiltinType::OCLSampler:
2511 case BuiltinType::OCLClkEvent:2212 case clang::BuiltinType::OCLEvent:
2512 case BuiltinType::OCLQueue:2213 case clang::BuiltinType::OCLClkEvent:
2513 case BuiltinType::OCLReserveID:2214 case clang::BuiltinType::OCLQueue:
2514 case BuiltinType::ShortAccum:2215 case clang::BuiltinType::OCLReserveID:
2515 case BuiltinType::Accum:2216 case clang::BuiltinType::ShortAccum:
2516 case BuiltinType::LongAccum:2217 case clang::BuiltinType::Accum:
2517 case BuiltinType::UShortAccum:2218 case clang::BuiltinType::LongAccum:
2518 case BuiltinType::UAccum:2219 case clang::BuiltinType::UShortAccum:
2519 case BuiltinType::ULongAccum:2220 case clang::BuiltinType::UAccum:
2520 case BuiltinType::ShortFract:2221 case clang::BuiltinType::ULongAccum:
2521 case BuiltinType::Fract:2222 case clang::BuiltinType::ShortFract:
2522 case BuiltinType::LongFract:2223 case clang::BuiltinType::Fract:
2523 case BuiltinType::UShortFract:2224 case clang::BuiltinType::LongFract:
2524 case BuiltinType::UFract:2225 case clang::BuiltinType::UShortFract:
2525 case BuiltinType::ULongFract:2226 case clang::BuiltinType::UFract:
2526 case BuiltinType::SatShortAccum:2227 case clang::BuiltinType::ULongFract:
2527 case BuiltinType::SatAccum:2228 case clang::BuiltinType::SatShortAccum:
2528 case BuiltinType::SatLongAccum:2229 case clang::BuiltinType::SatAccum:
2529 case BuiltinType::SatUShortAccum:2230 case clang::BuiltinType::SatLongAccum:
2530 case BuiltinType::SatUAccum:2231 case clang::BuiltinType::SatUShortAccum:
2531 case BuiltinType::SatULongAccum:2232 case clang::BuiltinType::SatUAccum:
2532 case BuiltinType::SatShortFract:2233 case clang::BuiltinType::SatULongAccum:
2533 case BuiltinType::SatFract:2234 case clang::BuiltinType::SatShortFract:
2534 case BuiltinType::SatLongFract:2235 case clang::BuiltinType::SatFract:
2535 case BuiltinType::SatUShortFract:2236 case clang::BuiltinType::SatLongFract:
2536 case BuiltinType::SatUFract:2237 case clang::BuiltinType::SatUShortFract:
2537 case BuiltinType::SatULongFract:2238 case clang::BuiltinType::SatUFract:
2538 case BuiltinType::OCLIntelSubgroupAVCMcePayload:2239 case clang::BuiltinType::SatULongFract:
2539 case BuiltinType::OCLIntelSubgroupAVCImePayload:2240 case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
2540 case BuiltinType::OCLIntelSubgroupAVCRefPayload:2241 case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
2541 case BuiltinType::OCLIntelSubgroupAVCSicPayload:2242 case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
2542 case BuiltinType::OCLIntelSubgroupAVCMceResult:2243 case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
2543 case BuiltinType::OCLIntelSubgroupAVCImeResult:2244 case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
2544 case BuiltinType::OCLIntelSubgroupAVCRefResult:2245 case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
2545 case BuiltinType::OCLIntelSubgroupAVCSicResult:2246 case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
2546 case BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:2247 case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
2547 case BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:2248 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
2548 case BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:2249 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
2549 case BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:2250 case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
2251 case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
2550 return res;2252 return res;
2551 }2253 }
2552 break;2254 break;
2553 }2255 }
2554 case Type::Pointer:2256 case clang::Type::Pointer:
2555 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));2257 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2258 trans_create_node_unsigned(c, 0));
25562259
2557 case Type::Typedef:2260 case clang::Type::Typedef:
2558 {2261 {
2559 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);2262 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
2560 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();2263 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
2561 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());2264 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
2562 if (existing_entry) {2265 if (existing_entry) {
2563 return existing_entry->value;2266 return existing_entry->value;
...@@ -2566,79 +2269,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2566,79 +2269,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2566 return res;2269 return res;
2567 }2270 }
25682271
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 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());2275 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
2573 return to_enum_zero_cmp(c, res, enum_type);2276 return to_enum_zero_cmp(c, res, enum_type);
2574 }2277 }
25752278
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 switch (elaborated_ty->getKeyword()) {2282 switch (elaborated_ty->getKeyword()) {
2580 case ETK_Enum: {2283 case clang::ETK_Enum: {
2581 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc());2284 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginloc());
2582 return to_enum_zero_cmp(c, res, enum_type);2285 return to_enum_zero_cmp(c, res, enum_type);
2583 }2286 }
2584 case ETK_Struct:2287 case clang::ETK_Struct:
2585 case ETK_Union:2288 case clang::ETK_Union:
2586 case ETK_Interface:2289 case clang::ETK_Interface:
2587 case ETK_Class:2290 case clang::ETK_Class:
2588 case ETK_Typename:2291 case clang::ETK_Typename:
2589 case ETK_None:2292 case clang::ETK_None:
2590 return res;2293 return res;
2591 }2294 }
2592 }2295 }
25932296
2594 case Type::FunctionProto:2297 case clang::Type::FunctionProto:
2595 case Type::Record:2298 case clang::Type::Record:
2596 case Type::ConstantArray:2299 case clang::Type::ConstantArray:
2597 case Type::Paren:2300 case clang::Type::Paren:
2598 case Type::Decayed:2301 case clang::Type::Decayed:
2599 case Type::Attributed:2302 case clang::Type::Attributed:
2600 case Type::IncompleteArray:2303 case clang::Type::IncompleteArray:
2601 case Type::BlockPointer:2304 case clang::Type::BlockPointer:
2602 case Type::LValueReference:2305 case clang::Type::LValueReference:
2603 case Type::RValueReference:2306 case clang::Type::RValueReference:
2604 case Type::MemberPointer:2307 case clang::Type::MemberPointer:
2605 case Type::VariableArray:2308 case clang::Type::VariableArray:
2606 case Type::DependentSizedArray:2309 case clang::Type::DependentSizedArray:
2607 case Type::DependentSizedExtVector:2310 case clang::Type::DependentSizedExtVector:
2608 case Type::Vector:2311 case clang::Type::Vector:
2609 case Type::ExtVector:2312 case clang::Type::ExtVector:
2610 case Type::FunctionNoProto:2313 case clang::Type::FunctionNoProto:
2611 case Type::UnresolvedUsing:2314 case clang::Type::UnresolvedUsing:
2612 case Type::Adjusted:2315 case clang::Type::Adjusted:
2613 case Type::TypeOfExpr:2316 case clang::Type::TypeOfExpr:
2614 case Type::TypeOf:2317 case clang::Type::TypeOf:
2615 case Type::Decltype:2318 case clang::Type::Decltype:
2616 case Type::UnaryTransform:2319 case clang::Type::UnaryTransform:
2617 case Type::TemplateTypeParm:2320 case clang::Type::TemplateTypeParm:
2618 case Type::SubstTemplateTypeParm:2321 case clang::Type::SubstTemplateTypeParm:
2619 case Type::SubstTemplateTypeParmPack:2322 case clang::Type::SubstTemplateTypeParmPack:
2620 case Type::TemplateSpecialization:2323 case clang::Type::TemplateSpecialization:
2621 case Type::Auto:2324 case clang::Type::Auto:
2622 case Type::InjectedClassName:2325 case clang::Type::InjectedClassName:
2623 case Type::DependentName:2326 case clang::Type::DependentName:
2624 case Type::DependentTemplateSpecialization:2327 case clang::Type::DependentTemplateSpecialization:
2625 case Type::PackExpansion:2328 case clang::Type::PackExpansion:
2626 case Type::ObjCObject:2329 case clang::Type::ObjCObject:
2627 case Type::ObjCInterface:2330 case clang::Type::ObjCInterface:
2628 case Type::Complex:2331 case clang::Type::Complex:
2629 case Type::ObjCObjectPointer:2332 case clang::Type::ObjCObjectPointer:
2630 case Type::Atomic:2333 case clang::Type::Atomic:
2631 case Type::Pipe:2334 case clang::Type::Pipe:
2632 case Type::ObjCTypeParam:2335 case clang::Type::ObjCTypeParam:
2633 case Type::DeducedTemplateSpecialization:2336 case clang::Type::DeducedTemplateSpecialization:
2634 case Type::DependentAddressSpace:2337 case clang::Type::DependentAddressSpace:
2635 case Type::DependentVector:2338 case clang::Type::DependentVector:
2636 return res;2339 return res;
2637 }2340 }
2638 zig_unreachable();2341 zig_unreachable();
2639}2342}
26402343
2641static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {2344static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {
2642 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);2345 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
26432346
2644 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);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,7 +2356,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt
2653 return while_scope->node;2356 return while_scope->node;
2654}2357}
26552358
2656static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {2359static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::IfStmt *stmt) {
2657 // if (c) t2360 // if (c) t
2658 // if (c) t else e2361 // if (c) t else e
2659 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);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,7 +2378,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2675 return if_node;2378 return if_node;
2676}2379}
26772380
2678static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {2381static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {
2679 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);2382 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
26802383
2681 AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);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,16 +2386,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2683 return nullptr;2386 return nullptr;
26842387
2685 bool is_ptr = false;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 AstNode *callee_node = nullptr;2390 AstNode *callee_node = nullptr;
2688 if (is_ptr && fn_ty) {2391 if (is_ptr && fn_ty) {
2689 if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {2392 if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
2690 const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee());2393 const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());
2691 if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {2394 if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
2692 if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) {2395 if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
2693 const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr());2396 const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());
2694 const Decl *decl = decl_ref->getFoundDecl();2397 const clang::Decl *decl = decl_ref->getFoundDecl();
2695 if (decl->getKind() == Decl::Function) {2398 if (decl->getKind() == clang::Decl::Function) {
2696 callee_node = callee_raw_node;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,7 +2411,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2708 node->data.fn_call_expr.fn_ref_expr = callee_node;2411 node->data.fn_call_expr.fn_ref_expr = callee_node;
27092412
2710 unsigned num_args = stmt->getNumArgs();2413 unsigned num_args = stmt->getNumArgs();
2711 const Expr * const* args = stmt->getArgs();2414 const clang::Expr * const* args = stmt->getArgs();
2712 for (unsigned i = 0; i < num_args; i += 1) {2415 for (unsigned i = 0; i < num_args; i += 1) {
2713 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);2416 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
2714 if (arg_node == nullptr)2417 if (arg_node == nullptr)
...@@ -2724,7 +2427,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2724,7 +2427,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2724 return node;2427 return node;
2725}2428}
27262429
2727static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) {2430static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) {
2728 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);2431 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
2729 if (container_node == nullptr)2432 if (container_node == nullptr)
2730 return nullptr;2433 return nullptr;
...@@ -2739,7 +2442,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp...@@ -2739,7 +2442,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp
2739 return node;2442 return node;
2740}2443}
27412444
2742static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) {2445static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
2743 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);2446 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
2744 if (container_node == nullptr)2447 if (container_node == nullptr)
2745 return nullptr;2448 return nullptr;
...@@ -2756,7 +2459,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const...@@ -2756,7 +2459,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
2756}2459}
27572460
2758static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,2461static 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 AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);2464 AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
2762 if (sub_expr_node == nullptr)2465 if (sub_expr_node == nullptr)
...@@ -2766,7 +2469,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran...@@ -2766,7 +2469,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
2766}2469}
27672470
2768static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,2471static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
2769 const UnaryExprOrTypeTraitExpr *stmt)2472 const clang::UnaryExprOrTypeTraitExpr *stmt)
2770{2473{
2771 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc());2474 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc());
2772 if (type_node == nullptr)2475 if (type_node == nullptr)
...@@ -2777,14 +2480,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop...@@ -2777,14 +2480,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
2777 return node;2480 return node;
2778}2481}
27792482
2780static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) {2483static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) {
2781 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);2484 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
27822485
2783 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);2486 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
27842487
2785 AstNode *body_node;2488 AstNode *body_node;
2786 TransScope *child_scope;2489 TransScope *child_scope;
2787 if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {2490 if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
2788 // there's already a block in C, so we'll append our condition to it.2491 // there's already a block in C, so we'll append our condition to it.
2789 // c: do {2492 // c: do {
2790 // c: a;2493 // c: a;
...@@ -2837,11 +2540,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt...@@ -2837,11 +2540,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
2837 return while_scope->node;2540 return while_scope->node;
2838}2541}
28392542
2840static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) {2543static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang::ForStmt *stmt) {
2841 AstNode *loop_block_node;2544 AstNode *loop_block_node;
2842 TransScopeWhile *while_scope;2545 TransScopeWhile *while_scope;
2843 TransScope *cond_scope;2546 TransScope *cond_scope;
2844 const Stmt *init_stmt = stmt->getInit();2547 const clang::Stmt *init_stmt = stmt->getInit();
2845 if (init_stmt == nullptr) {2548 if (init_stmt == nullptr) {
2846 while_scope = trans_scope_while_create(c, parent_scope);2549 while_scope = trans_scope_while_create(c, parent_scope);
2847 loop_block_node = while_scope->node;2550 loop_block_node = while_scope->node;
...@@ -2862,12 +2565,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt...@@ -2862,12 +2565,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2862 child_scope->node->data.block.statements.append(while_scope->node);2565 child_scope->node->data.block.statements.append(while_scope->node);
2863 }2566 }
28642567
2865 const Stmt *cond_stmt = stmt->getCond();2568 const clang::Stmt *cond_stmt = stmt->getCond();
2866 if (cond_stmt == nullptr) {2569 if (cond_stmt == nullptr) {
2867 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);2570 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2868 } else {2571 } else {
2869 if (Expr::classof(cond_stmt)) {2572 if (clang::Expr::classof(cond_stmt)) {
2870 const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);2573 const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt);
2871 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);2574 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
28722575
2873 if (while_scope->node->data.while_expr.condition == nullptr)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,7 +2583,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2880 }2583 }
2881 }2584 }
28822585
2883 const Stmt *inc_stmt = stmt->getInc();2586 const clang::Stmt *inc_stmt = stmt->getInc();
2884 if (inc_stmt != nullptr) {2587 if (inc_stmt != nullptr) {
2885 AstNode *inc_node;2588 AstNode *inc_node;
2886 TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);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,12 +2606,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2903 return loop_block_node;2606 return loop_block_node;
2904}2607}
29052608
2906static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) {2609static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const clang::SwitchStmt *stmt) {
2907 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);2610 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
29082611
2909 TransScopeSwitch *switch_scope;2612 TransScopeSwitch *switch_scope;
29102613
2911 const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();2614 const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
2912 if (var_decl_stmt == nullptr) {2615 if (var_decl_stmt == nullptr) {
2913 switch_scope = trans_scope_switch_create(c, &block_scope->base);2616 switch_scope = trans_scope_switch_create(c, &block_scope->base);
2914 } else {2617 } else {
...@@ -2927,7 +2630,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw...@@ -2927,7 +2630,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
2927 switch_scope->end_label_name = end_label_name;2630 switch_scope->end_label_name = end_label_name;
2928 block_scope->node->data.block.name = end_label_name;2631 block_scope->node->data.block.name = end_label_name;
29292632
2930 const Expr *cond_expr = stmt->getCond();2633 const clang::Expr *cond_expr = stmt->getCond();
2931 assert(cond_expr != nullptr);2634 assert(cond_expr != nullptr);
29322635
2933 AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);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,9 +2639,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
2936 switch_scope->switch_node->data.switch_expr.expr = expr_node;2639 switch_scope->switch_node->data.switch_expr.expr = expr_node;
29372640
2938 AstNode *body_node;2641 AstNode *body_node;
2939 const Stmt *body_stmt = stmt->getBody();2642 const clang::Stmt *body_stmt = stmt->getBody();
2940 if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {2643 if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
2941 if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,2644 if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
2942 block_scope->node, nullptr))2645 block_scope->node, nullptr))
2943 {2646 {
2944 return nullptr;2647 return nullptr;
...@@ -2970,7 +2673,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {...@@ -2970,7 +2673,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
2970 return nullptr;2673 return nullptr;
2971}2674}
29722675
2973static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node,2676static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::CaseStmt *stmt, AstNode **out_node,
2974 TransScope **out_scope) {2677 TransScope **out_scope) {
2975 *out_node = nullptr;2678 *out_node = nullptr;
29762679
...@@ -3015,7 +2718,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm...@@ -3015,7 +2718,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm
3015 return ErrorNone;2718 return ErrorNone;
3016}2719}
30172720
3018static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node,2721static int trans_switch_default(Context *c, TransScope *parent_scope, const clang::DefaultStmt *stmt, AstNode **out_node,
3019 TransScope **out_scope)2722 TransScope **out_scope)
3020{2723{
3021 *out_node = nullptr;2724 *out_node = nullptr;
...@@ -3052,25 +2755,27 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa...@@ -3052,25 +2755,27 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa
3052 return ErrorNone;2755 return ErrorNone;
3053}2756}
30542757
3055static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) {2758static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) {
3056 switch (stmt->getKind()) {2759 switch (stmt->getKind()) {
3057 case StringLiteral::Ascii:2760 case clang::StringLiteral::Ascii:
3058 case StringLiteral::UTF8:2761 case clang::StringLiteral::UTF8:
3059 return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));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 emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals");2764 emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals");
3062 return nullptr;2765 return nullptr;
3063 case StringLiteral::UTF32:2766 case clang::StringLiteral::UTF32:
3064 emit_warning(c, stmt->getBeginLoc(), "TODO support UTF32 string literals");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 return nullptr;2770 return nullptr;
3066 case StringLiteral::Wide:2771 case clang::StringLiteral::Wide:
3067 emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals");2772 emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals");
3068 return nullptr;2773 return nullptr;
3069 }2774 }
3070 zig_unreachable();2775 zig_unreachable();
3071}2776}
30722777
3073static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) {2778static AstNode *trans_break_stmt(Context *c, TransScope *scope, const clang::BreakStmt *stmt) {
3074 TransScope *cur_scope = scope;2779 TransScope *cur_scope = scope;
3075 while (cur_scope != nullptr) {2780 while (cur_scope != nullptr) {
3076 if (cur_scope->id == TransScopeIdWhile) {2781 if (cur_scope->id == TransScopeIdWhile) {
...@@ -3084,7 +2789,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt...@@ -3084,7 +2789,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt
3084 zig_unreachable();2789 zig_unreachable();
3085}2790}
30862791
3087static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) {2792static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::ContinueStmt *stmt) {
3088 return trans_create_node(c, NodeTypeContinue);2793 return trans_create_node(c, NodeTypeContinue);
3089}2794}
30902795
...@@ -3097,47 +2802,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_...@@ -3097,47 +2802,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
3097 return ErrorNone;2802 return ErrorNone;
3098}2803}
30992804
3100static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,2805static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
3101 ResultUsed result_used, TransLRValue lrvalue,2806 ResultUsed result_used, TransLRValue lrvalue,
3102 AstNode **out_node, TransScope **out_child_scope,2807 AstNode **out_node, TransScope **out_child_scope,
3103 TransScope **out_node_scope)2808 TransScope **out_node_scope)
3104{2809{
3105 Stmt::StmtClass sc = stmt->getStmtClass();2810 clang::Stmt::StmtClass sc = stmt->getStmtClass();
3106 switch (sc) {2811 switch (sc) {
3107 case Stmt::ReturnStmtClass:2812 case clang::Stmt::ReturnStmtClass:
3108 return wrap_stmt(out_node, out_child_scope, scope,2813 return wrap_stmt(out_node, out_child_scope, scope,
3109 trans_return_stmt(c, scope, (const ReturnStmt *)stmt));2814 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
3110 case Stmt::CompoundStmtClass:2815 case clang::Stmt::CompoundStmtClass:
3111 return wrap_stmt(out_node, out_child_scope, scope,2816 return wrap_stmt(out_node, out_child_scope, scope,
3112 trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope));2817 trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
3113 case Stmt::IntegerLiteralClass:2818 case clang::Stmt::IntegerLiteralClass:
3114 return wrap_stmt(out_node, out_child_scope, scope,2819 return wrap_stmt(out_node, out_child_scope, scope,
3115 trans_integer_literal(c, (const IntegerLiteral *)stmt));2820 trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
3116 case Stmt::ConditionalOperatorClass:2821 case clang::Stmt::ConditionalOperatorClass:
3117 return wrap_stmt(out_node, out_child_scope, scope,2822 return wrap_stmt(out_node, out_child_scope, scope,
3118 trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt));2823 trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
3119 case Stmt::BinaryOperatorClass:2824 case clang::Stmt::BinaryOperatorClass:
3120 return wrap_stmt(out_node, out_child_scope, scope,2825 return wrap_stmt(out_node, out_child_scope, scope,
3121 trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt));2826 trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
3122 case Stmt::CompoundAssignOperatorClass:2827 case clang::Stmt::CompoundAssignOperatorClass:
3123 return wrap_stmt(out_node, out_child_scope, scope,2828 return wrap_stmt(out_node, out_child_scope, scope,
3124 trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt));2829 trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
3125 case Stmt::ImplicitCastExprClass:2830 case clang::Stmt::ImplicitCastExprClass:
3126 return wrap_stmt(out_node, out_child_scope, scope,2831 return wrap_stmt(out_node, out_child_scope, scope,
3127 trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt));2832 trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
3128 case Stmt::DeclRefExprClass:2833 case clang::Stmt::DeclRefExprClass:
3129 return wrap_stmt(out_node, out_child_scope, scope,2834 return wrap_stmt(out_node, out_child_scope, scope,
3130 trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue));2835 trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
3131 case Stmt::UnaryOperatorClass:2836 case clang::Stmt::UnaryOperatorClass:
3132 return wrap_stmt(out_node, out_child_scope, scope,2837 return wrap_stmt(out_node, out_child_scope, scope,
3133 trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt));2838 trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
3134 case Stmt::DeclStmtClass:2839 case clang::Stmt::DeclStmtClass:
3135 return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope);2840 return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
3136 case Stmt::DoStmtClass:2841 case clang::Stmt::DoStmtClass:
3137 case Stmt::WhileStmtClass: {2842 case clang::Stmt::WhileStmtClass: {
3138 AstNode *while_node = sc == Stmt::DoStmtClass2843 AstNode *while_node = sc == clang::Stmt::DoStmtClass
3139 ? trans_do_loop(c, scope, (const DoStmt *)stmt)2844 ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
3140 : trans_while_loop(c, scope, (const WhileStmt *)stmt);2845 : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
31412846
3142 if (while_node == nullptr)2847 if (while_node == nullptr)
3143 return ErrorUnexpected;2848 return ErrorUnexpected;
...@@ -3148,567 +2853,63 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,...@@ -3148,567 +2853,63 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
31482853
3149 return wrap_stmt(out_node, out_child_scope, scope, while_node);2854 return wrap_stmt(out_node, out_child_scope, scope, while_node);
3150 }2855 }
3151 case Stmt::IfStmtClass:2856 case clang::Stmt::IfStmtClass:
3152 return wrap_stmt(out_node, out_child_scope, scope,2857 return wrap_stmt(out_node, out_child_scope, scope,
3153 trans_if_statement(c, scope, (const IfStmt *)stmt));2858 trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
3154 case Stmt::CallExprClass:2859 case clang::Stmt::CallExprClass:
3155 return wrap_stmt(out_node, out_child_scope, scope,2860 return wrap_stmt(out_node, out_child_scope, scope,
3156 trans_call_expr(c, result_used, scope, (const CallExpr *)stmt));2861 trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
3157 case Stmt::NullStmtClass:2862 case clang::Stmt::NullStmtClass:
3158 *out_node = nullptr;2863 *out_node = nullptr;
3159 *out_child_scope = scope;2864 *out_child_scope = scope;
3160 return ErrorNone;2865 return ErrorNone;
3161 case Stmt::MemberExprClass:2866 case clang::Stmt::MemberExprClass:
3162 return wrap_stmt(out_node, out_child_scope, scope,2867 return wrap_stmt(out_node, out_child_scope, scope,
3163 trans_member_expr(c, scope, (const MemberExpr *)stmt));2868 trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
3164 case Stmt::ArraySubscriptExprClass:2869 case clang::Stmt::ArraySubscriptExprClass:
3165 return wrap_stmt(out_node, out_child_scope, scope,2870 return wrap_stmt(out_node, out_child_scope, scope,
3166 trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt));2871 trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
3167 case Stmt::CStyleCastExprClass:2872 case clang::Stmt::CStyleCastExprClass:
3168 return wrap_stmt(out_node, out_child_scope, scope,2873 return wrap_stmt(out_node, out_child_scope, scope,
3169 trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue));2874 trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
3170 case Stmt::UnaryExprOrTypeTraitExprClass:2875 case clang::Stmt::UnaryExprOrTypeTraitExprClass:
3171 return wrap_stmt(out_node, out_child_scope, scope,2876 return wrap_stmt(out_node, out_child_scope, scope,
3172 trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt));2877 trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
3173 case Stmt::ForStmtClass: {2878 case clang::Stmt::ForStmtClass: {
3174 AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt);2879 AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
3175 return wrap_stmt(out_node, out_child_scope, scope, node);2880 return wrap_stmt(out_node, out_child_scope, scope, node);
3176 }2881 }
3177 case Stmt::StringLiteralClass:2882 case clang::Stmt::StringLiteralClass:
3178 return wrap_stmt(out_node, out_child_scope, scope,2883 return wrap_stmt(out_node, out_child_scope, scope,
3179 trans_string_literal(c, scope, (const StringLiteral *)stmt));2884 trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
3180 case Stmt::BreakStmtClass:2885 case clang::Stmt::BreakStmtClass:
3181 return wrap_stmt(out_node, out_child_scope, scope,2886 return wrap_stmt(out_node, out_child_scope, scope,
3182 trans_break_stmt(c, scope, (const BreakStmt *)stmt));2887 trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
3183 case Stmt::ContinueStmtClass:2888 case clang::Stmt::ContinueStmtClass:
3184 return wrap_stmt(out_node, out_child_scope, scope,2889 return wrap_stmt(out_node, out_child_scope, scope,
3185 trans_continue_stmt(c, scope, (const ContinueStmt *)stmt));2890 trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
3186 case Stmt::ParenExprClass:2891 case clang::Stmt::ParenExprClass:
3187 return wrap_stmt(out_node, out_child_scope, scope,2892 return wrap_stmt(out_node, out_child_scope, scope,
3188 trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));2893 trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
3189 case Stmt::SwitchStmtClass:2894 case clang::Stmt::SwitchStmtClass:
3190 return wrap_stmt(out_node, out_child_scope, scope,2895 return wrap_stmt(out_node, out_child_scope, scope,
3191 trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));2896 trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
3192 case Stmt::CaseStmtClass:2897 case clang::Stmt::CaseStmtClass:
3193 return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);2898 return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
3194 case Stmt::DefaultStmtClass:2899 case clang::Stmt::DefaultStmtClass:
3195 return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);2900 return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
3196 case Stmt::ConstantExprClass:2901 case clang::Stmt::ConstantExprClass:
3197 return wrap_stmt(out_node, out_child_scope, scope,2902 return wrap_stmt(out_node, out_child_scope, scope,
3198 trans_constant_expr(c, (const ConstantExpr *)stmt));2903 trans_constant_expr(c, (const clang::ConstantExpr *)stmt));
3199 case Stmt::NoStmtClass:2904 case clang::Stmt::NoStmtClass:
3200 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass");2905 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass");
3201 return ErrorUnexpected;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 zig_unreachable();2908 zig_unreachable();
3708}2909}
37092910
3710// Returns null if there was an error2911// Returns null if there was an error
3711static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr,2912static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr,
3712 TransLRValue lrval)2913 TransLRValue lrval)
3713{2914{
3714 AstNode *result_node;2915 AstNode *result_node;
...@@ -3721,7 +2922,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope...@@ -3721,7 +2922,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
37212922
3722// Statements have no result and no concept of L or R value.2923// Statements have no result and no concept of L or R value.
3723// Returns child scope, or null if there was an error2924// Returns child scope, or null if there was an error
3724static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node) {2925static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) {
3725 TransScope *child_scope;2926 TransScope *child_scope;
3726 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {2927 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
3727 return nullptr;2928 return nullptr;
...@@ -3729,7 +2930,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A...@@ -3729,7 +2930,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A
3729 return child_scope;2930 return child_scope;
3730}2931}
37312932
3732static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {2933static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
3733 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));2934 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
37342935
3735 if (get_global(c, fn_name)) {2936 if (get_global(c, fn_name)) {
...@@ -3746,13 +2947,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3746,13 +2947,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
3746 proto_node->data.fn_proto.name = fn_name;2947 proto_node->data.fn_proto.name = fn_name;
3747 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();2948 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
37482949
3749 StorageClass sc = fn_decl->getStorageClass();2950 clang::StorageClass sc = fn_decl->getStorageClass();
3750 if (sc == SC_None) {2951 if (sc == clang::SC_None) {
3751 proto_node->data.fn_proto.visib_mod = c->visib_mod;2952 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3752 proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;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 proto_node->data.fn_proto.visib_mod = c->visib_mod;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 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");2957 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
3757 return;2958 return;
3758 } else {2959 } else {
...@@ -3764,7 +2965,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3764,7 +2965,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37642965
3765 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {2966 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
3766 AstNode *param_node = proto_node->data.fn_proto.params.at(i);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 const char *name = decl_name(param);2969 const char *name = decl_name(param);
37692970
3770 Buf *proto_param_name;2971 Buf *proto_param_name;
...@@ -3791,7 +2992,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3791,7 +2992,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37912992
3792 // actual function definition with body2993 // actual function definition with body
3793 c->ptr_params.clear();2994 c->ptr_params.clear();
3794 Stmt *body = fn_decl->getBody();2995 clang::Stmt *body = fn_decl->getBody();
3795 AstNode *actual_body_node;2996 AstNode *actual_body_node;
3796 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);2997 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
3797 if (result_scope == nullptr) {2998 if (result_scope == nullptr) {
...@@ -3833,19 +3034,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3833,19 +3034,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
3833 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);3034 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
3834}3035}
38353036
3836static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {3037static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) {
3837 AstNode *node = trans_create_node_symbol_str(c, primitive_name);3038 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
3838 c->decl_table.put(typedef_decl, node);3039 c->decl_table.put(typedef_decl, node);
3839 return node;3040 return node;
3840}3041}
38413042
3842static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {3043static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
3843 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());3044 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
3844 if (existing_entry) {3045 if (existing_entry) {
3845 return existing_entry->value;3046 return existing_entry->value;
3846 }3047 }
38473048
3848 QualType child_qt = typedef_decl->getUnderlyingType();3049 clang::QualType child_qt = typedef_decl->getUnderlyingType();
3849 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));3050 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
38503051
3851 if (buf_eql_str(type_name, "uint8_t")) {3052 if (buf_eql_str(type_name, "uint8_t")) {
...@@ -3894,7 +3095,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_...@@ -3894,7 +3095,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_
3894 return symbol_node;3095 return symbol_node;
3895}3096}
38963097
3897struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,3098struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl,
3898 Buf *full_type_name, Buf *bare_name)3099 Buf *full_type_name, Buf *bare_name)
3899{3100{
3900 AstNode *opaque_node = trans_create_node_opaque(c);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,7 +3110,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
3909 return symbol_node;3110 return symbol_node;
3910}3111}
39113112
3912static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {3113static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
3913 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());3114 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
3914 if (existing_entry) {3115 if (existing_entry) {
3915 return existing_entry->value;3116 return existing_entry->value;
...@@ -3920,7 +3121,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3920,7 +3121,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3920 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);3121 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
3921 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));3122 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
39223123
3923 const EnumDecl *enum_def = enum_decl->getDefinition();3124 const clang::EnumDecl *enum_def = enum_decl->getDefinition();
3924 if (!enum_def) {3125 if (!enum_def) {
3925 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);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,7 +3133,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3932 it_end = enum_def->enumerator_end();3133 it_end = enum_def->enumerator_end();
3933 it != it_end; ++it, field_count += 1)3134 it != it_end; ++it, field_count += 1)
3934 {3135 {
3935 const EnumConstantDecl *enum_const = *it;3136 const clang::EnumConstantDecl *enum_const = *it;
3936 if (enum_const->getInitExpr()) {3137 if (enum_const->getInitExpr()) {
3937 pure_enum = false;3138 pure_enum = false;
3938 }3139 }
...@@ -3946,8 +3147,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3946,8 +3147,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3946 // TODO only emit this tag type if the enum tag type is not the default.3147 // TODO only emit this tag type if the enum tag type is not the default.
3947 // I don't know what the default is, need to figure out how clang is deciding.3148 // I don't know what the default is, need to figure out how clang is deciding.
3948 // it appears to at least be different across gcc/msvc3149 // it appears to at least be different across gcc/msvc
3949 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&3150 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&
3950 !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))3151 !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
3951 {3152 {
3952 enum_node->data.container_decl.init_arg_expr = tag_int_type;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,7 +3158,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3957 it_end = enum_def->enumerator_end();3158 it_end = enum_def->enumerator_end();
3958 it != it_end; ++it, i += 1)3159 it != it_end; ++it, i += 1)
3959 {3160 {
3960 const EnumConstantDecl *enum_const = *it;3161 const clang::EnumConstantDecl *enum_const = *it;
39613162
3962 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));3163 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
3963 Buf *field_name;3164 Buf *field_name;
...@@ -3998,7 +3199,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3998,7 +3199,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3998 }3199 }
3999}3200}
40003201
4001static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,3202static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl,
4002 Buf *full_type_name, Buf *bare_name)3203 Buf *full_type_name, Buf *bare_name)
4003{3204{
4004 AstNode *opaque_node = trans_create_node_opaque(c);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,7 +3214,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec
4013 return symbol_node;3214 return symbol_node;
4014}3215}
40153216
4016static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {3217static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
4017 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());3218 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
4018 if (existing_entry) {3219 if (existing_entry) {
4019 return existing_entry->value;3220 return existing_entry->value;
...@@ -4039,7 +3240,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -4039,7 +3240,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4039 Buf *full_type_name = (bare_name == nullptr) ?3240 Buf *full_type_name = (bare_name == nullptr) ?
4040 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));3241 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
40413242
4042 RecordDecl *record_def = record_decl->getDefinition();3243 clang::RecordDecl *record_def = record_decl->getDefinition();
4043 if (record_def == nullptr) {3244 if (record_def == nullptr) {
4044 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);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,7 +3251,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4050 it_end = record_def->field_end();3251 it_end = record_def->field_end();
4051 it != it_end; ++it, field_count += 1)3252 it != it_end; ++it, field_count += 1)
4052 {3253 {
4053 const FieldDecl *field_decl = *it;3254 const clang::FieldDecl *field_decl = *it;
40543255
4055 if (field_decl->isBitField()) {3256 if (field_decl->isBitField()) {
4056 emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",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,7 +3281,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4080 it_end = record_def->field_end();3281 it_end = record_def->field_end();
4081 it != it_end; ++it, i += 1)3282 it != it_end; ++it, i += 1)
4082 {3283 {
4083 const FieldDecl *field_decl = *it;3284 const clang::FieldDecl *field_decl = *it;
40843285
4085 AstNode *field_node = trans_create_node(c, NodeTypeStructField);3286 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
4086 field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));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,13 +3308,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4107 }3308 }
4108}3309}
41093310
4110static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) {3311static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) {
4111 switch (ap_value->getKind()) {3312 switch (ap_value->getKind()) {
4112 case APValue::Int:3313 case clang::APValue::Int:
4113 return trans_create_node_apint(c, ap_value->getInt());3314 return trans_create_node_apint(c, ap_value->getInt());
4114 case APValue::Uninitialized:3315 case clang::APValue::Uninitialized:
4115 return trans_create_node(c, NodeTypeUndefinedLiteral);3316 return trans_create_node(c, NodeTypeUndefinedLiteral);
4116 case APValue::Array: {3317 case clang::APValue::Array: {
4117 emit_warning(c, source_loc, "TODO add a test case for this code");3318 emit_warning(c, source_loc, "TODO add a test case for this code");
41183319
4119 unsigned init_count = ap_value->getArrayInitializedElts();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,13 +3322,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
4121 unsigned leftover_count = all_count - init_count;3322 unsigned leftover_count = all_count - init_count;
4122 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);3323 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
4123 AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);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 init_node->data.container_init_expr.type = arr_type_node;3328 init_node->data.container_init_expr.type = arr_type_node;
4125 init_node->data.container_init_expr.kind = ContainerInitKindArray;3329 init_node->data.container_init_expr.kind = ContainerInitKindArray;
41263330
4127 QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();3331 clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType();
41283332
4129 for (size_t i = 0; i < init_count; i += 1) {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 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);3335 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
4132 if (elem_node == nullptr)3336 if (elem_node == nullptr)
4133 return nullptr;3337 return nullptr;
...@@ -4137,15 +3341,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const...@@ -4137,15 +3341,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
4137 return init_node;3341 return init_node;
4138 }3342 }
41393343
4140 APValue &filler_ap_val = ap_value->getArrayFiller();3344 clang::APValue &filler_ap_val = ap_value->getArrayFiller();
4141 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);3345 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
4142 if (filler_node == nullptr)3346 if (filler_node == nullptr)
4143 return nullptr;3347 return nullptr;
41443348
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 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);3353 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
4146 init_node->data.container_init_expr.type = arr_type_node;3354 filler_arr_1->data.container_init_expr.type = filler_arr_type;
4147 init_node->data.container_init_expr.kind = ContainerInitKindArray;3355 filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
4148 init_node->data.container_init_expr.entries.append(filler_node);3356 filler_arr_1->data.container_init_expr.entries.append(filler_node);
41493357
4150 AstNode *rhs_node;3358 AstNode *rhs_node;
4151 if (leftover_count == 1) {3359 if (leftover_count == 1) {
...@@ -4155,62 +3363,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const...@@ -4155,62 +3363,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
4155 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);3363 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
4156 }3364 }
41573365
3366 if (init_count == 0) {
3367 return rhs_node;
3368 }
3369
4158 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);3370 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
4159 }3371 }
4160 case APValue::LValue: {3372 case clang::APValue::LValue: {
4161 const APValue::LValueBase lval_base = ap_value->getLValueBase();3373 const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
4162 if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) {3374 if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) {
4163 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);3375 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
4164 }3376 }
4165 //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>();3377 //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();
4166 emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");3378 emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
4167 return nullptr;3379 return nullptr;
4168 }3380 }
4169 case APValue::Float:3381 case clang::APValue::Float:
4170 emit_warning(c, source_loc, "unsupported initializer value kind: Float");3382 emit_warning(c, source_loc, "unsupported initializer value kind: Float");
4171 return nullptr;3383 return nullptr;
4172 case APValue::ComplexInt:3384 case clang::APValue::ComplexInt:
4173 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");3385 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
4174 return nullptr;3386 return nullptr;
4175 case APValue::ComplexFloat:3387 case clang::APValue::ComplexFloat:
4176 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");3388 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
4177 return nullptr;3389 return nullptr;
4178 case APValue::Vector:3390 case clang::APValue::Vector:
4179 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");3391 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
4180 return nullptr;3392 return nullptr;
4181 case APValue::Struct:3393 case clang::APValue::Struct:
4182 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");3394 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
4183 return nullptr;3395 return nullptr;
4184 case APValue::Union:3396 case clang::APValue::Union:
4185 emit_warning(c, source_loc, "unsupported initializer value kind: Union");3397 emit_warning(c, source_loc, "unsupported initializer value kind: Union");
4186 return nullptr;3398 return nullptr;
4187 case APValue::MemberPointer:3399 case clang::APValue::MemberPointer:
4188 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");3400 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
4189 return nullptr;3401 return nullptr;
4190 case APValue::AddrLabelDiff:3402 case clang::APValue::AddrLabelDiff:
4191 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");3403 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
4192 return nullptr;3404 return nullptr;
4193 }3405 }
4194 zig_unreachable();3406 zig_unreachable();
4195}3407}
41963408
4197static void visit_var_decl(Context *c, const VarDecl *var_decl) {3409static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
4198 Buf *name = buf_create_from_str(decl_name(var_decl));3410 Buf *name = buf_create_from_str(decl_name(var_decl));
41993411
4200 switch (var_decl->getTLSKind()) {3412 switch (var_decl->getTLSKind()) {
4201 case VarDecl::TLS_None:3413 case clang::VarDecl::TLS_None:
4202 break;3414 break;
4203 case VarDecl::TLS_Static:3415 case clang::VarDecl::TLS_Static:
4204 emit_warning(c, var_decl->getLocation(),3416 emit_warning(c, var_decl->getLocation(),
4205 "ignoring variable '%s' - static thread local storage", buf_ptr(name));3417 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
4206 return;3418 return;
4207 case VarDecl::TLS_Dynamic:3419 case clang::VarDecl::TLS_Dynamic:
4208 emit_warning(c, var_decl->getLocation(),3420 emit_warning(c, var_decl->getLocation(),
4209 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));3421 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
4210 return;3422 return;
4211 }3423 }
42123424
4213 QualType qt = var_decl->getType();3425 clang::QualType qt = var_decl->getType();
4214 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());3426 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
4215 if (var_type == nullptr) {3427 if (var_type == nullptr) {
4216 emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));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,7 +3436,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
4224 if (is_static && !is_extern) {3436 if (is_static && !is_extern) {
4225 AstNode *init_node;3437 AstNode *init_node;
4226 if (var_decl->hasInit()) {3438 if (var_decl->hasInit()) {
4227 APValue *ap_value = var_decl->evaluateValue();3439 clang::APValue *ap_value = var_decl->evaluateValue();
4228 if (ap_value == nullptr) {3440 if (ap_value == nullptr) {
4229 emit_warning(c, var_decl->getLocation(),3441 emit_warning(c, var_decl->getLocation(),
4230 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));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,24 +3466,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
4254 return;3466 return;
4255}3467}
42563468
4257static bool decl_visitor(void *context, const Decl *decl) {3469static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {
3470 const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl);
4258 Context *c = (Context*)context;3471 Context *c = (Context*)context;
42593472
4260 switch (decl->getKind()) {3473 switch (decl->getKind()) {
4261 case Decl::Function:3474 case clang::Decl::Function:
4262 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));3475 visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));
4263 break;3476 break;
4264 case Decl::Typedef:3477 case clang::Decl::Typedef:
4265 resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));3478 resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl));
4266 break;3479 break;
4267 case Decl::Enum:3480 case clang::Decl::Enum:
4268 resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));3481 resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl));
4269 break;3482 break;
4270 case Decl::Record:3483 case clang::Decl::Record:
4271 resolve_record_decl(c, static_cast<const RecordDecl *>(decl));3484 resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl));
4272 break;3485 break;
4273 case Decl::Var:3486 case clang::Decl::Var:
4274 visit_var_decl(c, static_cast<const VarDecl *>(decl));3487 visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));
4275 break;3488 break;
4276 default:3489 default:
4277 emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());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,7 +3826,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
4613 } else if (first_tok->id == CTokIdAsterisk) {3826 } else if (first_tok->id == CTokIdAsterisk) {
4614 *tok_i += 1;3827 *tok_i += 1;
46153828
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 } else {3830 } else {
4618 return node;3831 return node;
4619 }3832 }
...@@ -4692,24 +3905,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch...@@ -4692,24 +3905,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
4692 c->macro_table.put(name, result_node);3905 c->macro_table.put(name, result_node);
4693}3906}
46943907
4695static void process_preprocessor_entities(Context *c, ASTUnit &unit) {3908static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
3909 clang::ASTUnit *unit = reinterpret_cast<clang::ASTUnit *>(zunit);
4696 CTokenize ctok = {{0}};3910 CTokenize ctok = {{0}};
46973911
4698 // TODO if we see #undef, delete it from the table3912 // TODO if we see #undef, delete it from the table
46993913
4700 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {3914 for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) {
4701 switch (entity->getKind()) {3915 switch (entity->getKind()) {
4702 case PreprocessedEntity::InvalidKind:3916 case clang::PreprocessedEntity::InvalidKind:
4703 case PreprocessedEntity::InclusionDirectiveKind:3917 case clang::PreprocessedEntity::InclusionDirectiveKind:
4704 case PreprocessedEntity::MacroExpansionKind:3918 case clang::PreprocessedEntity::MacroExpansionKind:
4705 continue;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 const char *raw_name = macro->getName()->getNameStart();3923 const char *raw_name = macro->getName()->getNameStart();
4710 SourceRange range = macro->getSourceRange();3924 clang::SourceRange range = macro->getSourceRange();
4711 SourceLocation begin_loc = range.getBegin();3925 clang::SourceLocation begin_loc = range.getBegin();
4712 SourceLocation end_loc = range.getEnd();3926 clang::SourceLocation end_loc = range.getEnd();
47133927
4714 if (begin_loc == end_loc) {3928 if (begin_loc == end_loc) {
4715 // this means it is a macro without a value3929 // this means it is a macro without a value
...@@ -4721,7 +3935,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {...@@ -4721,7 +3935,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
4721 continue;3935 continue;
4722 }3936 }
47233937
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 process_macro(c, &ctok, name, begin_c);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,7 +3986,16 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4772 clang_argv.append("-x");3986 clang_argv.append("-x");
4773 clang_argv.append("c");3987 clang_argv.append("c");
47743988
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 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");3999 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
4777 if (ZIG_PARSEC_CFLAGS) {4000 if (ZIG_PARSEC_CFLAGS) {
4778 Buf tmp_buf = BUF_INIT;4001 Buf tmp_buf = BUF_INIT;
...@@ -4791,12 +4014,24 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4791,12 +4014,24 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4791 }4014 }
4792 }4015 }
47934016
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 clang_argv.append("-isystem");4024 clang_argv.append("-isystem");
4795 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));4025 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
47964026
4797 if (codegen->libc_include_dir != nullptr) {4027 if (codegen->libc != nullptr) {
4798 clang_argv.append("-isystem");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 }
48014036
4802 // windows c runtime requires -D_DEBUG if using debug libraries4037 // 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,7 +4051,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4816 clang_argv.append("-Xclang");4051 clang_argv.append("-Xclang");
4817 clang_argv.append("-detailed-preprocessing-record");4052 clang_argv.append("-detailed-preprocessing-record");
48184053
4819 if (!c->codegen->is_native_target) {4054 if (c->codegen->zig_target->is_native) {
4055 clang_argv.append("-march=native");
4056 } else {
4820 clang_argv.append("-target");4057 clang_argv.append("-target");
4821 clang_argv.append(buf_ptr(&c->codegen->triple_str));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,9 +4071,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4834 // to make the [start...end] argument work4071 // to make the [start...end] argument work
4835 clang_argv.append(nullptr);4072 clang_argv.append(nullptr);
48364073
4837 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));4074 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
48384075
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>();
48404077
4841 bool only_local_decls = true;4078 bool only_local_decls = true;
4842 bool capture_diagnostics = true;4079 bool capture_diagnostics = true;
...@@ -4845,13 +4082,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4845,13 +4082,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4845 bool single_file_parse = false;4082 bool single_file_parse = false;
4846 bool for_serialization = false;4083 bool for_serialization = false;
4847 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);4084 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
4848 std::unique_ptr<ASTUnit> err_unit;4085 std::unique_ptr<clang::ASTUnit> err_unit;
4849 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(4086 ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
4850 &clang_argv.at(0), &clang_argv.last(),4087 &clang_argv.at(0), &clang_argv.last(),
4851 pch_container_ops, diags, resources_path,4088 pch_container_ops, diags, resources_path,
4852 only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,4089 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
4853 false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None,4090 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
4854 single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,4091 single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
4855 nullptr));4092 nullptr));
48564093
4857 // Early failures in LoadFromCommandLine may return with ErrUnit unset.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,29 +4098,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48614098
4862 if (diags->getClient()->getNumErrors() > 0) {4099 if (diags->getClient()->getNumErrors() > 0) {
4863 if (ast_unit) {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 }
48664103
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 it_end = err_unit->stored_diag_end();4105 it_end = err_unit->stored_diag_end();
4869 it != it_end; ++it)4106 it != it_end; ++it)
4870 {4107 {
4871 switch (it->getLevel()) {4108 switch (it->getLevel()) {
4872 case DiagnosticsEngine::Ignored:4109 case clang::DiagnosticsEngine::Ignored:
4873 case DiagnosticsEngine::Note:4110 case clang::DiagnosticsEngine::Note:
4874 case DiagnosticsEngine::Remark:4111 case clang::DiagnosticsEngine::Remark:
4875 case DiagnosticsEngine::Warning:4112 case clang::DiagnosticsEngine::Warning:
4876 continue;4113 continue;
4877 case DiagnosticsEngine::Error:4114 case clang::DiagnosticsEngine::Error:
4878 case DiagnosticsEngine::Fatal:4115 case clang::DiagnosticsEngine::Fatal:
4879 break;4116 break;
4880 }4117 }
4881 StringRef msg_str_ref = it->getMessage();4118 StringRef msg_str_ref = it->getMessage();
4882 Buf *msg = string_ref_to_buf(msg_str_ref);4119 Buf *msg = string_ref_to_buf(msg_str_ref);
4883 FullSourceLoc fsl = it->getLocation();4120 clang::FullSourceLoc fsl = it->getLocation();
4884 if (fsl.hasManager()) {4121 if (fsl.hasManager()) {
4885 FileID file_id = fsl.getFileID();4122 clang::FileID file_id = fsl.getFileID();
4886 StringRef filename = fsl.getManager().getFilename(fsl);4123 clang::StringRef filename = fsl.getManager().getFilename(fsl);
4887 unsigned line = fsl.getSpellingLineNumber() - 1;4124 unsigned line = fsl.getSpellingLineNumber() - 1;
4888 unsigned column = fsl.getSpellingColumnNumber() - 1;4125 unsigned column = fsl.getSpellingColumnNumber() - 1;
4889 unsigned offset = fsl.getManager().getFileOffset(fsl);4126 unsigned offset = fsl.getManager().getFileOffset(fsl);
...@@ -4908,14 +4145,25 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4908,14 +4145,25 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4908 return ErrorCCompileErrors;4145 return ErrorCCompileErrors;
4909 }4146 }
49104147
4911 c->ctx = &ast_unit->getASTContext();4148 if (codegen->enable_cache) {
4912 c->source_manager = &ast_unit->getSourceManager();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 c->root = trans_create_node(c, NodeTypeContainerDecl);4161 c->root = trans_create_node(c, NodeTypeContainerDecl);
4914 c->root->data.container_decl.is_root = true;4162 c->root->data.container_decl.is_root = true;
49154163
4916 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);4164 ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor);
49174165
4918 process_preprocessor_entities(c, *ast_unit);4166 process_preprocessor_entities(c, ast_unit);
49194167
4920 render_macros(c);4168 render_macros(c);
4921 render_aliases(c);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,11 +147,14 @@ static inline T clamp(T min_value, T value, T max_value) {
147 return max(min(value, max_value), min_value);147 return max(min(value, max_value), min_value);
148}148}
149149
150static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {150static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
151 size_t str_len = strlen(str);151 if (a_len != b_len)
152 if (str_len != mem_len)
153 return false;152 return false;
154 return memcmp(mem, str, mem_len) == 0;153 return memcmp(a_ptr, b_ptr, a_len) == 0;
154}
155
156static 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}
156159
157static inline bool is_power_of_2(uint64_t x) {160static 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
31void 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
70static_assert((clang::BinaryOperatorKind)ZigClangBO_Add == clang::BO_Add, "");
71static_assert((clang::BinaryOperatorKind)ZigClangBO_AddAssign == clang::BO_AddAssign, "");
72static_assert((clang::BinaryOperatorKind)ZigClangBO_And == clang::BO_And, "");
73static_assert((clang::BinaryOperatorKind)ZigClangBO_AndAssign == clang::BO_AndAssign, "");
74static_assert((clang::BinaryOperatorKind)ZigClangBO_Assign == clang::BO_Assign, "");
75static_assert((clang::BinaryOperatorKind)ZigClangBO_Cmp == clang::BO_Cmp, "");
76static_assert((clang::BinaryOperatorKind)ZigClangBO_Comma == clang::BO_Comma, "");
77static_assert((clang::BinaryOperatorKind)ZigClangBO_Div == clang::BO_Div, "");
78static_assert((clang::BinaryOperatorKind)ZigClangBO_DivAssign == clang::BO_DivAssign, "");
79static_assert((clang::BinaryOperatorKind)ZigClangBO_EQ == clang::BO_EQ, "");
80static_assert((clang::BinaryOperatorKind)ZigClangBO_GE == clang::BO_GE, "");
81static_assert((clang::BinaryOperatorKind)ZigClangBO_GT == clang::BO_GT, "");
82static_assert((clang::BinaryOperatorKind)ZigClangBO_LAnd == clang::BO_LAnd, "");
83static_assert((clang::BinaryOperatorKind)ZigClangBO_LE == clang::BO_LE, "");
84static_assert((clang::BinaryOperatorKind)ZigClangBO_LOr == clang::BO_LOr, "");
85static_assert((clang::BinaryOperatorKind)ZigClangBO_LT == clang::BO_LT, "");
86static_assert((clang::BinaryOperatorKind)ZigClangBO_Mul == clang::BO_Mul, "");
87static_assert((clang::BinaryOperatorKind)ZigClangBO_MulAssign == clang::BO_MulAssign, "");
88static_assert((clang::BinaryOperatorKind)ZigClangBO_NE == clang::BO_NE, "");
89static_assert((clang::BinaryOperatorKind)ZigClangBO_Or == clang::BO_Or, "");
90static_assert((clang::BinaryOperatorKind)ZigClangBO_OrAssign == clang::BO_OrAssign, "");
91static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemD == clang::BO_PtrMemD, "");
92static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemI == clang::BO_PtrMemI, "");
93static_assert((clang::BinaryOperatorKind)ZigClangBO_Rem == clang::BO_Rem, "");
94static_assert((clang::BinaryOperatorKind)ZigClangBO_RemAssign == clang::BO_RemAssign, "");
95static_assert((clang::BinaryOperatorKind)ZigClangBO_Shl == clang::BO_Shl, "");
96static_assert((clang::BinaryOperatorKind)ZigClangBO_ShlAssign == clang::BO_ShlAssign, "");
97static_assert((clang::BinaryOperatorKind)ZigClangBO_Shr == clang::BO_Shr, "");
98static_assert((clang::BinaryOperatorKind)ZigClangBO_ShrAssign == clang::BO_ShrAssign, "");
99static_assert((clang::BinaryOperatorKind)ZigClangBO_Sub == clang::BO_Sub, "");
100static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAssign, "");
101static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");
102static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");
103
104// This function detects additions to the enum
105void 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
125static_assert((clang::UnaryOperatorKind)ZigClangUO_AddrOf == clang::UO_AddrOf, "");
126static_assert((clang::UnaryOperatorKind)ZigClangUO_Coawait == clang::UO_Coawait, "");
127static_assert((clang::UnaryOperatorKind)ZigClangUO_Deref == clang::UO_Deref, "");
128static_assert((clang::UnaryOperatorKind)ZigClangUO_Extension == clang::UO_Extension, "");
129static_assert((clang::UnaryOperatorKind)ZigClangUO_Imag == clang::UO_Imag, "");
130static_assert((clang::UnaryOperatorKind)ZigClangUO_LNot == clang::UO_LNot, "");
131static_assert((clang::UnaryOperatorKind)ZigClangUO_Minus == clang::UO_Minus, "");
132static_assert((clang::UnaryOperatorKind)ZigClangUO_Not == clang::UO_Not, "");
133static_assert((clang::UnaryOperatorKind)ZigClangUO_Plus == clang::UO_Plus, "");
134static_assert((clang::UnaryOperatorKind)ZigClangUO_PostDec == clang::UO_PostDec, "");
135static_assert((clang::UnaryOperatorKind)ZigClangUO_PostInc == clang::UO_PostInc, "");
136static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "");
137static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");
138static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");
139
140static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
141static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
142 ZigClangSourceLocation dest;
143 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangSourceLocation));
144 return dest;
145}
146static clang::SourceLocation bitcast(ZigClangSourceLocation src) {
147 clang::SourceLocation dest;
148 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangSourceLocation));
149 return dest;
150}
151
152static_assert(sizeof(ZigClangQualType) == sizeof(clang::QualType), "");
153static ZigClangQualType bitcast(clang::QualType src) {
154 ZigClangQualType dest;
155 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
156 return dest;
157}
158static clang::QualType bitcast(ZigClangQualType src) {
159 clang::QualType dest;
160 memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangQualType));
161 return dest;
162}
163
164ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
165 ZigClangSourceLocation Loc)
166{
167 return bitcast(reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLoc(bitcast(Loc)));
168}
169
170const 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
177unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *self,
178 ZigClangSourceLocation Loc)
179{
180 return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLineNumber(bitcast(Loc));
181}
182
183unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *self,
184 ZigClangSourceLocation Loc)
185{
186 return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingColumnNumber(bitcast(Loc));
187}
188
189const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *self,
190 ZigClangSourceLocation SL)
191{
192 return reinterpret_cast<const clang::SourceManager *>(self)->getCharacterData(bitcast(SL));
193}
194
195ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* self, ZigClangQualType T) {
196 return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T)));
197}
198
199ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {
200 clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext();
201 return reinterpret_cast<ZigClangASTContext *>(result);
202}
203
204ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
205 clang::SourceManager *result = &reinterpret_cast<clang::ASTUnit *>(self)->getSourceManager();
206 return reinterpret_cast<ZigClangSourceManager *>(result);
207}
208
209bool 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
20struct ZigClangSourceLocation {
21 unsigned ID;
22};
23
24struct ZigClangQualType {
25 void *ptr;
26};
27
28struct ZigClangAPValue;
29struct ZigClangASTContext;
30struct ZigClangASTUnit;
31struct ZigClangArraySubscriptExpr;
32struct ZigClangArrayType;
33struct ZigClangAttributedType;
34struct ZigClangBinaryOperator;
35struct ZigClangBreakStmt;
36struct ZigClangBuiltinType;
37struct ZigClangCStyleCastExpr;
38struct ZigClangCallExpr;
39struct ZigClangCaseStmt;
40struct ZigClangCompoundAssignOperator;
41struct ZigClangCompoundStmt;
42struct ZigClangConditionalOperator;
43struct ZigClangConstantArrayType;
44struct ZigClangContinueStmt;
45struct ZigClangDecayedType;
46struct ZigClangDecl;
47struct ZigClangDeclRefExpr;
48struct ZigClangDeclStmt;
49struct ZigClangDefaultStmt;
50struct ZigClangDiagnosticOptions;
51struct ZigClangDiagnosticsEngine;
52struct ZigClangDoStmt;
53struct ZigClangElaboratedType;
54struct ZigClangEnumConstantDecl;
55struct ZigClangEnumDecl;
56struct ZigClangEnumType;
57struct ZigClangExpr;
58struct ZigClangFieldDecl;
59struct ZigClangFileID;
60struct ZigClangForStmt;
61struct ZigClangFullSourceLoc;
62struct ZigClangFunctionDecl;
63struct ZigClangFunctionProtoType;
64struct ZigClangIfStmt;
65struct ZigClangImplicitCastExpr;
66struct ZigClangIncompleteArrayType;
67struct ZigClangIntegerLiteral;
68struct ZigClangMacroDefinitionRecord;
69struct ZigClangMemberExpr;
70struct ZigClangNamedDecl;
71struct ZigClangNone;
72struct ZigClangPCHContainerOperations;
73struct ZigClangParenExpr;
74struct ZigClangParenType;
75struct ZigClangParmVarDecl;
76struct ZigClangPointerType;
77struct ZigClangPreprocessedEntity;
78struct ZigClangRecordDecl;
79struct ZigClangRecordType;
80struct ZigClangReturnStmt;
81struct ZigClangSkipFunctionBodiesScope;
82struct ZigClangSourceManager;
83struct ZigClangSourceRange;
84struct ZigClangStmt;
85struct ZigClangStorageClass;
86struct ZigClangStringLiteral;
87struct ZigClangStringRef;
88struct ZigClangSwitchStmt;
89struct ZigClangType;
90struct ZigClangTypedefNameDecl;
91struct ZigClangTypedefType;
92struct ZigClangUnaryExprOrTypeTraitExpr;
93struct ZigClangUnaryOperator;
94struct ZigClangValueDecl;
95struct ZigClangVarDecl;
96struct ZigClangWhileStmt;
97
98enum 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
134enum 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
242ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *,
243 ZigClangSourceLocation Loc);
244ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *,
245 ZigClangSourceLocation SpellingLoc);
246ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *,
247 ZigClangSourceLocation Loc);
248ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *,
249 ZigClangSourceLocation Loc);
250ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *,
251 ZigClangSourceLocation SL);
252
253ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T);
254
255ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *);
256ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *);
257ZIG_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
47using namespace clang;
48using namespace llvm::opt;
49
50//===----------------------------------------------------------------------===//
51// Main driver
52//===----------------------------------------------------------------------===//
53
54static 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__)
72static 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
107LLVM_ATTRIBUTE_NOINLINE
108static 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
126static void ensureStackAddressSpace() {}
127#endif
128
129/// Attempt to ensure that we have at least 8MiB of usable stack space.
130static 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
158static void ensureSufficientStack() {}
159#endif
160
161int 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>
57using namespace clang;
58using namespace clang::driver;
59using namespace clang::driver::options;
60using namespace llvm;
61using namespace llvm::opt;
62
63namespace {
64
65/// Helper class for representing a single invocation of the assembler.
66struct 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
141public:
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
165bool 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
290static std::unique_ptr<raw_fd_ostream>
291getOutputStream(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
308static 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
501static 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
511int 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>
49using namespace clang;
50using namespace clang::driver;
51using namespace llvm::opt;
52
53std::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
70static 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.
102static 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.
175static 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
202extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
203 void *MainAddr);
204extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
205 void *MainAddr);
206
207static 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
231static 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
240static 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
257static 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.
269static DiagnosticOptions *
270CreateAndPopulateDiagOpts(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
283static 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
305static 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
318extern "C" int ZigClang_main(int argc_, const char **argv_);
319int 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,7 +732,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
732const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {732const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
733 switch (sub_arch) {733 switch (sub_arch) {
734 case ZigLLVM_NoSubArch:734 case ZigLLVM_NoSubArch:
735 return "(none)";735 return "";
736 case ZigLLVM_ARMSubArch_v8_5a:736 case ZigLLVM_ARMSubArch_v8_5a:
737 return "v8_5a";737 return "v8_5a";
738 case ZigLLVM_ARMSubArch_v8_4a: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,7 +215,7 @@ ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const
215215
216216
217// copied from include/llvm/ADT/Triple.h217// copied from include/llvm/ADT/Triple.h
218218// synchronize with target.cpp::arch_list
219enum ZigLLVM_ArchType {219enum ZigLLVM_ArchType {
220 ZigLLVM_UnknownArch,220 ZigLLVM_UnknownArch,
221221
...@@ -272,6 +272,7 @@ enum ZigLLVM_ArchType {...@@ -272,6 +272,7 @@ enum ZigLLVM_ArchType {
272 ZigLLVM_LastArchType = ZigLLVM_renderscript64272 ZigLLVM_LastArchType = ZigLLVM_renderscript64
273};273};
274274
275// synchronize with lists in target.cpp
275enum ZigLLVM_SubArchType {276enum ZigLLVM_SubArchType {
276 ZigLLVM_NoSubArch,277 ZigLLVM_NoSubArch,
277278
...@@ -409,7 +410,7 @@ ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);...@@ -409,7 +410,7 @@ ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
409ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);410ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);
410ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);411ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
411ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os);412ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os);
412ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType env_type);413ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi);
413414
414ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,415ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
415 void (*append_diagnostic)(void *, const char *, size_t), void *context);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,6 +32,10 @@ pub const BufSet = struct {
32 }32 }
33 }33 }
3434
35 pub fn exists(self: BufSet, key: []const u8) bool {
36 return self.hash_map.get(key) != null;
37 }
38
35 pub fn delete(self: *BufSet, key: []const u8) void {39 pub fn delete(self: *BufSet, key: []const u8) void {
36 const entry = self.hash_map.remove(key) orelse return;40 const entry = self.hash_map.remove(key) orelse return;
37 self.free(entry.key);41 self.free(entry.key);
std/build.zig+205-724
...@@ -15,6 +15,8 @@ const BufSet = std.BufSet;...@@ -15,6 +15,8 @@ const BufSet = std.BufSet;
15const BufMap = std.BufMap;15const BufMap = std.BufMap;
16const fmt_lib = std.fmt;16const fmt_lib = std.fmt;
1717
18pub const FmtStep = @import("build/fmt.zig").FmtStep;
19
18pub const Builder = struct {20pub const Builder = struct {
19 uninstall_tls: TopLevelStep,21 uninstall_tls: TopLevelStep,
20 install_tls: TopLevelStep,22 install_tls: TopLevelStep,
...@@ -31,6 +33,7 @@ pub const Builder = struct {...@@ -31,6 +33,7 @@ pub const Builder = struct {
31 verbose_tokenize: bool,33 verbose_tokenize: bool,
32 verbose_ast: bool,34 verbose_ast: bool,
33 verbose_link: bool,35 verbose_link: bool,
36 verbose_cc: bool,
34 verbose_ir: bool,37 verbose_ir: bool,
35 verbose_llvm_ir: bool,38 verbose_llvm_ir: bool,
36 verbose_cimport: bool,39 verbose_cimport: bool,
...@@ -99,6 +102,7 @@ pub const Builder = struct {...@@ -99,6 +102,7 @@ pub const Builder = struct {
99 .verbose_tokenize = false,102 .verbose_tokenize = false,
100 .verbose_ast = false,103 .verbose_ast = false,
101 .verbose_link = false,104 .verbose_link = false,
105 .verbose_cc = false,
102 .verbose_ir = false,106 .verbose_ir = false,
103 .verbose_llvm_ir = false,107 .verbose_llvm_ir = false,
104 .verbose_cimport = false,108 .verbose_cimport = false,
...@@ -157,7 +161,7 @@ pub const Builder = struct {...@@ -157,7 +161,7 @@ pub const Builder = struct {
157 return LibExeObjStep.createExecutable(self, name, root_src, true);161 return LibExeObjStep.createExecutable(self, name, root_src, true);
158 }162 }
159163
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 return LibExeObjStep.createObject(self, name, root_src);165 return LibExeObjStep.createObject(self, name, root_src);
162 }166 }
163167
...@@ -169,10 +173,8 @@ pub const Builder = struct {...@@ -169,10 +173,8 @@ pub const Builder = struct {
169 return LibExeObjStep.createStaticLibrary(self, name, root_src);173 return LibExeObjStep.createStaticLibrary(self, name, root_src);
170 }174 }
171175
172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {176 pub fn addTest(self: *Builder, root_src: []const u8) *LibExeObjStep {
173 const test_step = self.allocator.create(TestStep) catch unreachable;177 return LibExeObjStep.createTest(self, "test", root_src);
174 test_step.* = TestStep.init(self, root_src);
175 return test_step;
176 }178 }
177179
178 pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {180 pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
...@@ -181,22 +183,6 @@ pub const Builder = struct {...@@ -181,22 +183,6 @@ pub const Builder = struct {
181 return obj_step;183 return obj_step;
182 }184 }
183185
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 /// ::argv is copied.186 /// ::argv is copied.
201 pub fn addCommand(self: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {187 pub fn addCommand(self: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {
202 return CommandStep.create(self, cwd, env_map, argv);188 return CommandStep.create(self, cwd, env_map, argv);
...@@ -221,6 +207,10 @@ pub const Builder = struct {...@@ -221,6 +207,10 @@ pub const Builder = struct {
221 return remove_dir_step;207 return remove_dir_step;
222 }208 }
223209
210 pub fn addFmt(self: *Builder, paths: []const []const u8) *FmtStep {
211 return FmtStep.create(self, paths);
212 }
213
224 pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version {214 pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version {
225 return Version{215 return Version{
226 .major = major,216 .major = major,
...@@ -663,14 +653,6 @@ pub const Builder = struct {...@@ -663,14 +653,6 @@ pub const Builder = struct {
663 return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;653 return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;
664 }654 }
665655
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 pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {656 pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
675 // TODO report error for ambiguous situations657 // TODO report error for ambiguous situations
676 const exe_extension = (Target{ .Native = {} }).exeFileExt();658 const exe_extension = (Target{ .Native = {} }).exeFileExt();
...@@ -755,20 +737,40 @@ const Version = struct {...@@ -755,20 +737,40 @@ const Version = struct {
755const CrossTarget = struct {737const CrossTarget = struct {
756 arch: builtin.Arch,738 arch: builtin.Arch,
757 os: builtin.Os,739 os: builtin.Os,
758 environ: builtin.Environ,740 abi: builtin.Abi,
759};741};
760742
761pub const Target = union(enum) {743pub const Target = union(enum) {
762 Native: void,744 Native: void,
763 Cross: CrossTarget,745 Cross: CrossTarget,
764746
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 pub fn oFileExt(self: *const Target) []const u8 {767 pub fn oFileExt(self: *const Target) []const u8 {
766 const environ = switch (self.*) {768 const abi = switch (self.*) {
767 Target.Native => builtin.environ,769 Target.Native => builtin.abi,
768 Target.Cross => |t| t.environ,770 Target.Cross => |t| t.abi,
769 };771 };
770 return switch (environ) {772 return switch (abi) {
771 builtin.Environ.msvc => ".obj",773 builtin.Abi.msvc => ".obj",
772 else => ".o",774 else => ".o",
773 };775 };
774 }776 }
...@@ -825,6 +827,11 @@ const Pkg = struct {...@@ -825,6 +827,11 @@ const Pkg = struct {
825 path: []const u8,827 path: []const u8,
826};828};
827829
830const CSourceFile = struct {
831 source_path: []const u8,
832 args: []const []const u8,
833};
834
828pub const LibExeObjStep = struct {835pub const LibExeObjStep = struct {
829 step: Step,836 step: Step,
830 builder: *Builder,837 builder: *Builder,
...@@ -834,6 +841,7 @@ pub const LibExeObjStep = struct {...@@ -834,6 +841,7 @@ pub const LibExeObjStep = struct {
834 linker_script: ?[]const u8,841 linker_script: ?[]const u8,
835 out_filename: []const u8,842 out_filename: []const u8,
836 output_path: ?[]const u8,843 output_path: ?[]const u8,
844 output_lib_path: ?[]const u8,
837 static: bool,845 static: bool,
838 version: Version,846 version: Version,
839 object_files: ArrayList([]const u8),847 object_files: ArrayList([]const u8),
...@@ -844,33 +852,34 @@ pub const LibExeObjStep = struct {...@@ -844,33 +852,34 @@ pub const LibExeObjStep = struct {
844 strip: bool,852 strip: bool,
845 full_path_libs: ArrayList([]const u8),853 full_path_libs: ArrayList([]const u8),
846 need_flat_namespace_hack: bool,854 need_flat_namespace_hack: bool,
847 is_zig: bool,
848 cflags: ArrayList([]const u8),
849 include_dirs: ArrayList([]const u8),855 include_dirs: ArrayList([]const u8),
850 lib_paths: ArrayList([]const u8),856 lib_paths: ArrayList([]const u8),
851 disable_libc: bool,
852 frameworks: BufSet,857 frameworks: BufSet,
853 verbose_link: bool,858 verbose_link: bool,
854 no_rosegment: bool,859 verbose_cc: bool,
855 c_std: Builder.CStd,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,
856865
857 // zig only stuff
858 root_src: ?[]const u8,866 root_src: ?[]const u8,
859 output_h_path: ?[]const u8,867 output_h_path: ?[]const u8,
860 out_h_filename: []const u8,868 out_h_filename: []const u8,
869 out_lib_filename: []const u8,
861 assembly_files: ArrayList([]const u8),870 assembly_files: ArrayList([]const u8),
862 packages: ArrayList(Pkg),871 packages: ArrayList(Pkg),
863 build_options_contents: std.Buffer,872 build_options_contents: std.Buffer,
864 system_linker_hack: bool,873 system_linker_hack: bool,
865874
866 // C only stuff875 c_source_files: ArrayList(*CSourceFile),
867 source_files: ArrayList([]const u8),
868 object_src: []const u8,876 object_src: []const u8,
869877
870 const Kind = enum {878 const Kind = enum {
871 Exe,879 Exe,
872 Lib,880 Lib,
873 Obj,881 Obj,
882 Test,
874 };883 };
875884
876 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {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,55 +888,36 @@ pub const LibExeObjStep = struct {
879 return self;888 return self;
880 }889 }
881890
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 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {891 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
889 const self = builder.allocator.create(LibExeObjStep) catch unreachable;892 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
890 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));893 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
891 return self;894 return self;
892 }895 }
893896
894 pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep {897 pub fn createObject(builder: *Builder, name: []const u8, root_src: ?[]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 {
901 const self = builder.allocator.create(LibExeObjStep) catch unreachable;898 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
902 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));899 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
903 return self;900 return self;
904 }901 }
905902
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 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {903 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
914 const self = builder.allocator.create(LibExeObjStep) catch unreachable;904 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
915 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0));905 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0));
916 return self;906 return self;
917 }907 }
918908
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 const self = builder.allocator.create(LibExeObjStep) catch unreachable;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 return self;912 return self;
923 }913 }
924914
925 fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: Version) LibExeObjStep {915 fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: Version) LibExeObjStep {
926 var self = LibExeObjStep{916 var self = LibExeObjStep{
927 .no_rosegment = false,
928 .strip = false,917 .strip = false,
929 .builder = builder,918 .builder = builder,
930 .verbose_link = false,919 .verbose_link = false,
920 .verbose_cc = false,
931 .build_mode = builtin.Mode.Debug,921 .build_mode = builtin.Mode.Debug,
932 .static = static,922 .static = static,
933 .kind = kind,923 .kind = kind,
...@@ -939,80 +929,35 @@ pub const LibExeObjStep = struct {...@@ -939,80 +929,35 @@ pub const LibExeObjStep = struct {
939 .frameworks = BufSet.init(builder.allocator),929 .frameworks = BufSet.init(builder.allocator),
940 .step = Step.init(name, builder.allocator, make),930 .step = Step.init(name, builder.allocator, make),
941 .output_path = null,931 .output_path = null,
932 .output_lib_path = null,
942 .output_h_path = null,933 .output_h_path = null,
943 .version = ver,934 .version = ver,
944 .out_filename = undefined,935 .out_filename = undefined,
945 .out_h_filename = builder.fmt("{}.h", name),936 .out_h_filename = builder.fmt("{}.h", name),
937 .out_lib_filename = undefined,
946 .major_only_filename = undefined,938 .major_only_filename = undefined,
947 .name_only_filename = undefined,939 .name_only_filename = undefined,
948 .object_files = ArrayList([]const u8).init(builder.allocator),940 .object_files = ArrayList([]const u8).init(builder.allocator),
949 .assembly_files = ArrayList([]const u8).init(builder.allocator),941 .assembly_files = ArrayList([]const u8).init(builder.allocator),
950 .packages = ArrayList(Pkg).init(builder.allocator),942 .packages = ArrayList(Pkg).init(builder.allocator),
951 .is_zig = true,
952 .full_path_libs = ArrayList([]const u8).init(builder.allocator),943 .full_path_libs = ArrayList([]const u8).init(builder.allocator),
953 .need_flat_namespace_hack = false,944 .need_flat_namespace_hack = false,
954 .cflags = ArrayList([]const u8).init(builder.allocator),945 .c_source_files = ArrayList(*CSourceFile).init(builder.allocator),
955 .source_files = undefined,
956 .include_dirs = ArrayList([]const u8).init(builder.allocator),946 .include_dirs = ArrayList([]const u8).init(builder.allocator),
957 .lib_paths = ArrayList([]const u8).init(builder.allocator),947 .lib_paths = ArrayList([]const u8).init(builder.allocator),
958 .object_src = undefined,948 .object_src = undefined,
959 .disable_libc = true,
960 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,949 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
961 .c_std = Builder.CStd.C99,950 .c_std = Builder.CStd.C99,
962 .system_linker_hack = false,951 .system_linker_hack = false,
952 .override_std_dir = null,
953 .exec_cmd_args = null,
954 .name_prefix = "",
955 .filter = null,
963 };956 };
964 self.computeOutFileNames();957 self.computeOutFileNames();
965 return self;958 return self;
966 }959 }
967960
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 fn computeOutFileNames(self: *LibExeObjStep) void {961 fn computeOutFileNames(self: *LibExeObjStep) void {
1017 switch (self.kind) {962 switch (self.kind) {
1018 Kind.Obj => {963 Kind.Obj => {
...@@ -1021,23 +966,37 @@ pub const LibExeObjStep = struct {...@@ -1021,23 +966,37 @@ pub const LibExeObjStep = struct {
1021 Kind.Exe => {966 Kind.Exe => {
1022 self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());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 Kind.Lib => {972 Kind.Lib => {
1025 if (self.static) {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 } else {983 } else {
1028 switch (self.target.getOs()) {984 switch (self.target.getOs()) {
1029 builtin.Os.ios, builtin.Os.macosx => {985 builtin.Os.ios, builtin.Os.macosx => {
1030 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);986 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);
1031 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);987 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);
1032 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);988 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
989 self.out_lib_filename = self.out_filename;
1033 },990 },
1034 builtin.Os.windows => {991 builtin.Os.windows => {
1035 self.out_filename = self.builder.fmt("{}.dll", self.name);992 self.out_filename = self.builder.fmt("{}.dll", self.name);
993 self.out_lib_filename = self.builder.fmt("{}.lib", self.name);
1036 },994 },
1037 else => {995 else => {
1038 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch);996 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch);
1039 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);997 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);
1040 self.name_only_filename = self.builder.fmt("lib{}.so", self.name);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,12 +1004,17 @@ pub const LibExeObjStep = struct {
1045 }1004 }
1046 }1005 }
10471006
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 self.target = Target{1013 self.target = Target{
1050 .Cross = CrossTarget{1014 .Cross = CrossTarget{
1051 .arch = target_arch,1015 .arch = target_arch,
1052 .os = target_os,1016 .os = target_os,
1053 .environ = target_environ,1017 .abi = target_abi,
1054 },1018 },
1055 };1019 };
1056 self.computeOutFileNames();1020 self.computeOutFileNames();
...@@ -1072,7 +1036,15 @@ pub const LibExeObjStep = struct {...@@ -1072,7 +1036,15 @@ pub const LibExeObjStep = struct {
10721036
1073 self.step.dependOn(&lib.step);1037 self.step.dependOn(&lib.step);
10741038
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 }
10761048
1077 // TODO should be some kind of isolated directory that only has this header in it1049 // TODO should be some kind of isolated directory that only has this header in it
1078 self.include_dirs.append(self.builder.cache_root) catch unreachable;1050 self.include_dirs.append(self.builder.cache_root) catch unreachable;
...@@ -1088,24 +1060,44 @@ pub const LibExeObjStep = struct {...@@ -1088,24 +1060,44 @@ pub const LibExeObjStep = struct {
1088 }1060 }
10891061
1090 pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {1062 pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {
1091 assert(self.kind != Kind.Obj);
1092 self.link_libs.put(name) catch unreachable;1063 self.link_libs.put(name) catch unreachable;
1093 }1064 }
10941065
1095 pub fn addSourceFile(self: *LibExeObjStep, file: []const u8) void {1066 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
1096 assert(self.kind != Kind.Obj);1067 assert(self.kind == Kind.Test);
1097 assert(!self.is_zig);1068 self.name_prefix = text;
1098 self.source_files.append(file) catch unreachable;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 }
11001084
1101 pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {1085 pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {
1102 self.verbose_link = value;1086 self.verbose_link = value;
1103 }1087 }
11041088
1089 pub fn setVerboseCC(self: *LibExeObjStep, value: bool) void {
1090 self.verbose_cc = value;
1091 }
1092
1105 pub fn setBuildMode(self: *LibExeObjStep, mode: builtin.Mode) void {1093 pub fn setBuildMode(self: *LibExeObjStep, mode: builtin.Mode) void {
1106 self.build_mode = mode;1094 self.build_mode = mode;
1107 }1095 }
11081096
1097 pub fn overrideStdDir(self: *LibExeObjStep, dir_path: []const u8) void {
1098 self.override_std_dir = dir_path;
1099 }
1100
1109 pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void {1101 pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void {
1110 self.output_path = file_path;1102 self.output_path = file_path;
11111103
...@@ -1122,6 +1114,22 @@ pub const LibExeObjStep = struct {...@@ -1122,6 +1114,22 @@ pub const LibExeObjStep = struct {
1122 ) catch unreachable;1114 ) catch unreachable;
1123 }1115 }
11241116
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 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {1133 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {
1126 self.output_h_path = file_path;1134 self.output_h_path = file_path;
11271135
...@@ -1156,17 +1164,15 @@ pub const LibExeObjStep = struct {...@@ -1156,17 +1164,15 @@ pub const LibExeObjStep = struct {
11561164
1157 self.object_files.append(obj.getOutputPath()) catch unreachable;1165 self.object_files.append(obj.getOutputPath()) catch unreachable;
11581166
1159 // TODO make this lazy instead of stateful
1160 if (!obj.disable_libc) {
1161 self.disable_libc = false;
1162 }
1163
1164 // TODO should be some kind of isolated directory that only has this header in it1167 // TODO should be some kind of isolated directory that only has this header in it
1165 self.include_dirs.append(self.builder.cache_root) catch unreachable;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 }
11671174
1168 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {1175 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
1169 assert(self.is_zig);
1170 const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream;1176 const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream;
1171 out.print("pub const {} = {};\n", name, value) catch unreachable;1177 out.print("pub const {} = {};\n", name, value) catch unreachable;
1172 }1178 }
...@@ -1180,23 +1186,15 @@ pub const LibExeObjStep = struct {...@@ -1180,23 +1186,15 @@ pub const LibExeObjStep = struct {
1180 }1186 }
11811187
1182 pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {1188 pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
1183 assert(self.is_zig);
1184
1185 self.packages.append(Pkg{1189 self.packages.append(Pkg{
1186 .name = name,1190 .name = name,
1187 .path = pkg_index_path,1191 .path = pkg_index_path,
1188 }) catch unreachable;1192 }) catch unreachable;
1189 }1193 }
11901194
1191 pub fn addCompileFlags(self: *LibExeObjStep, flags: []const []const u8) void {1195 pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void {
1192 for (flags) |flag| {1196 assert(self.kind == Kind.Test);
1193 self.cflags.append(flag) catch unreachable;1197 self.exec_cmd_args = args;
1194 }
1195 }
1196
1197 pub fn setNoStdLib(self: *LibExeObjStep, disable: bool) void {
1198 assert(!self.is_zig);
1199 self.disable_libc = disable;
1200 }1198 }
12011199
1202 pub fn enableSystemLinkerHack(self: *LibExeObjStep) void {1200 pub fn enableSystemLinkerHack(self: *LibExeObjStep) void {
...@@ -1205,15 +1203,11 @@ pub const LibExeObjStep = struct {...@@ -1205,15 +1203,11 @@ pub const LibExeObjStep = struct {
12051203
1206 fn make(step: *Step) !void {1204 fn make(step: *Step) !void {
1207 const self = @fieldParentPtr(LibExeObjStep, "step", step);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 const builder = self.builder;1206 const builder = self.builder;
12131207
1214 assert(self.is_zig);1208 if (self.root_src == null and self.object_files.len == 0 and
12151209 self.assembly_files.len == 0 and self.c_source_files.len == 0)
1216 if (self.root_src == null and self.object_files.len == 0 and self.assembly_files.len == 0) {1210 {
1217 warn("{}: linker needs 1 or more objects to link\n", self.step.name);1211 warn("{}: linker needs 1 or more objects to link\n", self.step.name);
1218 return error.NeedAnObject;1212 return error.NeedAnObject;
1219 }1213 }
...@@ -1227,6 +1221,7 @@ pub const LibExeObjStep = struct {...@@ -1227,6 +1221,7 @@ pub const LibExeObjStep = struct {
1227 Kind.Lib => "build-lib",1221 Kind.Lib => "build-lib",
1228 Kind.Exe => "build-exe",1222 Kind.Exe => "build-exe",
1229 Kind.Obj => "build-obj",1223 Kind.Obj => "build-obj",
1224 Kind.Test => "test",
1230 };1225 };
1231 zig_args.append(cmd) catch unreachable;1226 zig_args.append(cmd) catch unreachable;
12321227
...@@ -1234,6 +1229,14 @@ pub const LibExeObjStep = struct {...@@ -1234,6 +1229,14 @@ pub const LibExeObjStep = struct {
1234 zig_args.append(builder.pathFromRoot(root_src)) catch unreachable;1229 zig_args.append(builder.pathFromRoot(root_src)) catch unreachable;
1235 }1230 }
12361231
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 if (self.build_options_contents.len() > 0) {1240 if (self.build_options_contents.len() > 0) {
1238 const build_options_file = try os.path.join(1241 const build_options_file = try os.path.join(
1239 builder.allocator,1242 builder.allocator,
...@@ -1246,6 +1249,16 @@ pub const LibExeObjStep = struct {...@@ -1246,6 +1249,16 @@ pub const LibExeObjStep = struct {
1246 try zig_args.append("--pkg-end");1249 try zig_args.append("--pkg-end");
1247 }1250 }
12481251
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 for (self.object_files.toSliceConst()) |object_file| {1262 for (self.object_files.toSliceConst()) |object_file| {
1250 zig_args.append("--object") catch unreachable;1263 zig_args.append("--object") catch unreachable;
1251 zig_args.append(builder.pathFromRoot(object_file)) catch unreachable;1264 zig_args.append(builder.pathFromRoot(object_file)) catch unreachable;
...@@ -1262,6 +1275,7 @@ pub const LibExeObjStep = struct {...@@ -1262,6 +1275,7 @@ pub const LibExeObjStep = struct {
1262 if (builder.verbose_ir) zig_args.append("--verbose-ir") catch unreachable;1275 if (builder.verbose_ir) zig_args.append("--verbose-ir") catch unreachable;
1263 if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;1276 if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;
1264 if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;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;
12651279
1266 if (self.strip) {1280 if (self.strip) {
1267 zig_args.append("--strip") catch unreachable;1281 zig_args.append("--strip") catch unreachable;
...@@ -1281,7 +1295,13 @@ pub const LibExeObjStep = struct {...@@ -1281,7 +1295,13 @@ pub const LibExeObjStep = struct {
1281 zig_args.append("--output") catch unreachable;1295 zig_args.append("--output") catch unreachable;
1282 zig_args.append(output_path) catch unreachable;1296 zig_args.append(output_path) catch unreachable;
12831297
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 const output_h_path = self.getOutputHPath();1305 const output_h_path = self.getOutputHPath();
1286 zig_args.append("--output-h") catch unreachable;1306 zig_args.append("--output-h") catch unreachable;
1287 zig_args.append(builder.pathFromRoot(output_h_path)) catch unreachable;1307 zig_args.append(builder.pathFromRoot(output_h_path)) catch unreachable;
...@@ -1300,21 +1320,23 @@ pub const LibExeObjStep = struct {...@@ -1300,21 +1320,23 @@ pub const LibExeObjStep = struct {
1300 zig_args.append("--ver-patch") catch unreachable;1320 zig_args.append("--ver-patch") catch unreachable;
1301 zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;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 zig_args.append("--static") catch unreachable;1324 zig_args.append("--static") catch unreachable;
1305 }1325 }
13061326
1307 switch (self.target) {1327 switch (self.target) {
1308 Target.Native => {},1328 Target.Native => {},
1309 Target.Cross => |cross_target| {1329 Target.Cross => |cross_target| {
1310 zig_args.append("--target-arch") catch unreachable;1330 const triple = builder.fmt(
1311 zig_args.append(@tagName(cross_target.arch)) catch unreachable;1331 "{}{}-{}-{}",
13121332 @tagName(cross_target.arch),
1313 zig_args.append("--target-os") catch unreachable;1333 Target.archSubArchName(cross_target.arch),
1314 zig_args.append(@tagName(cross_target.os)) catch unreachable;1334 @tagName(cross_target.os),
13151335 @tagName(cross_target.abi),
1316 zig_args.append("--target-environ") catch unreachable;1336 );
1317 zig_args.append(@tagName(cross_target.environ)) catch unreachable;1337
1338 try zig_args.append("-target");
1339 try zig_args.append(triple);
1318 },1340 },
1319 }1341 }
13201342
...@@ -1332,11 +1354,16 @@ pub const LibExeObjStep = struct {...@@ -1332,11 +1354,16 @@ pub const LibExeObjStep = struct {
1332 }1354 }
1333 }1355 }
13341356
1335 if (!self.disable_libc) {1357 if (self.exec_cmd_args) |exec_cmd_args| {
1336 zig_args.append("--library") catch unreachable;1358 for (exec_cmd_args) |cmd_arg| {
1337 zig_args.append("c") catch unreachable;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 for (self.packages.toSliceConst()) |pkg| {1367 for (self.packages.toSliceConst()) |pkg| {
1341 zig_args.append("--pkg-begin") catch unreachable;1368 zig_args.append("--pkg-begin") catch unreachable;
1342 zig_args.append(pkg.name) catch unreachable;1369 zig_args.append(pkg.name) catch unreachable;
...@@ -1370,8 +1397,14 @@ pub const LibExeObjStep = struct {...@@ -1370,8 +1397,14 @@ pub const LibExeObjStep = struct {
1370 }1397 }
13711398
1372 for (self.full_path_libs.toSliceConst()) |full_path_lib| {1399 for (self.full_path_libs.toSliceConst()) |full_path_lib| {
1373 zig_args.append("--library") catch unreachable;1400 try zig_args.append("--library");
1374 zig_args.append(builder.pathFromRoot(full_path_lib)) catch unreachable;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 }
13761409
1377 if (self.target.isDarwin()) {1410 if (self.target.isDarwin()) {
...@@ -1382,574 +1415,20 @@ pub const LibExeObjStep = struct {...@@ -1382,574 +1415,20 @@ pub const LibExeObjStep = struct {
1382 }1415 }
1383 }1416 }
13841417
1385 if (self.no_rosegment) {
1386 try zig_args.append("--no-rosegment");
1387 }
1388 if (self.system_linker_hack) {1418 if (self.system_linker_hack) {
1389 try zig_args.append("--system-linker-hack");1419 try zig_args.append("--system-linker-hack");
1390 }1420 }
13911421
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
1692pub 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 if (self.override_std_dir) |dir| {1422 if (self.override_std_dir) |dir| {
1948 try zig_args.append("--override-std-dir");1423 try zig_args.append("--override-std-dir");
1949 try zig_args.append(builder.pathFromRoot(dir));1424 try zig_args.append(builder.pathFromRoot(dir));
1950 }1425 }
19511426
1952 try builder.spawnChild(zig_args.toSliceConst());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};
19551434
...@@ -1995,6 +1474,7 @@ const InstallArtifactStep = struct {...@@ -1995,6 +1474,7 @@ const InstallArtifactStep = struct {
1995 pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {1474 pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {
1996 const dest_dir = switch (artifact.kind) {1475 const dest_dir = switch (artifact.kind) {
1997 LibExeObjStep.Kind.Obj => unreachable,1476 LibExeObjStep.Kind.Obj => unreachable,
1477 LibExeObjStep.Kind.Test => unreachable,
1998 LibExeObjStep.Kind.Exe => builder.exe_dir,1478 LibExeObjStep.Kind.Exe => builder.exe_dir,
1999 LibExeObjStep.Kind.Lib => builder.lib_dir,1479 LibExeObjStep.Kind.Lib => builder.lib_dir,
2000 };1480 };
...@@ -2031,6 +1511,7 @@ const InstallArtifactStep = struct {...@@ -2031,6 +1511,7 @@ const InstallArtifactStep = struct {
2031 builtin.Os.windows => {},1511 builtin.Os.windows => {},
2032 else => switch (self.artifact.kind) {1512 else => switch (self.artifact.kind) {
2033 LibExeObjStep.Kind.Obj => unreachable,1513 LibExeObjStep.Kind.Obj => unreachable,
1514 LibExeObjStep.Kind.Test => unreachable,
2034 LibExeObjStep.Kind.Exe => u32(0o755),1515 LibExeObjStep.Kind.Exe => u32(0o755),
2035 LibExeObjStep.Kind.Lib => if (self.artifact.static) u32(0o666) else u32(0o755),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 @@
1const std = @import("../index.zig");
2const build = @import("../build.zig");
3const Step = build.Step;
4const Builder = build.Builder;
5const BufMap = std.BufMap;
6const mem = std.mem;
7
8pub 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,11 +36,20 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi
36pub extern "c" fn bind(socket: c_int, address: ?*const sockaddr, address_len: socklen_t) c_int;36pub extern "c" fn bind(socket: c_int, address: ?*const sockaddr, address_len: socklen_t) c_int;
37pub extern "c" fn socket(domain: c_int, type: c_int, protocol: c_int) c_int;37pub extern "c" fn socket(domain: c_int, type: c_int, protocol: c_int) c_int;
3838
39const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
40
39/// The value of the link editor defined symbol _MH_EXECUTE_SYM is the address41/// The value of the link editor defined symbol _MH_EXECUTE_SYM is the address
40/// of the mach header in a Mach-O executable file type. It does not appear in42/// of the mach header in a Mach-O executable file type. It does not appear in
41/// any file type other than a MH_EXECUTE file type. The type of the symbol is43/// any file type other than a MH_EXECUTE file type. The type of the symbol is
42/// absolute as the header is not part of any section.44/// absolute as the header is not part of any section.
43pub 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.
49pub extern "c" var _mh_execute_header: mach_hdr = undefined;
50comptime {
51 @export("__mh_execute_header", _mh_execute_header, @import("builtin").GlobalLinkage.Weak);
52}
4453
45pub const mach_header_64 = macho.mach_header_64;54pub const mach_header_64 = macho.mach_header_64;
46pub const mach_header = macho.mach_header;55pub const mach_header = macho.mach_header;
std/c/index.zig+1
...@@ -6,6 +6,7 @@ pub use switch (builtin.os) {...@@ -6,6 +6,7 @@ pub use switch (builtin.os) {
6 Os.windows => @import("windows.zig"),6 Os.windows => @import("windows.zig"),
7 Os.macosx, Os.ios => @import("darwin.zig"),7 Os.macosx, Os.ios => @import("darwin.zig"),
8 Os.freebsd => @import("freebsd.zig"),8 Os.freebsd => @import("freebsd.zig"),
9 Os.netbsd => @import("netbsd.zig"),
9 else => empty_import,10 else => empty_import,
10};11};
11const empty_import = @import("../empty.zig");12const empty_import = @import("../empty.zig");
std/c/netbsd.zig created+116
...@@ -0,0 +1,116 @@
1extern "c" fn __errno() *c_int;
2pub const _errno = __errno;
3
4pub extern "c" fn kqueue() c_int;
5pub 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;
13pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
14pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
15pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
16pub extern "c" fn getdirentries(fd: c_int, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize;
17pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
18pub extern "c" fn pipe2(arg0: *[2]c_int, arg1: u32) c_int;
19pub extern "c" fn preadv(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize;
20pub extern "c" fn pwritev(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize;
21pub extern "c" fn openat(fd: c_int, path: ?[*]const u8, flags: c_int) c_int;
22pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
23pub extern "c" fn setuid(uid: c_uint) c_int;
24pub extern "c" fn kill(pid: c_int, sig: c_int) c_int;
25pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int;
26pub 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.
29pub const Kevent = extern struct {
30 ident: usize,
31 filter: i32,
32 flags: u32,
33 fflags: u32,
34 data: i64,
35 udata: usize,
36};
37
38pub const pthread_attr_t = extern struct {
39 pta_magic: u32,
40 pta_flags: c_int,
41 pta_private: *c_void,
42};
43
44pub 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
56pub 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
79pub const timespec = extern struct {
80 tv_sec: i64,
81 tv_nsec: isize,
82};
83
84pub 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
93pub const in_port_t = u16;
94pub const sa_family_t = u8;
95
96pub const sockaddr = extern union {
97 in: sockaddr_in,
98 in6: sockaddr_in6,
99};
100
101pub 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
109pub 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,9 +90,60 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
90 };90 };
91}91}
9292
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.
99pub 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/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.144/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
94/// TODO multithreaded awareness145/// TODO multithreaded awareness
95pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {146pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void {
96 const stderr = getStderrStream() catch return;147 const stderr = getStderrStream() catch return;
97 const debug_info = getSelfDebugInfo() catch |err| {148 const debug_info = getSelfDebugInfo() catch |err| {
98 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;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,7 +192,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
141 const stderr = getStderrStream() catch os.abort();192 const stderr = getStderrStream() catch os.abort();
142 stderr.print(format ++ "\n", args) catch os.abort();193 stderr.print(format ++ "\n", args) catch os.abort();
143 if (trace) |t| {194 if (trace) |t| {
144 dumpStackTrace(t);195 dumpStackTrace(t.*);
145 }196 }
146 dumpCurrentStackTrace(first_trace_addr);197 dumpCurrentStackTrace(first_trace_addr);
147198
...@@ -155,16 +206,15 @@ const WHITE = "\x1b[37;1m";...@@ -155,16 +206,15 @@ const WHITE = "\x1b[37;1m";
155const DIM = "\x1b[2m";206const DIM = "\x1b[2m";
156const RESET = "\x1b[0m";207const RESET = "\x1b[0m";
157208
158pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, tty_color: bool) !void {209pub fn writeStackTrace(
159 var frame_index: usize = undefined;210 stack_trace: builtin.StackTrace,
160 var frames_left: usize = undefined;211 out_stream: var,
161 if (stack_trace.index < stack_trace.instruction_addresses.len) {212 allocator: *mem.Allocator,
162 frame_index = 0;213 debug_info: *DebugInfo,
163 frames_left = stack_trace.index;214 tty_color: bool,
164 } else {215) !void {
165 frame_index = (stack_trace.index + 1) % stack_trace.instruction_addresses.len;216 var frame_index: usize = 0;
166 frames_left = stack_trace.instruction_addresses.len;217 var frames_left: usize = stack_trace.index;
167 }
168218
169 while (frames_left != 0) : ({219 while (frames_left != 0) : ({
170 frames_left -= 1;220 frames_left -= 1;
...@@ -240,7 +290,7 @@ pub fn writeCurrentStackTraceWindows(...@@ -240,7 +290,7 @@ pub fn writeCurrentStackTraceWindows(
240pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {290pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
241 switch (builtin.os) {291 switch (builtin.os) {
242 builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color),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 builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),294 builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),
245 else => return error.UnsupportedOperatingSystem,295 else => return error.UnsupportedOperatingSystem,
246 }296 }
...@@ -574,7 +624,7 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach...@@ -574,7 +624,7 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
574}624}
575625
576fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {626fn 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 const adjusted_addr = 0x100000000 + (address - base_addr);628 const adjusted_addr = 0x100000000 + (address - base_addr);
579629
580 const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {630 const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
...@@ -717,7 +767,7 @@ pub const OpenSelfDebugInfoError = error{...@@ -717,7 +767,7 @@ pub const OpenSelfDebugInfoError = error{
717767
718pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {768pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
719 switch (builtin.os) {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 builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),771 builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),
722 builtin.Os.windows => return openSelfDebugInfoWindows(allocator),772 builtin.Os.windows => return openSelfDebugInfoWindows(allocator),
723 else => return error.UnsupportedOperatingSystem,773 else => return error.UnsupportedOperatingSystem,
...@@ -1141,7 +1191,7 @@ pub const DebugInfo = switch (builtin.os) {...@@ -1141,7 +1191,7 @@ pub const DebugInfo = switch (builtin.os) {
1141 sect_contribs: []pdb.SectionContribEntry,1191 sect_contribs: []pdb.SectionContribEntry,
1142 modules: []Module,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 else => @compileError("Unsupported OS"),1195 else => @compileError("Unsupported OS"),
1146};1196};
11471197
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,6 +85,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o
85 builtin.Os.macosx,85 builtin.Os.macosx,
86 builtin.Os.linux,86 builtin.Os.linux,
87 builtin.Os.freebsd,87 builtin.Os.freebsd,
88 builtin.Os.netbsd,
88 => {89 => {
89 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);90 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
90 defer loop.allocator.free(iovecs);91 defer loop.allocator.free(iovecs);
...@@ -222,6 +223,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:...@@ -222,6 +223,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:
222 builtin.Os.macosx,223 builtin.Os.macosx,
223 builtin.Os.linux,224 builtin.Os.linux,
224 builtin.Os.freebsd,225 builtin.Os.freebsd,
226 builtin.Os.netbsd,
225 => {227 => {
226 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);228 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
227 defer loop.allocator.free(iovecs);229 defer loop.allocator.free(iovecs);
...@@ -402,7 +404,11 @@ pub async fn openPosix(...@@ -402,7 +404,11 @@ pub async fn openPosix(
402404
403pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {405pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {
404 switch (builtin.os) {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 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;412 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
407 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);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,6 +437,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
431 builtin.Os.macosx,437 builtin.Os.macosx,
432 builtin.Os.linux,438 builtin.Os.linux,
433 builtin.Os.freebsd,439 builtin.Os.freebsd,
440 builtin.Os.netbsd,
434 => {441 => {
435 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;442 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
436 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);443 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
...@@ -453,7 +460,7 @@ pub async fn openReadWrite(...@@ -453,7 +460,7 @@ pub async fn openReadWrite(
453 mode: os.File.Mode,460 mode: os.File.Mode,
454) os.File.OpenError!os.FileHandle {461) os.File.OpenError!os.FileHandle {
455 switch (builtin.os) {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 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;464 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
458 return await (async openPosix(loop, path, flags, mode) catch unreachable);465 return await (async openPosix(loop, path, flags, mode) catch unreachable);
459 },466 },
...@@ -481,7 +488,7 @@ pub const CloseOperation = struct {...@@ -481,7 +488,7 @@ pub const CloseOperation = struct {
481 os_data: OsData,488 os_data: OsData,
482489
483 const OsData = switch (builtin.os) {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,
485492
486 builtin.Os.windows => struct {493 builtin.Os.windows => struct {
487 handle: ?os.FileHandle,494 handle: ?os.FileHandle,
...@@ -500,7 +507,7 @@ pub const CloseOperation = struct {...@@ -500,7 +507,7 @@ pub const CloseOperation = struct {
500 self.* = CloseOperation{507 self.* = CloseOperation{
501 .loop = loop,508 .loop = loop,
502 .os_data = switch (builtin.os) {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 builtin.Os.windows => OsData{ .handle = null },511 builtin.Os.windows => OsData{ .handle = null },
505 else => @compileError("Unsupported OS"),512 else => @compileError("Unsupported OS"),
506 },513 },
...@@ -530,6 +537,7 @@ pub const CloseOperation = struct {...@@ -530,6 +537,7 @@ pub const CloseOperation = struct {
530 builtin.Os.linux,537 builtin.Os.linux,
531 builtin.Os.macosx,538 builtin.Os.macosx,
532 builtin.Os.freebsd,539 builtin.Os.freebsd,
540 builtin.Os.netbsd,
533 => {541 => {
534 if (self.os_data.have_fd) {542 if (self.os_data.have_fd) {
535 self.loop.posixFsRequest(&self.os_data.close_req_node);543 self.loop.posixFsRequest(&self.os_data.close_req_node);
...@@ -552,6 +560,7 @@ pub const CloseOperation = struct {...@@ -552,6 +560,7 @@ pub const CloseOperation = struct {
552 builtin.Os.linux,560 builtin.Os.linux,
553 builtin.Os.macosx,561 builtin.Os.macosx,
554 builtin.Os.freebsd,562 builtin.Os.freebsd,
563 builtin.Os.netbsd,
555 => {564 => {
556 self.os_data.close_req_node.data.msg.Close.fd = handle;565 self.os_data.close_req_node.data.msg.Close.fd = handle;
557 self.os_data.have_fd = true;566 self.os_data.have_fd = true;
...@@ -569,6 +578,7 @@ pub const CloseOperation = struct {...@@ -569,6 +578,7 @@ pub const CloseOperation = struct {
569 builtin.Os.linux,578 builtin.Os.linux,
570 builtin.Os.macosx,579 builtin.Os.macosx,
571 builtin.Os.freebsd,580 builtin.Os.freebsd,
581 builtin.Os.netbsd,
572 => {582 => {
573 self.os_data.have_fd = false;583 self.os_data.have_fd = false;
574 },584 },
...@@ -584,6 +594,7 @@ pub const CloseOperation = struct {...@@ -584,6 +594,7 @@ pub const CloseOperation = struct {
584 builtin.Os.linux,594 builtin.Os.linux,
585 builtin.Os.macosx,595 builtin.Os.macosx,
586 builtin.Os.freebsd,596 builtin.Os.freebsd,
597 builtin.Os.netbsd,
587 => {598 => {
588 assert(self.os_data.have_fd);599 assert(self.os_data.have_fd);
589 return self.os_data.close_req_node.data.msg.Close.fd;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,6 +619,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8,
608 builtin.Os.linux,619 builtin.Os.linux,
609 builtin.Os.macosx,620 builtin.Os.macosx,
610 builtin.Os.freebsd,621 builtin.Os.freebsd,
622 builtin.Os.netbsd,
611 => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),623 => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),
612 builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),624 builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),
613 else => @compileError("Unsupported OS"),625 else => @compileError("Unsupported OS"),
...@@ -713,7 +725,7 @@ pub fn Watch(comptime V: type) type {...@@ -713,7 +725,7 @@ pub fn Watch(comptime V: type) type {
713 os_data: OsData,725 os_data: OsData,
714726
715 const OsData = switch (builtin.os) {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 file_table: FileTable,729 file_table: FileTable,
718 table_lock: event.Lock,730 table_lock: event.Lock,
719731
...@@ -802,7 +814,7 @@ pub fn Watch(comptime V: type) type {...@@ -802,7 +814,7 @@ pub fn Watch(comptime V: type) type {
802 return self;814 return self;
803 },815 },
804816
805 builtin.Os.macosx, builtin.Os.freebsd => {817 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
806 const self = try loop.allocator.create(Self);818 const self = try loop.allocator.create(Self);
807 errdefer loop.allocator.destroy(self);819 errdefer loop.allocator.destroy(self);
808820
...@@ -822,7 +834,7 @@ pub fn Watch(comptime V: type) type {...@@ -822,7 +834,7 @@ pub fn Watch(comptime V: type) type {
822 /// All addFile calls and removeFile calls must have completed.834 /// All addFile calls and removeFile calls must have completed.
823 pub fn destroy(self: *Self) void {835 pub fn destroy(self: *Self) void {
824 switch (builtin.os) {836 switch (builtin.os) {
825 builtin.Os.macosx, builtin.Os.freebsd => {837 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
826 // TODO we need to cancel the coroutines before destroying the lock838 // TODO we need to cancel the coroutines before destroying the lock
827 self.os_data.table_lock.deinit();839 self.os_data.table_lock.deinit();
828 var it = self.os_data.file_table.iterator();840 var it = self.os_data.file_table.iterator();
...@@ -864,7 +876,10 @@ pub fn Watch(comptime V: type) type {...@@ -864,7 +876,10 @@ pub fn Watch(comptime V: type) type {
864876
865 pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {877 pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
866 switch (builtin.os) {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 builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),883 builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),
869 builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),884 builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),
870 else => @compileError("Unsupported OS"),885 else => @compileError("Unsupported OS"),
std/event/loop.zig+11-10
...@@ -50,7 +50,7 @@ pub const Loop = struct {...@@ -50,7 +50,7 @@ pub const Loop = struct {
50 };50 };
5151
52 pub const EventFd = switch (builtin.os) {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 builtin.Os.linux => struct {54 builtin.Os.linux => struct {
55 base: ResumeNode,55 base: ResumeNode,
56 epoll_op: u32,56 epoll_op: u32,
...@@ -69,7 +69,7 @@ pub const Loop = struct {...@@ -69,7 +69,7 @@ pub const Loop = struct {
69 };69 };
7070
71 pub const Basic = switch (builtin.os) {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 builtin.Os.linux => struct {73 builtin.Os.linux => struct {
74 base: ResumeNode,74 base: ResumeNode,
75 },75 },
...@@ -221,7 +221,7 @@ pub const Loop = struct {...@@ -221,7 +221,7 @@ pub const Loop = struct {
221 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);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 self.os_data.kqfd = try os.bsdKQueue();225 self.os_data.kqfd = try os.bsdKQueue();
226 errdefer os.close(self.os_data.kqfd);226 errdefer os.close(self.os_data.kqfd);
227227
...@@ -386,7 +386,7 @@ pub const Loop = struct {...@@ -386,7 +386,7 @@ pub const Loop = struct {
386 os.close(self.os_data.epollfd);386 os.close(self.os_data.epollfd);
387 self.allocator.free(self.eventfd_resume_nodes);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 os.close(self.os_data.kqfd);390 os.close(self.os_data.kqfd);
391 os.close(self.os_data.fs_kqfd);391 os.close(self.os_data.fs_kqfd);
392 },392 },
...@@ -501,7 +501,7 @@ pub const Loop = struct {...@@ -501,7 +501,7 @@ pub const Loop = struct {
501 const eventfd_node = &resume_stack_node.data;501 const eventfd_node = &resume_stack_node.data;
502 eventfd_node.base.handle = next_tick_node.data;502 eventfd_node.base.handle = next_tick_node.data;
503 switch (builtin.os) {503 switch (builtin.os) {
504 builtin.Os.macosx, builtin.Os.freebsd => {504 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
505 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);505 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
506 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];506 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
507 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {507 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
...@@ -564,6 +564,7 @@ pub const Loop = struct {...@@ -564,6 +564,7 @@ pub const Loop = struct {
564 builtin.Os.linux,564 builtin.Os.linux,
565 builtin.Os.macosx,565 builtin.Os.macosx,
566 builtin.Os.freebsd,566 builtin.Os.freebsd,
567 builtin.Os.netbsd,
567 => self.os_data.fs_thread.wait(),568 => self.os_data.fs_thread.wait(),
568 else => {},569 else => {},
569 }570 }
...@@ -628,7 +629,7 @@ pub const Loop = struct {...@@ -628,7 +629,7 @@ pub const Loop = struct {
628 os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;629 os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
629 return;630 return;
630 },631 },
631 builtin.Os.macosx, builtin.Os.freebsd => {632 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
632 self.posixFsRequest(&self.os_data.fs_end_request);633 self.posixFsRequest(&self.os_data.fs_end_request);
633 const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);634 const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
634 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];635 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
...@@ -686,7 +687,7 @@ pub const Loop = struct {...@@ -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 var eventlist: [1]posix.Kevent = undefined;691 var eventlist: [1]posix.Kevent = undefined;
691 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];692 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
692 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;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,7 +750,7 @@ pub const Loop = struct {
749 self.beginOneEvent(); // finished in posixFsRun after processing the msg750 self.beginOneEvent(); // finished in posixFsRun after processing the msg
750 self.os_data.fs_queue.put(request_node);751 self.os_data.fs_queue.put(request_node);
751 switch (builtin.os) {752 switch (builtin.os) {
752 builtin.Os.macosx, builtin.Os.freebsd => {753 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
753 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);754 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
754 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];755 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
755 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;756 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
...@@ -819,7 +820,7 @@ pub const Loop = struct {...@@ -819,7 +820,7 @@ pub const Loop = struct {
819 else => unreachable,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 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);824 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
824 var out_kevs: [1]posix.Kevent = undefined;825 var out_kevs: [1]posix.Kevent = undefined;
825 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;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,7 +832,7 @@ pub const Loop = struct {
831832
832 const OsData = switch (builtin.os) {833 const OsData = switch (builtin.os) {
833 builtin.Os.linux => LinuxOsData,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 builtin.Os.windows => struct {836 builtin.Os.windows => struct {
836 io_port: windows.HANDLE,837 io_port: windows.HANDLE,
837 extra_thread_count: usize,838 extra_thread_count: usize,
std/fmt/index.zig+11-2
...@@ -236,6 +236,9 @@ pub fn formatType(...@@ -236,6 +236,9 @@ pub fn formatType(
236 const casted_value = ([]const u8)(value);236 const casted_value = ([]const u8)(value);
237 return output(context, casted_value);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 builtin.TypeId.Array => |info| {243 builtin.TypeId.Array => |info| {
241 if (info.child == u8) {244 if (info.child == u8) {
...@@ -828,7 +831,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned...@@ -828,7 +831,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
828 return x;831 return x;
829}832}
830833
831test "parseUnsigned" {834test "fmt.parseUnsigned" {
832 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);835 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
833 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);836 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
834 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));837 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
...@@ -855,6 +858,12 @@ test "parseUnsigned" {...@@ -855,6 +858,12 @@ test "parseUnsigned" {
855 testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));858 testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
856}859}
857860
861pub const parseFloat = @import("parse_float.zig").parseFloat;
862
863test "fmt.parseFloat" {
864 _ = @import("parse_float.zig");
865}
866
858pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {867pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
859 const value = switch (c) {868 const value = switch (c) {
860 '0'...'9' => c - '0',869 '0'...'9' => c - '0',
...@@ -1109,7 +1118,7 @@ test "fmt.format" {...@@ -1109,7 +1118,7 @@ test "fmt.format" {
1109 const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);1118 const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);
1110 testing.expect(mem.eql(u8, result, "f64: nan\n"));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 // negative nan is not defined by IEE 754,1122 // negative nan is not defined by IEE 754,
1114 // and ARM thus normalizes it to positive nan1123 // and ARM thus normalizes it to positive nan
1115 var buf1: [32]u8 = undefined;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
32const std = @import("../index.zig");
33
34const max_digits = 25;
35
36const f64_plus_zero: u64 = 0x0000000000000000;
37const f64_minus_zero: u64 = 0x8000000000000000;
38const f64_plus_infinity: u64 = 0x7FF0000000000000;
39const f64_minus_infinity: u64 = 0xFFF0000000000000;
40
41const 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
89const FloatRepr = struct {
90 negative: bool,
91 exponent: i32,
92 mantissa: u64,
93};
94
95fn 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
176const State = enum {
177 MaybeSign,
178 LeadingMantissaZeros,
179 LeadingFractionalZeros,
180 MantissaIntegral,
181 MantissaFractional,
182 ExponentSign,
183 LeadingExponentZeros,
184 Exponent,
185};
186
187const ParseResult = enum {
188 Ok,
189 PlusZero,
190 MinusZero,
191 PlusInf,
192 MinusInf,
193};
194
195inline fn isDigit(c: u8) bool {
196 return c >= '0' and c <= '9';
197}
198
199inline fn isSpace(c: u8) bool {
200 return (c >= 0x09 and c <= 0x13) or c == 0x20;
201}
202
203fn 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
338inline fn isLower(c: u8) bool {
339 return c -% 'a' < 26;
340}
341
342inline fn toUpper(c: u8) u8 {
343 return if (isLower(c)) (c & 0x5f) else c;
344}
345
346fn 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
358pub 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
386test "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,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
496 builtin.TypeId.Pointer => |info| switch (info.size) {496 builtin.TypeId.Pointer => |info| switch (info.size) {
497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
498 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),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 builtin.TypeInfo.Pointer.Size.Slice => {500 builtin.TypeInfo.Pointer.Size.Slice => {
500 const interval = std.math.max(1, key.len / 256);501 const interval = std.math.max(1, key.len / 256);
501 var i: usize = 0;502 var i: usize = 0;
...@@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
543 builtin.TypeId.Pointer => |info| switch (info.size) {544 builtin.TypeId.Pointer => |info| switch (info.size) {
544 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),545 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
545 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),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 builtin.TypeInfo.Pointer.Size.Slice => {548 builtin.TypeInfo.Pointer.Size.Slice => {
547 if (a.len != b.len) return false;549 if (a.len != b.len) return false;
548 for (a) |a_item, i| {550 for (a) |a_item, i| {
std/heap.zig+3-3
...@@ -71,7 +71,7 @@ pub const DirectAllocator = struct {...@@ -71,7 +71,7 @@ pub const DirectAllocator = struct {
71 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);71 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
7272
73 switch (builtin.os) {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 const p = os.posix;75 const p = os.posix;
76 const alloc_size = if (alignment <= os.page_size) n else n + alignment;76 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
77 const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);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,7 +120,7 @@ pub const DirectAllocator = struct {
120 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);120 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
121121
122 switch (builtin.os) {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 if (new_size <= old_mem.len) {124 if (new_size <= old_mem.len) {
125 const base_addr = @ptrToInt(old_mem.ptr);125 const base_addr = @ptrToInt(old_mem.ptr);
126 const old_addr_end = base_addr + old_mem.len;126 const old_addr_end = base_addr + old_mem.len;
...@@ -164,7 +164,7 @@ pub const DirectAllocator = struct {...@@ -164,7 +164,7 @@ pub const DirectAllocator = struct {
164 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);164 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
165165
166 switch (builtin.os) {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 _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);168 _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
169 },169 },
170 Os.windows => {170 Os.windows => {
std/index.zig+3-1
...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
9pub const HashMap = @import("hash_map.zig").HashMap;9pub const HashMap = @import("hash_map.zig").HashMap;
10pub const LinkedList = @import("linked_list.zig").LinkedList;10pub const LinkedList = @import("linked_list.zig").LinkedList;
11pub const Mutex = @import("mutex.zig").Mutex;11pub const Mutex = @import("mutex.zig").Mutex;
12pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;
12pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;13pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
13pub const SegmentedList = @import("segmented_list.zig").SegmentedList;14pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
14pub const SpinLock = @import("spinlock.zig").SpinLock;15pub const SpinLock = @import("spinlock.zig").SpinLock;
...@@ -59,7 +60,7 @@ test "std" {...@@ -59,7 +60,7 @@ test "std" {
59 _ = @import("statically_initialized_mutex.zig");60 _ = @import("statically_initialized_mutex.zig");
60 _ = @import("segmented_list.zig");61 _ = @import("segmented_list.zig");
61 _ = @import("spinlock.zig");62 _ = @import("spinlock.zig");
62 63
63 _ = @import("base64.zig");64 _ = @import("base64.zig");
64 _ = @import("build.zig");65 _ = @import("build.zig");
65 _ = @import("c/index.zig");66 _ = @import("c/index.zig");
...@@ -85,6 +86,7 @@ test "std" {...@@ -85,6 +86,7 @@ test "std" {
85 _ = @import("net.zig");86 _ = @import("net.zig");
86 _ = @import("os/index.zig");87 _ = @import("os/index.zig");
87 _ = @import("pdb.zig");88 _ = @import("pdb.zig");
89 _ = @import("priority_queue.zig");
88 _ = @import("rand/index.zig");90 _ = @import("rand/index.zig");
89 _ = @import("sort.zig");91 _ = @import("sort.zig");
90 _ = @import("testing.zig");92 _ = @import("testing.zig");
std/io.zig+61-22
...@@ -343,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)...@@ -343,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
343 const amt_buffered = self.end_index - self.start_index;343 const amt_buffered = self.end_index - self.start_index;
344 if (amt_buffered == 0) {344 if (amt_buffered == 0) {
345 assert(self.end_index <= buffer_size);345 assert(self.end_index <= buffer_size);
346 if (self.end_index == buffer_size) {346 // Make sure the last read actually gave us some data
347 // we can read more data from the unbuffered stream347 if (self.end_index == 0) {
348 if (dest_space < buffer_size) {348 // reading from the unbuffered stream returned nothing
349 self.start_index = 0;349 // so we have nothing left to read.
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.
360 return dest_index;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 const copy_amount = math.min(dest_space, amt_buffered);364 const copy_amount = math.min(dest_space, amt_buffered);
364 const copy_end_index = self.start_index + copy_amount;365 const copy_end_index = self.start_index + copy_amount;
365 mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);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,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
370 };371 };
371}372}
372373
374test "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/// Creates a stream which supports 'un-reading' data, so that it can be read again.414/// Creates a stream which supports 'un-reading' data, so that it can be read again.
374/// This makes look-ahead style parsing much easier.415/// This makes look-ahead style parsing much easier.
375pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {416pub 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,8 +976,6 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
935 };976 };
936}977}
937978
938
939
940pub const BufferedAtomicFile = struct {979pub const BufferedAtomicFile = struct {
941 atomic_file: os.AtomicFile,980 atomic_file: os.AtomicFile,
942 file_stream: os.File.OutStream,981 file_stream: os.File.OutStream,
...@@ -978,7 +1017,6 @@ pub const BufferedAtomicFile = struct {...@@ -978,7 +1017,6 @@ pub const BufferedAtomicFile = struct {
978 }1017 }
979};1018};
9801019
981
982pub fn readLine(buf: *std.Buffer) ![]u8 {1020pub fn readLine(buf: *std.Buffer) ![]u8 {
983 var stdin = try getStdIn();1021 var stdin = try getStdIn();
984 var stdin_stream = stdin.inStream();1022 var stdin_stream = stdin.inStream();
...@@ -1073,13 +1111,13 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E...@@ -1073,13 +1111,13 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E
1073 else => in_stream,1111 else => in_stream,
1074 } };1112 } };
1075 }1113 }
1076 1114
1077 pub fn alignToByte(self: *Self) void {1115 pub fn alignToByte(self: *Self) void {
1078 if(!is_packed) return;1116 if (!is_packed) return;
1079 self.in_stream.alignToByte();1117 self.in_stream.alignToByte();
1080 }1118 }
10811119
1082 //@BUG: inferred error issue. See: #1386 1120 //@BUG: inferred error issue. See: #1386
1083 fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {1121 fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
1084 comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));1122 comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
10851123
...@@ -1088,7 +1126,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E...@@ -1088,7 +1126,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E
10881126
1089 const U = @IntType(false, t_bit_count);1127 const U = @IntType(false, t_bit_count);
1090 const Log2U = math.Log2Int(U);1128 const Log2U = math.Log2Int(U);
1091 const int_size = @sizeOf(U);1129 const int_size = (U.bit_count + 7) / 8;
10921130
1093 if (is_packed) {1131 if (is_packed) {
1094 const result = try self.in_stream.readBitsNoEof(U, t_bit_count);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,7 +1339,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, com
13011339
1302 const U = @IntType(false, t_bit_count);1340 const U = @IntType(false, t_bit_count);
1303 const Log2U = math.Log2Int(U);1341 const Log2U = math.Log2Int(U);
1304 const int_size = @sizeOf(U);1342 const int_size = (U.bit_count + 7) / 8;
13051343
1306 const u_value = @bitCast(U, value);1344 const u_value = @bitCast(U, value);
13071345
...@@ -1414,3 +1452,4 @@ test "import io tests" {...@@ -1414,3 +1452,4 @@ test "import io tests" {
1414 _ = @import("io_test.zig");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,6 +29,17 @@ test "write a file, read it, then delete it" {
29 try st.print("end");29 try st.print("end");
30 try buf_stream.flush();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 var file = try os.File.openRead(tmp_file_name);44 var file = try os.File.openRead(tmp_file_name);
34 defer file.close();45 defer file.close();
std/json.zig+6-2
...@@ -1345,7 +1345,7 @@ pub const Parser = struct {...@@ -1345,7 +1345,7 @@ pub const Parser = struct {
1345 return if (token.number_is_integer)1345 return if (token.number_is_integer)
1346 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }1346 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
1347 else1347 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};
13511351
...@@ -1366,7 +1366,8 @@ test "json.parser.dynamic" {...@@ -1366,7 +1366,8 @@ test "json.parser.dynamic" {
1366 \\ },1366 \\ },
1367 \\ "Animated" : false,1367 \\ "Animated" : false,
1368 \\ "IDs": [116, 943, 234, 38793],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,4 +1396,7 @@ test "json.parser.dynamic" {
13951396
1396 const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;1397 const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
1397 testing.expect(mem.eql(u8, obj0.String, "m"));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,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) {
14 f16 => fabs16(x),14 f16 => fabs16(x),
15 f32 => fabs32(x),15 f32 => fabs32(x),
16 f64 => fabs64(x),16 f64 => fabs64(x),
17 f128 => fabs128(x),
17 else => @compileError("fabs not implemented for " ++ @typeName(T)),18 else => @compileError("fabs not implemented for " ++ @typeName(T)),
18 };19 };
19}20}
...@@ -36,10 +37,17 @@ fn fabs64(x: f64) f64 {...@@ -36,10 +37,17 @@ fn fabs64(x: f64) f64 {
36 return @bitCast(f64, u);37 return @bitCast(f64, u);
37}38}
3839
40fn fabs128(x: f128) f128 {
41 var u = @bitCast(u128, x);
42 u &= maxInt(u128) >> 1;
43 return @bitCast(f128, u);
44}
45
39test "math.fabs" {46test "math.fabs" {
40 expect(fabs(f16(1.0)) == fabs16(1.0));47 expect(fabs(f16(1.0)) == fabs16(1.0));
41 expect(fabs(f32(1.0)) == fabs32(1.0));48 expect(fabs(f32(1.0)) == fabs32(1.0));
42 expect(fabs(f64(1.0)) == fabs64(1.0));49 expect(fabs(f64(1.0)) == fabs64(1.0));
50 expect(fabs(f128(1.0)) == fabs128(1.0));
43}51}
4452
45test "math.fabs16" {53test "math.fabs16" {
...@@ -57,6 +65,11 @@ test "math.fabs64" {...@@ -57,6 +65,11 @@ test "math.fabs64" {
57 expect(fabs64(-1.0) == 1.0);65 expect(fabs64(-1.0) == 1.0);
58}66}
5967
68test "math.fabs128" {
69 expect(fabs128(1.0) == 1.0);
70 expect(fabs128(-1.0) == 1.0);
71}
72
60test "math.fabs16.special" {73test "math.fabs16.special" {
61 expect(math.isPositiveInf(fabs(math.inf(f16))));74 expect(math.isPositiveInf(fabs(math.inf(f16))));
62 expect(math.isPositiveInf(fabs(-math.inf(f16))));75 expect(math.isPositiveInf(fabs(-math.inf(f16))));
...@@ -74,3 +87,9 @@ test "math.fabs64.special" {...@@ -74,3 +87,9 @@ test "math.fabs64.special" {
74 expect(math.isPositiveInf(fabs(-math.inf(f64))));87 expect(math.isPositiveInf(fabs(-math.inf(f64))));
75 expect(math.isNan(fabs(math.nan(f64))));88 expect(math.isNan(fabs(math.nan(f64))));
76}89}
90
91test "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,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64);
51pub const inf_u64 = u64(0x7FF << 52);51pub const inf_u64 = u64(0x7FF << 52);
52pub const inf_f64 = @bitCast(f64, inf_u64);52pub const inf_f64 = @bitCast(f64, inf_u64);
5353
54pub const nan_u128 = u128(0x7fff0000000000000000000000000001);
55pub const nan_f128 = @bitCast(f128, nan_u128);
56
57pub const inf_u128 = u128(0x7fff0000000000000000000000000000);
58pub const inf_f128 = @bitCast(f128, inf_u128);
59
54pub const nan = @import("nan.zig").nan;60pub const nan = @import("nan.zig").nan;
55pub const snan = @import("nan.zig").snan;61pub const snan = @import("nan.zig").snan;
56pub const inf = @import("inf.zig").inf;62pub const inf = @import("inf.zig").inf;
...@@ -379,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t...@@ -379,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
379 return u0;385 return u0;
380 }386 }
381 const is_signed = from < 0;387 const is_signed = from < 0;
382 const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement388 const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
383 const base = log2(largest_positive_integer);389 const base = log2(largest_positive_integer);
384 const upper = (1 << base) - 1;390 const upper = (1 << base) - 1;
385 var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;391 var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
...@@ -752,6 +758,7 @@ test "minInt and maxInt" {...@@ -752,6 +758,7 @@ test "minInt and maxInt" {
752 testing.expect(maxInt(u16) == 65535);758 testing.expect(maxInt(u16) == 65535);
753 testing.expect(maxInt(u32) == 4294967295);759 testing.expect(maxInt(u32) == 4294967295);
754 testing.expect(maxInt(u64) == 18446744073709551615);760 testing.expect(maxInt(u64) == 18446744073709551615);
761 testing.expect(maxInt(u128) == 340282366920938463463374607431768211455);
755762
756 testing.expect(maxInt(i0) == 0);763 testing.expect(maxInt(i0) == 0);
757 testing.expect(maxInt(i1) == 0);764 testing.expect(maxInt(i1) == 0);
...@@ -760,6 +767,7 @@ test "minInt and maxInt" {...@@ -760,6 +767,7 @@ test "minInt and maxInt" {
760 testing.expect(maxInt(i32) == 2147483647);767 testing.expect(maxInt(i32) == 2147483647);
761 testing.expect(maxInt(i63) == 4611686018427387903);768 testing.expect(maxInt(i63) == 4611686018427387903);
762 testing.expect(maxInt(i64) == 9223372036854775807);769 testing.expect(maxInt(i64) == 9223372036854775807);
770 testing.expect(maxInt(i128) == 170141183460469231731687303715884105727);
763771
764 testing.expect(minInt(u0) == 0);772 testing.expect(minInt(u0) == 0);
765 testing.expect(minInt(u1) == 0);773 testing.expect(minInt(u1) == 0);
...@@ -768,6 +776,7 @@ test "minInt and maxInt" {...@@ -768,6 +776,7 @@ test "minInt and maxInt" {
768 testing.expect(minInt(u32) == 0);776 testing.expect(minInt(u32) == 0);
769 testing.expect(minInt(u63) == 0);777 testing.expect(minInt(u63) == 0);
770 testing.expect(minInt(u64) == 0);778 testing.expect(minInt(u64) == 0);
779 testing.expect(minInt(u128) == 0);
771780
772 testing.expect(minInt(i0) == 0);781 testing.expect(minInt(i0) == 0);
773 testing.expect(minInt(i1) == -1);782 testing.expect(minInt(i1) == -1);
...@@ -776,6 +785,7 @@ test "minInt and maxInt" {...@@ -776,6 +785,7 @@ test "minInt and maxInt" {
776 testing.expect(minInt(i32) == -2147483648);785 testing.expect(minInt(i32) == -2147483648);
777 testing.expect(minInt(i63) == -4611686018427387904);786 testing.expect(minInt(i63) == -4611686018427387904);
778 testing.expect(minInt(i64) == -9223372036854775808);787 testing.expect(minInt(i64) == -9223372036854775808);
788 testing.expect(minInt(i128) == -170141183460469231731687303715884105728);
779}789}
780790
781test "max value type" {791test "max value type" {
std/math/inf.zig+4-3
...@@ -3,9 +3,10 @@ const math = std.math;...@@ -3,9 +3,10 @@ const math = std.math;
33
4pub fn inf(comptime T: type) T {4pub fn inf(comptime T: type) T {
5 return switch (T) {5 return switch (T) {
6 f16 => @bitCast(f16, math.inf_u16),6 f16 => math.inf_f16,
7 f32 => @bitCast(f32, math.inf_u32),7 f32 => math.inf_f32,
8 f64 => @bitCast(f64, math.inf_u64),8 f64 => math.inf_f64,
9 f128 => math.inf_f128,
9 else => @compileError("inf not implemented for " ++ @typeName(T)),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,6 +18,10 @@ pub fn isInf(x: var) bool {
18 const bits = @bitCast(u64, x);18 const bits = @bitCast(u64, x);
19 return bits & (maxInt(u64) >> 1) == (0x7FF << 52);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 else => {25 else => {
22 @compileError("isInf not implemented for " ++ @typeName(T));26 @compileError("isInf not implemented for " ++ @typeName(T));
23 },27 },
...@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {...@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {
36 f64 => {40 f64 => {
37 return @bitCast(u64, x) == 0x7FF << 52;41 return @bitCast(u64, x) == 0x7FF << 52;
38 },42 },
43 f128 => {
44 return @bitCast(u128, x) == 0x7FFF << 112;
45 },
39 else => {46 else => {
40 @compileError("isPositiveInf not implemented for " ++ @typeName(T));47 @compileError("isPositiveInf not implemented for " ++ @typeName(T));
41 },48 },
...@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {...@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {
54 f64 => {61 f64 => {
55 return @bitCast(u64, x) == 0xFFF << 52;62 return @bitCast(u64, x) == 0xFFF << 52;
56 },63 },
64 f128 => {
65 return @bitCast(u128, x) == 0xFFFF << 112;
66 },
57 else => {67 else => {
58 @compileError("isNegativeInf not implemented for " ++ @typeName(T));68 @compileError("isNegativeInf not implemented for " ++ @typeName(T));
59 },69 },
...@@ -67,12 +77,16 @@ test "math.isInf" {...@@ -67,12 +77,16 @@ test "math.isInf" {
67 expect(!isInf(f32(-0.0)));77 expect(!isInf(f32(-0.0)));
68 expect(!isInf(f64(0.0)));78 expect(!isInf(f64(0.0)));
69 expect(!isInf(f64(-0.0)));79 expect(!isInf(f64(-0.0)));
80 expect(!isInf(f128(0.0)));
81 expect(!isInf(f128(-0.0)));
70 expect(isInf(math.inf(f16)));82 expect(isInf(math.inf(f16)));
71 expect(isInf(-math.inf(f16)));83 expect(isInf(-math.inf(f16)));
72 expect(isInf(math.inf(f32)));84 expect(isInf(math.inf(f32)));
73 expect(isInf(-math.inf(f32)));85 expect(isInf(-math.inf(f32)));
74 expect(isInf(math.inf(f64)));86 expect(isInf(math.inf(f64)));
75 expect(isInf(-math.inf(f64)));87 expect(isInf(-math.inf(f64)));
88 expect(isInf(math.inf(f128)));
89 expect(isInf(-math.inf(f128)));
76}90}
7791
78test "math.isPositiveInf" {92test "math.isPositiveInf" {
...@@ -82,12 +96,16 @@ test "math.isPositiveInf" {...@@ -82,12 +96,16 @@ test "math.isPositiveInf" {
82 expect(!isPositiveInf(f32(-0.0)));96 expect(!isPositiveInf(f32(-0.0)));
83 expect(!isPositiveInf(f64(0.0)));97 expect(!isPositiveInf(f64(0.0)));
84 expect(!isPositiveInf(f64(-0.0)));98 expect(!isPositiveInf(f64(-0.0)));
99 expect(!isPositiveInf(f128(0.0)));
100 expect(!isPositiveInf(f128(-0.0)));
85 expect(isPositiveInf(math.inf(f16)));101 expect(isPositiveInf(math.inf(f16)));
86 expect(!isPositiveInf(-math.inf(f16)));102 expect(!isPositiveInf(-math.inf(f16)));
87 expect(isPositiveInf(math.inf(f32)));103 expect(isPositiveInf(math.inf(f32)));
88 expect(!isPositiveInf(-math.inf(f32)));104 expect(!isPositiveInf(-math.inf(f32)));
89 expect(isPositiveInf(math.inf(f64)));105 expect(isPositiveInf(math.inf(f64)));
90 expect(!isPositiveInf(-math.inf(f64)));106 expect(!isPositiveInf(-math.inf(f64)));
107 expect(isPositiveInf(math.inf(f128)));
108 expect(!isPositiveInf(-math.inf(f128)));
91}109}
92110
93test "math.isNegativeInf" {111test "math.isNegativeInf" {
...@@ -97,10 +115,14 @@ test "math.isNegativeInf" {...@@ -97,10 +115,14 @@ test "math.isNegativeInf" {
97 expect(!isNegativeInf(f32(-0.0)));115 expect(!isNegativeInf(f32(-0.0)));
98 expect(!isNegativeInf(f64(0.0)));116 expect(!isNegativeInf(f64(0.0)));
99 expect(!isNegativeInf(f64(-0.0)));117 expect(!isNegativeInf(f64(-0.0)));
118 expect(!isNegativeInf(f128(0.0)));
119 expect(!isNegativeInf(f128(-0.0)));
100 expect(!isNegativeInf(math.inf(f16)));120 expect(!isNegativeInf(math.inf(f16)));
101 expect(isNegativeInf(-math.inf(f16)));121 expect(isNegativeInf(-math.inf(f16)));
102 expect(!isNegativeInf(math.inf(f32)));122 expect(!isNegativeInf(math.inf(f32)));
103 expect(isNegativeInf(-math.inf(f32)));123 expect(isNegativeInf(-math.inf(f32)));
104 expect(!isNegativeInf(math.inf(f64)));124 expect(!isNegativeInf(math.inf(f64)));
105 expect(isNegativeInf(-math.inf(f64)));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,6 +18,10 @@ pub fn isNan(x: var) bool {
18 const bits = @bitCast(u64, x);18 const bits = @bitCast(u64, x);
19 return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52);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 else => {25 else => {
22 @compileError("isNan not implemented for " ++ @typeName(T));26 @compileError("isNan not implemented for " ++ @typeName(T));
23 },27 },
...@@ -34,7 +38,9 @@ test "math.isNan" {...@@ -34,7 +38,9 @@ test "math.isNan" {
34 expect(isNan(math.nan(f16)));38 expect(isNan(math.nan(f16)));
35 expect(isNan(math.nan(f32)));39 expect(isNan(math.nan(f32)));
36 expect(isNan(math.nan(f64)));40 expect(isNan(math.nan(f64)));
41 expect(isNan(math.nan(f128)));
37 expect(!isNan(f16(1.0)));42 expect(!isNan(f16(1.0)));
38 expect(!isNan(f32(1.0)));43 expect(!isNan(f32(1.0)));
39 expect(!isNan(f64(1.0)));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,9 +2,10 @@ const math = @import("index.zig");
22
3pub fn nan(comptime T: type) T {3pub fn nan(comptime T: type) T {
4 return switch (T) {4 return switch (T) {
5 f16 => @bitCast(f16, math.nan_u16),5 f16 => math.nan_f16,
6 f32 => @bitCast(f32, math.nan_u32),6 f32 => math.nan_f32,
7 f64 => @bitCast(f64, math.nan_u64),7 f64 => math.nan_f64,
8 f128 => math.nan_f128,
8 else => @compileError("nan not implemented for " ++ @typeName(T)),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,7 +25,7 @@ pub fn powi(comptime T: type, x: T, y: T) (error{
2525
26 // powi(x, +-0) = 1 for any x26 // powi(x, +-0) = 1 for any x
27 if (y == 0 or y == -0) {27 if (y == 0 or y == -0) {
28 return 0;28 return 1;
29 }29 }
3030
31 switch (x) {31 switch (x) {
...@@ -174,4 +174,11 @@ test "math.powi.special" {...@@ -174,4 +174,11 @@ test "math.powi.special" {
174 testing.expectError(error.Overflow, powi(u64, 2, 64));174 testing.expectError(error.Overflow, powi(u64, 2, 64));
175 testing.expectError(error.Overflow, powi(u17, 2, 17));175 testing.expectError(error.Overflow, powi(u17, 2, 17));
176 testing.expectError(error.Overflow, powi(u42, 2, 42));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,8 +423,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.
423/// This function cannot fail and cannot cause undefined behavior.423/// This function cannot fail and cannot cause undefined behavior.
424/// Assumes the endianness of memory is native. This means the function can424/// Assumes the endianness of memory is native. This means the function can
425/// simply pointer cast memory.425/// simply pointer cast memory.
426pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {426pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
427 comptime assert(T.bit_count % 8 == 0);
428 return @ptrCast(*align(1) const T, bytes).*;427 return @ptrCast(*align(1) const T, bytes).*;
429}428}
430429
...@@ -432,7 +431,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {...@@ -432,7 +431,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
432/// The bit count of T must be evenly divisible by 8.431/// The bit count of T must be evenly divisible by 8.
433/// This function cannot fail and cannot cause undefined behavior.432/// This function cannot fail and cannot cause undefined behavior.
434/// Assumes the endianness of memory is foreign, so it must byte-swap.433/// Assumes the endianness of memory is foreign, so it must byte-swap.
435pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {434pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
436 return @bswap(T, readIntNative(T, bytes));435 return @bswap(T, readIntNative(T, bytes));
437}436}
438437
...@@ -446,22 +445,20 @@ pub const readIntBig = switch (builtin.endian) {...@@ -446,22 +445,20 @@ pub const readIntBig = switch (builtin.endian) {
446 builtin.Endian.Big => readIntNative,445 builtin.Endian.Big => readIntNative,
447};446};
448447
449/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0448/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
450/// and ignores extra bytes.449/// and ignores extra bytes.
451/// Note that @sizeOf(u24) is 3.
452/// The bit count of T must be evenly divisible by 8.450/// The bit count of T must be evenly divisible by 8.
453/// Assumes the endianness of memory is native. This means the function can451/// Assumes the endianness of memory is native. This means the function can
454/// simply pointer cast memory.452/// simply pointer cast memory.
455pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {453pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
456 assert(@sizeOf(u24) == 3);454 const n = @divExact(T.bit_count, 8);
457 assert(bytes.len >= @sizeOf(T));455 assert(bytes.len >= n);
458 // TODO https://github.com/ziglang/zig/issues/863456 // 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}
461459
462/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0460/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
463/// and ignores extra bytes.461/// and ignores extra bytes.
464/// Note that @sizeOf(u24) is 3.
465/// The bit count of T must be evenly divisible by 8.462/// The bit count of T must be evenly divisible by 8.
466/// Assumes the endianness of memory is foreign, so it must byte-swap.463/// Assumes the endianness of memory is foreign, so it must byte-swap.
467pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {464pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
...@@ -481,7 +478,7 @@ pub const readIntSliceBig = switch (builtin.endian) {...@@ -481,7 +478,7 @@ pub const readIntSliceBig = switch (builtin.endian) {
481/// Reads an integer from memory with bit count specified by T.478/// Reads an integer from memory with bit count specified by T.
482/// The bit count of T must be evenly divisible by 8.479/// The bit count of T must be evenly divisible by 8.
483/// This function cannot fail and cannot cause undefined behavior.480/// This function cannot fail and cannot cause undefined behavior.
484pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T {481pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T {
485 if (endian == builtin.endian) {482 if (endian == builtin.endian) {
486 return readIntNative(T, bytes);483 return readIntNative(T, bytes);
487 } else {484 } else {
...@@ -489,15 +486,14 @@ pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.E...@@ -489,15 +486,14 @@ pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.E
489 }486 }
490}487}
491488
492/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0489/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
493/// and ignores extra bytes.490/// and ignores extra bytes.
494/// Note that @sizeOf(u24) is 3.
495/// The bit count of T must be evenly divisible by 8.491/// The bit count of T must be evenly divisible by 8.
496pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {492pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
497 assert(@sizeOf(u24) == 3);493 const n = @divExact(T.bit_count, 8);
498 assert(bytes.len >= @sizeOf(T));494 assert(bytes.len >= n);
499 // TODO https://github.com/ziglang/zig/issues/863495 // 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}
502498
503test "comptime read/write int" {499test "comptime read/write int" {
...@@ -540,7 +536,7 @@ test "readIntBig and readIntLittle" {...@@ -540,7 +536,7 @@ test "readIntBig and readIntLittle" {
540/// accepts any integer bit width.536/// accepts any integer bit width.
541/// This function stores in native endian, which means it is implemented as a simple537/// This function stores in native endian, which means it is implemented as a simple
542/// memory store.538/// memory store.
543pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {539pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void {
544 @ptrCast(*align(1) T, buf).* = value;540 @ptrCast(*align(1) T, buf).* = value;
545}541}
546542
...@@ -548,7 +544,7 @@ pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {...@@ -548,7 +544,7 @@ pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
548/// This function always succeeds, has defined behavior for all inputs, but544/// This function always succeeds, has defined behavior for all inputs, but
549/// the integer bit width must be divisible by 8.545/// the integer bit width must be divisible by 8.
550/// This function stores in foreign endian, which means it does a @bswap first.546/// This function stores in foreign endian, which means it does a @bswap first.
551pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {547pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {
552 writeIntNative(T, buf, @bswap(T, value));548 writeIntNative(T, buf, @bswap(T, value));
553}549}
554550
...@@ -565,8 +561,7 @@ pub const writeIntBig = switch (builtin.endian) {...@@ -565,8 +561,7 @@ pub const writeIntBig = switch (builtin.endian) {
565/// Writes an integer to memory, storing it in twos-complement.561/// Writes an integer to memory, storing it in twos-complement.
566/// This function always succeeds, has defined behavior for all inputs, but562/// This function always succeeds, has defined behavior for all inputs, but
567/// the integer bit width must be divisible by 8.563/// the integer bit width must be divisible by 8.
568pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void {564pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void {
569 comptime assert(T.bit_count % 8 == 0);
570 if (endian == builtin.endian) {565 if (endian == builtin.endian) {
571 return writeIntNative(T, buffer, value);566 return writeIntNative(T, buffer, value);
572 } else {567 } else {
...@@ -575,15 +570,13 @@ pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: bui...@@ -575,15 +570,13 @@ pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: bui
575}570}
576571
577/// Writes a twos-complement little-endian integer to memory.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/// The bit count of T must be divisible by 8.574/// The bit count of T must be divisible by 8.
580/// Any extra bytes in buffer after writing the integer are set to zero. To575/// Any extra bytes in buffer after writing the integer are set to zero. To
581/// avoid the branch to check for extra buffer bytes, use writeIntLittle576/// avoid the branch to check for extra buffer bytes, use writeIntLittle
582/// instead.577/// instead.
583pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {578pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
584 comptime assert(@sizeOf(u24) == 3);579 assert(buffer.len >= @divExact(T.bit_count, 8));
585 comptime assert(T.bit_count % 8 == 0);
586 assert(buffer.len >= @sizeOf(T));
587580
588 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough581 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
589 const uint = @IntType(false, T.bit_count);582 const uint = @IntType(false, T.bit_count);
...@@ -595,14 +588,12 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {...@@ -595,14 +588,12 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
595}588}
596589
597/// Writes a twos-complement big-endian integer to memory.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/// The bit count of T must be divisible by 8.592/// The bit count of T must be divisible by 8.
600/// Any extra bytes in buffer before writing the integer are set to zero. To593/// Any extra bytes in buffer before writing the integer are set to zero. To
601/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.594/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
602pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {595pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
603 comptime assert(@sizeOf(u24) == 3);596 assert(buffer.len >= @divExact(T.bit_count, 8));
604 comptime assert(T.bit_count % 8 == 0);
605 assert(buffer.len >= @sizeOf(T));
606597
607 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough598 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
608 const uint = @IntType(false, T.bit_count);599 const uint = @IntType(false, T.bit_count);
...@@ -626,7 +617,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) {...@@ -626,7 +617,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) {
626};617};
627618
628/// Writes a twos-complement integer to memory, with the specified endianness.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/// The bit count of T must be evenly divisible by 8.621/// The bit count of T must be evenly divisible by 8.
631/// Any extra bytes in buffer not part of the integer are set to zero, with622/// Any extra bytes in buffer not part of the integer are set to zero, with
632/// respect to endianness. To avoid the branch to check for extra buffer bytes,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,13 +463,16 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
463 builtin.TypeId.Pointer => {463 builtin.TypeId.Pointer => {
464 const info = @typeInfo(T).Pointer;464 const info = @typeInfo(T).Pointer;
465 switch (info.size) {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 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,470 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
468 }471 }
469 },472 },
470 builtin.TypeId.Optional => {473 builtin.TypeId.Optional => {
471 if(a == null and b == null) return true;474 if (a == null and b == null) return true;
472 if(a == null or b == null) return false;475 if (a == null or b == null) return false;
473 return eql(a.?, b.?);476 return eql(a.?, b.?);
474 },477 },
475 else => return a == b,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,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
665665
666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
667 const ptr_result = c.mmap(667 const ptr_result = c.mmap(
668 @ptrCast(*c_void, address),668 @ptrCast(?*c_void, address),
669 length,669 length,
670 @bitCast(c_int, @intCast(c_uint, prot)),670 @bitCast(c_int, @intCast(c_uint, prot)),
671 @bitCast(c_int, c_uint(flags)),671 @bitCast(c_int, c_uint(flags)),
std/os/file.zig+4-4
...@@ -105,7 +105,7 @@ pub const File = struct {...@@ -105,7 +105,7 @@ pub const File = struct {
105 pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {105 pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
106 if (is_posix) {106 if (is_posix) {
107 const path_c = try os.toPosixPath(path);107 const path_c = try os.toPosixPath(path);
108 return openWriteNoClobberC(path_c, file_mode);108 return openWriteNoClobberC(&path_c, file_mode);
109 } else if (is_windows) {109 } else if (is_windows) {
110 const path_w = try windows_util.sliceToPrefixedFileW(path);110 const path_w = try windows_util.sliceToPrefixedFileW(path);
111 return openWriteNoClobberW(&path_w, file_mode);111 return openWriteNoClobberW(&path_w, file_mode);
...@@ -237,7 +237,7 @@ pub const File = struct {...@@ -237,7 +237,7 @@ pub const File = struct {
237237
238 pub fn seekForward(self: File, amount: isize) SeekError!void {238 pub fn seekForward(self: File, amount: isize) SeekError!void {
239 switch (builtin.os) {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 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);241 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
242 const err = posix.getErrno(result);242 const err = posix.getErrno(result);
243 if (err > 0) {243 if (err > 0) {
...@@ -268,7 +268,7 @@ pub const File = struct {...@@ -268,7 +268,7 @@ pub const File = struct {
268268
269 pub fn seekTo(self: File, pos: usize) SeekError!void {269 pub fn seekTo(self: File, pos: usize) SeekError!void {
270 switch (builtin.os) {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 const ipos = try math.cast(isize, pos);272 const ipos = try math.cast(isize, pos);
273 const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);273 const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);
274 const err = posix.getErrno(result);274 const err = posix.getErrno(result);
...@@ -309,7 +309,7 @@ pub const File = struct {...@@ -309,7 +309,7 @@ pub const File = struct {
309309
310 pub fn getPos(self: File) GetSeekPosError!usize {310 pub fn getPos(self: File) GetSeekPosError!usize {
311 switch (builtin.os) {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 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);313 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
314 const err = posix.getErrno(result);314 const err = posix.getErrno(result);
315 if (err > 0) {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,7 +617,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
617617
618pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {618pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
619 const ptr_result = c.mmap(619 const ptr_result = c.mmap(
620 @ptrCast(*c_void, address),620 @ptrCast(?*c_void, address),
621 length,621 length,
622 @bitCast(c_int, @intCast(c_uint, prot)),622 @bitCast(c_int, @intCast(c_uint, prot)),
623 @bitCast(c_int, c_uint(flags)),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,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
43 };43 };
44 return os.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname });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 const home_dir = os.getEnvPosix("HOME") orelse {47 const home_dir = os.getEnvPosix("HOME") orelse {
48 // TODO look in /etc/passwd48 // TODO look in /etc/passwd
49 return error.AppDataDirUnavailable;49 return error.AppDataDirUnavailable;
std/os/get_user_id.zig+1-1
...@@ -11,7 +11,7 @@ pub const UserInfo = struct {...@@ -11,7 +11,7 @@ pub const UserInfo = struct {
11/// POSIX function which gets a uid from username.11/// POSIX function which gets a uid from username.
12pub fn getUserInfo(name: []const u8) !UserInfo {12pub fn getUserInfo(name: []const u8) !UserInfo {
13 return switch (builtin.os) {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 else => @compileError("Unsupported OS"),15 else => @compileError("Unsupported OS"),
16 };16 };
17}17}
std/os/index.zig+34-16
...@@ -3,7 +3,7 @@ const builtin = @import("builtin");...@@ -3,7 +3,7 @@ const builtin = @import("builtin");
3const Os = builtin.Os;3const Os = builtin.Os;
4const is_windows = builtin.os == Os.windows;4const is_windows = builtin.os == Os.windows;
5const is_posix = switch (builtin.os) {5const 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 else => false,7 else => false,
8};8};
9const os = @This();9const os = @This();
...@@ -30,6 +30,7 @@ pub const windows = @import("windows/index.zig");...@@ -30,6 +30,7 @@ pub const windows = @import("windows/index.zig");
30pub const darwin = @import("darwin.zig");30pub const darwin = @import("darwin.zig");
31pub const linux = @import("linux/index.zig");31pub const linux = @import("linux/index.zig");
32pub const freebsd = @import("freebsd/index.zig");32pub const freebsd = @import("freebsd/index.zig");
33pub const netbsd = @import("netbsd/index.zig");
33pub const zen = @import("zen.zig");34pub const zen = @import("zen.zig");
34pub const uefi = @import("uefi.zig");35pub const uefi = @import("uefi.zig");
3536
...@@ -37,6 +38,7 @@ pub const posix = switch (builtin.os) {...@@ -37,6 +38,7 @@ pub const posix = switch (builtin.os) {
37 Os.linux => linux,38 Os.linux => linux,
38 Os.macosx, Os.ios => darwin,39 Os.macosx, Os.ios => darwin,
39 Os.freebsd => freebsd,40 Os.freebsd => freebsd,
41 Os.netbsd => netbsd,
40 Os.zen => zen,42 Os.zen => zen,
41 else => @compileError("Unsupported OS"),43 else => @compileError("Unsupported OS"),
42};44};
...@@ -50,7 +52,7 @@ pub const time = @import("time.zig");...@@ -50,7 +52,7 @@ pub const time = @import("time.zig");
5052
51pub const page_size = 4 * 1024;53pub const page_size = 4 * 1024;
52pub const MAX_PATH_BYTES = switch (builtin.os) {54pub 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 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.56 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
55 // If it would require 4 UTF-8 bytes, then there would be a surrogate57 // If it would require 4 UTF-8 bytes, then there would be a surrogate
56 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.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,7 +127,7 @@ pub fn getRandomBytes(buf: []u8) !void {
125 else => return unexpectedErrorPosix(errno),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 Os.windows => {131 Os.windows => {
130 // Call RtlGenRandom() instead of CryptGetRandom() on Windows132 // Call RtlGenRandom() instead of CryptGetRandom() on Windows
131 // https://github.com/rust-lang-nursery/rand/issues/111133 // https://github.com/rust-lang-nursery/rand/issues/111
...@@ -185,7 +187,7 @@ pub fn abort() noreturn {...@@ -185,7 +187,7 @@ pub fn abort() noreturn {
185 c.abort();187 c.abort();
186 }188 }
187 switch (builtin.os) {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 _ = posix.raise(posix.SIGABRT);191 _ = posix.raise(posix.SIGABRT);
190 _ = posix.raise(posix.SIGKILL);192 _ = posix.raise(posix.SIGKILL);
191 while (true) {}193 while (true) {}
...@@ -211,7 +213,7 @@ pub fn exit(status: u8) noreturn {...@@ -211,7 +213,7 @@ pub fn exit(status: u8) noreturn {
211 c.exit(status);213 c.exit(status);
212 }214 }
213 switch (builtin.os) {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 posix.exit(status);217 posix.exit(status);
216 },218 },
217 Os.windows => {219 Os.windows => {
...@@ -327,7 +329,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6...@@ -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 const rc = posix.preadv(fd, iov, count, offset);333 const rc = posix.preadv(fd, iov, count, offset);
332 const err = posix.getErrno(rc);334 const err = posix.getErrno(rc);
333 switch (err) {335 switch (err) {
...@@ -434,7 +436,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off...@@ -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 const rc = posix.pwritev(fd, iov, count, offset);440 const rc = posix.pwritev(fd, iov, count, offset);
439 const err = posix.getErrno(rc);441 const err = posix.getErrno(rc);
440 switch (err) {442 switch (err) {
...@@ -699,7 +701,9 @@ pub fn getBaseAddress() usize {...@@ -699,7 +701,9 @@ pub fn getBaseAddress() usize {
699 const phdr = linuxGetAuxVal(std.elf.AT_PHDR);701 const phdr = linuxGetAuxVal(std.elf.AT_PHDR);
700 return phdr - @sizeOf(std.elf.Ehdr);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 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),707 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
704 else => @compileError("Unsupported OS"),708 else => @compileError("Unsupported OS"),
705 }709 }
...@@ -1339,7 +1343,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {...@@ -1339,7 +1343,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
1339 const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);1343 const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);
1340 return deleteDirW(&dir_path_w);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 const err = posix.getErrno(posix.rmdir(dir_path));1347 const err = posix.getErrno(posix.rmdir(dir_path));
1344 switch (err) {1348 switch (err) {
1345 0 => return,1349 0 => return,
...@@ -1382,7 +1386,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {...@@ -1382,7 +1386,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
1382 const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);1386 const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);
1383 return deleteDirW(&dir_path_w);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 const dir_path_c = try toPosixPath(dir_path);1390 const dir_path_c = try toPosixPath(dir_path);
1387 return deleteDirC(&dir_path_c);1391 return deleteDirC(&dir_path_c);
1388 },1392 },
...@@ -1501,7 +1505,7 @@ pub const Dir = struct {...@@ -1501,7 +1505,7 @@ pub const Dir = struct {
1501 allocator: *Allocator,1505 allocator: *Allocator,
15021506
1503 pub const Handle = switch (builtin.os) {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 fd: i32,1509 fd: i32,
1506 seek: i64,1510 seek: i64,
1507 buf: []u8,1511 buf: []u8,
...@@ -1578,7 +1582,7 @@ pub const Dir = struct {...@@ -1578,7 +1582,7 @@ pub const Dir = struct {
1578 .name_data = undefined,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 .fd = try posixOpen(1586 .fd = try posixOpen(
1583 dir_path,1587 dir_path,
1584 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,1588 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
...@@ -1609,7 +1613,7 @@ pub const Dir = struct {...@@ -1609,7 +1613,7 @@ pub const Dir = struct {
1609 Os.windows => {1613 Os.windows => {
1610 _ = windows.FindClose(self.handle.handle);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 self.allocator.free(self.handle.buf);1617 self.allocator.free(self.handle.buf);
1614 os.close(self.handle.fd);1618 os.close(self.handle.fd);
1615 },1619 },
...@@ -1625,6 +1629,7 @@ pub const Dir = struct {...@@ -1625,6 +1629,7 @@ pub const Dir = struct {
1625 Os.macosx, Os.ios => return self.nextDarwin(),1629 Os.macosx, Os.ios => return self.nextDarwin(),
1626 Os.windows => return self.nextWindows(),1630 Os.windows => return self.nextWindows(),
1627 Os.freebsd => return self.nextFreebsd(),1631 Os.freebsd => return self.nextFreebsd(),
1632 Os.netbsd => return self.nextFreebsd(),
1628 else => @compileError("unimplemented"),1633 else => @compileError("unimplemented"),
1629 }1634 }
1630 }1635 }
...@@ -2256,7 +2261,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {...@@ -2256,7 +2261,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
2256pub fn openSelfExe() !os.File {2261pub fn openSelfExe() !os.File {
2257 switch (builtin.os) {2262 switch (builtin.os) {
2258 Os.linux => return os.File.openReadC(c"/proc/self/exe"),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 var buf: [MAX_PATH_BYTES]u8 = undefined;2265 var buf: [MAX_PATH_BYTES]u8 = undefined;
2261 const self_exe_path = try selfExePath(&buf);2266 const self_exe_path = try selfExePath(&buf);
2262 buf[self_exe_path.len] = 0;2267 buf[self_exe_path.len] = 0;
...@@ -2317,6 +2322,19 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {...@@ -2317,6 +2322,19 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
2317 else => unexpectedErrorPosix(err),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 Os.windows => {2338 Os.windows => {
2321 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;2339 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
2322 const utf16le_slice = try selfExePathW(&utf16le_buf);2340 const utf16le_slice = try selfExePathW(&utf16le_buf);
...@@ -2355,7 +2373,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {...@@ -2355,7 +2373,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
2355 // will not return null.2373 // will not return null.
2356 return path.dirname(full_exe_path).?;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 const self_exe_path = try selfExePath(out_buffer);2377 const self_exe_path = try selfExePath(out_buffer);
2360 // Assume that the OS APIs return absolute paths, and therefore dirname2378 // Assume that the OS APIs return absolute paths, and therefore dirname
2361 // will not return null.2379 // will not return null.
...@@ -3227,7 +3245,7 @@ pub const CpuCountError = error{...@@ -3227,7 +3245,7 @@ pub const CpuCountError = error{
32273245
3228pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {3246pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
3229 switch (builtin.os) {3247 switch (builtin.os) {
3230 builtin.Os.macosx, builtin.Os.freebsd => {3248 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
3231 var count: c_int = undefined;3249 var count: c_int = undefined;
3232 var count_len: usize = @sizeOf(c_int);3250 var count_len: usize = @sizeOf(c_int);
3233 const rc = posix.sysctlbyname(switch (builtin.os) {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,7 +6,7 @@ const vdso = @import("vdso.zig");
6pub use switch (builtin.arch) {6pub use switch (builtin.arch) {
7 builtin.Arch.x86_64 => @import("x86_64.zig"),7 builtin.Arch.x86_64 => @import("x86_64.zig"),
8 builtin.Arch.i386 => @import("i386.zig"),8 builtin.Arch.i386 => @import("i386.zig"),
9 builtin.Arch.aarch64v8 => @import("arm64.zig"),9 builtin.Arch.aarch64 => @import("arm64.zig"),
10 else => @compileError("unsupported arch"),10 else => @compileError("unsupported arch"),
11};11};
12pub use @import("errno.zig");12pub use @import("errno.zig");
std/os/netbsd/errno.zig created+134
...@@ -0,0 +1,134 @@
1pub const EPERM = 1; // Operation not permitted
2pub const ENOENT = 2; // No such file or directory
3pub const ESRCH = 3; // No such process
4pub const EINTR = 4; // Interrupted system call
5pub const EIO = 5; // Input/output error
6pub const ENXIO = 6; // Device not configured
7pub const E2BIG = 7; // Argument list too long
8pub const ENOEXEC = 8; // Exec format error
9pub const EBADF = 9; // Bad file descriptor
10pub const ECHILD = 10; // No child processes
11pub const EDEADLK = 11; // Resource deadlock avoided
12// 11 was EAGAIN
13pub const ENOMEM = 12; // Cannot allocate memory
14pub const EACCES = 13; // Permission denied
15pub const EFAULT = 14; // Bad address
16pub const ENOTBLK = 15; // Block device required
17pub const EBUSY = 16; // Device busy
18pub const EEXIST = 17; // File exists
19pub const EXDEV = 18; // Cross-device link
20pub const ENODEV = 19; // Operation not supported by device
21pub const ENOTDIR = 20; // Not a directory
22pub const EISDIR = 21; // Is a directory
23pub const EINVAL = 22; // Invalid argument
24pub const ENFILE = 23; // Too many open files in system
25pub const EMFILE = 24; // Too many open files
26pub const ENOTTY = 25; // Inappropriate ioctl for device
27pub const ETXTBSY = 26; // Text file busy
28pub const EFBIG = 27; // File too large
29pub const ENOSPC = 28; // No space left on device
30pub const ESPIPE = 29; // Illegal seek
31pub const EROFS = 30; // Read-only file system
32pub const EMLINK = 31; // Too many links
33pub const EPIPE = 32; // Broken pipe
34
35// math software
36pub const EDOM = 33; // Numerical argument out of domain
37pub const ERANGE = 34; // Result too large or too small
38
39// non-blocking and interrupt i/o
40pub const EAGAIN = 35; // Resource temporarily unavailable
41pub const EWOULDBLOCK = EAGAIN; // Operation would block
42pub const EINPROGRESS = 36; // Operation now in progress
43pub const EALREADY = 37; // Operation already in progress
44
45// ipc/network software -- argument errors
46pub const ENOTSOCK = 38; // Socket operation on non-socket
47pub const EDESTADDRREQ = 39; // Destination address required
48pub const EMSGSIZE = 40; // Message too long
49pub const EPROTOTYPE = 41; // Protocol wrong type for socket
50pub const ENOPROTOOPT = 42; // Protocol option not available
51pub const EPROTONOSUPPORT = 43; // Protocol not supported
52pub const ESOCKTNOSUPPORT = 44; // Socket type not supported
53pub const EOPNOTSUPP = 45; // Operation not supported
54pub const EPFNOSUPPORT = 46; // Protocol family not supported
55pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family
56pub const EADDRINUSE = 48; // Address already in use
57pub const EADDRNOTAVAIL = 49; // Can't assign requested address
58
59// ipc/network software -- operational errors
60pub const ENETDOWN = 50; // Network is down
61pub const ENETUNREACH = 51; // Network is unreachable
62pub const ENETRESET = 52; // Network dropped connection on reset
63pub const ECONNABORTED = 53; // Software caused connection abort
64pub const ECONNRESET = 54; // Connection reset by peer
65pub const ENOBUFS = 55; // No buffer space available
66pub const EISCONN = 56; // Socket is already connected
67pub const ENOTCONN = 57; // Socket is not connected
68pub const ESHUTDOWN = 58; // Can't send after socket shutdown
69pub const ETOOMANYREFS = 59; // Too many references: can't splice
70pub const ETIMEDOUT = 60; // Operation timed out
71pub const ECONNREFUSED = 61; // Connection refused
72
73pub const ELOOP = 62; // Too many levels of symbolic links
74pub const ENAMETOOLONG = 63; // File name too long
75
76// should be rearranged
77pub const EHOSTDOWN = 64; // Host is down
78pub const EHOSTUNREACH = 65; // No route to host
79pub const ENOTEMPTY = 66; // Directory not empty
80
81// quotas & mush
82pub const EPROCLIM = 67; // Too many processes
83pub const EUSERS = 68; // Too many users
84pub const EDQUOT = 69; // Disc quota exceeded
85
86// Network File System
87pub const ESTALE = 70; // Stale NFS file handle
88pub const EREMOTE = 71; // Too many levels of remote in path
89pub const EBADRPC = 72; // RPC struct is bad
90pub const ERPCMISMATCH = 73; // RPC version wrong
91pub const EPROGUNAVAIL = 74; // RPC prog. not avail
92pub const EPROGMISMATCH = 75; // Program version wrong
93pub const EPROCUNAVAIL = 76; // Bad procedure for program
94
95pub const ENOLCK = 77; // No locks available
96pub const ENOSYS = 78; // Function not implemented
97
98pub const EFTYPE = 79; // Inappropriate file type or format
99pub const EAUTH = 80; // Authentication error
100pub const ENEEDAUTH = 81; // Need authenticator
101
102// SystemV IPC
103pub const EIDRM = 82; // Identifier removed
104pub const ENOMSG = 83; // No message of desired type
105pub const EOVERFLOW = 84; // Value too large to be stored in data type
106
107// Wide/multibyte-character handling, ISO/IEC 9899/AMD1:1995
108pub const EILSEQ = 85; // Illegal byte sequence
109
110// From IEEE Std 1003.1-2001
111// Base, Realtime, Threads or Thread Priority Scheduling option errors
112pub const ENOTSUP = 86; // Not supported
113
114// Realtime option errors
115pub const ECANCELED = 87; // Operation canceled
116
117// Realtime, XSI STREAMS option errors
118pub const EBADMSG = 88; // Bad or Corrupt message
119
120// XSI STREAMS option errors
121pub const ENODATA = 89; // No message available
122pub const ENOSR = 90; // No STREAM resources
123pub const ENOSTR = 91; // Not a STREAM
124pub const ETIME = 92; // STREAM ioctl timeout
125
126// File system extended attribute errors
127pub const ENOATTR = 93; // Attribute not found
128
129// Realtime, XSI STREAMS option errors
130pub const EMULTIHOP = 94; // Multihop attempted
131pub const ENOLINK = 95; // Link has been severed
132pub const EPROTO = 96; // Protocol error
133
134pub const ELAST = 96; // Must equal largest errno
std/os/netbsd/index.zig created+725
...@@ -0,0 +1,725 @@
1const builtin = @import("builtin");
2
3pub use @import("errno.zig");
4
5const std = @import("../../index.zig");
6const c = std.c;
7
8const assert = std.debug.assert;
9const maxInt = std.math.maxInt;
10pub const Kevent = c.Kevent;
11
12pub const CTL_KERN = 1;
13pub const CTL_DEBUG = 5;
14
15pub const KERN_PROC_ARGS = 48; // struct: process argv/env
16pub const KERN_PROC_PATHNAME = 5; // path to executable
17
18pub const PATH_MAX = 1024;
19
20pub const STDIN_FILENO = 0;
21pub const STDOUT_FILENO = 1;
22pub const STDERR_FILENO = 2;
23
24pub const PROT_NONE = 0;
25pub const PROT_READ = 1;
26pub const PROT_WRITE = 2;
27pub const PROT_EXEC = 4;
28
29pub const CLOCK_REALTIME = 0;
30pub const CLOCK_VIRTUAL = 1;
31pub const CLOCK_PROF = 2;
32pub const CLOCK_MONOTONIC = 3;
33pub const CLOCK_THREAD_CPUTIME_ID = 0x20000000;
34pub const CLOCK_PROCESS_CPUTIME_ID = 0x40000000;
35
36pub const MAP_FAILED = maxInt(usize);
37pub const MAP_SHARED = 0x0001;
38pub const MAP_PRIVATE = 0x0002;
39pub const MAP_REMAPDUP = 0x0004;
40pub const MAP_FIXED = 0x0010;
41pub const MAP_RENAME = 0x0020;
42pub const MAP_NORESERVE = 0x0040;
43pub const MAP_INHERIT = 0x0080;
44pub const MAP_HASSEMAPHORE = 0x0200;
45pub const MAP_TRYFIXED = 0x0400;
46pub const MAP_WIRED = 0x0800;
47
48pub const MAP_FILE = 0x0000;
49pub const MAP_NOSYNC = 0x0800;
50pub const MAP_ANON = 0x1000;
51pub const MAP_ANONYMOUS = MAP_ANON;
52pub const MAP_STACK = 0x2000;
53
54pub const WNOHANG = 0x00000001;
55pub const WUNTRACED = 0x00000002;
56pub const WSTOPPED = WUNTRACED;
57pub const WCONTINUED = 0x00000010;
58pub const WNOWAIT = 0x00010000;
59pub const WEXITED = 0x00000020;
60pub const WTRAPPED = 0x00000040;
61
62pub const SA_ONSTACK = 0x0001;
63pub const SA_RESTART = 0x0002;
64pub const SA_RESETHAND = 0x0004;
65pub const SA_NOCLDSTOP = 0x0008;
66pub const SA_NODEFER = 0x0010;
67pub const SA_NOCLDWAIT = 0x0020;
68pub const SA_SIGINFO = 0x0040;
69
70pub const SIGHUP = 1;
71pub const SIGINT = 2;
72pub const SIGQUIT = 3;
73pub const SIGILL = 4;
74pub const SIGTRAP = 5;
75pub const SIGABRT = 6;
76pub const SIGIOT = SIGABRT;
77pub const SIGEMT = 7;
78pub const SIGFPE = 8;
79pub const SIGKILL = 9;
80pub const SIGBUS = 10;
81pub const SIGSEGV = 11;
82pub const SIGSYS = 12;
83pub const SIGPIPE = 13;
84pub const SIGALRM = 14;
85pub const SIGTERM = 15;
86pub const SIGURG = 16;
87pub const SIGSTOP = 17;
88pub const SIGTSTP = 18;
89pub const SIGCONT = 19;
90pub const SIGCHLD = 20;
91pub const SIGTTIN = 21;
92pub const SIGTTOU = 22;
93pub const SIGIO = 23;
94pub const SIGXCPU = 24;
95pub const SIGXFSZ = 25;
96pub const SIGVTALRM = 26;
97pub const SIGPROF = 27;
98pub const SIGWINCH = 28;
99pub const SIGINFO = 29;
100pub const SIGUSR1 = 30;
101pub const SIGUSR2 = 31;
102pub const SIGPWR = 32;
103
104pub const SIGRTMIN = 33;
105pub const SIGRTMAX = 63;
106
107// access function
108pub const F_OK = 0; // test for existence of file
109pub const X_OK = 1; // test for execute or search permission
110pub const W_OK = 2; // test for write permission
111pub const R_OK = 4; // test for read permission
112
113
114pub const O_RDONLY = 0x0000;
115pub const O_WRONLY = 0x0001;
116pub const O_RDWR = 0x0002;
117pub const O_ACCMODE = 0x0003;
118
119pub const O_CREAT = 0x0200;
120pub const O_EXCL = 0x0800;
121pub const O_NOCTTY = 0x8000;
122pub const O_TRUNC = 0x0400;
123pub const O_APPEND = 0x0008;
124pub const O_NONBLOCK = 0x0004;
125pub const O_DSYNC = 0x00010000;
126pub const O_SYNC = 0x0080;
127pub const O_RSYNC = 0x00020000;
128pub const O_DIRECTORY = 0x00080000;
129pub const O_NOFOLLOW = 0x00000100;
130pub const O_CLOEXEC = 0x00400000;
131
132pub const O_ASYNC = 0x0040;
133pub const O_DIRECT = 0x00080000;
134pub const O_LARGEFILE = 0;
135pub const O_NOATIME = 0;
136pub const O_PATH = 0;
137pub const O_TMPFILE = 0;
138pub const O_NDELAY = O_NONBLOCK;
139
140pub const F_DUPFD = 0;
141pub const F_GETFD = 1;
142pub const F_SETFD = 2;
143pub const F_GETFL = 3;
144pub const F_SETFL = 4;
145
146pub const F_GETOWN = 5;
147pub const F_SETOWN = 6;
148
149pub const F_GETLK = 7;
150pub const F_SETLK = 8;
151pub const F_SETLKW = 9;
152
153pub const SEEK_SET = 0;
154pub const SEEK_CUR = 1;
155pub const SEEK_END = 2;
156
157pub const SIG_BLOCK = 1;
158pub const SIG_UNBLOCK = 2;
159pub const SIG_SETMASK = 3;
160
161pub const SOCK_STREAM = 1;
162pub const SOCK_DGRAM = 2;
163pub const SOCK_RAW = 3;
164pub const SOCK_RDM = 4;
165pub const SOCK_SEQPACKET = 5;
166
167pub const SOCK_CLOEXEC = 0x10000000;
168pub const SOCK_NONBLOCK = 0x20000000;
169
170pub const PROTO_ip = 0;
171pub const PROTO_icmp = 1;
172pub const PROTO_igmp = 2;
173pub const PROTO_ggp = 3;
174pub const PROTO_ipencap = 4;
175pub const PROTO_tcp = 6;
176pub const PROTO_egp = 8;
177pub const PROTO_pup = 12;
178pub const PROTO_udp = 17;
179pub const PROTO_xns_idp = 22;
180pub const PROTO_iso_tp4 = 29;
181pub const PROTO_ipv6 = 41;
182pub const PROTO_ipv6_route = 43;
183pub const PROTO_ipv6_frag = 44;
184pub const PROTO_rsvp = 46;
185pub const PROTO_gre = 47;
186pub const PROTO_esp = 50;
187pub const PROTO_ah = 51;
188pub const PROTO_ipv6_icmp = 58;
189pub const PROTO_ipv6_nonxt = 59;
190pub const PROTO_ipv6_opts = 60;
191pub const PROTO_encap = 98;
192pub const PROTO_pim = 103;
193pub const PROTO_raw = 255;
194
195pub const PF_UNSPEC = 0;
196pub const PF_LOCAL = 1;
197pub const PF_UNIX = PF_LOCAL;
198pub const PF_FILE = PF_LOCAL;
199pub const PF_INET = 2;
200pub const PF_APPLETALK = 16;
201pub const PF_INET6 = 24;
202pub const PF_DECnet = 12;
203pub const PF_KEY = 29;
204pub const PF_ROUTE = 34;
205pub const PF_SNA = 11;
206pub const PF_MPLS = 33;
207pub const PF_CAN = 35;
208pub const PF_BLUETOOTH = 31;
209pub const PF_ISDN = 26;
210pub const PF_MAX = 37;
211
212pub const AF_UNSPEC = PF_UNSPEC;
213pub const AF_LOCAL = PF_LOCAL;
214pub const AF_UNIX = AF_LOCAL;
215pub const AF_FILE = AF_LOCAL;
216pub const AF_INET = PF_INET;
217pub const AF_APPLETALK = PF_APPLETALK;
218pub const AF_INET6 = PF_INET6;
219pub const AF_KEY = PF_KEY;
220pub const AF_ROUTE = PF_ROUTE;
221pub const AF_SNA = PF_SNA;
222pub const AF_MPLS = PF_MPLS;
223pub const AF_CAN = PF_CAN;
224pub const AF_BLUETOOTH = PF_BLUETOOTH;
225pub const AF_ISDN = PF_ISDN;
226pub const AF_MAX = PF_MAX;
227
228pub const DT_UNKNOWN = 0;
229pub const DT_FIFO = 1;
230pub const DT_CHR = 2;
231pub const DT_DIR = 4;
232pub const DT_BLK = 6;
233pub const DT_REG = 8;
234pub const DT_LNK = 10;
235pub const DT_SOCK = 12;
236pub const DT_WHT = 14;
237
238/// add event to kq (implies enable)
239pub const EV_ADD = 0x0001;
240
241/// delete event from kq
242pub const EV_DELETE = 0x0002;
243
244/// enable event
245pub const EV_ENABLE = 0x0004;
246
247/// disable event (not reported)
248pub const EV_DISABLE = 0x0008;
249
250/// only report one occurrence
251pub const EV_ONESHOT = 0x0010;
252
253/// clear event state after reporting
254pub 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
260pub const EV_RECEIPT = 0x0040;
261
262/// disable event after reporting
263pub const EV_DISPATCH = 0x0080;
264
265pub const EVFILT_READ = 0;
266pub const EVFILT_WRITE = 1;
267
268/// attached to aio requests
269pub const EVFILT_AIO = 2;
270
271/// attached to vnodes
272pub const EVFILT_VNODE = 3;
273
274/// attached to struct proc
275pub const EVFILT_PROC = 4;
276
277/// attached to struct proc
278pub const EVFILT_SIGNAL = 5;
279
280/// timers
281pub const EVFILT_TIMER = 6;
282
283/// Filesystem events
284pub const EVFILT_FS = 7;
285
286/// On input, NOTE_TRIGGER causes the event to be triggered for output.
287pub const NOTE_TRIGGER = 0x08000000;
288
289/// low water mark
290pub const NOTE_LOWAT = 0x00000001;
291
292/// vnode was removed
293pub const NOTE_DELETE = 0x00000001;
294
295/// data contents changed
296pub const NOTE_WRITE = 0x00000002;
297
298/// size increased
299pub const NOTE_EXTEND = 0x00000004;
300
301/// attributes changed
302pub const NOTE_ATTRIB = 0x00000008;
303
304/// link count changed
305pub const NOTE_LINK = 0x00000010;
306
307/// vnode was renamed
308pub const NOTE_RENAME = 0x00000020;
309
310/// vnode access was revoked
311pub const NOTE_REVOKE = 0x00000040;
312
313/// process exited
314pub const NOTE_EXIT = 0x80000000;
315
316/// process forked
317pub const NOTE_FORK = 0x40000000;
318
319/// process exec'd
320pub const NOTE_EXEC = 0x20000000;
321
322/// mask for signal & exit status
323pub const NOTE_PDATAMASK = 0x000fffff;
324pub const NOTE_PCTRLMASK = 0xf0000000;
325
326pub const TIOCCBRK = 0x2000747a;
327pub const TIOCCDTR = 0x20007478;
328pub const TIOCCONS = 0x80047462;
329pub const TIOCDCDTIMESTAMP = 0x40107458;
330pub const TIOCDRAIN = 0x2000745e;
331pub const TIOCEXCL = 0x2000740d;
332pub const TIOCEXT = 0x80047460;
333pub const TIOCFLAG_CDTRCTS = 0x10;
334pub const TIOCFLAG_CLOCAL = 0x2;
335pub const TIOCFLAG_CRTSCTS = 0x4;
336pub const TIOCFLAG_MDMBUF = 0x8;
337pub const TIOCFLAG_SOFTCAR = 0x1;
338pub const TIOCFLUSH = 0x80047410;
339pub const TIOCGETA = 0x402c7413;
340pub const TIOCGETD = 0x4004741a;
341pub const TIOCGFLAGS = 0x4004745d;
342pub const TIOCGLINED = 0x40207442;
343pub const TIOCGPGRP = 0x40047477;
344pub const TIOCGQSIZE = 0x40047481;
345pub const TIOCGRANTPT = 0x20007447;
346pub const TIOCGSID = 0x40047463;
347pub const TIOCGSIZE = 0x40087468;
348pub const TIOCGWINSZ = 0x40087468;
349pub const TIOCMBIC = 0x8004746b;
350pub const TIOCMBIS = 0x8004746c;
351pub const TIOCMGET = 0x4004746a;
352pub const TIOCMSET = 0x8004746d;
353pub const TIOCM_CAR = 0x40;
354pub const TIOCM_CD = 0x40;
355pub const TIOCM_CTS = 0x20;
356pub const TIOCM_DSR = 0x100;
357pub const TIOCM_DTR = 0x2;
358pub const TIOCM_LE = 0x1;
359pub const TIOCM_RI = 0x80;
360pub const TIOCM_RNG = 0x80;
361pub const TIOCM_RTS = 0x4;
362pub const TIOCM_SR = 0x10;
363pub const TIOCM_ST = 0x8;
364pub const TIOCNOTTY = 0x20007471;
365pub const TIOCNXCL = 0x2000740e;
366pub const TIOCOUTQ = 0x40047473;
367pub const TIOCPKT = 0x80047470;
368pub const TIOCPKT_DATA = 0x0;
369pub const TIOCPKT_DOSTOP = 0x20;
370pub const TIOCPKT_FLUSHREAD = 0x1;
371pub const TIOCPKT_FLUSHWRITE = 0x2;
372pub const TIOCPKT_IOCTL = 0x40;
373pub const TIOCPKT_NOSTOP = 0x10;
374pub const TIOCPKT_START = 0x8;
375pub const TIOCPKT_STOP = 0x4;
376pub const TIOCPTMGET = 0x40287446;
377pub const TIOCPTSNAME = 0x40287448;
378pub const TIOCRCVFRAME = 0x80087445;
379pub const TIOCREMOTE = 0x80047469;
380pub const TIOCSBRK = 0x2000747b;
381pub const TIOCSCTTY = 0x20007461;
382pub const TIOCSDTR = 0x20007479;
383pub const TIOCSETA = 0x802c7414;
384pub const TIOCSETAF = 0x802c7416;
385pub const TIOCSETAW = 0x802c7415;
386pub const TIOCSETD = 0x8004741b;
387pub const TIOCSFLAGS = 0x8004745c;
388pub const TIOCSIG = 0x2000745f;
389pub const TIOCSLINED = 0x80207443;
390pub const TIOCSPGRP = 0x80047476;
391pub const TIOCSQSIZE = 0x80047480;
392pub const TIOCSSIZE = 0x80087467;
393pub const TIOCSTART = 0x2000746e;
394pub const TIOCSTAT = 0x80047465;
395pub const TIOCSTI = 0x80017472;
396pub const TIOCSTOP = 0x2000746f;
397pub const TIOCSWINSZ = 0x80087467;
398pub const TIOCUCNTL = 0x80047466;
399pub const TIOCXMTFRAME = 0x80087444;
400
401pub const sockaddr = c.sockaddr;
402pub const sockaddr_in = c.sockaddr_in;
403pub const sockaddr_in6 = c.sockaddr_in6;
404
405fn unsigned(s: i32) u32 {
406 return @bitCast(u32, s);
407}
408fn signed(s: u32) i32 {
409 return @bitCast(i32, s);
410}
411pub fn WEXITSTATUS(s: i32) i32 {
412 return signed((unsigned(s) >> 8) & 0xff);
413}
414pub fn WTERMSIG(s: i32) i32 {
415 return signed(unsigned(s) & 0x7f);
416}
417pub fn WSTOPSIG(s: i32) i32 {
418 return WEXITSTATUS(s);
419}
420pub fn WIFEXITED(s: i32) bool {
421 return WTERMSIG(s) == 0;
422}
423
424pub fn WIFCONTINUED(s: i32) bool {
425 return ((s & 0x7f) == 0xffff);
426}
427
428pub fn WIFSTOPPED(s: i32) bool {
429 return ((s & 0x7f != 0x7f) and !WIFCONTINUED(s));
430}
431
432pub fn WIFSIGNALED(s: i32) bool {
433 return !WIFSTOPPED(s) and !WIFCONTINUED(s) and !WIFEXITED(s);
434}
435
436pub 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.
444pub 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
449pub fn dup2(old: i32, new: i32) usize {
450 return errnoWrap(c.dup2(old, new));
451}
452
453pub fn chdir(path: [*]const u8) usize {
454 return errnoWrap(c.chdir(path));
455}
456
457pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
458 return errnoWrap(c.execve(path, argv, envp));
459}
460
461pub fn fork() usize {
462 return errnoWrap(c.fork());
463}
464
465pub fn access(path: [*]const u8, mode: u32) usize {
466 return errnoWrap(c.access(path, mode));
467}
468
469pub fn getcwd(buf: [*]u8, size: usize) usize {
470 return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
471}
472
473pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
474 return errnoWrap(@bitCast(isize, c.getdents(fd, drip, count)));
475}
476
477pub 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
481pub 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
485pub fn isatty(fd: i32) bool {
486 return c.isatty(fd) != 0;
487}
488
489pub 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
493pub fn mkdir(path: [*]const u8, mode: u32) usize {
494 return errnoWrap(c.mkdir(path, mode));
495}
496
497pub 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
510pub fn munmap(address: usize, length: usize) usize {
511 return errnoWrap(c.munmap(@intToPtr(*c_void, address), length));
512}
513
514pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
515 return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte));
516}
517
518pub fn rmdir(path: [*]const u8) usize {
519 return errnoWrap(c.rmdir(path));
520}
521
522pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
523 return errnoWrap(c.symlink(existing, new));
524}
525
526pub 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
530pub 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
534pub fn pipe(fd: *[2]i32) usize {
535 return pipe2(fd, 0);
536}
537
538pub 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
543pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
544 return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte));
545}
546
547pub 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
551pub 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
555pub fn rename(old: [*]const u8, new: [*]const u8) usize {
556 return errnoWrap(c.rename(old, new));
557}
558
559pub fn open(path: [*]const u8, flags: u32, mode: usize) usize {
560 return errnoWrap(c.open(path, @bitCast(c_int, flags), mode));
561}
562
563pub fn create(path: [*]const u8, perm: usize) usize {
564 return arch.syscall2(SYS_creat, @ptrToInt(path), perm);
565}
566
567pub 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
571pub fn close(fd: i32) usize {
572 return errnoWrap(c.close(fd));
573}
574
575pub fn lseek(fd: i32, offset: isize, whence: c_int) usize {
576 return errnoWrap(c.lseek(fd, offset, whence));
577}
578
579pub fn exit(code: i32) noreturn {
580 c.exit(code);
581}
582
583pub fn kill(pid: i32, sig: i32) usize {
584 return errnoWrap(c.kill(pid, sig));
585}
586
587pub fn unlink(path: [*]const u8) usize {
588 return errnoWrap(c.unlink(path));
589}
590
591pub 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
596pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
597 return errnoWrap(c.nanosleep(req, rem));
598}
599
600pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
601 return errnoWrap(c.clock_gettime(clk_id, tp));
602}
603
604pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
605 return errnoWrap(c.clock_getres(clk_id, tp));
606}
607
608pub fn setuid(uid: u32) usize {
609 return errnoWrap(c.setuid(uid));
610}
611
612pub fn setgid(gid: u32) usize {
613 return errnoWrap(c.setgid(gid));
614}
615
616pub fn setreuid(ruid: u32, euid: u32) usize {
617 return errnoWrap(c.setreuid(ruid, euid));
618}
619
620pub fn setregid(rgid: u32, egid: u32) usize {
621 return errnoWrap(c.setregid(rgid, egid));
622}
623
624const NSIG = 32;
625
626pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
627pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
628pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
629
630/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
631pub 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
645pub const _SIG_WORDS = 4;
646pub const _SIG_MAXSIG = 128;
647
648pub inline fn _SIG_IDX(sig: usize) usize {
649 return sig - 1;
650}
651pub inline fn _SIG_WORD(sig: usize) usize {
652 return_SIG_IDX(sig) >> 5;
653}
654pub inline fn _SIG_BIT(sig: usize) usize {
655 return 1 << (_SIG_IDX(sig) & 31);
656}
657pub inline fn _SIG_VALID(sig: usize) usize {
658 return sig <= _SIG_MAXSIG and sig > 0;
659}
660
661pub const sigset_t = extern struct {
662 __bits: [_SIG_WORDS]u32,
663};
664
665pub fn raise(sig: i32) usize {
666 return errnoWrap(c.raise(sig));
667}
668
669pub const Stat = c.Stat;
670pub const dirent = c.dirent;
671pub const timespec = c.timespec;
672
673pub fn fstat(fd: i32, buf: *c.Stat) usize {
674 return errnoWrap(c.fstat(fd, buf));
675}
676pub const iovec = extern struct {
677 iov_base: [*]u8,
678 iov_len: usize,
679};
680
681pub const iovec_const = extern struct {
682 iov_base: [*]const u8,
683 iov_len: usize,
684};
685
686// TODO avoid libc dependency
687pub fn kqueue() usize {
688 return errnoWrap(c.kqueue());
689}
690
691// TODO avoid libc dependency
692pub 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
704pub 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
709pub 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
714pub 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.
723fn 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,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
1226 const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);1226 const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);
1227 return realW(out_buffer, pathname_w);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 // TODO instead of calling the libc function here, port the implementation to Zig1230 // TODO instead of calling the libc function here, port the implementation to Zig
1231 const err = posix.getErrno(posix.realpath(pathname, out_buffer));1231 const err = posix.getErrno(posix.realpath(pathname, out_buffer));
1232 switch (err) {1232 switch (err) {
...@@ -1267,7 +1267,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!...@@ -1267,7 +1267,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!
1267 const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);1267 const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);
1268 return realW(out_buffer, &pathname_w);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 const pathname_c = try os.toPosixPath(pathname);1271 const pathname_c = try os.toPosixPath(pathname);
1272 return realC(out_buffer, &pathname_c);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,7 +14,7 @@ pub const epoch = @import("epoch.zig");
14/// Sleep for the specified duration14/// Sleep for the specified duration
15pub fn sleep(nanoseconds: u64) void {15pub fn sleep(nanoseconds: u64) void {
16 switch (builtin.os) {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 const s = nanoseconds / ns_per_s;18 const s = nanoseconds / ns_per_s;
19 const ns = nanoseconds % ns_per_s;19 const ns = nanoseconds % ns_per_s;
20 posixSleep(@intCast(u63, s), @intCast(u63, ns));20 posixSleep(@intCast(u63, s), @intCast(u63, ns));
...@@ -62,7 +62,7 @@ pub fn timestamp() u64 {...@@ -62,7 +62,7 @@ pub fn timestamp() u64 {
62/// Get the posix timestamp, UTC, in milliseconds62/// Get the posix timestamp, UTC, in milliseconds
63pub const milliTimestamp = switch (builtin.os) {63pub const milliTimestamp = switch (builtin.os) {
64 Os.windows => milliTimestampWindows,64 Os.windows => milliTimestampWindows,
65 Os.linux, Os.freebsd => milliTimestampPosix,65 Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
66 Os.macosx, Os.ios => milliTimestampDarwin,66 Os.macosx, Os.ios => milliTimestampDarwin,
67 else => @compileError("Unsupported OS"),67 else => @compileError("Unsupported OS"),
68};68};
...@@ -178,7 +178,7 @@ pub const Timer = struct {...@@ -178,7 +178,7 @@ pub const Timer = struct {
178 debug.assert(err != windows.FALSE);178 debug.assert(err != windows.FALSE);
179 self.start_time = @intCast(u64, start_time);179 self.start_time = @intCast(u64, start_time);
180 },180 },
181 Os.linux, Os.freebsd => {181 Os.linux, Os.freebsd, Os.netbsd => {
182 //On Linux, seccomp can do arbitrary things to our ability to call182 //On Linux, seccomp can do arbitrary things to our ability to call
183 // syscalls, including return any errno value it wants and183 // syscalls, including return any errno value it wants and
184 // inconsistently throwing errors. Since we can't account for184 // inconsistently throwing errors. Since we can't account for
...@@ -214,7 +214,7 @@ pub const Timer = struct {...@@ -214,7 +214,7 @@ pub const Timer = struct {
214 var clock = clockNative() - self.start_time;214 var clock = clockNative() - self.start_time;
215 return switch (builtin.os) {215 return switch (builtin.os) {
216 Os.windows => @divFloor(clock * ns_per_s, self.frequency),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 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),218 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
219 else => @compileError("Unsupported OS"),219 else => @compileError("Unsupported OS"),
220 };220 };
...@@ -235,7 +235,7 @@ pub const Timer = struct {...@@ -235,7 +235,7 @@ pub const Timer = struct {
235235
236 const clockNative = switch (builtin.os) {236 const clockNative = switch (builtin.os) {
237 Os.windows => clockWindows,237 Os.windows => clockWindows,
238 Os.linux, Os.freebsd => clockLinux,238 Os.linux, Os.freebsd, Os.netbsd => clockLinux,
239 Os.macosx, Os.ios => clockDarwin,239 Os.macosx, Os.ios => clockDarwin,
240 else => @compileError("Unsupported OS"),240 else => @compileError("Unsupported OS"),
241 };241 };
std/priority_queue.zig created+331
...@@ -0,0 +1,331 @@
1const std = @import("index.zig");
2const Allocator = std.mem.Allocator;
3const debug = std.debug;
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6
7pub 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
170fn lessThan(a: u32, b: u32) bool {
171 return a < b;
172}
173
174fn greaterThan(a: u32, b: u32) bool {
175 return a > b;
176}
177
178const PQ = PriorityQueue(u32);
179
180test "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
198test "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
216test "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
223test "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
235test "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
247test "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
275test "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
293test "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
311test "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,15 +23,15 @@ nakedcc fn _start() noreturn {
23 switch (builtin.arch) {23 switch (builtin.arch) {
24 builtin.Arch.x86_64 => {24 builtin.Arch.x86_64 => {
25 argc_ptr = asm ("lea (%%rsp), %[argc]"25 argc_ptr = asm ("lea (%%rsp), %[argc]"
26 : [argc] "=r" (-> [*]usize)26 : [argc] "=r" (-> [*]usize)
27 );27 );
28 },28 },
29 builtin.Arch.i386 => {29 builtin.Arch.i386 => {
30 argc_ptr = asm ("lea (%%esp), %[argc]"30 argc_ptr = asm ("lea (%%esp), %[argc]"
31 : [argc] "=r" (-> [*]usize)31 : [argc] "=r" (-> [*]usize)
32 );32 );
33 },33 },
34 builtin.Arch.aarch64v8 => {34 builtin.Arch.aarch64, builtin.Arch.aarch64_be => {
35 argc_ptr = asm ("mov %[argc], sp"35 argc_ptr = asm ("mov %[argc], sp"
36 : [argc] "=r" (-> [*]usize)36 : [argc] "=r" (-> [*]usize)
37 );37 );
...@@ -123,7 +123,7 @@ inline fn callMain() u8 {...@@ -123,7 +123,7 @@ inline fn callMain() u8 {
123 std.debug.warn("error: {}\n", @errorName(err));123 std.debug.warn("error: {}\n", @errorName(err));
124 if (builtin.os != builtin.Os.zen) {124 if (builtin.os != builtin.Os.zen) {
125 if (@errorReturnTrace()) |trace| {125 if (@errorReturnTrace()) |trace| {
126 std.debug.dumpStackTrace(trace);126 std.debug.dumpStackTrace(trace.*);
127 }127 }
128 }128 }
129 return 1;129 return 1;
...@@ -142,7 +142,10 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent:...@@ -142,7 +142,10 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent:
142 var phdr_addr = at_phdr;142 var phdr_addr = at_phdr;
143 var n = at_phnum;143 var n = at_phnum;
144 var base: usize = 0;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 const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);149 const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);
147 // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917150 // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
148 switch (phdr.p_type) {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
5const std = @import("std");
6const builtin = @import("builtin");
7const compiler_rt = @import("index.zig");
8
9pub extern fn __addtf3(a: f128, b: f128) f128 {
10 return addXf3(f128, a, b);
11}
12
13pub 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
18inline 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
28inline 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
189test "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
6const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64);
7const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64);
8
9const __addtf3 = @import("addXf3.zig").__addtf3;
10
11fn 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
33test "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
49const __subtf3 = @import("addXf3.zig").__subtf3;
50
51fn 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
73test "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,6 +21,9 @@ comptime {
2121
22 @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage);22 @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage);
2323
24 @export("__addtf3", @import("addXf3.zig").__addtf3, linkage);
25 @export("__subtf3", @import("addXf3.zig").__subtf3, linkage);
26
24 @export("__floattitf", @import("floattitf.zig").__floattitf, linkage);27 @export("__floattitf", @import("floattitf.zig").__floattitf, linkage);
25 @export("__floattidf", @import("floattidf.zig").__floattidf, linkage);28 @export("__floattidf", @import("floattidf.zig").__floattidf, linkage);
26 @export("__floattisf", @import("floattisf.zig").__floattisf, linkage);29 @export("__floattisf", @import("floattisf.zig").__floattisf, linkage);
...@@ -37,6 +40,7 @@ comptime {...@@ -37,6 +40,7 @@ comptime {
37 @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);40 @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);
3841
39 @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);42 @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);
43 @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage);
40 @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);44 @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);
41 @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);45 @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);
4246
...@@ -180,60 +184,10 @@ const is_arm_64 = switch (builtin.arch) {...@@ -180,60 +184,10 @@ const is_arm_64 = switch (builtin.arch) {
180};184};
181185
182const is_arm_arch = switch (builtin.arch) {186const is_arm_arch = switch (builtin.arch) {
183 builtin.Arch.armv8_3a,187 builtin.Arch.arm,
184 builtin.Arch.armv8_2a,188 builtin.Arch.armeb,
185 builtin.Arch.armv8_1a,189 builtin.Arch.aarch64,
186 builtin.Arch.armv8,190 builtin.Arch.aarch64_be,
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,
237 builtin.Arch.thumb,191 builtin.Arch.thumb,
238 builtin.Arch.thumbeb,192 builtin.Arch.thumbeb,
239 => true,193 => true,
std/special/compiler_rt/truncXfYf2.zig+4
...@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {...@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {
4 return @bitCast(u16, truncXfYf2(f16, f32, a));4 return @bitCast(u16, truncXfYf2(f16, f32, a));
5}5}
66
7pub extern fn __truncdfhf2(a: f64) u16 {
8 return @bitCast(u16, truncXfYf2(f16, f64, a));
9}
10
7pub extern fn __trunctfsf2(a: f128) f32 {11pub extern fn __trunctfsf2(a: f128) f32 {
8 return truncXfYf2(f32, f128, a);12 return truncXfYf2(f32, f128, a);
9}13}
std/special/compiler_rt/truncXfYf2_test.zig+68
...@@ -63,6 +63,74 @@ test "truncsfhf2" {...@@ -63,6 +63,74 @@ test "truncsfhf2" {
63 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero63 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
64}64}
6565
66const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2;
67
68fn 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
84fn 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
94test "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
66const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;134const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
67135
68fn test__trunctfsf2(a: f128, expected: u32) void {136fn test__trunctfsf2(a: f128, expected: u32) void {
std/special/fmt_runner.zig created+260
...@@ -0,0 +1,260 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4const os = std.os;
5const io = std.io;
6const mem = std.mem;
7const Allocator = mem.Allocator;
8const ArrayList = std.ArrayList;
9const Buffer = std.Buffer;
10const ast = std.zig.ast;
11
12const arg = @import("fmt/arg.zig");
13const self_hosted_main = @import("fmt/main.zig");
14const Args = arg.Args;
15const Flag = arg.Flag;
16const errmsg = @import("fmt/errmsg.zig");
17
18var stderr_file: os.File = undefined;
19var stderr: *io.OutStream(os.File.WriteError) = undefined;
20var stdout: *io.OutStream(os.File.WriteError) = undefined;
21
22// This brings `zig fmt` to stage 1.
23pub fn main() !void {
24 // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived,
25 // one shot program. We don't need to waste time freeing memory and finding places to squish
26 // bytes into. So we free everything all at once at the very end.
27 var direct_allocator = std.heap.DirectAllocator.init();
28 var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
29 const allocator = &arena.allocator;
30
31 var stdout_file = try std.io.getStdOut();
32 var stdout_out_stream = stdout_file.outStream();
33 stdout = &stdout_out_stream.stream;
34
35 stderr_file = try std.io.getStdErr();
36 var stderr_out_stream = stderr_file.outStream();
37 stderr = &stderr_out_stream.stream;
38 const args = try std.os.argsAlloc(allocator);
39
40 var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args[1..]);
41 defer flags.deinit();
42
43 if (flags.present("help")) {
44 try stdout.write(self_hosted_main.usage_fmt);
45 os.exit(0);
46 }
47
48 const color = blk: {
49 if (flags.single("color")) |color_flag| {
50 if (mem.eql(u8, color_flag, "auto")) {
51 break :blk errmsg.Color.Auto;
52 } else if (mem.eql(u8, color_flag, "on")) {
53 break :blk errmsg.Color.On;
54 } else if (mem.eql(u8, color_flag, "off")) {
55 break :blk errmsg.Color.Off;
56 } else unreachable;
57 } else {
58 break :blk errmsg.Color.Auto;
59 }
60 };
61
62 if (flags.present("stdin")) {
63 if (flags.positionals.len != 0) {
64 try stderr.write("cannot use --stdin with positional arguments\n");
65 os.exit(1);
66 }
67
68 var stdin_file = try io.getStdIn();
69 var stdin = stdin_file.inStream();
70
71 const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
72 defer allocator.free(source_code);
73
74 var tree = std.zig.parse(allocator, source_code) catch |err| {
75 try stderr.print("error parsing stdin: {}\n", err);
76 os.exit(1);
77 };
78 defer tree.deinit();
79
80 var error_it = tree.errors.iterator(0);
81 while (error_it.next()) |parse_error| {
82 try printErrMsgToFile(allocator, parse_error, &tree, "<stdin>", stderr_file, color);
83 }
84 if (tree.errors.len != 0) {
85 os.exit(1);
86 }
87 if (flags.present("check")) {
88 const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
89 const code = if (anything_changed) u8(1) else u8(0);
90 os.exit(code);
91 }
92
93 _ = try std.zig.render(allocator, stdout, &tree);
94 return;
95 }
96
97 if (flags.positionals.len == 0) {
98 try stderr.write("expected at least one source file argument\n");
99 os.exit(1);
100 }
101
102 var fmt = Fmt{
103 .seen = Fmt.SeenMap.init(allocator),
104 .any_error = false,
105 .color = color,
106 .allocator = allocator,
107 };
108
109 const check_mode = flags.present("check");
110
111 for (flags.positionals.toSliceConst()) |file_path| {
112 try fmtPath(&fmt, file_path, check_mode);
113 }
114 if (fmt.any_error) {
115 os.exit(1);
116 }
117}
118
119const FmtError = error{
120 SystemResources,
121 OperationAborted,
122 IoPending,
123 BrokenPipe,
124 Unexpected,
125 WouldBlock,
126 FileClosed,
127 DestinationAddressRequired,
128 DiskQuota,
129 FileTooBig,
130 InputOutput,
131 NoSpaceLeft,
132 AccessDenied,
133 OutOfMemory,
134 RenameAcrossMountPoints,
135 ReadOnlyFileSystem,
136 LinkQuotaExceeded,
137 FileBusy,
138} || os.File.OpenError;
139
140fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
141 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
142 defer fmt.allocator.free(file_path);
143
144 if (try fmt.seen.put(file_path, {})) |_| return;
145
146 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
147 error.IsDir, error.AccessDenied => {
148 // TODO make event based (and dir.next())
149 var dir = try std.os.Dir.open(fmt.allocator, file_path);
150 defer dir.close();
151
152 while (try dir.next()) |entry| {
153 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
154 const full_path = try os.path.join(fmt.allocator, [][]const u8{ file_path, entry.name });
155 try fmtPath(fmt, full_path, check_mode);
156 }
157 }
158 return;
159 },
160 else => {
161 // TODO lock stderr printing
162 try stderr.print("unable to open '{}': {}\n", file_path, err);
163 fmt.any_error = true;
164 return;
165 },
166 };
167 defer fmt.allocator.free(source_code);
168
169 var tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
170 try stderr.print("error parsing file '{}': {}\n", file_path, err);
171 fmt.any_error = true;
172 return;
173 };
174 defer tree.deinit();
175
176 var error_it = tree.errors.iterator(0);
177 while (error_it.next()) |parse_error| {
178 try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color);
179 }
180 if (tree.errors.len != 0) {
181 fmt.any_error = true;
182 return;
183 }
184
185 if (check_mode) {
186 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree);
187 if (anything_changed) {
188 try stderr.print("{}\n", file_path);
189 fmt.any_error = true;
190 }
191 } else {
192 // TODO make this evented
193 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
194 defer baf.destroy();
195
196 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree);
197 if (anything_changed) {
198 try stderr.print("{}\n", file_path);
199 try baf.finish();
200 }
201 }
202}
203
204const Fmt = struct {
205 seen: SeenMap,
206 any_error: bool,
207 color: errmsg.Color,
208 allocator: *mem.Allocator,
209
210 const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
211};
212
213fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree,
214 path: []const u8, file: os.File, color: errmsg.Color,) !void
215{
216 const color_on = switch (color) {
217 errmsg.Color.Auto => file.isTty(),
218 errmsg.Color.On => true,
219 errmsg.Color.Off => false,
220 };
221 const lok_token = parse_error.loc();
222 const span = errmsg.Span{
223 .first = lok_token,
224 .last = lok_token,
225 };
226
227 const first_token = tree.tokens.at(span.first);
228 const last_token = tree.tokens.at(span.last);
229 const start_loc = tree.tokenLocationPtr(0, first_token);
230 const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
231
232 var text_buf = try std.Buffer.initSize(allocator, 0);
233 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
234 try parse_error.render(&tree.tokens, out_stream);
235 const text = text_buf.toOwnedSlice();
236
237 const stream = &file.outStream().stream;
238 if (!color_on) {
239 try stream.print(
240 "{}:{}:{}: error: {}\n",
241 path,
242 start_loc.line + 1,
243 start_loc.column + 1,
244 text,
245 );
246 return;
247 }
248
249 try stream.print(
250 "{}:{}:{}: error: {}\n{}\n",
251 path,
252 start_loc.line + 1,
253 start_loc.column + 1,
254 text,
255 tree.source[start_loc.line_start..start_loc.line_end],
256 );
257 try stream.writeByteNTimes(' ', start_loc.column);
258 try stream.writeByteNTimes('~', last_token.end - first_token.start);
259 try stream.write("\n");
260}
std/testing.zig+2-2
...@@ -59,13 +59,14 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {...@@ -59,13 +59,14 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
59 switch (pointer.size) {59 switch (pointer.size) {
60 builtin.TypeInfo.Pointer.Size.One,60 builtin.TypeInfo.Pointer.Size.One,
61 builtin.TypeInfo.Pointer.Size.Many,61 builtin.TypeInfo.Pointer.Size.Many,
62 builtin.TypeInfo.Pointer.Size.C,
62 => {63 => {
63 if (actual != expected) {64 if (actual != expected) {
64 std.debug.panic("expected {}, found {}", expected, actual);65 std.debug.panic("expected {}, found {}", expected, actual);
65 }66 }
66 },67 },
6768
68 builtin.TypeInfo.Pointer.Size.Slice => { 69 builtin.TypeInfo.Pointer.Size.Slice => {
69 if (actual.ptr != expected.ptr) {70 if (actual.ptr != expected.ptr) {
70 std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);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,7 +119,6 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
118 }119 }
119 }120 }
120 },121 },
121
122 }122 }
123}123}
124124
std/zig/parse.zig+6-1
...@@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {...@@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
3525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },3525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
3526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },3526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
3527 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} },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 .PtrType = ast.Node.PrefixOp.PtrInfo{3534 .PtrType = ast.Node.PrefixOp.PtrInfo{
3530 .align_info = null,3535 .align_info = null,
3531 .const_token = null,3536 .const_token = null,
std/zig/parser_test.zig+16
...@@ -1,3 +1,19 @@...@@ -1,3 +1,19 @@
1test "zig fmt: infix operator and then multiline string literal" {
2 try testCanonical(
3 \\const x = "" ++
4 \\ \\ hi
5 \\;
6 \\
7 );
8}
9
10test "zig fmt: C pointers" {
11 try testCanonical(
12 \\const Ptr = [*c]i32;
13 \\
14 );
15}
16
1test "zig fmt: threadlocal" {17test "zig fmt: threadlocal" {
2 try testCanonical(18 try testCanonical(
3 \\threadlocal var x: i32 = 1234;19 \\threadlocal var x: i32 = 1234;
std/zig/render.zig+3-2
...@@ -340,7 +340,6 @@ fn renderExpression(...@@ -340,7 +340,6 @@ fn renderExpression(
340 ast.Node.Id.InfixOp => {340 ast.Node.Id.InfixOp => {
341 const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);341 const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);
342342
343 const op_token = tree.tokens.at(infix_op_node.op_token);
344 const op_space = switch (infix_op_node.op) {343 const op_space = switch (infix_op_node.op) {
345 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,344 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
346 else => Space.Space,345 else => Space.Space,
...@@ -353,7 +352,9 @@ fn renderExpression(...@@ -353,7 +352,9 @@ fn renderExpression(
353 };352 };
354353
355 try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space);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 try stream.writeByteNTimes(' ', indent + indent_delta);358 try stream.writeByteNTimes(' ', indent + indent_delta);
358 start_col.* = indent + indent_delta;359 start_col.* = indent + indent_delta;
359 }360 }
std/zig/tokenizer.zig+22-1
...@@ -141,6 +141,7 @@ pub const Token = struct {...@@ -141,6 +141,7 @@ pub const Token = struct {
141 LineComment,141 LineComment,
142 DocComment,142 DocComment,
143 BracketStarBracket,143 BracketStarBracket,
144 BracketStarCBracket,
144 ShebangLine,145 ShebangLine,
145 Keyword_align,146 Keyword_align,
146 Keyword_and,147 Keyword_and,
...@@ -279,6 +280,7 @@ pub const Tokenizer = struct {...@@ -279,6 +280,7 @@ pub const Tokenizer = struct {
279 SawAtSign,280 SawAtSign,
280 LBracket,281 LBracket,
281 LBracketStar,282 LBracketStar,
283 LBracketStarC,
282 };284 };
283285
284 pub fn next(self: *Tokenizer) Token {286 pub fn next(self: *Tokenizer) Token {
...@@ -456,6 +458,9 @@ pub const Tokenizer = struct {...@@ -456,6 +458,9 @@ pub const Tokenizer = struct {
456 },458 },
457459
458 State.LBracketStar => switch (c) {460 State.LBracketStar => switch (c) {
461 'c' => {
462 state = State.LBracketStarC;
463 },
459 ']' => {464 ']' => {
460 result.id = Token.Id.BracketStarBracket;465 result.id = Token.Id.BracketStarBracket;
461 self.index += 1;466 self.index += 1;
...@@ -467,6 +472,18 @@ pub const Tokenizer = struct {...@@ -467,6 +472,18 @@ pub const Tokenizer = struct {
467 },472 },
468 },473 },
469474
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 State.Ampersand => switch (c) {487 State.Ampersand => switch (c) {
471 '=' => {488 '=' => {
472 result.id = Token.Id.AmpersandEqual;489 result.id = Token.Id.AmpersandEqual;
...@@ -1035,6 +1052,7 @@ pub const Tokenizer = struct {...@@ -1035,6 +1052,7 @@ pub const Tokenizer = struct {
1035 State.CharLiteralEnd,1052 State.CharLiteralEnd,
1036 State.StringLiteralBackslash,1053 State.StringLiteralBackslash,
1037 State.LBracketStar,1054 State.LBracketStar,
1055 State.LBracketStarC,
1038 => {1056 => {
1039 result.id = Token.Id.Invalid;1057 result.id = Token.Id.Invalid;
1040 },1058 },
...@@ -1169,12 +1187,15 @@ test "tokenizer" {...@@ -1169,12 +1187,15 @@ test "tokenizer" {
1169 testTokenize("test", []Token.Id{Token.Id.Keyword_test});1187 testTokenize("test", []Token.Id{Token.Id.Keyword_test});
1170}1188}
11711189
1172test "tokenizer - unknown length pointer" {1190test "tokenizer - unknown length pointer and then c pointer" {
1173 testTokenize(1191 testTokenize(
1174 \\[*]u81192 \\[*]u8
1193 \\[*c]u8
1175 , []Token.Id{1194 , []Token.Id{
1176 Token.Id.BracketStarBracket,1195 Token.Id.BracketStarBracket,
1177 Token.Id.Identifier,1196 Token.Id.Identifier,
1197 Token.Id.BracketStarCBracket,
1198 Token.Id.Identifier,
1178 });1199 });
1179}1200}
11801201
test/build_examples.zig+2-6
...@@ -7,12 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {...@@ -7,12 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
7 cases.addC("example/hello_world/hello_libc.zig");7 cases.addC("example/hello_world/hello_libc.zig");
8 cases.add("example/cat/main.zig");8 cases.add("example/cat/main.zig");
9 cases.add("example/guess_number/main.zig");9 cases.add("example/guess_number/main.zig");
10 if (!is_windows) {10 cases.addBuildFile("example/shared_library/build.zig");
11 // TODO get this test passing on windows11 cases.addBuildFile("example/mix_o_files/build.zig");
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 }
16 if (builtin.os != builtin.Os.macosx) {12 if (builtin.os != builtin.Os.macosx) {
17 // TODO https://github.com/ziglang/zig/issues/112613 // TODO https://github.com/ziglang/zig/issues/1126
18 cases.addBuildFile("test/standalone/issue_339/build.zig");14 cases.addBuildFile("test/standalone/issue_339/build.zig");
test/compile_errors.zig+405-69
...@@ -1,13 +1,330 @@...@@ -1,13 +1,330 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
2const builtin = @import("builtin");
23
3pub fn addCases(cases: *tests.CompileErrorContext) void {4pub 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 cases.addTest(321 cases.addTest(
5 "@truncate undefined value",322 "@truncate undefined value",
6 \\export fn entry() void {323 \\export fn entry() void {
7 \\ var z = @truncate(u8, u16(undefined));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 );
12329
13 cases.addTest(330 cases.addTest(
...@@ -121,12 +438,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -121,12 +438,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
121 "reading past end of pointer casted array",438 "reading past end of pointer casted array",
122 \\comptime {439 \\comptime {
123 \\ const array = "aoeu";440 \\ const array = "aoeu";
124 \\ const slice = array[2..];441 \\ const slice = array[1..];
125 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);442 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
126 \\ const deref = int_ptr.*;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 );
131448
132 cases.add(449 cases.add(
...@@ -210,13 +527,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -210,13 +527,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
210 );527 );
211528
212 cases.add(529 cases.add(
213 "Panic declared with wrong type signature in tests",530 "wrong panic signature, runtime function",
214 \\test "" {}531 \\test "" {}
215 \\532 \\
216 \\pub fn panic() void {}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 );
221548
222 cases.add(549 cases.add(
...@@ -301,7 +628,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -301,7 +628,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
301 \\ _ = a.*.len;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 );
306633
307 cases.add(634 cases.add(
...@@ -368,7 +695,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -368,7 +695,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
368 \\ f(i32);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 );
373700
374 cases.add(701 cases.add(
...@@ -768,7 +1095,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -768,7 +1095,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
768 \\ command.exec();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 );
7731100
774 cases.add(1101 cases.add(
...@@ -781,7 +1108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -781,7 +1108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
781 \\ command.exec();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 );
7861113
787 cases.add(1114 cases.add(
...@@ -1012,7 +1339,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1012,7 +1339,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1012 \\ Filled,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 );
10171344
1018 cases.add(1345 cases.add(
...@@ -2089,7 +2416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2089,7 +2416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2089 \\}2416 \\}
2090 ,2417 ,
2091 ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'",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 );
20942420
2095 cases.add(2421 cases.add(
...@@ -2752,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2752,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2752 \\3078 \\
2753 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }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 );
27573083
2758 cases.add(3084 cases.add(
...@@ -2762,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2762,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2762 \\ _ = a / a;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 );
27673093
2768 cases.add(3094 cases.add(
...@@ -2772,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2772,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2772 \\ a /= a;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 );
27773103
2778 cases.add(3104 cases.add(
...@@ -2782,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2782,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2782 \\ _ = a % a;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 );
27873113
2788 cases.add(3114 cases.add(
...@@ -2792,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2792,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2792 \\ a %= a;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 );
27973123
2798 cases.add(3124 cases.add(
...@@ -2802,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2802,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2802 \\ _ = a + a;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 );
28073133
2808 cases.add(3134 cases.add(
...@@ -2812,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2812,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2812 \\ a += a;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 );
28173143
2818 cases.add(3144 cases.add(
...@@ -2822,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2822,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2822 \\ _ = a +% a;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 );
28273153
2828 cases.add(3154 cases.add(
...@@ -2832,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2832,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2832 \\ a +%= a;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 );
28373163
2838 cases.add(3164 cases.add(
...@@ -2842,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2842,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2842 \\ _ = a - a;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 );
28473173
2848 cases.add(3174 cases.add(
...@@ -2852,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2852,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2852 \\ a -= a;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 );
28573183
2858 cases.add(3184 cases.add(
...@@ -2862,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2862,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2862 \\ _ = a -% a;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 );
28673193
2868 cases.add(3194 cases.add(
...@@ -2872,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2872,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2872 \\ a -%= a;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 );
28773203
2878 cases.add(3204 cases.add(
...@@ -2882,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2882,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2882 \\ _ = a * a;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 );
28873213
2888 cases.add(3214 cases.add(
...@@ -2892,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2892,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2892 \\ a *= a;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 );
28973223
2898 cases.add(3224 cases.add(
...@@ -2902,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2902,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2902 \\ _ = a *% a;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 );
29073233
2908 cases.add(3234 cases.add(
...@@ -2912,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2912,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2912 \\ a *%= a;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 );
29173243
2918 cases.add(3244 cases.add(
...@@ -2922,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2922,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2922 \\ _ = a << 2;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 );
29273253
2928 cases.add(3254 cases.add(
...@@ -2932,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2932,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2932 \\ a <<= 2;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 );
29373263
2938 cases.add(3264 cases.add(
...@@ -2942,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2942,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2942 \\ _ = a >> 2;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 );
29473273
2948 cases.add(3274 cases.add(
...@@ -2952,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2952,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2952 \\ a >>= 2;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 );
29573283
2958 cases.add(3284 cases.add(
...@@ -2962,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2962,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2962 \\ _ = a & a;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 );
29673293
2968 cases.add(3294 cases.add(
...@@ -2972,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2972,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2972 \\ a &= a;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 );
29773303
2978 cases.add(3304 cases.add(
...@@ -2982,7 +3308,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2982,7 +3308,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2982 \\ _ = a | a;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 );
29873313
2988 cases.add(3314 cases.add(
...@@ -2992,7 +3318,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2992,7 +3318,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2992 \\ a |= a;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 );
29973323
2998 cases.add(3324 cases.add(
...@@ -3002,7 +3328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3002,7 +3328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3002 \\ _ = a ^ a;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 );
30073333
3008 cases.add(3334 cases.add(
...@@ -3012,7 +3338,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3012,7 +3338,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3012 \\ a ^= a;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 );
30173343
3018 cases.add(3344 cases.add(
...@@ -3022,7 +3348,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3022,7 +3348,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3022 \\ _ = a == a;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 );
30273353
3028 cases.add(3354 cases.add(
...@@ -3032,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3032,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3032 \\ _ = a != a;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 );
30373363
3038 cases.add(3364 cases.add(
...@@ -3042,7 +3368,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3042,7 +3368,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3042 \\ _ = a > a;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 );
30473373
3048 cases.add(3374 cases.add(
...@@ -3052,7 +3378,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3052,7 +3378,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3052 \\ _ = a >= a;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 );
30573383
3058 cases.add(3384 cases.add(
...@@ -3062,7 +3388,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3062,7 +3388,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3062 \\ _ = a < a;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 );
30673393
3068 cases.add(3394 cases.add(
...@@ -3072,7 +3398,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3072,7 +3398,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3072 \\ _ = a <= a;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 );
30773403
3078 cases.add(3404 cases.add(
...@@ -3082,7 +3408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3082,7 +3408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3082 \\ _ = a and a;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 );
30873413
3088 cases.add(3414 cases.add(
...@@ -3092,7 +3418,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3092,7 +3418,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3092 \\ _ = a or a;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 );
30973423
3098 cases.add(3424 cases.add(
...@@ -3102,7 +3428,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3102,7 +3428,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3102 \\ _ = -a;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 );
31073433
3108 cases.add(3434 cases.add(
...@@ -3112,7 +3438,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3112,7 +3438,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3112 \\ _ = -%a;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 );
31173443
3118 cases.add(3444 cases.add(
...@@ -3122,7 +3448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3122,7 +3448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3122 \\ _ = ~a;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 );
31273453
3128 cases.add(3454 cases.add(
...@@ -3132,7 +3458,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3132,7 +3458,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3132 \\ _ = !a;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 );
31373463
3138 cases.add(3464 cases.add(
...@@ -3142,7 +3468,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3142,7 +3468,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3142 \\ _ = a orelse false;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 );
31473473
3148 cases.add(3474 cases.add(
...@@ -3152,7 +3478,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3152,7 +3478,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3152 \\ _ = a catch |err| false;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 );
31573483
3158 cases.add(3484 cases.add(
...@@ -3854,7 +4180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3854,7 +4180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3854 \\4180 \\
3855 \\export fn entry() usize { return @sizeOf(@typeOf(pass)); }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 );
38594185
3860 cases.add(4186 cases.add(
...@@ -4554,20 +4880,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4554,20 +4880,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4554 ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",4880 ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",
4555 );4881 );
45564882
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 cases.add(4883 cases.add(
4572 "wrong pointer implicitly casted to pointer to @OpaqueType()",4884 "wrong pointer implicitly casted to pointer to @OpaqueType()",
4573 \\const Derp = @OpaqueType();4885 \\const Derp = @OpaqueType();
...@@ -4788,7 +5100,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4788,7 +5100,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
47885100
4789 cases.add(5101 cases.add(
4790 "non-printable invalid character",5102 "non-printable invalid character",
4791 "\xff\xfe" ++ 5103 "\xff\xfe" ++
4792 \\fn test() bool {\r5104 \\fn test() bool {\r
4793 \\ true\r5105 \\ true\r
4794 \\}5106 \\}
...@@ -5348,7 +5660,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5348,7 +5660,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5348 \\ Baz: void,5660 \\ Baz: void,
5349 \\};5661 \\};
5350 \\comptime {5662 \\comptime {
5351 \\ var foo = Foo {.Baz = {}}; 5663 \\ var foo = Foo {.Baz = {}};
5352 \\ const bar_val = foo.Bar;5664 \\ const bar_val = foo.Bar;
5353 \\}5665 \\}
5354 ,5666 ,
...@@ -5430,4 +5742,28 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5430,4 +5742,28 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5430 ,5742 ,
5431 ".tmp_source.zig:7:30: error: unable to evaluate constant expression",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,6 +1,16 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub fn addCases(cases: *tests.CompareOutputContext) void {
4 cases.addRuntimeSafety("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 cases.addRuntimeSafety("@intToEnum - no matching tag value",14 cases.addRuntimeSafety("@intToEnum - no matching tag value",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {15 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);16 \\ @import("std").os.exit(126);
...@@ -108,6 +118,47 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -108,6 +118,47 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
108 \\}118 \\}
109 );119 );
110120
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 cases.addRuntimeSafety("integer subtraction overflow",162 cases.addRuntimeSafety("integer subtraction overflow",
112 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {163 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
113 \\ @import("std").os.exit(126);164 \\ @import("std").os.exit(126);
test/stage1/behavior.zig+8
...@@ -11,15 +11,22 @@ comptime {...@@ -11,15 +11,22 @@ comptime {
11 _ = @import("behavior/bswap.zig");11 _ = @import("behavior/bswap.zig");
12 _ = @import("behavior/bugs/1076.zig");12 _ = @import("behavior/bugs/1076.zig");
13 _ = @import("behavior/bugs/1111.zig");13 _ = @import("behavior/bugs/1111.zig");
14 _ = @import("behavior/bugs/1120.zig");
14 _ = @import("behavior/bugs/1277.zig");15 _ = @import("behavior/bugs/1277.zig");
15 _ = @import("behavior/bugs/1322.zig");16 _ = @import("behavior/bugs/1322.zig");
16 _ = @import("behavior/bugs/1381.zig");17 _ = @import("behavior/bugs/1381.zig");
17 _ = @import("behavior/bugs/1421.zig");18 _ = @import("behavior/bugs/1421.zig");
18 _ = @import("behavior/bugs/1442.zig");19 _ = @import("behavior/bugs/1442.zig");
19 _ = @import("behavior/bugs/1486.zig");20 _ = @import("behavior/bugs/1486.zig");
21 _ = @import("behavior/bugs/1851.zig");
22 _ = @import("behavior/bugs/2006.zig");
20 _ = @import("behavior/bugs/394.zig");23 _ = @import("behavior/bugs/394.zig");
24 _ = @import("behavior/bugs/421.zig");
25 _ = @import("behavior/bugs/529.zig");
21 _ = @import("behavior/bugs/655.zig");26 _ = @import("behavior/bugs/655.zig");
22 _ = @import("behavior/bugs/656.zig");27 _ = @import("behavior/bugs/656.zig");
28 _ = @import("behavior/bugs/704.zig");
29 _ = @import("behavior/bugs/718.zig");
23 _ = @import("behavior/bugs/726.zig");30 _ = @import("behavior/bugs/726.zig");
24 _ = @import("behavior/bugs/828.zig");31 _ = @import("behavior/bugs/828.zig");
25 _ = @import("behavior/bugs/920.zig");32 _ = @import("behavior/bugs/920.zig");
...@@ -59,6 +66,7 @@ comptime {...@@ -59,6 +66,7 @@ comptime {
59 _ = @import("behavior/reflection.zig");66 _ = @import("behavior/reflection.zig");
60 _ = @import("behavior/sizeof_and_typeof.zig");67 _ = @import("behavior/sizeof_and_typeof.zig");
61 _ = @import("behavior/slice.zig");68 _ = @import("behavior/slice.zig");
69 _ = @import("behavior/slicetobytes.zig");
62 _ = @import("behavior/struct.zig");70 _ = @import("behavior/struct.zig");
63 _ = @import("behavior/struct_contains_null_ptr_itself.zig");71 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
64 _ = @import("behavior/struct_contains_slice_of_itself.zig");72 _ = @import("behavior/struct_contains_slice_of_itself.zig");
test/stage1/behavior/bitcast.zig+78
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
3const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
45
...@@ -34,3 +35,80 @@ test "@bitCast extern enum to its integer type" {...@@ -34,3 +35,80 @@ test "@bitCast extern enum to its integer type" {
34 SOCK.testBitCastExternEnum();35 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();36 comptime SOCK.testBitCastExternEnum();
36}37}
38
39test "@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
70test "@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
98test "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 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const A = packed struct {
5 a: u2,
6 b: u6,
7};
8const B = packed struct {
9 q: u8,
10 a: u2,
11 b: u6,
12};
13test "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 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "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 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const S = struct {
5 p: *S,
6};
7test "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 @@
1const assert = @import("std").debug.assert;
2
3test "bitCast to array" {
4 comptime testBitCastArray();
5 testBitCastArray();
6}
7
8fn testBitCastArray() void {
9 assert(extractOne64(0x0123456789abcdef0123456789abcdef) == 0x0123456789abcdef);
10}
11
12fn 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 @@
1const A = extern struct {
2 field: c_int,
3};
4
5extern fn issue529(?*A) void;
6
7comptime {
8 _ = @import("529_other_file_2.zig");
9}
10
11test "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 @@
1pub const A = extern struct {
2 field: c_int,
3};
4
5pub extern fn issue529(?*A) void;
test/stage1/behavior/bugs/529_other_file_2.zig created+4
...@@ -0,0 +1,4 @@
1pub const A = extern struct {
2 field: c_int,
3};
4export fn issue529(a: ?*A) void {}
test/stage1/behavior/bugs/704.zig created+7
...@@ -0,0 +1,7 @@
1const xxx = struct {
2 pub fn bar(self: *xxx) void {}
3};
4test "bug 704" {
5 var x: xxx = undefined;
6 x.bar();
7}
test/stage1/behavior/bugs/718.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4const Keys = struct {
5 up: bool,
6 down: bool,
7 left: bool,
8 right: bool,
9};
10var keys: Keys = undefined;
11test "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,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
34
4test "dereference pointer" {5test "dereference pointer" {
5 comptime testDerefPtr();6 comptime testDerefPtr();
...@@ -42,3 +43,84 @@ test "double pointer parsing" {...@@ -42,3 +43,84 @@ test "double pointer parsing" {
42fn PtrOf(comptime T: type) type {43fn PtrOf(comptime T: type) type {
43 return *T;44 return *T;
44}45}
46
47test "assigning integer to C pointer" {
48 var x: i32 = 0;
49 var ptr: [*c]u8 = 0;
50 var ptr2: [*c]u8 = x;
51}
52
53test "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
61test "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
87test "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
102test "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
112test "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,3 +50,11 @@ const Bytes = struct {
50 return res;50 return res;
51 }51 }
52};52};
53
54test "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 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5test "@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,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
3const builtin = @import("builtin");4const builtin = @import("builtin");
4const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
56
...@@ -103,19 +104,20 @@ fn structInitializer() void {...@@ -103,19 +104,20 @@ fn structInitializer() void {
103}104}
104105
105test "fn call of struct field" {106test "fn call of struct field" {
106 expect(callStructField(Foo{ .ptr = aFunc }) == 13);107 const Foo = struct {
107}108 ptr: fn () i32,
108109 };
109const Foo = struct {110 const S = struct {
110 ptr: fn () i32,111 fn aFunc() i32 {
111};112 return 13;
113 }
112114
113fn aFunc() i32 {115 fn callStructField(foo: Foo) i32 {
114 return 13;116 return foo.ptr();
115}117 }
118 };
116119
117fn callStructField(foo: Foo) i32 {120 expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
118 return foo.ptr();
119}121}
120122
121test "store member function in variable" {123test "store member function in variable" {
...@@ -468,3 +470,32 @@ test "pointer to packed struct member in a stack variable" {...@@ -468,3 +470,32 @@ test "pointer to packed struct member in a stack variable" {
468 b_ptr.* = 2;470 b_ptr.* = 2;
469 expect(s.b == 2);471 expect(s.b == 2);
470}472}
473
474test "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
495test "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,3 +29,8 @@ test "truncate sign mismatch but comptime known so it works anyway" {
29 var result = @truncate(i8, x);29 var result = @truncate(i8, x);
30 expect(result == 10);30 expect(result == 10);
31}31}
32
33test "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,6 +61,21 @@ fn testUnknownLenPtr() void {
61 expect(u32_ptr_info.Pointer.child == f64);61 expect(u32_ptr_info.Pointer.child == f64);
62}62}
6363
64test "type info: C pointer type info" {
65 testCPtr();
66 comptime testCPtr();
67}
68
69fn 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
64test "type info: slice type info" {79test "type info: slice type info" {
65 testSlice();80 testSlice();
66 comptime testSlice();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,3 +350,18 @@ test "union with only 1 field casted to its enum type which has enum value speci
350 expect(@enumToInt(t) == 33);350 expect(@enumToInt(t) == 33);
351 comptime expect(@enumToInt(t) == 33);351 comptime expect(@enumToInt(t) == 33);
352}352}
353
354test "@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,11 +5,57 @@ const expect = std.testing.expect;
5test "vector wrap operators" {5test "vector wrap operators" {
6 const S = struct {6 const S = struct {
7 fn doTheTest() void {7 fn doTheTest() void {
8 const v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };8 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
9 const x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };9 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
10 expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ 11, 22, 33, 44 }));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{ 9, 18, 27, 36 }));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{ 10, 40, 90, 160 }));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
21test "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
36test "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
51test "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 S.doTheTest();61 S.doTheTest();
test/stage1/c_abi/build.zig+3-2
...@@ -3,9 +3,10 @@ const Builder = @import("std").build.Builder;...@@ -3,9 +3,10 @@ const Builder = @import("std").build.Builder;
3pub fn build(b: *Builder) void {3pub fn build(b: *Builder) void {
4 const rel_opts = b.standardReleaseOptions();4 const rel_opts = b.standardReleaseOptions();
55
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 c_obj.setBuildMode(rel_opts);8 c_obj.setBuildMode(rel_opts);
8 c_obj.setNoStdLib(true);9 c_obj.linkSystemLibrary("c");
910
10 const main = b.addTest("main.zig");11 const main = b.addTest("main.zig");
11 main.setBuildMode(rel_opts);12 main.setBuildMode(rel_opts);
test/tests.zig+66-16
...@@ -24,24 +24,24 @@ const gen_h = @import("gen_h.zig");...@@ -24,24 +24,24 @@ const gen_h = @import("gen_h.zig");
24const TestTarget = struct {24const TestTarget = struct {
25 os: builtin.Os,25 os: builtin.Os,
26 arch: builtin.Arch,26 arch: builtin.Arch,
27 environ: builtin.Environ,27 abi: builtin.Abi,
28};28};
2929
30const test_targets = []TestTarget{30const test_targets = []TestTarget{
31 TestTarget{31 TestTarget{
32 .os = builtin.Os.linux,32 .os = builtin.Os.linux,
33 .arch = builtin.Arch.x86_64,33 .arch = builtin.Arch.x86_64,
34 .environ = builtin.Environ.gnu,34 .abi = builtin.Abi.gnu,
35 },35 },
36 TestTarget{36 TestTarget{
37 .os = builtin.Os.macosx,37 .os = builtin.Os.macosx,
38 .arch = builtin.Arch.x86_64,38 .arch = builtin.Arch.x86_64,
39 .environ = builtin.Environ.unknown,39 .abi = builtin.Abi.gnu,
40 },40 },
41 TestTarget{41 TestTarget{
42 .os = builtin.Os.windows,42 .os = builtin.Os.windows,
43 .arch = builtin.Arch.x86_64,43 .arch = builtin.Arch.x86_64,
44 .environ = builtin.Environ.msvc,44 .abi = builtin.Abi.msvc,
45 },45 },
46};46};
4747
...@@ -189,7 +189,7 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons...@@ -189,7 +189,7 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
189 these_tests.setFilter(test_filter);189 these_tests.setFilter(test_filter);
190 these_tests.setBuildMode(mode);190 these_tests.setBuildMode(mode);
191 if (!is_native) {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 if (link_libc) {194 if (link_libc) {
195 these_tests.linkSystemLibrary("c");195 these_tests.linkSystemLibrary("c");
...@@ -536,6 +536,7 @@ pub const CompileErrorContext = struct {...@@ -536,6 +536,7 @@ pub const CompileErrorContext = struct {
536 name: []const u8,536 name: []const u8,
537 sources: ArrayList(SourceFile),537 sources: ArrayList(SourceFile),
538 expected_errors: ArrayList([]const u8),538 expected_errors: ArrayList([]const u8),
539 expect_exact: bool,
539 link_libc: bool,540 link_libc: bool,
540 is_exe: bool,541 is_exe: bool,
541 is_test: bool,542 is_test: bool,
...@@ -565,6 +566,24 @@ pub const CompileErrorContext = struct {...@@ -565,6 +566,24 @@ pub const CompileErrorContext = struct {
565 case: *const TestCase,566 case: *const TestCase,
566 build_mode: Mode,567 build_mode: Mode,
567568
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 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {587 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
569 const allocator = context.b.allocator;588 const allocator = context.b.allocator;
570 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;589 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
...@@ -674,19 +693,49 @@ pub const CompileErrorContext = struct {...@@ -674,19 +693,49 @@ pub const CompileErrorContext = struct {
674 return error.TestFailed;693 return error.TestFailed;
675 }694 }
676695
677 for (self.case.expected_errors.toSliceConst()) |expected_error| {696 var ok = true;
678 if (mem.indexOf(u8, stderr, expected_error) == null) {697 if (self.case.expect_exact) {
679 warn(698 var err_iter = ErrLineIter.init(stderr);
680 \\699 var i: usize = 0;
681 \\========= Expected this compile error: =========700 ok = while (err_iter.next()) |line| : (i += 1) {
682 \\{}701 if (i >= self.case.expected_errors.len) break false;
683 \\================================================702 const expected = self.case.expected_errors.at(i);
684 \\{}703 if (mem.indexOf(u8, line, expected) == null) break false;
685 \\704 continue;
686 , expected_error, stderr);705 } else true;
687 return error.TestFailed;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 warn("OK\n");739 warn("OK\n");
691 }740 }
692 };741 };
...@@ -704,6 +753,7 @@ pub const CompileErrorContext = struct {...@@ -704,6 +753,7 @@ pub const CompileErrorContext = struct {
704 .name = name,753 .name = name,
705 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),754 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
706 .expected_errors = ArrayList([]const u8).init(self.b.allocator),755 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
756 .expect_exact = false,
707 .link_libc = false,757 .link_libc = false,
708 .is_exe = false,758 .is_exe = false,
709 .is_test = false,759 .is_test = false,
test/translate_c.zig+69-31
...@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
117 \\};117 \\};
118 ,118 ,
119 \\pub const struct_Foo = extern struct {119 \\pub const struct_Foo = extern struct {
120 \\ a: ?[*]Foo,120 \\ a: [*c]Foo,
121 \\};121 \\};
122 \\pub const Foo = struct_Foo;122 \\pub const Foo = struct_Foo;
123 \\pub const struct_Bar = extern struct {123 \\pub const struct_Bar = extern struct {
124 \\ a: ?[*]Foo,124 \\ a: [*c]Foo,
125 \\};125 \\};
126 );126 );
127127
...@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213 ,213 ,
214 \\const struct_Foo = extern struct {214 \\const struct_Foo = extern struct {
215 \\ x: c_int,215 \\ x: c_int,
216 \\ y: ?[*]u8,216 \\ y: [*c]u8,
217 \\};217 \\};
218 ,218 ,
219 \\pub const Foo = struct_Foo;219 \\pub const Foo = struct_Foo;
...@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
244 ,244 ,
245 \\pub const BarB = enum_Bar.B;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 \\pub const Foo = struct_Foo;249 \\pub const Foo = struct_Foo;
250 ,250 ,
...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
254 cases.add("constant size array",254 cases.add("constant size array",
255 \\void func(int array[20]);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 );
259259
260 cases.add("self referential struct with function pointer",260 cases.add("self referential struct with function pointer",
...@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263 \\};263 \\};
264 ,264 ,
265 \\pub const struct_Foo = extern struct {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 \\pub const Foo = struct_Foo;269 \\pub const Foo = struct_Foo;
...@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
322 \\};322 \\};
323 ,323 ,
324 \\pub const struct_Bar = extern struct {324 \\pub const struct_Bar = extern struct {
325 \\ next: ?[*]struct_Foo,325 \\ next: [*c]struct_Foo,
326 \\};326 \\};
327 ,327 ,
328 \\pub const struct_Foo = extern struct {328 \\pub const struct_Foo = extern struct {
329 \\ next: ?[*]struct_Bar,329 \\ next: [*c]struct_Bar,
330 \\};330 \\};
331 );331 );
332332
...@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
610 ,610 ,
611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612 \\ if ((a != 0) and (b != 0)) return 0;612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != null)) return 1;613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != null)) return 2;614 \\ if ((a != 0) and (c != 0)) return 2;
615 \\ if ((a != 0) or (b != 0)) return 3;615 \\ if ((a != 0) or (b != 0)) return 3;
616 \\ if ((b != 0) or (c != null)) return 4;616 \\ if ((b != 0) or (c != 0)) return 4;
617 \\ if ((a != 0) or (c != null)) return 5;617 \\ if ((a != 0) or (c != 0)) return 5;
618 \\ return 6;618 \\ return 6;
619 \\}619 \\}
620 );620 );
...@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
710 \\pub const struct_Foo = extern struct {710 \\pub const struct_Foo = extern struct {
711 \\ field: c_int,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 \\ return foo.?.field;714 \\ return foo.?.field;
715 \\}715 \\}
716 );716 );
...@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756 \\ return x;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 \\ return @ptrCast(?*c_void, x);760 \\ return @ptrCast(?*c_void, x);
761 \\}761 \\}
762 );762 );
...@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
777 \\ return 0;777 \\ return 0;
778 \\}778 \\}
779 ,779 ,
780 \\pub export fn foo() ?[*]c_int {780 \\pub export fn foo() [*c]c_int {
781 \\ return null;781 \\ return 0;
782 \\}782 \\}
783 );783 );
784784
...@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1086 \\ *x = 1;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 \\ x.?.* = 1;1090 \\ x.?.* = 1;
1091 \\}1091 \\}
1092 );1092 );
...@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1114 ,1114 ,
1115 \\pub fn foo() c_int {1115 \\pub fn foo() c_int {
1116 \\ var x: c_int = 1234;1116 \\ var x: c_int = 1234;
1117 \\ var ptr: ?[*]c_int = &x;1117 \\ var ptr: [*c]c_int = &x;
1118 \\ return ptr.?.*;1118 \\ return ptr.?.*;
1119 \\}1119 \\}
1120 );1120 );
...@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1124 \\ return "bar";1124 \\ return "bar";
1125 \\}1125 \\}
1126 ,1126 ,
1127 \\pub fn foo() ?[*]const u8 {1127 \\pub fn foo() [*c]const u8 {
1128 \\ return c"bar";1128 \\ return c"bar";
1129 \\}1129 \\}
1130 );1130 );
...@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1253 \\ return (float *)a;1253 \\ return (float *)a;
1254 \\}1254 \\}
1255 ,1255 ,
1256 \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {1256 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1257 \\ return @ptrCast(?[*]f32, a);1257 \\ return @ptrCast([*c]f32, a);
1258 \\}1258 \\}
1259 );1259 );
12601260
...@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1280 \\ return !(a == 0);1280 \\ return !(a == 0);
1281 \\ return !(a != 0);1281 \\ return !(a != 0);
1282 \\ return !(b != 0);1282 \\ return !(b != 0);
1283 \\ return !(c != null);1283 \\ return !(c != 0);
1284 \\}1284 \\}
1285 );1285 );
12861286
...@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1297 cases.add("const ptr initializer",1297 cases.add("const ptr initializer",
1298 \\static const char *v0 = "0.0.0";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 );
13021302
1303 cases.add("static incomplete array inside function",1303 cases.add("static incomplete array inside function",
...@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1306 \\}1306 \\}
1307 ,1307 ,
1308 \\pub fn foo() void {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 );
13121312
1313 cases.add("macro pointer cast",1313 cases.add("macro pointer cast",
1314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)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 );
13181318
1319 cases.add("if on none bool",1319 cases.add("if on non-bool",
1320 \\enum SomeEnum { A, B, C };1320 \\enum SomeEnum { A, B, C };
1321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {1321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
1322 \\ if (a) return 0;1322 \\ if (a) return 0;
...@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
1338 \\ if (a != 0) return 0;1338 \\ if (a != 0) return 0;
1339 \\ if (b != 0) return 1;1339 \\ if (b != 0) return 1;
1340 \\ if (c != null) return 2;1340 \\ if (c != 0) return 2;
1341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;1341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
1342 \\ return 4;1342 \\ return 4;
1343 \\}1343 \\}
1344 );1344 );
13451345
1346 cases.add("while on none bool",1346 cases.add("while on non-bool",
1347 \\int while_none_bool(int a, float b, void *c) {1347 \\int while_none_bool(int a, float b, void *c) {
1348 \\ while (a) return 0;1348 \\ while (a) return 0;
1349 \\ while (b) return 1;1349 \\ while (b) return 1;
...@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1355 \\ while (a != 0) return 0;1355 \\ while (a != 0) return 0;
1356 \\ while (b != 0) return 1;1356 \\ while (b != 0) return 1;
1357 \\ while (c != null) return 2;1357 \\ while (c != 0) return 2;
1358 \\ return 3;1358 \\ return 3;
1359 \\}1359 \\}
1360 );1360 );
13611361
1362 cases.add("for on none bool",1362 cases.add("for on non-bool",
1363 \\int for_none_bool(int a, float b, void *c) {1363 \\int for_none_bool(int a, float b, void *c) {
1364 \\ for (;a;) return 0;1364 \\ for (;a;) return 0;
1365 \\ for (;b;) return 1;1365 \\ for (;b;) return 1;
...@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1371 \\ while (a != 0) return 0;1371 \\ while (a != 0) return 0;
1372 \\ while (b != 0) return 1;1372 \\ while (b != 0) return 1;
1373 \\ while (c != null) return 2;1373 \\ while (c != 0) return 2;
1374 \\ return 3;1374 \\ return 3;
1375 \\}1375 \\}
1376 );1376 );
...@@ -1416,4 +1416,42 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -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}