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
signaturelock-open 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:
44 - ninja
55 - llvm70
66sources:
7 - https://github.com/ziglang/zig.git
7 - https://github.com/ziglang/zig
88tasks:
99 - build: |
1010 cd zig && mkdir build && cd build
.gitignore+3-3
......@@ -10,6 +10,6 @@
1010# -andrewrk
1111
1212zig-cache/
13build/
14build-*/
15docgen_tmp/
13/build/
14/build-*/
15/docgen_tmp/
CMakeLists.txt+17
......@@ -417,6 +417,7 @@ set(ZIG_SOURCES
417417 "${CMAKE_SOURCE_DIR}/src/error.cpp"
418418 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
419419 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
420 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
420421 "${CMAKE_SOURCE_DIR}/src/link.cpp"
421422 "${CMAKE_SOURCE_DIR}/src/main.cpp"
422423 "${CMAKE_SOURCE_DIR}/src/os.cpp"
......@@ -432,6 +433,10 @@ set(BLAKE_SOURCES
432433)
433434set(ZIG_CPP_SOURCES
434435 "${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"
435440 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
436441)
437442
......@@ -446,10 +451,12 @@ set(ZIG_STD_FILES
446451 "buf_set.zig"
447452 "buffer.zig"
448453 "build.zig"
454 "build/fmt.zig"
449455 "c/darwin.zig"
450456 "c/freebsd.zig"
451457 "c/index.zig"
452458 "c/linux.zig"
459 "c/netbsd.zig"
453460 "c/windows.zig"
454461 "coff.zig"
455462 "crypto/blake2.zig"
......@@ -485,6 +492,7 @@ set(ZIG_STD_FILES
485492 "fmt/errol/index.zig"
486493 "fmt/errol/lookup.zig"
487494 "fmt/index.zig"
495 "fmt/parse_float.zig"
488496 "hash/adler.zig"
489497 "hash/crc.zig"
490498 "hash/fnv.zig"
......@@ -589,6 +597,8 @@ set(ZIG_STD_FILES
589597 "os/linux/index.zig"
590598 "os/linux/vdso.zig"
591599 "os/linux/x86_64.zig"
600 "os/netbsd/errno.zig"
601 "os/netbsd/index.zig"
592602 "os/path.zig"
593603 "os/time.zig"
594604 "os/uefi.zig"
......@@ -603,6 +613,7 @@ set(ZIG_STD_FILES
603613 "os/windows/util.zig"
604614 "os/zen.zig"
605615 "pdb.zig"
616 "priority_queue.zig"
606617 "rand/index.zig"
607618 "rand/ziggurat.zig"
608619 "segmented_list.zig"
......@@ -611,6 +622,7 @@ set(ZIG_STD_FILES
611622 "special/bootstrap_lib.zig"
612623 "special/build_runner.zig"
613624 "special/builtin.zig"
625 "special/compiler_rt/addXf3.zig"
614626 "special/compiler_rt/aulldiv.zig"
615627 "special/compiler_rt/aullrem.zig"
616628 "special/compiler_rt/comparetf2.zig"
......@@ -653,6 +665,7 @@ set(ZIG_STD_FILES
653665 "special/compiler_rt/udivmodti4.zig"
654666 "special/compiler_rt/udivti3.zig"
655667 "special/compiler_rt/umodti3.zig"
668 "special/fmt_runner.zig"
656669 "special/init-exe/build.zig"
657670 "special/init-exe/src/main.zig"
658671 "special/init-lib/build.zig"
......@@ -906,3 +919,7 @@ foreach(file ${ZIG_STD_FILES})
906919 get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)
907920 install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")
908921endforeach()
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 @@
33A programming language designed for robustness, optimality, and
44clarity.
55
6[ziglang.org](https://ziglang.org)
6[Download & Documentation](https://ziglang.org/download/)
77
88## Feature Highlights
99
......@@ -77,36 +77,54 @@ clarity.
7777 - what sizes are the C integer types
7878 - C ABI calling convention for this target
7979 - bootstrap code and default panic handler
80 * `zig targets` is guaranteed to include this target.
8081
8182#### Tier 4 Support
8283
8384 * Support for these targets is entirely experimental.
8485 * LLVM may have the target as an experimental target, which means that you
8586 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
8894#### Support Table
8995
90| | freestanding | linux | macosx | windows | freebsd | UEFI | other |
91|--------|--------------|--------|--------|---------|---------|--------|--------|
92|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 |
93|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 |
94|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
95|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
96|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
97|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
98|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
99|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
100|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
101|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
102|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
103|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
104|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
105|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
106|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
107|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
108|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
109|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
96| | freestanding | linux | macosx | windows | freebsd | netbsd | UEFI | other |
97|-------------|--------------|--------|--------|---------|---------|------- | -------|--------|
98|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 2 | Tier 3 |
99|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
100|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
101|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
102|avr | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
103|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
104|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
105|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
106|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
107|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
108|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
109|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
110|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | N/A | Tier 3 |
111|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
112|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
113|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
114|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | Tier 4 |
115|xcore | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
116|nvptx | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
117|msp430 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
118|r600 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
119|arc | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
120|tce | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
121|le | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
122|amdil | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
123|hsail | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
124|spir | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
125|kalimba | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
126|shave | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
127|renderscript | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | N/A | Tier 4 |
110128
111129## Community
112130
build.zig+7-4
......@@ -49,13 +49,14 @@ pub fn build(b: *Builder) !void {
4949 .c_header_files = nextValue(&index, build_info),
5050 .dia_guids_lib = nextValue(&index, build_info),
5151 .llvm = undefined,
52 .no_rosegment = b.option(bool, "no-rosegment", "Workaround to enable valgrind builds") orelse false,
5352 };
5453 ctx.llvm = try findLLVM(b, ctx.llvm_config_exe);
5554
5655 var test_stage2 = b.addTest("src-self-hosted/test.zig");
5756 test_stage2.setBuildMode(builtin.Mode.Debug);
5857
58 const fmt_build_zig = b.addFmt([][]const u8{"build.zig"});
59
5960 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
6061 exe.setBuildMode(mode);
6162
......@@ -107,6 +108,11 @@ pub fn build(b: *Builder) !void {
107108 }
108109 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
110116 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
111117
112118 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 {
289295}
290296
291297fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
292 exe.setNoRoSegment(ctx.no_rosegment);
293
294298 exe.addIncludeDir("src");
295299 exe.addIncludeDir(ctx.cmake_binary_dir);
296300 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
......@@ -375,5 +379,4 @@ const Context = struct {
375379 c_header_files: []const u8,
376380 dia_guids_lib: []const u8,
377381 llvm: LibraryDep,
378 no_rosegment: bool,
379382};
cmake/Findclang.cmake+22
......@@ -11,17 +11,28 @@ if(MSVC)
1111 find_package(CLANG REQUIRED CONFIG)
1212
1313 set(CLANG_LIBRARIES
14 clangFrontendTool
15 clangCodeGen
1416 clangFrontend
1517 clangDriver
1618 clangSerialization
1719 clangSema
20 clangStaticAnalyzerFrontend
21 clangStaticAnalyzerCheckers
22 clangStaticAnalyzerCore
1823 clangAnalysis
24 clangASTMatchers
1925 clangAST
2026 clangParse
2127 clangSema
2228 clangBasic
2329 clangEdit
2430 clangLex
31 clangARCMigrate
32 clangRewriteFrontend
33 clangRewrite
34 clangCrossTU
35 clangIndex
2536 )
2637
2738else()
......@@ -50,17 +61,28 @@ else()
5061 endif()
5162 endmacro(FIND_AND_ADD_CLANG_LIB)
5263
64 FIND_AND_ADD_CLANG_LIB(clangFrontendTool)
65 FIND_AND_ADD_CLANG_LIB(clangCodeGen)
5366 FIND_AND_ADD_CLANG_LIB(clangFrontend)
5467 FIND_AND_ADD_CLANG_LIB(clangDriver)
5568 FIND_AND_ADD_CLANG_LIB(clangSerialization)
5669 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)
5773 FIND_AND_ADD_CLANG_LIB(clangAnalysis)
74 FIND_AND_ADD_CLANG_LIB(clangASTMatchers)
5875 FIND_AND_ADD_CLANG_LIB(clangAST)
5976 FIND_AND_ADD_CLANG_LIB(clangParse)
6077 FIND_AND_ADD_CLANG_LIB(clangSema)
6178 FIND_AND_ADD_CLANG_LIB(clangBasic)
6279 FIND_AND_ADD_CLANG_LIB(clangEdit)
6380 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)
6486endif()
6587
6688include(FindPackageHandleStandardArgs)
doc/docgen.zig+2-8
......@@ -916,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
916916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
917917 std.zig.Token.Id.Tilde,
918918 std.zig.Token.Id.BracketStarBracket,
919 std.zig.Token.Id.BracketStarCBracket,
919920 => try writeEscaped(out, src[token.start..token.end]),
920921
921922 std.zig.Token.Id.Invalid => return parseError(
......@@ -1104,14 +1105,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
11041105 },
11051106 }
11061107 if (code.target_windows) {
1107 try test_args.appendSlice([][]const u8{
1108 "--target-os",
1109 "windows",
1110 "--target-arch",
1111 "x86_64",
1112 "--target-environ",
1113 "msvc",
1114 });
1108 try test_args.appendSlice([][]const u8{ "-target", "x86_64-windows" });
11151109 }
11161110 const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
11171111 const escaped_stderr = try escapeHtml(allocator, result.stderr);
doc/langref.html.in+541-142
......@@ -8,13 +8,7 @@
88 body{
99 background-color:#111;
1010 color: #bbb;
11 font-family: system-ui,
12 /* Fallbacks for browsers that don't support system-ui */
13 /* https://caniuse.com/#search=system-ui */
14 -apple-system, /* iOS and macOS */
15 Roboto, /* Android */
16 "Segoe UI", /* Windows */
17 sans-serif;
11 font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
1812 }
1913 a {
2014 color: #88f;
......@@ -243,8 +237,9 @@ const Timestamp = struct {
243237 {#header_close#}
244238 {#header_open|Values#}
245239 {#code_begin|exe|values#}
246const std = @import("std");
240// Top-level declarations are order-independent:
247241const warn = std.debug.warn;
242const std = @import("std");
248243const os = std.os;
249244const assert = std.debug.assert;
250245
......@@ -262,7 +257,7 @@ pub fn main() void {
262257 true and false,
263258 true or false,
264259 !true);
265
260
266261 // optional
267262 var optional_value: ?[]const u8 = null;
268263 assert(optional_value == null);
......@@ -281,7 +276,7 @@ pub fn main() void {
281276
282277 warn("\nerror union 1\ntype: {}\nvalue: {}\n",
283278 @typeName(@typeOf(number_or_error)), number_or_error);
284
279
285280 number_or_error = 1234;
286281
287282 warn("\nerror union 2\ntype: {}\nvalue: {}\n",
......@@ -706,15 +701,21 @@ fn divide(a: i32, b: i32) i32 {
706701 {#code_end#}
707702 <p>
708703 In this function, values {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are known only at runtime,
709 and thus this division operation is vulnerable to both integer overflow and
710 division by zero.
704 and thus this division operation is vulnerable to both {#link|Integer Overflow#} and
705 {#link|Division by Zero#}.
711706 </p>
712707 <p>
713708 Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
714709 integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and
715710 {#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.
716711 </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#}
718719 {#header_close#}
719720 {#header_close#}
720721 {#header_open|Floats#}
......@@ -1651,7 +1652,7 @@ test "pointer slicing" {
16511652 assert(array[3] == 5);
16521653}
16531654 {#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
16551656 an undefined memory layout:</p>
16561657 {#code_begin|test#}
16571658const assert = @import("std").debug.assert;
......@@ -1694,7 +1695,7 @@ test "comptime @intToPtr" {
16941695 }
16951696}
16961697 {#code_end#}
1697 {#see_also|Optional Pointers#}
1698 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
16981699 {#header_open|volatile#}
16991700 <p>Loads and stores are assumed to not have side effects. If a given load or store
17001701 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
......@@ -1823,7 +1824,9 @@ fn foo(bytes: []u8) u32 {
18231824}
18241825 {#code_end#}
18251826 {#header_close#}
1827 {#see_also|C Pointers|Pointers to Zero Bit Types#}
18261828 {#header_close#}
1829
18271830 {#header_open|Slices#}
18281831 {#code_begin|test_safety|index out of bounds#}
18291832const assert = @import("std").debug.assert;
......@@ -2043,14 +2046,211 @@ test "linked list" {
20432046 assert(list2.first.?.data == 1234);
20442047}
20452048 {#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
20462056 {#header_open|packed struct#}
2047 <p>{#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout.</p>
2048 <p>TODO bit fields</p>
2049 <p>TODO alignment</p>
2050 <p>TODO endianness</p>
2051 <p>TODO @bitOffsetOf and @byteOffsetOf</p>
2052 <p>TODO mention how volatile loads and stores of bit packed fields could be more efficient when
2053 done by hand instead of with packed struct</p>
2057 <p>
2058 Unlike normal structs, {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout:
2059 </p>
2060 <ul>
2061 <li>Fields remain in the order declared.</li>
2062 <li>There is no padding between fields.</li>
2063 <li>Zig supports arbitrary width {#link|Integers#} and although normally, integers with fewer
2064 than 8 bits will still use 1 byte of memory, in packed structs, they use
2065 exactly their bit width.
2066 </li>
2067 <li>{#syntax#}bool{#endsyntax#} fields use exactly 1 bit.</li>
2068 <li>A {#link|packed enum#} field uses exactly the bit width of its integer tag type.</li>
2069 <li>A {#link|packed union#} field uses exactly the bit width of the union field with
2070 the largest bit width.</li>
2071 <li>Non-byte-aligned fields are packed into the smallest possible
2072 byte-aligned integers in accordance with the target endianness.
2073 </li>
2074 </ul>
2075 <p>
2076 This means that a {#syntax#}packed struct{#endsyntax#} can participate
2077 in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.
2078 This even works at {#link|comptime#}:
2079 </p>
2080 {#code_begin|test#}
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>
20542254 {#header_close#}
20552255 {#header_open|struct Naming#}
20562256 <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 { }
22002400 {#header_close#}
22012401 {#header_open|packed enum#}
22022402 <p>By default, the size of enums is not guaranteed.</p>
2203 <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the integer tag type
2204 of the enum:</p>
2403 <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the
2404 integer tag type of the enum:</p>
22052405 {#code_begin|test#}
22062406const std = @import("std");
22072407
......@@ -2214,131 +2414,179 @@ test "packed enum" {
22142414 std.debug.assert(@sizeOf(Number) == @sizeOf(u8));
22152415}
22162416 {#code_end#}
2417 <p>This makes the enum eligible to be in a {#link|packed struct#}.</p>
22172418 {#header_close#}
22182419 {#see_also|@memberName|@memberCount|@tagName|@sizeOf#}
22192420 {#header_close#}
22202421 {#header_open|union#}
2221 {#code_begin|test|union#}
2222const assert = @import("std").debug.assert;
2223const mem = @import("std").mem;
2422 <p>
2423 A bare {#syntax#}union{#endsyntax#} defines a set of possible types that a value
2424 can be as a list of fields. Only one field can be active at a time.
2425 The in-memory representation of bare unions is not guaranteed.
2426 Bare unions cannot be used to reinterpret memory. For that, use {#link|@ptrCast#},
2427 or use an {#link|extern union#} or a {#link|packed union#} which have
2428 guaranteed in-memory layout.
2429 {#link|Accessing the non-active field|Wrong Union Field Access#} is
2430 safety-checked {#link|Undefined Behavior#}:
2431 </p>
2432 {#code_begin|test_err|inactive union field#}
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.
22262448const Payload = union {
22272449 Int: i64,
22282450 Float: f64,
22292451 Bool: bool,
22302452};
22312453test "simple union" {
2232 var payload = Payload {.Int = 1234};
2233 // payload.Float = 12.34; // ERROR! field not active
2454 var payload = Payload{ .Int = 1234 };
22342455 assert(payload.Int == 1234);
2235 // You can activate another field by assigning the entire union.
2236 payload = Payload {.Float = 12.34};
2456 payload = Payload{ .Float = 12.34 };
22372457 assert(payload.Float == 12.34);
22382458}
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:
2241const ComplexTypeTag = enum { Ok, NotOk };
2474const ComplexTypeTag = enum {
2475 Ok,
2476 NotOk,
2477};
22422478const ComplexType = union(ComplexTypeTag) {
22432479 Ok: u8,
22442480 NotOk: void,
22452481};
22462482
2247// Declare a specific instance of the union variant.
2248test "declare union value" {
2249 const c = ComplexType { .Ok = 0 };
2483test "switch on tagged union" {
2484 const c = ComplexType{ .Ok = 42 };
22502485 assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
2486
2487 switch (c) {
2488 ComplexTypeTag.Ok => |value| assert(value == 42),
2489 ComplexTypeTag.NotOk => unreachable,
2490 }
22512491}
22522492
2253// @TagType can be used to access the enum tag type of a union.
22542493test "@TagType" {
22552494 assert(@TagType(ComplexType) == ComplexTypeTag);
22562495}
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.
2259const Foo = union(enum) {
2260 String: []const u8,
2261 Number: u64,
2262
2263 // void can be omitted when inferring enum tag type.
2264 None,
2504const ComplexTypeTag = enum {
2505 Ok,
2506 NotOk,
2507};
2508const ComplexType = union(ComplexTypeTag) {
2509 Ok: u8,
2510 NotOk: void,
22652511};
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 value
2275 Foo.Number => |x| blk: {
2276 assert(x == 54);
2277 break :blk "this is a number";
2278 },
2513test "modify tagged union in switch" {
2514 var c = ComplexType{ .Ok = 42 };
2515 assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
22792516
2280 Foo.None => blk: {
2281 break :blk "this is a none";
2282 },
2283 };
2284 assert(mem.eql(u8, what_is_it, "this is a number"));
2285}
2517 switch (c) {
2518 ComplexTypeTag.Ok => |*value| value.* += 1,
2519 ComplexTypeTag.NotOk => unreachable,
2520 }
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
22892533const Variant = union(enum) {
22902534 Int: i32,
22912535 Bool: bool,
22922536
2537 // void can be omitted when inferring enum tag type.
2538 None,
2539
22932540 fn truthy(self: Variant) bool {
22942541 return switch (self) {
22952542 Variant.Int => |x_int| x_int != 0,
22962543 Variant.Bool => |x_bool| x_bool,
2544 Variant.None => false,
22972545 };
22982546 }
22992547};
23002548
23012549test "union method" {
2302 var v1 = Variant { .Int = 1 };
2303 var v2 = Variant { .Bool = false };
2550 var v1 = Variant{ .Int = 1 };
2551 var v2 = Variant{ .Bool = false };
23042552
23052553 assert(v1.truthy());
23062554 assert(!v2.truthy());
23072555}
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.
23282565const Small2 = union(enum) {
23292566 A: i32,
23302567 B: bool,
23312568 C: u8,
23322569};
23332570test "@tagName" {
2334 assert(mem.eql(u8, @tagName(Small2.C), "C"));
2571 assert(std.mem.eql(u8, @tagName(Small2.C), "C"));
23352572}
23362573 {#code_end#}
2574 {#header_close#}
2575
2576 {#header_open|extern union#}
23372577 <p>
2338 Unions with an enum tag are generated as a struct with a tag field and union field. Zig
2339 sorts the order of the tag and union field by the largest alignment.
2578 An {#syntax#}extern union{#endsyntax#} has memory layout guaranteed to be compatible with
2579 the target C ABI.
23402580 </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#}
23412588 {#header_close#}
2589
23422590 {#header_open|blocks#}
23432591 <p>
23442592 Blocks are used to limit the scope of variable declarations:
......@@ -2371,7 +2619,36 @@ test "labeled break from labeled block expression" {
23712619 {#code_end#}
23722620 <p>Here, {#syntax#}blk{#endsyntax#} can be any name.</p>
23732621 {#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#}
23742650 {#header_close#}
2651
23752652 {#header_open|switch#}
23762653 {#code_begin|test|switch#}
23772654const assert = @import("std").debug.assert;
......@@ -2392,7 +2669,7 @@ test "switch simple" {
23922669
23932670 // Ranges can be specified using the ... syntax. These are inclusive
23942671 // both ends.
2395 5 ... 100 => 1,
2672 5...100 => 1,
23962673
23972674 // Branches can be arbitrarily complex.
23982675 101 => blk: {
......@@ -2418,14 +2695,47 @@ test "switch simple" {
24182695 assert(b == 1);
24192696}
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 };
24222732 const Item = union(enum) {
24232733 A: u32,
2424 C: struct { x: u8, y: u8 },
2734 C: Point,
24252735 D,
24262736 };
24272737
2428 var a = Item { .A = 3 };
2738 var a = Item{ .C = Point{ .x = 1, .y = 2 } };
24292739
24302740 // Switching on more complex enums is allowed.
24312741 const b = switch (a) {
......@@ -2443,27 +2753,8 @@ test "switch enum" {
24432753 Item.D => 8,
24442754 };
24452755
2446 assert(b == 3);
2447}
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 }
2756 assert(b == 6);
2757 assert(a.C.x == 2);
24672758}
24682759 {#code_end#}
24692760 {#see_also|comptime|enum|@compileError|Compile Variables#}
......@@ -3134,7 +3425,6 @@ const assert = @import("std").debug.assert;
31343425// Functions are declared like this
31353426fn add(a: i8, b: i8) i8 {
31363427 if (a == 0) {
3137 // You can still return manually if needed.
31383428 return b;
31393429 }
31403430
......@@ -3158,12 +3448,18 @@ fn abort() noreturn {
31583448 while (true) {}
31593449}
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.
31623452// This can be useful when integrating with assembly.
31633453nakedcc fn _start() noreturn {
31643454 abort();
31653455}
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
31673463// The pub specifier allows the function to be visible when importing.
31683464// Another file can use @import and call sub2
31693465pub fn sub2(a: i8, b: i8) i8 { return a - b; }
......@@ -3731,7 +4027,7 @@ fn bang2() void {
37314027 Here, the stack trace does not explain how the control
37324028 flow in {#syntax#}bar{#endsyntax#} got to the {#syntax#}hello(){#endsyntax#} call.
37334029 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,
37354031 shows exactly how the error bubbled up.
37364032 </p>
37374033 <p>
......@@ -3923,7 +4219,7 @@ test "optional type" {
39234219 cast it to a different type:
39244220 </p>
39254221 {#code_begin|syntax#}
3926const optional_value: ?i32 = null;
4222const optional_value: ?i32 = null;
39274223 {#code_end#}
39284224 {#header_close#}
39294225 {#header_open|Optional Pointers#}
......@@ -3981,7 +4277,7 @@ test "implicit cast - invoke a type as a function" {
39814277 {#code_end#}
39824278 <p>
39834279 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#}.
39854281 </p>
39864282 {#header_open|Implicit Cast: Stricter Qualification#}
39874283 <p>
......@@ -4228,9 +4524,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
42284524 {#header_close#}
42294525 {#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>
42324538 <p>
4233 {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is
4539 These types can only ever have one possible value, and thus
4540 require 0 bits to represent. Code that makes use of these types is
42344541 not included in the final generated code:
42354542 </p>
42364543 {#code_begin|syntax#}
......@@ -4240,8 +4547,8 @@ export fn entry() void {
42404547 x = y;
42414548}
42424549 {#code_end#}
4243 <p>When this turns into LLVM IR, there is no code generated in the body of {#syntax#}entry{#endsyntax#},
4244 even in debug mode. For example, on x86_64:</p>
4550 <p>When this turns into machine code, there is no code generated in the
4551 body of {#syntax#}entry{#endsyntax#}, even in {#link|Debug#} mode. For example, on x86_64:</p>
42454552 <pre><code>0000000000000010 &lt;entry&gt;:
42464553 10: 55 push %rbp
42474554 11: 48 89 e5 mov %rsp,%rbp
......@@ -4249,6 +4556,8 @@ export fn entry() void {
42494556 15: c3 retq </code></pre>
42504557 <p>These assembly instructions do not have any code associated with the void values -
42514558 they only perform the function call prologue and epilog.</p>
4559
4560 {#header_open|void#}
42524561 <p>
42534562 {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a
42544563 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}
......@@ -4320,6 +4629,38 @@ fn foo() i32 {
43204629 {#code_end#}
43214630 {#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
43234664 {#header_open|comptime#}
43244665 <p>
43254666 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 {
51015442 <p>
51025443 {#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes
51035444 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,
51055446 then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value.
51065447 Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its
51075448 promise handle with the target coroutine. It becomes the target coroutine's responsibility
......@@ -5185,7 +5526,7 @@ fn seq(c: u8) void {
51855526 </li>
51865527 </ul>
51875528 {#header_close#}
5188
5529
51895530 {#header_close#}
51905531 {#header_open|Builtin Functions#}
51915532 <p>
......@@ -5540,13 +5881,13 @@ const warn = @import("std").debug.warn;
55405881
55415882const num1 = blk: {
55425883 var val1: i32 = 99;
5543 @compileLog("comptime val1 = ", val1);
5884 @compileLog("comptime val1 = ", val1);
55445885 val1 = val1 + 1;
55455886 break :blk val1;
55465887};
55475888
55485889test "main" {
5549 @compileLog("comptime in main");
5890 @compileLog("comptime in main");
55505891
55515892 warn("Runtime in main, num1 = {}.\n", num1);
55525893}
......@@ -5556,10 +5897,10 @@ test "main" {
55565897 will ouput:
55575898 </p>
55585899 <p>
5559 If all {#syntax#}@compileLog{#endsyntax#} calls are removed or
5900 If all {#syntax#}@compileLog{#endsyntax#} calls are removed or
55605901 not encountered by analysis, the
55615902 program compiles successfully and the generated executable prints:
5562 </p>
5903 </p>
55635904 {#code_begin|test#}
55645905const warn = @import("std").debug.warn;
55655906
......@@ -5658,12 +5999,13 @@ test "main" {
56585999 {#header_close#}
56596000
56606001 {#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>
56626003 <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.
56646006 </p>
56656007 <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#}
56676009 known at {#link|comptime#}.
56686010 </p>
56696011 {#see_also|@intToEnum#}
......@@ -6104,6 +6446,10 @@ test "call foo" {
61046446 <p>
61056447 Converts a pointer of one type to a pointer of another type.
61066448 </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>
61076453 {#header_close#}
61086454
61096455 {#header_open|@ptrToInt#}
......@@ -6293,10 +6639,15 @@ pub const FloatMode = enum {
62936639 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
62946640 <p>
62956641 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.
62966643 </p>
62976644 <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#}.
62996649 </p>
6650 {#see_also|@typeInfo#}
63006651 {#header_close#}
63016652
63026653 {#header_open|@sliceToBytes#}
......@@ -6375,7 +6726,7 @@ fn List(comptime T: type) type {
63756726 <p>
63766727 When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the
63776728 current import. There is a proposal to remove the import type and use an empty struct
6378 type instead. See
6729 type instead. See
63796730 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
63806731 </p>
63816732 {#header_close#}
......@@ -6730,11 +7081,7 @@ pub fn build(b: *Builder) void {
67307081 {#header_open|Single Threaded Builds#}
67317082 <p>Zig has a compile option <code>--single-threaded</code> which has the following effects:
67327083 <ul>
6733 <li>{#link|@atomicLoad#} is emitted as a normal load.</li>
6734 <li>{#link|@atomicRmw#} is emitted as a normal memory load, modify, store.</li>
6735 <li>{#link|@fence#} becomes a no-op.</li>
6736 <li>Variables which have Thread Local Storage instead become globals. TODO thread local variables
6737 are not implemented yet.</li>
7084 <li>Variables which have Thread Local Storage instead become globals.</li>
67387085 <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.
67397086 TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li>
67407087 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
......@@ -7343,12 +7690,30 @@ fn bar(f: *Foo) void {
73437690 f.float = 12.34;
73447691}
73457692 {#code_end#}
7693 {#see_also|union|extern union#}
73467694 {#header_close#}
73477695
7348 {#header_open|Out of Bounds Float To Integer Cast#}
7696 {#header_open|Out of Bounds Float to Integer Cast#}
73497697 <p>TODO</p>
73507698 {#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
73527717 {#header_close#}
73537718 {#header_open|Memory#}
73547719 <p>TODO: explain no default allocator in zig</p>
......@@ -7439,6 +7804,7 @@ pub fn main() void {
74397804 {#code_end#}
74407805 {#see_also|String Literals#}
74417806 {#header_close#}
7807
74427808 {#header_open|Import from C Header File#}
74437809 <p>
74447810 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
......@@ -7477,6 +7843,36 @@ const c = @cImport({
74777843 {#code_end#}
74787844 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
74797845 {#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
74807876 {#header_open|Exporting a C Library#}
74817877 <p>
74827878 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:
77298125 coreclr
77308126 opencl</code></pre>
77318127 <p>
7732 The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem
8128 The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system
77338129 abstractions, and thus takes additional work to support more platforms.
77348130 Not all standard library code requires operating system abstractions, however,
77358131 so things such as generic data structures work an all above platforms.
......@@ -8164,7 +8560,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
81648560PtrTypeStart
81658561 &lt;- ASTERISK
81668562 / ASTERISK2
8167 / LBRACKET ASTERISK RBRACKET
8563 / PTRUNKNOWN
8564 / PTRC
81688565
81698566# ContainerDecl specific
81708567ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
......@@ -8262,7 +8659,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip
82628659LARROW2EQUAL &lt;- '&lt;&lt;=' skip
82638660LARROWEQUAL &lt;- '&lt;=' skip
82648661LBRACE &lt;- '{' skip
8265LBRACKET &lt;- '[' skip
8662LBRACKET &lt;- '[' ![*] skip
82668663LPAREN &lt;- '(' skip
82678664MINUS &lt;- '-' ![%=&gt;] skip
82688665MINUSEQUAL &lt;- '-=' skip
......@@ -8279,6 +8676,8 @@ PLUS2 &lt;- '++' skip
82798676PLUSEQUAL &lt;- '+=' skip
82808677PLUSPERCENT &lt;- '+%' ![=] skip
82818678PLUSPERCENTEQUAL &lt;- '+%=' skip
8679PTRC &lt;- '[*c]' skip
8680PTRUNKNOWN &lt;- '[*]' skip
82828681QUESTIONMARK &lt;- '?' skip
82838682RARROW &lt;- '&gt;' ![&gt;=] skip
82848683RARROW2 &lt;- '&gt;&gt;' ![=] skip
example/mix_o_files/build.zig+3-3
......@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;
33pub fn build(b: *Builder) void {
44 const obj = b.addObject("base64", "base64.zig");
55
6 const exe = b.addCExecutable("test");
7 exe.addCompileFlags([][]const u8{"-std=c99"});
8 exe.addSourceFile("test.c");
6 const exe = b.addExecutable("test", null);
7 exe.addCSourceFile("test.c",[][]const u8{"-std=c99"});
98 exe.addObject(obj);
9 exe.linkSystemLibrary("c");
1010
1111 b.default_step.dependOn(&exe.step);
1212
example/shared_library/build.zig+3-3
......@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;
33pub fn build(b: *Builder) void {
44 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
55
6 const exe = b.addCExecutable("test");
7 exe.addCompileFlags([][]const u8{"-std=c99"});
8 exe.addSourceFile("test.c");
6 const exe = b.addExecutable("test", null);
7 exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
98 exe.linkLibrary(lib);
9 exe.linkSystemLibrary("c");
1010
1111 b.default_step.dependOn(&exe.step);
1212
example/shared_library/mathtest.zig-9
......@@ -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
101export fn add(a: i32, b: i32) i32 {
112 return a + b;
123}
src-self-hosted/codegen.zig+21-21
......@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
137137
138138pub const ObjectFile = struct {
139139 comp: *Compilation,
140 module: llvm.ModuleRef,
141 builder: llvm.BuilderRef,
140 module: *llvm.Module,
141 builder: *llvm.Builder,
142142 dibuilder: *llvm.DIBuilder,
143 context: llvm.ContextRef,
143 context: *llvm.Context,
144144 lock: event.Lock,
145145 arena: *std.mem.Allocator,
146146
......@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
323323
324324fn addLLVMAttr(
325325 ofile: *ObjectFile,
326 val: llvm.ValueRef,
326 val: *llvm.Value,
327327 attr_index: llvm.AttributeIndex,
328328 attr_name: []const u8,
329329) !void {
......@@ -335,7 +335,7 @@ fn addLLVMAttr(
335335
336336fn addLLVMAttrStr(
337337 ofile: *ObjectFile,
338 val: llvm.ValueRef,
338 val: *llvm.Value,
339339 attr_index: llvm.AttributeIndex,
340340 attr_name: []const u8,
341341 attr_val: []const u8,
......@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
351351}
352352
353353fn addLLVMAttrInt(
354 val: llvm.ValueRef,
354 val: *llvm.Value,
355355 attr_index: llvm.AttributeIndex,
356356 attr_name: []const u8,
357357 attr_val: u64,
......@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
362362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
363363}
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 {
366366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
367367}
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 {
370370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
371371}
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 {
374374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
375375}
376376
377377fn renderLoadUntyped(
378378 ofile: *ObjectFile,
379 ptr: llvm.ValueRef,
379 ptr: *llvm.Value,
380380 alignment: Type.Pointer.Align,
381381 vol: Type.Pointer.Vol,
382382 name: [*]const u8,
383) !llvm.ValueRef {
383) !*llvm.Value {
384384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385385 switch (vol) {
386386 Type.Pointer.Vol.Non => {},
......@@ -390,11 +390,11 @@ fn renderLoadUntyped(
390390 return result;
391391}
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 {
394394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395395}
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 {
398398 const child_type = ptr_type.key.child_type;
399399 if (!child_type.hasBits()) {
400400 return null;
......@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
407407
408408pub fn renderStoreUntyped(
409409 ofile: *ObjectFile,
410 value: llvm.ValueRef,
411 ptr: llvm.ValueRef,
410 value: *llvm.Value,
411 ptr: *llvm.Value,
412412 alignment: Type.Pointer.Align,
413413 vol: Type.Pointer.Vol,
414) !llvm.ValueRef {
414) !*llvm.Value {
415415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416416 switch (vol) {
417417 Type.Pointer.Vol.Non => {},
......@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
423423
424424pub fn renderStore(
425425 ofile: *ObjectFile,
426 value: llvm.ValueRef,
427 ptr: llvm.ValueRef,
426 value: *llvm.Value,
427 ptr: *llvm.Value,
428428 ptr_type: *Type.Pointer,
429) !llvm.ValueRef {
429) !*llvm.Value {
430430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
431431}
432432
......@@ -435,7 +435,7 @@ pub fn renderAlloca(
435435 var_type: *Type,
436436 name: []const u8,
437437 alignment: Type.Pointer.Align,
438) !llvm.ValueRef {
438) !*llvm.Value {
439439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
......@@ -443,7 +443,7 @@ pub fn renderAlloca(
443443 return result;
444444}
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 {
447447 return switch (alignment) {
448448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449449 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
3737/// Data that is local to the event loop.
3838pub const ZigCompiler = struct {
3939 loop: *event.Loop,
40 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
40 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
4141 lld_lock: event.Lock,
4242
4343 /// TODO pool these so that it doesn't have to lock
......@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {
6060 return ZigCompiler{
6161 .loop = loop,
6262 .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(),
6464 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
6565 .native_libc = event.Future(LibCInstallation).init(loop),
6666 };
......@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
7070 fn deinit(self: *ZigCompiler) void {
7171 self.lld_lock.deinit();
7272 while (self.llvm_handle_pool.pop()) |node| {
73 c.LLVMContextDispose(node.data);
73 llvm.ContextDispose(node.data);
7474 self.loop.allocator.destroy(node);
7575 }
7676 }
......@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {
8080 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
8181 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
8282
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);
83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
84 errdefer llvm.ContextDispose(context_ref);
8585
86 const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node);
87 node.* = std.atomic.Stack(llvm.ContextRef).Node{
86 const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node);
87 node.* = std.atomic.Stack(*llvm.Context).Node{
8888 .next = undefined,
8989 .data = context_ref,
9090 };
......@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {
114114};
115115
116116pub const LlvmHandle = struct {
117 node: *std.atomic.Stack(llvm.ContextRef).Node,
117 node: *std.atomic.Stack(*llvm.Context).Node,
118118
119119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
120120 zig_compiler.llvm_handle_pool.push(self.node);
......@@ -128,7 +128,7 @@ pub const Compilation = struct {
128128 llvm_triple: Buffer,
129129 root_src_path: ?[]const u8,
130130 target: Target,
131 llvm_target: llvm.TargetRef,
131 llvm_target: *llvm.Target,
132132 build_mode: builtin.Mode,
133133 zig_lib_dir: []const u8,
134134 zig_std_dir: []const u8,
......@@ -212,8 +212,8 @@ pub const Compilation = struct {
212212 false_value: *Value.Bool,
213213 noreturn_value: *Value.NoReturn,
214214
215 target_machine: llvm.TargetMachineRef,
216 target_data_ref: llvm.TargetDataRef,
215 target_machine: *llvm.TargetMachine,
216 target_data_ref: *llvm.TargetData,
217217 target_layout_str: [*]u8,
218218 target_ptr_bits: u32,
219219
src-self-hosted/ir.zig+10-10
......@@ -67,7 +67,7 @@ pub const Inst = struct {
6767 parent: ?*Inst,
6868
6969 /// populated durign codegen
70 llvm_value: ?llvm.ValueRef,
70 llvm_value: ?*llvm.Value,
7171
7272 pub fn cast(base: *Inst, comptime T: type) ?*T {
7373 if (base.id == comptime typeToId(T)) {
......@@ -129,7 +129,7 @@ pub const Inst = struct {
129129 }
130130 }
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) {
133133 switch (base.id) {
134134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
......@@ -313,10 +313,10 @@ pub const Inst = struct {
313313 return new_inst;
314314 }
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 {
317317 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);
320320 for (self.params.args) |arg, i| {
321321 args[i] = arg.llvm_value.?;
322322 }
......@@ -360,7 +360,7 @@ pub const Inst = struct {
360360 return new_inst;
361361 }
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 {
364364 return self.base.val.KnownValue.getLlvmConst(ofile);
365365 }
366366 };
......@@ -392,7 +392,7 @@ pub const Inst = struct {
392392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
393393 }
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 {
396396 const value = self.params.return_value.llvm_value;
397397 const return_type = self.params.return_value.getKnownType();
398398
......@@ -540,7 +540,7 @@ pub const Inst = struct {
540540 }
541541 }
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 {
544544 switch (self.params.var_scope.data) {
545545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546546 Scope.Var.Data.Param => |param| return param.llvm_value,
......@@ -596,7 +596,7 @@ pub const Inst = struct {
596596 return new_inst;
597597 }
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 {
600600 const child_type = self.base.getKnownType();
601601 if (!child_type.hasBits()) {
602602 return null;
......@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
935935 ref_instruction: ?*Inst,
936936
937937 /// for codegen
938 llvm_block: llvm.BasicBlockRef,
939 llvm_exit_block: llvm.BasicBlockRef,
938 llvm_block: *llvm.BasicBlock,
939 llvm_exit_block: *llvm.BasicBlock,
940940
941941 /// the basic block that is derived from this one in analysis
942942 child: ?*BasicBlock,
src-self-hosted/libc_installation.zig+13-13
......@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
154154 c.ZigFindWindowsSdkError.None => {
155155 windows_sdk = sdk;
156156
157 if (sdk.msvc_lib_dir_ptr) |ptr| {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);
157 if (sdk.msvc_lib_dir_ptr != 0) {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
159159 }
160160 try group.call(findNativeKernel32LibDir, self, loop, sdk);
161161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
......@@ -172,7 +172,7 @@ pub const LibCInstallation = struct {
172172 try group.call(findNativeStaticLibDir, self, loop);
173173 try group.call(findNativeDynamicLinker, self, loop);
174174 },
175 builtin.Os.macosx, builtin.Os.freebsd => {
175 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
176176 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
177177 },
178178 else => @compileError("unimplemented: find libc for this OS"),
......@@ -283,7 +283,7 @@ pub const LibCInstallation = struct {
283283 switch (builtin.arch) {
284284 builtin.Arch.i386 => try stream.write("x86"),
285285 builtin.Arch.x86_64 => try stream.write("x64"),
286 builtin.Arch.aarch64v8 => try stream.write("arm"),
286 builtin.Arch.aarch64 => try stream.write("arm"),
287287 else => return error.UnsupportedArchitecture,
288288 }
289289 const ucrt_lib_path = try std.os.path.join(
......@@ -361,7 +361,7 @@ pub const LibCInstallation = struct {
361361 switch (builtin.arch) {
362362 builtin.Arch.i386 => try stream.write("x86\\"),
363363 builtin.Arch.x86_64 => try stream.write("x64\\"),
364 builtin.Arch.aarch64v8 => try stream.write("arm\\"),
364 builtin.Arch.aarch64 => try stream.write("arm\\"),
365365 else => return error.UnsupportedArchitecture,
366366 }
367367 const kernel32_path = try std.os.path.join(
......@@ -437,20 +437,20 @@ const Search = struct {
437437
438438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
439439 var search_end: usize = 0;
440 if (sdk.path10_ptr) |path10_ptr| {
441 if (sdk.version10_ptr) |ver10_ptr| {
440 if (sdk.path10_ptr != 0) {
441 if (sdk.version10_ptr != 0) {
442442 search_buf[search_end] = Search{
443 .path = path10_ptr[0..sdk.path10_len],
444 .version = ver10_ptr[0..sdk.version10_len],
443 .path = sdk.path10_ptr[0..sdk.path10_len],
444 .version = sdk.version10_ptr[0..sdk.version10_len],
445445 };
446446 search_end += 1;
447447 }
448448 }
449 if (sdk.path81_ptr) |path81_ptr| {
450 if (sdk.version81_ptr) |ver81_ptr| {
449 if (sdk.path81_ptr != 0) {
450 if (sdk.version81_ptr != 0) {
451451 search_buf[search_end] = Search{
452 .path = path81_ptr[0..sdk.path81_len],
453 .version = ver81_ptr[0..sdk.version81_len],
452 .path = sdk.path81_ptr[0..sdk.path81_len],
453 .version = sdk.version81_ptr[0..sdk.version81_len],
454454 };
455455 search_end += 1;
456456 }
src-self-hosted/link.zig+2-6
......@@ -145,10 +145,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
145145 // lj->args.append("-T");
146146 // lj->args.append(g->linker_script);
147147 //}
148
149 //if (g->no_rosegment_workaround) {
150 // lj->args.append("--no-rosegment");
151 //}
152148 try ctx.args.append(c"--gc-sections");
153149
154150 //lj->args.append("-m");
......@@ -330,7 +326,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
330326 switch (ctx.comp.target.getArch()) {
331327 builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),
332328 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"),
334330 else => return error.UnsupportedLinkArchitecture,
335331 }
336332
......@@ -556,7 +552,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
556552 }
557553 },
558554 DarwinPlatform.Kind.IPhoneOS => {
559 if (ctx.comp.target.getArch() == builtin.Arch.aarch64v8) {
555 if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
560556 // iOS does not need any crt1 files for arm64
561557 } else if (platform.versionLessThan(3, 1)) {
562558 try ctx.args.append(c"-lcrt1.o");
src-self-hosted/llvm.zig+129-52
......@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
1111pub const AttributeIndex = c_uint;
1212pub const Bool = c_int;
1313
14pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
15pub const ContextRef = removeNullability(c.LLVMContextRef);
16pub const ModuleRef = removeNullability(c.LLVMModuleRef);
17pub const ValueRef = removeNullability(c.LLVMValueRef);
18pub const TypeRef = removeNullability(c.LLVMTypeRef);
19pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);
20pub const AttributeRef = removeNullability(c.LLVMAttributeRef);
21pub const TargetRef = removeNullability(c.LLVMTargetRef);
22pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);
23pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);
14pub const Builder = c.LLVMBuilderRef.Child.Child;
15pub const Context = c.LLVMContextRef.Child.Child;
16pub const Module = c.LLVMModuleRef.Child.Child;
17pub const Value = c.LLVMValueRef.Child.Child;
18pub const Type = c.LLVMTypeRef.Child.Child;
19pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
20pub const Attribute = c.LLVMAttributeRef.Child.Child;
21pub const Target = c.LLVMTargetRef.Child.Child;
22pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
23pub const TargetData = c.LLVMTargetDataRef.Child.Child;
2424pub const DIBuilder = c.ZigLLVMDIBuilder;
25pub const DIFile = c.ZigLLVMDIFile;
26pub const DICompileUnit = c.ZigLLVMDICompileUnit;
2527
2628pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
2729pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
28pub const AddFunction = c.LLVMAddFunction;
29pub const AddGlobal = c.LLVMAddGlobal;
3030pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
3131pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
32pub const ArrayType = c.LLVMArrayType;
33pub const BuildLoad = c.LLVMBuildLoad;
3432pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
3533pub const ConstAllOnes = c.LLVMConstAllOnes;
3634pub const ConstArray = c.LLVMConstArray;
3735pub const ConstBitCast = c.LLVMConstBitCast;
38pub const ConstInt = c.LLVMConstInt;
3936pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
4037pub const ConstNeg = c.LLVMConstNeg;
41pub const ConstNull = c.LLVMConstNull;
42pub const ConstStringInContext = c.LLVMConstStringInContext;
4338pub 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;
5339pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
5440pub const DisposeBuilder = c.LLVMDisposeBuilder;
5541pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
......@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
6248pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
6349pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
6450pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
65pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
6651pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
67pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
6852pub const GetUndef = c.LLVMGetUndef;
6953pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
7054pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
......@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
8165pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
8266pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
8367pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
84pub const IntTypeInContext = c.LLVMIntTypeInContext;
8568pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
8669pub const MDNodeInContext = c.LLVMMDNodeInContext;
8770pub const MDStringInContext = c.LLVMMDStringInContext;
8871pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
89pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
9072pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
91pub const PointerType = c.LLVMPointerType;
9273pub const SetAlignment = c.LLVMSetAlignment;
9374pub const SetDataLayout = c.LLVMSetDataLayout;
9475pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
......@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
9980pub const SetVolatile = c.LLVMSetVolatile;
10081pub const StructTypeInContext = c.LLVMStructTypeInContext;
10182pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
102pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
10383pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
10484pub 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
106183pub const GetElementType = LLVMGetElementType;
107extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;
184extern fn LLVMGetElementType(Ty: *Type) *Type;
108185
109186pub const TypeOf = LLVMTypeOf;
110extern fn LLVMTypeOf(Val: ValueRef) TypeRef;
187extern fn LLVMTypeOf(Val: *Value) *Type;
111188
112189pub const BuildStore = LLVMBuildStore;
113extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;
190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
114191
115192pub 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
118195pub 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
121198pub 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
124201pub const VerifyModule = LLVMVerifyModule;
125extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
126203
127204pub const GetInsertBlock = LLVMGetInsertBlock;
128extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;
205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
129206
130207pub const FunctionType = LLVMFunctionType;
131208extern fn LLVMFunctionType(
132 ReturnType: TypeRef,
133 ParamTypes: [*]TypeRef,
209 ReturnType: *Type,
210 ParamTypes: [*]*Type,
134211 ParamCount: c_uint,
135212 IsVarArg: Bool,
136) ?TypeRef;
213) ?*Type;
137214
138215pub const GetParam = LLVMGetParam;
139extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;
216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
140217
141218pub 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
144221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
145extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;
222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
146223
147224pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
148225pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
......@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
190267};
191268
192269fn removeNullability(comptime T: type) type {
193 comptime assert(@typeId(T) == builtin.TypeId.Optional);
194 return T.Child;
270 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
271 return *T.Child;
195272}
196273
197274pub const BuildRet = LLVMBuildRet;
198extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;
275extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
199276
200277pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
201278extern fn ZigLLVMTargetMachineEmitToFile(
202 targ_machine_ref: TargetMachineRef,
203 module_ref: ModuleRef,
279 targ_machine_ref: *TargetMachine,
280 module_ref: *Module,
204281 filename: [*]const u8,
205282 output_type: EmitOutputType,
206283 error_message: *[*]u8,
......@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
209286) bool;
210287
211288pub 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
214291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/main.zig+10-14
......@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
2424var stderr: *io.OutStream(os.File.WriteError) = undefined;
2525var stdout: *io.OutStream(os.File.WriteError) = undefined;
2626
27const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
27pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
2828
2929const usage =
3030 \\usage: zig [command] [options]
......@@ -154,9 +154,7 @@ const usage_build_generic =
154154 \\ release-small optimize for small binary, safety off
155155 \\ --static Output will be statically linked
156156 \\ --strip Exclude debug symbols
157 \\ --target-arch [name] Specify target architecture
158 \\ --target-environ [name] Specify target environment
159 \\ --target-os [name] Specify target operating system
157 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
160158 \\ --verbose-tokenize Turn on compiler debug output for tokenization
161159 \\ --verbose-ast-tree Turn on compiler debug output for parsing into an AST (tree view)
162160 \\ --verbose-ast-fmt Turn on compiler debug output for parsing into an AST (render source)
......@@ -220,9 +218,7 @@ const args_build_generic = []Flag{
220218 Flag.Bool("--pkg-end"),
221219 Flag.Bool("--static"),
222220 Flag.Bool("--strip"),
223 Flag.Arg1("--target-arch"),
224 Flag.Arg1("--target-environ"),
225 Flag.Arg1("--target-os"),
221 Flag.Arg1("-target"),
226222 Flag.Bool("--verbose-tokenize"),
227223 Flag.Bool("--verbose-ast-tree"),
228224 Flag.Bool("--verbose-ast-fmt"),
......@@ -510,7 +506,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
510506 return buildOutputType(allocator, args, Compilation.Kind.Obj);
511507}
512508
513const usage_fmt =
509pub const usage_fmt =
514510 \\usage: zig fmt [file]...
515511 \\
516512 \\ Formats the input files and modifies them in-place.
......@@ -527,7 +523,7 @@ const usage_fmt =
527523 \\
528524;
529525
530const args_fmt_spec = []Flag{
526pub const args_fmt_spec = []Flag{
531527 Flag.Bool("--help"),
532528 Flag.Bool("--check"),
533529 Flag.Option("--color", []const []const u8{
......@@ -839,15 +835,15 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
839835 }
840836 try stdout.write("\n");
841837
842 try stdout.write("Environments:\n");
838 try stdout.write("C ABIs:\n");
843839 {
844840 comptime var i: usize = 0;
845 inline while (i < @memberCount(builtin.Environ)) : (i += 1) {
846 comptime const environ_tag = @memberName(builtin.Environ, i);
841 inline while (i < @memberCount(builtin.Abi)) : (i += 1) {
842 comptime const abi_tag = @memberName(builtin.Abi, i);
847843 // 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);
851847 }
852848 }
853849}
src-self-hosted/scope.zig+1-1
......@@ -362,7 +362,7 @@ pub const Scope = struct {
362362 pub const Param = struct {
363363 index: usize,
364364 typ: *Type,
365 llvm_value: llvm.ValueRef,
365 llvm_value: *llvm.Value,
366366 };
367367
368368 pub fn createParam(
src-self-hosted/target.zig+47-234
......@@ -16,7 +16,7 @@ pub const Target = union(enum) {
1616 pub const Cross = struct {
1717 arch: builtin.Arch,
1818 os: builtin.Os,
19 environ: builtin.Environ,
19 abi: builtin.Abi,
2020 object_format: builtin.ObjectFormat,
2121 };
2222
......@@ -49,16 +49,16 @@ pub const Target = union(enum) {
4949 }
5050
5151 pub fn getArch(self: Target) builtin.Arch {
52 return switch (self) {
53 Target.Native => builtin.arch,
54 @TagType(Target).Cross => |t| t.arch,
55 };
52 switch (self) {
53 Target.Native => return builtin.arch,
54 @TagType(Target).Cross => |t| return t.arch,
55 }
5656 }
5757
58 pub fn getEnviron(self: Target) builtin.Environ {
58 pub fn getAbi(self: Target) builtin.Abi {
5959 return switch (self) {
60 Target.Native => builtin.environ,
61 @TagType(Target).Cross => |t| t.environ,
60 Target.Native => builtin.abi,
61 @TagType(Target).Cross => |t| t.abi,
6262 };
6363 }
6464
......@@ -93,50 +93,10 @@ pub const Target = union(enum) {
9393 /// TODO expose the arch and subarch separately
9494 pub fn isArmOrThumb(self: Target) bool {
9595 return switch (self.getArch()) {
96 builtin.Arch.armv8_5a,
97 builtin.Arch.armv8_4a,
98 builtin.Arch.armv8_3a,
99 builtin.Arch.armv8_2a,
100 builtin.Arch.armv8_1a,
101 builtin.Arch.armv8,
102 builtin.Arch.armv8r,
103 builtin.Arch.armv8m_baseline,
104 builtin.Arch.armv8m_mainline,
105 builtin.Arch.armv7,
106 builtin.Arch.armv7em,
107 builtin.Arch.armv7m,
108 builtin.Arch.armv7s,
109 builtin.Arch.armv7k,
110 builtin.Arch.armv7ve,
111 builtin.Arch.armv6,
112 builtin.Arch.armv6m,
113 builtin.Arch.armv6k,
114 builtin.Arch.armv6t2,
115 builtin.Arch.armv5,
116 builtin.Arch.armv5te,
117 builtin.Arch.armv4t,
118 builtin.Arch.armebv8_5a,
119 builtin.Arch.armebv8_4a,
120 builtin.Arch.armebv8_3a,
121 builtin.Arch.armebv8_2a,
122 builtin.Arch.armebv8_1a,
123 builtin.Arch.armebv8,
124 builtin.Arch.armebv8r,
125 builtin.Arch.armebv8m_baseline,
126 builtin.Arch.armebv8m_mainline,
127 builtin.Arch.armebv7,
128 builtin.Arch.armebv7em,
129 builtin.Arch.armebv7m,
130 builtin.Arch.armebv7s,
131 builtin.Arch.armebv7k,
132 builtin.Arch.armebv7ve,
133 builtin.Arch.armebv6,
134 builtin.Arch.armebv6m,
135 builtin.Arch.armebv6k,
136 builtin.Arch.armebv6t2,
137 builtin.Arch.armebv5,
138 builtin.Arch.armebv5te,
139 builtin.Arch.armebv4t,
96 builtin.Arch.arm,
97 builtin.Arch.armeb,
98 builtin.Arch.aarch64,
99 builtin.Arch.aarch64_be,
140100 builtin.Arch.thumb,
141101 builtin.Arch.thumbeb,
142102 => true,
......@@ -159,14 +119,14 @@ pub const Target = union(enum) {
159119 // LLVM WebAssembly output support requires the target to be activated at
160120 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
161121 //
162 // LLVM determines the output format based on the environment suffix,
122 // LLVM determines the output format based on the abi suffix,
163123 // defaulting to an object based on the architecture. The default format in
164124 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
165125 // explicitly set this ourself in order for it to work.
166126 //
167127 // This is fixed in LLVM 7 and you will be able to get wasm output by
168128 // 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
171131 var out = &std.io.BufferOutStream.init(&result).stream;
172132 try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name);
......@@ -185,50 +145,8 @@ pub const Target = union(enum) {
185145 => return 16,
186146
187147 builtin.Arch.arc,
188 builtin.Arch.armv8_5a,
189 builtin.Arch.armv8_4a,
190 builtin.Arch.armv8_3a,
191 builtin.Arch.armv8_2a,
192 builtin.Arch.armv8_1a,
193 builtin.Arch.armv8,
194 builtin.Arch.armv8r,
195 builtin.Arch.armv8m_baseline,
196 builtin.Arch.armv8m_mainline,
197 builtin.Arch.armv7,
198 builtin.Arch.armv7em,
199 builtin.Arch.armv7m,
200 builtin.Arch.armv7s,
201 builtin.Arch.armv7k,
202 builtin.Arch.armv7ve,
203 builtin.Arch.armv6,
204 builtin.Arch.armv6m,
205 builtin.Arch.armv6k,
206 builtin.Arch.armv6t2,
207 builtin.Arch.armv5,
208 builtin.Arch.armv5te,
209 builtin.Arch.armv4t,
210 builtin.Arch.armebv8_5a,
211 builtin.Arch.armebv8_4a,
212 builtin.Arch.armebv8_3a,
213 builtin.Arch.armebv8_2a,
214 builtin.Arch.armebv8_1a,
215 builtin.Arch.armebv8,
216 builtin.Arch.armebv8r,
217 builtin.Arch.armebv8m_baseline,
218 builtin.Arch.armebv8m_mainline,
219 builtin.Arch.armebv7,
220 builtin.Arch.armebv7em,
221 builtin.Arch.armebv7m,
222 builtin.Arch.armebv7s,
223 builtin.Arch.armebv7k,
224 builtin.Arch.armebv7ve,
225 builtin.Arch.armebv6,
226 builtin.Arch.armebv6m,
227 builtin.Arch.armebv6k,
228 builtin.Arch.armebv6t2,
229 builtin.Arch.armebv5,
230 builtin.Arch.armebv5te,
231 builtin.Arch.armebv4t,
148 builtin.Arch.arm,
149 builtin.Arch.armeb,
232150 builtin.Arch.hexagon,
233151 builtin.Arch.le32,
234152 builtin.Arch.mipsr6,
......@@ -248,35 +166,17 @@ pub const Target = union(enum) {
248166 builtin.Arch.amdil,
249167 builtin.Arch.hsail,
250168 builtin.Arch.spir,
251 builtin.Arch.kalimbav3,
252 builtin.Arch.kalimbav4,
253 builtin.Arch.kalimbav5,
169 builtin.Arch.kalimba,
254170 builtin.Arch.shave,
255171 builtin.Arch.lanai,
256172 builtin.Arch.wasm32,
257173 builtin.Arch.renderscript32,
258174 => return 32,
259175
260 builtin.Arch.aarch64v8_5a,
261 builtin.Arch.aarch64v8_4a,
262 builtin.Arch.aarch64v8_3a,
263 builtin.Arch.aarch64v8_2a,
264 builtin.Arch.aarch64v8_1a,
265 builtin.Arch.aarch64v8,
266 builtin.Arch.aarch64v8r,
267 builtin.Arch.aarch64v8m_baseline,
268 builtin.Arch.aarch64v8m_mainline,
269 builtin.Arch.aarch64_bev8_5a,
270 builtin.Arch.aarch64_bev8_4a,
271 builtin.Arch.aarch64_bev8_3a,
272 builtin.Arch.aarch64_bev8_2a,
273 builtin.Arch.aarch64_bev8_1a,
274 builtin.Arch.aarch64_bev8,
275 builtin.Arch.aarch64_bev8r,
276 builtin.Arch.aarch64_bev8m_baseline,
277 builtin.Arch.aarch64_bev8m_mainline,
278 builtin.Arch.mips64r6,
279 builtin.Arch.mips64elr6,
176 builtin.Arch.aarch64,
177 builtin.Arch.aarch64_be,
178 builtin.Arch.mips64,
179 builtin.Arch.mips64el,
280180 builtin.Arch.powerpc64,
281181 builtin.Arch.powerpc64le,
282182 builtin.Arch.riscv64,
......@@ -298,17 +198,17 @@ pub const Target = union(enum) {
298198 }
299199
300200 pub fn getFloatAbi(self: Target) FloatAbi {
301 return switch (self.getEnviron()) {
302 builtin.Environ.gnueabihf,
303 builtin.Environ.eabihf,
304 builtin.Environ.musleabihf,
201 return switch (self.getAbi()) {
202 builtin.Abi.gnueabihf,
203 builtin.Abi.eabihf,
204 builtin.Abi.musleabihf,
305205 => FloatAbi.Hard,
306206 else => FloatAbi.Soft,
307207 };
308208 }
309209
310210 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
311 const env = self.getEnviron();
211 const env = self.getAbi();
312212 const arch = self.getArch();
313213 const os = self.getOs();
314214 switch (os) {
......@@ -317,21 +217,21 @@ pub const Target = union(enum) {
317217 },
318218 builtin.Os.linux => {
319219 switch (env) {
320 builtin.Environ.android => {
220 builtin.Abi.android => {
321221 if (self.is64bit()) {
322222 return "/system/bin/linker64";
323223 } else {
324224 return "/system/bin/linker";
325225 }
326226 },
327 builtin.Environ.gnux32 => {
227 builtin.Abi.gnux32 => {
328228 if (arch == builtin.Arch.x86_64) {
329229 return "/libx32/ld-linux-x32.so.2";
330230 }
331231 },
332 builtin.Environ.musl,
333 builtin.Environ.musleabi,
334 builtin.Environ.musleabihf,
232 builtin.Abi.musl,
233 builtin.Abi.musleabi,
234 builtin.Abi.musleabihf,
335235 => {
336236 if (arch == builtin.Arch.x86_64) {
337237 return "/lib/ld-musl-x86_64.so.1";
......@@ -345,73 +245,18 @@ pub const Target = union(enum) {
345245 builtin.Arch.sparcel,
346246 => return "/lib/ld-linux.so.2",
347247
348 builtin.Arch.aarch64v8_5a,
349 builtin.Arch.aarch64v8_4a,
350 builtin.Arch.aarch64v8_3a,
351 builtin.Arch.aarch64v8_2a,
352 builtin.Arch.aarch64v8_1a,
353 builtin.Arch.aarch64v8,
354 builtin.Arch.aarch64v8r,
355 builtin.Arch.aarch64v8m_baseline,
356 builtin.Arch.aarch64v8m_mainline,
357 => return "/lib/ld-linux-aarch64.so.1",
358
359 builtin.Arch.aarch64_bev8_5a,
360 builtin.Arch.aarch64_bev8_4a,
361 builtin.Arch.aarch64_bev8_3a,
362 builtin.Arch.aarch64_bev8_2a,
363 builtin.Arch.aarch64_bev8_1a,
364 builtin.Arch.aarch64_bev8,
365 builtin.Arch.aarch64_bev8r,
366 builtin.Arch.aarch64_bev8m_baseline,
367 builtin.Arch.aarch64_bev8m_mainline,
368 => return "/lib/ld-linux-aarch64_be.so.1",
369
370 builtin.Arch.armv8_5a,
371 builtin.Arch.armv8_4a,
372 builtin.Arch.armv8_3a,
373 builtin.Arch.armv8_2a,
374 builtin.Arch.armv8_1a,
375 builtin.Arch.armv8,
376 builtin.Arch.armv8r,
377 builtin.Arch.armv8m_baseline,
378 builtin.Arch.armv8m_mainline,
379 builtin.Arch.armv7,
380 builtin.Arch.armv7em,
381 builtin.Arch.armv7m,
382 builtin.Arch.armv7s,
383 builtin.Arch.armv7k,
384 builtin.Arch.armv7ve,
385 builtin.Arch.armv6,
386 builtin.Arch.armv6m,
387 builtin.Arch.armv6k,
388 builtin.Arch.armv6t2,
389 builtin.Arch.armv5,
390 builtin.Arch.armv5te,
391 builtin.Arch.armv4t,
248 builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
249
250 builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
251
252 builtin.Arch.arm,
392253 builtin.Arch.thumb,
393 builtin.Arch.armebv8_5a,
394 builtin.Arch.armebv8_4a,
395 builtin.Arch.armebv8_3a,
396 builtin.Arch.armebv8_2a,
397 builtin.Arch.armebv8_1a,
398 builtin.Arch.armebv8,
399 builtin.Arch.armebv8r,
400 builtin.Arch.armebv8m_baseline,
401 builtin.Arch.armebv8m_mainline,
402 builtin.Arch.armebv7,
403 builtin.Arch.armebv7em,
404 builtin.Arch.armebv7m,
405 builtin.Arch.armebv7s,
406 builtin.Arch.armebv7k,
407 builtin.Arch.armebv7ve,
408 builtin.Arch.armebv6,
409 builtin.Arch.armebv6m,
410 builtin.Arch.armebv6k,
411 builtin.Arch.armebv6t2,
412 builtin.Arch.armebv5,
413 builtin.Arch.armebv5te,
414 builtin.Arch.armebv4t,
254 => return switch (self.getFloatAbi()) {
255 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
256 else => return "/lib/ld-linux.so.3",
257 },
258
259 builtin.Arch.armeb,
415260 builtin.Arch.thumbeb,
416261 => return switch (self.getFloatAbi()) {
417262 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
......@@ -454,9 +299,7 @@ pub const Target = union(enum) {
454299 builtin.Arch.hsail64,
455300 builtin.Arch.spir,
456301 builtin.Arch.spir64,
457 builtin.Arch.kalimbav3,
458 builtin.Arch.kalimbav4,
459 builtin.Arch.kalimbav5,
302 builtin.Arch.kalimba,
460303 builtin.Arch.shave,
461304 builtin.Arch.lanai,
462305 builtin.Arch.wasm32,
......@@ -470,8 +313,8 @@ pub const Target = union(enum) {
470313 }
471314 }
472315
473 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
474 var result: llvm.TargetRef = undefined;
316 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
317 var result: *llvm.Target = undefined;
475318 var err_msg: [*]u8 = undefined;
476319 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
477320 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
......@@ -582,39 +425,9 @@ pub const Target = union(enum) {
582425 pub fn getDarwinArchString(self: Target) []const u8 {
583426 const arch = self.getArch();
584427 switch (arch) {
585 builtin.Arch.aarch64v8_5a,
586 builtin.Arch.aarch64v8_4a,
587 builtin.Arch.aarch64v8_3a,
588 builtin.Arch.aarch64v8_2a,
589 builtin.Arch.aarch64v8_1a,
590 builtin.Arch.aarch64v8,
591 builtin.Arch.aarch64v8r,
592 builtin.Arch.aarch64v8m_baseline,
593 builtin.Arch.aarch64v8m_mainline,
594 => return "arm64",
428 builtin.Arch.aarch64 => return "arm64",
595429 builtin.Arch.thumb,
596 builtin.Arch.armv8_5a,
597 builtin.Arch.armv8_4a,
598 builtin.Arch.armv8_3a,
599 builtin.Arch.armv8_2a,
600 builtin.Arch.armv8_1a,
601 builtin.Arch.armv8,
602 builtin.Arch.armv8r,
603 builtin.Arch.armv8m_baseline,
604 builtin.Arch.armv8m_mainline,
605 builtin.Arch.armv7,
606 builtin.Arch.armv7em,
607 builtin.Arch.armv7m,
608 builtin.Arch.armv7s,
609 builtin.Arch.armv7k,
610 builtin.Arch.armv7ve,
611 builtin.Arch.armv6,
612 builtin.Arch.armv6m,
613 builtin.Arch.armv6k,
614 builtin.Arch.armv6t2,
615 builtin.Arch.armv5,
616 builtin.Arch.armv5te,
617 builtin.Arch.armv4t,
430 builtin.Arch.arm,
618431 => return "arm",
619432 builtin.Arch.powerpc => return "ppc",
620433 builtin.Arch.powerpc64 => return "ppc64",
src-self-hosted/type.zig+23-21
......@@ -51,8 +51,8 @@ pub const Type = struct {
5151 pub fn getLlvmType(
5252 base: *Type,
5353 allocator: *Allocator,
54 llvm_context: llvm.ContextRef,
55 ) (error{OutOfMemory}!llvm.TypeRef) {
54 llvm_context: *llvm.Context,
55 ) (error{OutOfMemory}!*llvm.Type) {
5656 switch (base.id) {
5757 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
5858 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
......@@ -196,7 +196,7 @@ pub const Type = struct {
196196 }
197197
198198 /// 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 {
200200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
201201
202202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
......@@ -205,7 +205,7 @@ pub const Type = struct {
205205 }
206206
207207 /// 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 {
209209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
210210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
211211 }
......@@ -218,7 +218,7 @@ pub const Type = struct {
218218 comp.gpa().destroy(self);
219219 }
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 {
222222 @panic("TODO");
223223 }
224224 };
......@@ -496,13 +496,13 @@ pub const Type = struct {
496496 comp.gpa().destroy(self);
497497 }
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 {
500500 const normal = &self.key.data.Normal;
501501 const llvm_return_type = switch (normal.return_type.id) {
502502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
503503 else => try normal.return_type.getLlvmType(allocator, llvm_context),
504504 };
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);
506506 defer allocator.free(llvm_param_types);
507507 for (llvm_param_types) |*llvm_param_type, i| {
508508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
......@@ -559,7 +559,7 @@ pub const Type = struct {
559559 comp.gpa().destroy(self);
560560 }
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 {
563563 @panic("TODO");
564564 }
565565 };
......@@ -658,7 +658,7 @@ pub const Type = struct {
658658 comp.gpa().destroy(self);
659659 }
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 {
662662 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
663663 }
664664 };
......@@ -670,7 +670,7 @@ pub const Type = struct {
670670 comp.gpa().destroy(self);
671671 }
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 {
674674 @panic("TODO");
675675 }
676676 };
......@@ -794,6 +794,7 @@ pub const Type = struct {
794794 Size.One => "*",
795795 Size.Many => "[*]",
796796 Size.Slice => "[]",
797 Size.C => "[*c]",
797798 };
798799 const mut_str = switch (self.key.mut) {
799800 Mut.Const => "const ",
......@@ -835,7 +836,7 @@ pub const Type = struct {
835836 return self;
836837 }
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 {
839840 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
840841 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
841842 }
......@@ -903,7 +904,7 @@ pub const Type = struct {
903904 return self;
904905 }
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 {
907908 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
908909 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
909910 }
......@@ -916,7 +917,7 @@ pub const Type = struct {
916917 comp.gpa().destroy(self);
917918 }
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 {
920921 @panic("TODO");
921922 }
922923 };
......@@ -966,7 +967,7 @@ pub const Type = struct {
966967 comp.gpa().destroy(self);
967968 }
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 {
970971 @panic("TODO");
971972 }
972973 };
......@@ -978,7 +979,7 @@ pub const Type = struct {
978979 comp.gpa().destroy(self);
979980 }
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 {
982983 @panic("TODO");
983984 }
984985 };
......@@ -990,7 +991,7 @@ pub const Type = struct {
990991 comp.gpa().destroy(self);
991992 }
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 {
994995 @panic("TODO");
995996 }
996997 };
......@@ -1002,7 +1003,7 @@ pub const Type = struct {
10021003 comp.gpa().destroy(self);
10031004 }
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 {
10061007 @panic("TODO");
10071008 }
10081009 };
......@@ -1014,7 +1015,7 @@ pub const Type = struct {
10141015 comp.gpa().destroy(self);
10151016 }
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 {
10181019 @panic("TODO");
10191020 }
10201021 };
......@@ -1034,7 +1035,7 @@ pub const Type = struct {
10341035 comp.gpa().destroy(self);
10351036 }
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 {
10381039 @panic("TODO");
10391040 }
10401041 };
......@@ -1054,7 +1055,7 @@ pub const Type = struct {
10541055 comp.gpa().destroy(self);
10551056 }
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 {
10581059 @panic("TODO");
10591060 }
10601061 };
......@@ -1066,7 +1067,7 @@ pub const Type = struct {
10661067 comp.gpa().destroy(self);
10671068 }
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 {
10701071 @panic("TODO");
10711072 }
10721073 };
......@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
10881089 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
10891090 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
10901091 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1092 builtin.TypeInfo.Pointer.Size.C => unreachable,
10911093 }
10921094 },
10931095 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
src-self-hosted/value.zig+9-9
......@@ -57,7 +57,7 @@ pub const Value = struct {
5757 std.debug.warn("{}", @tagName(base.id));
5858 }
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) {
6161 switch (base.id) {
6262 Id.Type => unreachable,
6363 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
......@@ -153,7 +153,7 @@ pub const Value = struct {
153153 comp.gpa().destroy(self);
154154 }
155155
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
157157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
158158 const llvm_fn = llvm.AddFunction(
159159 ofile.module,
......@@ -238,7 +238,7 @@ pub const Value = struct {
238238 /// We know that the function definition will end up in an .o file somewhere.
239239 /// Here, all we have to do is generate a global prototype.
240240 /// 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 {
242242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
243243 const llvm_fn = llvm.AddFunction(
244244 ofile.module,
......@@ -283,8 +283,8 @@ pub const Value = struct {
283283 comp.gpa().destroy(self);
284284 }
285285
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context);
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
288288 if (self.x) {
289289 return llvm.ConstAllOnes(llvm_type);
290290 } else {
......@@ -381,7 +381,7 @@ pub const Value = struct {
381381 comp.gpa().destroy(self);
382382 }
383383
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
385385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
386386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
387387 switch (self.special) {
......@@ -391,7 +391,7 @@ pub const Value = struct {
391391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
392392 const ptr_bit_count = ofile.comp.target_ptr_bits;
393393 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{
395395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
396396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
397397 };
......@@ -459,7 +459,7 @@ pub const Value = struct {
459459 comp.gpa().destroy(self);
460460 }
461461
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
463463 switch (self.special) {
464464 Special.Undefined => {
465465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
......@@ -534,7 +534,7 @@ pub const Value = struct {
534534 return self;
535535 }
536536
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
538538 switch (self.base.typ.id) {
539539 Type.Id.Int => {
540540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
src/all_types.hpp+112-50
......@@ -18,6 +18,7 @@
1818#include "bigfloat.hpp"
1919#include "target.hpp"
2020#include "tokenizer.hpp"
21#include "libc_installation.hpp"
2122
2223struct AstNode;
2324struct ImportTableEntry;
......@@ -630,24 +631,12 @@ struct AstNodeUnwrapOptional {
630631 AstNode *expr;
631632};
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
646634struct AstNodeFnCallExpr {
647635 AstNode *fn_ref_expr;
648636 ZigList<AstNode *> params;
649637 bool is_builtin;
650638 bool is_async;
639 bool seen; // used by @compileLog
651640 AstNode *async_allocator;
652641};
653642
......@@ -691,15 +680,17 @@ struct AstNodePointerType {
691680 AstNode *align_expr;
692681 BigInt *bit_offset_start;
693682 BigInt *host_int_bytes;
683 AstNode *op_expr;
684 Token *allow_zero_token;
694685 bool is_const;
695686 bool is_volatile;
696 AstNode *op_expr;
697687};
698688
699689struct AstNodeArrayType {
700690 AstNode *size;
701691 AstNode *child_type;
702692 AstNode *align_expr;
693 Token *allow_zero_token;
703694 bool is_const;
704695 bool is_volatile;
705696};
......@@ -1038,6 +1029,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
10381029enum PtrLen {
10391030 PtrLenUnknown,
10401031 PtrLenSingle,
1032 PtrLenC,
10411033};
10421034
10431035struct ZigTypePointer {
......@@ -1049,6 +1041,7 @@ struct ZigTypePointer {
10491041 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
10501042 bool is_const;
10511043 bool is_volatile;
1044 bool allow_zero;
10521045};
10531046
10541047struct ZigTypeInt {
......@@ -1247,6 +1240,12 @@ enum ZigTypeId {
12471240 ZigTypeIdVector,
12481241};
12491242
1243enum OnePossibleValue {
1244 OnePossibleValueInvalid,
1245 OnePossibleValueNo,
1246 OnePossibleValueYes,
1247};
1248
12501249struct ZigType {
12511250 ZigTypeId id;
12521251 Buf name;
......@@ -1254,9 +1253,6 @@ struct ZigType {
12541253 LLVMTypeRef type_ref;
12551254 ZigLLVMDIType *di_type;
12561255
1257 bool zero_bits; // this is denormalized data
1258 bool gen_h_loop_flag;
1259
12601256 union {
12611257 ZigTypePointer pointer;
12621258 ZigTypeInt integral;
......@@ -1282,6 +1278,11 @@ struct ZigType {
12821278 // If we generate a constant name value for this type, we memoize it here.
12831279 // The type of this is array
12841280 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;
12851286};
12861287
12871288struct PackageTableEntry {
......@@ -1340,15 +1341,11 @@ struct ZigFn {
13401341 // in the case of async functions this is the implicit return type according to the
13411342 // zig source code, not according to zig ir
13421343 ZigType *src_implicit_return_type;
1343 bool is_test;
1344 FnInline fn_inline;
1345 FnAnalState anal_state;
13461344 IrExecutable ir_executable;
13471345 IrExecutable analyzed_executable;
13481346 size_t prealloc_bbc;
13491347 AstNode **param_source_nodes;
13501348 Buf **param_names;
1351 uint32_t align_bytes;
13521349
13531350 AstNode *fn_no_inline_set_node;
13541351 AstNode *fn_static_eval_set_node;
......@@ -1358,13 +1355,22 @@ struct ZigFn {
13581355
13591356 Buf *section_name;
13601357 AstNode *set_alignstack_node;
1361 uint32_t alignstack_value;
13621358
13631359 AstNode *set_cold_node;
1364 bool is_cold;
13651360
13661361 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
13671371 bool calls_or_awaits_errorable_fn;
1372 bool is_cold;
1373 bool is_test;
13681374};
13691375
13701376uint32_t fn_table_entry_hash(ZigFn*);
......@@ -1484,6 +1490,7 @@ enum PanicMsgId {
14841490 PanicMsgIdBadUnionField,
14851491 PanicMsgIdBadEnumValue,
14861492 PanicMsgIdFloatToInt,
1493 PanicMsgIdPtrCastNull,
14871494
14881495 PanicMsgIdCount,
14891496};
......@@ -1498,11 +1505,12 @@ struct TypeId {
14981505 struct {
14991506 ZigType *child_type;
15001507 PtrLen ptr_len;
1501 bool is_const;
1502 bool is_volatile;
15031508 uint32_t alignment;
15041509 uint32_t bit_offset_in_host;
15051510 uint32_t host_int_bytes;
1511 bool is_const;
1512 bool is_volatile;
1513 bool allow_zero;
15061514 } pointer;
15071515 struct {
15081516 ZigType *child_type;
......@@ -1605,6 +1613,17 @@ struct LinkLib {
16051613 bool provided_explicitly;
16061614};
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
16081627// When adding fields, check if they should be added to the hash computation in build_with_cache
16091628struct CodeGen {
16101629 //////////////////////////// Runtime State
......@@ -1660,7 +1679,7 @@ struct CodeGen {
16601679 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
16611680 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
16621681 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;
16641683 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
16651684 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
16661685 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
......@@ -1732,12 +1751,16 @@ struct CodeGen {
17321751 Buf triple_str;
17331752 Buf global_asm;
17341753 Buf *out_h_path;
1754 Buf *out_lib_path;
17351755 Buf artifact_dir;
17361756 Buf output_file_path;
17371757 Buf o_file_output_path;
17381758 Buf *wanted_output_file_path;
17391759 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
17411764 IrInstruction *invalid_instruction;
17421765 IrInstruction *unreach_instruction;
17431766
......@@ -1752,6 +1775,7 @@ struct CodeGen {
17521775 ZigFn *cur_fn;
17531776 ZigFn *main_fn;
17541777 ZigFn *panic_fn;
1778 TldFn *panic_tld_fn;
17551779 AstNode *root_export_decl;
17561780
17571781 CacheHash cache_hash;
......@@ -1760,7 +1784,8 @@ struct CodeGen {
17601784 unsigned pointer_size_bytes;
17611785 uint32_t target_os_index;
17621786 uint32_t target_arch_index;
1763 uint32_t target_environ_index;
1787 uint32_t target_sub_arch_index;
1788 uint32_t target_abi_index;
17641789 uint32_t target_oformat_index;
17651790 bool is_big_endian;
17661791 bool have_pub_main;
......@@ -1778,13 +1803,17 @@ struct CodeGen {
17781803 bool verbose_ir;
17791804 bool verbose_llvm_ir;
17801805 bool verbose_cimport;
1806 bool verbose_cc;
17811807 bool error_during_imports;
17821808 bool generate_error_name_table;
17831809 bool enable_cache;
17841810 bool enable_time_report;
17851811 bool system_linker_hack;
1812 bool reported_bad_link_libc_error;
17861813
17871814 //////////////////////////// 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.
17881817 ZigList<LinkLib *> link_libs_list;
17891818 // add -framework [name] args to linker
17901819 ZigList<Buf *> darwin_frameworks;
......@@ -1793,8 +1822,11 @@ struct CodeGen {
17931822 ZigList<Buf *> forbidden_libs;
17941823 ZigList<Buf *> link_objects;
17951824 ZigList<Buf *> assembly_files;
1825 ZigList<CFile *> c_source_files;
17961826 ZigList<const char *> lib_dirs;
17971827
1828 ZigLibCInstallation *libc;
1829
17981830 size_t version_major;
17991831 size_t version_minor;
18001832 size_t version_patch;
......@@ -1803,15 +1835,14 @@ struct CodeGen {
18031835 EmitFileType emit_file_type;
18041836 BuildMode build_mode;
18051837 OutType out_type;
1806 ZigTarget zig_target;
1838 const ZigTarget *zig_target;
18071839 TargetSubsystem subsystem;
1840 ValgrindSupport valgrind_support;
18081841 bool is_static;
18091842 bool strip_debug_symbols;
18101843 bool is_test_build;
18111844 bool is_single_threaded;
1812 bool is_native_target;
18131845 bool linker_rdynamic;
1814 bool no_rosegment_workaround;
18151846 bool each_lib_rpath;
18161847 bool disable_pic;
18171848
......@@ -1821,31 +1852,21 @@ struct CodeGen {
18211852 Buf *test_filter;
18221853 Buf *test_name_prefix;
18231854 PackageTableEntry *root_package;
1855 Buf *zig_lib_dir;
1856 Buf *zig_std_dir;
18241857
18251858 const char **llvm_argv;
18261859 size_t llvm_argv_len;
18271860
18281861 const char **clang_argv;
18291862 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;
18441863};
18451864
18461865enum VarLinkage {
18471866 VarLinkageInternal,
1848 VarLinkageExport,
1867 VarLinkageExportStrong,
1868 VarLinkageExportWeak,
1869 VarLinkageExportLinkOnce,
18491870 VarLinkageExternal,
18501871};
18511872
......@@ -2084,6 +2105,11 @@ struct IrBasicBlock {
20842105 IrInstruction *must_be_comptime_source_instr;
20852106};
20862107
2108enum LVal {
2109 LValNone,
2110 LValPtr,
2111};
2112
20872113// These instructions are in transition to having "pass 1" instructions
20882114// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
20892115// and pass 2 are suffixed with Gen.
......@@ -2106,6 +2132,7 @@ enum IrInstructionId {
21062132 IrInstructionIdUnOp,
21072133 IrInstructionIdBinOp,
21082134 IrInstructionIdLoadPtr,
2135 IrInstructionIdLoadPtrGen,
21092136 IrInstructionIdStorePtr,
21102137 IrInstructionIdFieldPtr,
21112138 IrInstructionIdStructFieldPtr,
......@@ -2116,6 +2143,7 @@ enum IrInstructionId {
21162143 IrInstructionIdConst,
21172144 IrInstructionIdReturn,
21182145 IrInstructionIdCast,
2146 IrInstructionIdResizeSlice,
21192147 IrInstructionIdContainerInitList,
21202148 IrInstructionIdContainerInitFields,
21212149 IrInstructionIdStructInit,
......@@ -2183,6 +2211,7 @@ enum IrInstructionId {
21832211 IrInstructionIdPtrCastSrc,
21842212 IrInstructionIdPtrCastGen,
21852213 IrInstructionIdBitCast,
2214 IrInstructionIdBitCastGen,
21862215 IrInstructionIdWidenOrShorten,
21872216 IrInstructionIdIntToPtr,
21882217 IrInstructionIdPtrToInt,
......@@ -2347,6 +2376,7 @@ struct IrInstructionUnOp {
23472376
23482377 IrUnOp op_id;
23492378 IrInstruction *value;
2379 LVal lval;
23502380};
23512381
23522382enum IrBinOp {
......@@ -2399,6 +2429,13 @@ struct IrInstructionLoadPtr {
23992429 IrInstruction *ptr;
24002430};
24012431
2432struct IrInstructionLoadPtrGen {
2433 IrInstruction base;
2434
2435 IrInstruction *ptr;
2436 LLVMValueRef tmp_ptr;
2437};
2438
24022439struct IrInstructionStorePtr {
24032440 IrInstruction base;
24042441
......@@ -2476,6 +2513,18 @@ struct IrInstructionReturn {
24762513 IrInstruction *value;
24772514};
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
24792528// TODO get rid of this instruction, replace with instructions for each op code
24802529struct IrInstructionCast {
24812530 IrInstruction base;
......@@ -2486,6 +2535,13 @@ struct IrInstructionCast {
24862535 LLVMValueRef tmp_ptr;
24872536};
24882537
2538struct IrInstructionResizeSlice {
2539 IrInstruction base;
2540
2541 IrInstruction *operand;
2542 LLVMValueRef tmp_ptr;
2543};
2544
24892545struct IrInstructionContainerInitList {
24902546 IrInstruction base;
24912547
......@@ -2591,6 +2647,7 @@ struct IrInstructionPtrType {
25912647 PtrLen ptr_len;
25922648 bool is_const;
25932649 bool is_volatile;
2650 bool allow_zero;
25942651};
25952652
25962653struct IrInstructionPromiseType {
......@@ -2606,6 +2663,7 @@ struct IrInstructionSliceType {
26062663 IrInstruction *child_type;
26072664 bool is_const;
26082665 bool is_volatile;
2666 bool allow_zero;
26092667};
26102668
26112669struct IrInstructionAsm {
......@@ -2994,12 +3052,14 @@ struct IrInstructionPtrCastSrc {
29943052
29953053 IrInstruction *dest_type;
29963054 IrInstruction *ptr;
3055 bool safety_check_on;
29973056};
29983057
29993058struct IrInstructionPtrCastGen {
30003059 IrInstruction base;
30013060
30023061 IrInstruction *ptr;
3062 bool safety_check_on;
30033063};
30043064
30053065struct IrInstructionBitCast {
......@@ -3009,6 +3069,13 @@ struct IrInstructionBitCast {
30093069 IrInstruction *value;
30103070};
30113071
3072struct IrInstructionBitCastGen {
3073 IrInstruction base;
3074
3075 IrInstruction *operand;
3076 LLVMValueRef tmp_ptr;
3077};
3078
30123079struct IrInstructionWidenOrShorten {
30133080 IrInstruction base;
30143081
......@@ -3079,11 +3146,6 @@ struct IrInstructionTypeName {
30793146 IrInstruction *type_value;
30803147};
30813148
3082enum LVal {
3083 LValNone,
3084 LValPtr,
3085};
3086
30873149struct IrInstructionDeclRef {
30883150 IrInstruction base;
30893151
src/analyze.cpp+246-294
......@@ -356,7 +356,7 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
356356 }
357357 }
358358
359 return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
359 return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
360360}
361361
362362uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
......@@ -365,19 +365,19 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
365365 if (!type_has_bits(type_entry))
366366 return 0;
367367
368 if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
369 uint64_t result = 0;
370 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
371 result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry);
368 if (type_entry->id == ZigTypeIdStruct) {
369 if (type_entry->data.structure.layout == ContainerLayoutPacked) {
370 uint64_t result = 0;
371 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
372 result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry);
373 }
374 return result;
375 } else if (type_entry->data.structure.layout == ContainerLayoutExtern) {
376 return type_size(g, type_entry) * 8;
372377 }
373 return result;
374378 } else if (type_entry->id == ZigTypeIdArray) {
375379 ZigType *child_type = type_entry->data.array.child_type;
376 if (child_type->id == ZigTypeIdStruct &&
377 child_type->data.structure.layout == ContainerLayoutPacked)
378 {
379 return type_entry->data.array.len * type_size_bits(g, child_type);
380 }
380 return type_entry->data.array.len * type_size_bits(g, child_type);
381381 }
382382
383383 return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref);
......@@ -417,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
417417 return entry;
418418}
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
420432ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
421433 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
422434 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
423435{
436 // TODO when implementing https://github.com/ziglang/zig/issues/1953
437 // move this to a parameter
438 bool allow_zero = (ptr_len == PtrLenC);
424439 assert(!type_is_invalid(child_type));
425440 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
440455
441456 TypeId type_id = {};
442457 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) {
444459 type_id.id = ZigTypeIdPointer;
445460 type_id.data.pointer.child_type = child_type;
446461 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
449464 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
450465 type_id.data.pointer.host_int_bytes = host_int_bytes;
451466 type_id.data.pointer.ptr_len = ptr_len;
467 type_id.data.pointer.allow_zero = allow_zero;
452468
453469 auto existing_entry = g->type_table.maybe_get(type_id);
454470 if (existing_entry)
......@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
466482
467483 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);
470486 const char *const_str = is_const ? "const " : "";
471487 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 }
472495 buf_resize(&entry->name, 0);
473496 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));
475499 } else if (host_int_bytes == 0) {
476 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
477 const_str, volatile_str, buf_ptr(&child_type->name));
500 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
501 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
478502 } else if (byte_alignment == 0) {
479 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
480 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
503 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
504 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
505 buf_ptr(&child_type->name));
481506 } else {
482 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
483 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
507 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
508 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
509 buf_ptr(&child_type->name));
484510 }
485511
486512 assert(child_type->id != ZigTypeIdInvalid);
......@@ -488,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
488514 entry->zero_bits = !type_has_bits(child_type);
489515
490516 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 {
492520 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
493521 PtrLenSingle, 0, 0, host_int_bytes);
494522 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
522550 entry->data.pointer.explicit_alignment = byte_alignment;
523551 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
524552 entry->data.pointer.host_int_bytes = host_int_bytes;
553 entry->data.pointer.allow_zero = allow_zero;
525554
526555 if (parent_pointer) {
527556 *parent_pointer = entry;
......@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
838867
839868 ZigType *child_type = ptr_type->data.pointer.child_type;
840869 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)
842871 {
843872 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
844873 PtrLenUnknown, 0, 0, 0);
......@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
861890 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
862891 assert(child_ptr_type->id == ZigTypeIdPointer);
863892 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)
865894 {
866895 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
867896 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) {
10731102 if (type_is_c_abi_int(g, fn_type_id->return_type)) {
10741103 return false;
10751104 }
1076 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
1105 if (g->zig_target->arch == ZigLLVM_x86_64) {
10771106 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
10781107 return abi_class == X64CABIClass_MEMORY;
1079 } else if (target_is_arm(&g->zig_target)) {
1108 } else if (target_is_arm(g->zig_target)) {
10801109 return type_size(g, fn_type_id->return_type) > 16;
10811110 }
10821111 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
13001329 size_t backward_branch_count = 0;
13011330 return ir_eval_const_value(g, scope, node, type_entry,
13021331 &backward_branch_count, default_backward_branch_quota,
1303 nullptr, nullptr, node, type_name, nullptr);
1332 nullptr, nullptr, node, type_name, nullptr, nullptr);
13041333}
13051334
13061335ZigType *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 **
14151444 return true;
14161445}
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;
14191451 switch (type_entry->id) {
14201452 case ZigTypeIdInvalid:
14211453 zig_unreachable();
......@@ -1432,32 +1464,79 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
14321464 case ZigTypeIdArgTuple:
14331465 case ZigTypeIdOpaque:
14341466 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;
14361471 case ZigTypeIdVoid:
14371472 case ZigTypeIdBool:
14381473 case ZigTypeIdInt:
14391474 case ZigTypeIdFloat:
14401475 case ZigTypeIdPointer:
1441 case ZigTypeIdArray:
14421476 case ZigTypeIdFn:
14431477 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 }
14451490 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();
14471502 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();
14491514 case ZigTypeIdOptional:
1450 {
1451 ZigType *child_type = type_entry->data.maybe.child_type;
1452 return type_is_codegen_pointer(child_type);
1515 if (get_codegen_ptr_type(type_entry) != nullptr) {
1516 return ErrorNone;
1517 } else {
1518 add_node_error(g, source_node,
1519 buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
1520 buf_ptr(&type_entry->name)));
1521 return ErrorSemanticAnalyzeFail;
14531522 }
1454 case ZigTypeIdEnum:
1455 return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
1523 case ZigTypeIdEnum: {
1524 AstNode *decl_node = type_entry->data.enumeration.decl_node;
1525 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
1526 return ErrorNone;
1527 }
1528 ErrorMsg *msg = add_node_error(g, source_node,
1529 buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
1530 buf_ptr(&type_entry->name)));
1531 add_error_note(g, msg, decl_node,
1532 buf_sprintf("enum declaration does not specify an integer tag type"));
1533 return ErrorSemanticAnalyzeFail;
1534 }
14561535 }
14571536 zig_unreachable();
14581537}
14591538
1460static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1539bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14611540 switch (type_entry->id) {
14621541 case ZigTypeIdInvalid:
14631542 zig_unreachable();
......@@ -1583,7 +1662,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
15831662 }
15841663 } else if (param_node->data.param_decl.var_token != nullptr) {
15851664 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,
15871666 buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
15881667 calling_convention_name(fn_type_id.cc)));
15891668 return g->builtin_types.entry_invalid;
......@@ -2022,11 +2101,8 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
20222101 type_struct_field->gen_index = gen_field_index;
20232102
20242103 if (packed) {
2025 if (!type_allowed_in_packed_struct(field_type)) {
2026 AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
2027 add_node_error(g, field_source_node,
2028 buf_sprintf("packed structs cannot contain fields of type '%s'",
2029 buf_ptr(&field_type->name)));
2104 AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
2105 if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) {
20302106 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
20312107 break;
20322108 }
......@@ -2650,6 +2726,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26502726 buf_sprintf("enums, not structs, support field assignment"));
26512727 }
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
26532736 switch (type_requires_comptime(g, field_type)) {
26542737 case ReqCompTimeYes:
26552738 struct_type->data.structure.requires_comptime = true;
......@@ -2828,7 +2911,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
28282911 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
28292912 enum_type_node != nullptr;
28302913 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);
28322915 ZigType *tag_type;
28332916 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
28342917 bool *covered_enum_fields;
......@@ -2934,6 +3017,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
29343017 }
29353018 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
29373027 switch (type_requires_comptime(g, field_type)) {
29383028 case ReqCompTimeInvalid:
29393029 union_type->data.unionation.is_invalid = true;
......@@ -3182,36 +3272,19 @@ static bool scope_is_root_decls(Scope *scope) {
31823272 zig_unreachable();
31833273}
31843274
3185static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {
3186 add_node_error(g, proto_node,
3187 buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",
3188 buf_ptr(&fn_type->name)));
3189}
3190
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 }
3275void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
3276 ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
3277 assert(panic_fn_type_val != nullptr);
3278 assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
3279 ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
32053280
3206 ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));
3207 if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
3208 return wrong_panic_prototype(g, proto_node, fn_type);
3209 }
3281 AstNode *fake_decl = allocate<AstNode>(1);
3282 *fake_decl = *panic_fn->proto_node;
3283 fake_decl->type = NodeTypeSymbol;
3284 fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
32103285
3211 ZigType *actual_return_type = fn_type_id->return_type;
3212 if (actual_return_type != g->builtin_types.entry_unreachable) {
3213 return wrong_panic_prototype(g, proto_node, fn_type);
3214 }
3286 // call this for the side effects of casting to panic_fn_type
3287 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
32153288}
32163289
32173290ZigType *get_test_fn_type(CodeGen *g) {
......@@ -3231,16 +3304,16 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
32313304 g->have_c_main = true;
32323305 g->subsystem = TargetSubsystemConsole;
32333306 } else if (buf_eql_str(symbol_name, "WinMain") &&
3234 g->zig_target.os == OsWindows)
3307 g->zig_target->os == OsWindows)
32353308 {
32363309 g->have_winmain = true;
32373310 g->subsystem = TargetSubsystemWindows;
32383311 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
3239 g->zig_target.os == OsWindows)
3312 g->zig_target->os == OsWindows)
32403313 {
32413314 g->have_winmain_crt_startup = true;
32423315 } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") &&
3243 g->zig_target.os == OsWindows)
3316 g->zig_target->os == OsWindows)
32443317 {
32453318 g->have_dllmain_crt_startup = true;
32463319 }
......@@ -3306,18 +3379,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
33063379 if (!fn_table_entry->type_entry->data.fn.is_generic) {
33073380 if (fn_def_node)
33083381 g->fn_defs.append(fn_table_entry);
3382 }
33093383
3310 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
3311 (import == g->root_import || import->package == g->panic_package))
3384 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
3385 (import == g->root_import || import->package == g->panic_package))
3386 {
3387 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
3388 g->main_fn = fn_table_entry;
3389 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
3390 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
33123391 {
3313 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
3314 g->main_fn = fn_table_entry;
3315 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
3316 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
3317 {
3318 g->panic_fn = fn_table_entry;
3319 typecheck_panic_fn(g, fn_table_entry);
3320 }
3392 g->panic_fn = fn_table_entry;
3393 g->panic_tld_fn = tld_fn;
33213394 }
33223395 }
33233396 } else if (source_node->type == NodeTypeTestDecl) {
......@@ -3366,9 +3439,9 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
33663439 if (is_export) {
33673440 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);
33703443 if (entry) {
3371 AstNode *other_source_node = entry->value;
3444 AstNode *other_source_node = entry->value->source_node;
33723445 ErrorMsg *msg = add_node_error(g, tld->source_node,
33733446 buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name)));
33743447 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) {
36983771
36993772 VarLinkage linkage;
37003773 if (is_export) {
3701 linkage = VarLinkageExport;
3774 linkage = VarLinkageExportStrong;
37023775 } else if (is_extern) {
37033776 linkage = VarLinkageExternal;
37043777 } else {
......@@ -4041,7 +4114,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
40414114 if (type->id == ZigTypeIdFn) return type;
40424115 if (type->id == ZigTypeIdPromise) return type;
40434116 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 }
40454120 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
40464121 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
40474122 }
......@@ -4055,6 +4130,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
40554130 return ty;
40564131}
40574132
4133bool type_is_nonnull_ptr(ZigType *type) {
4134 return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
4135}
4136
40584137bool type_is_codegen_pointer(ZigType *type) {
40594138 return get_codegen_ptr_type(type) == type;
40604139}
......@@ -4572,185 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) {
45724651 zig_unreachable();
45734652}
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
47544654static uint32_t hash_ptr(void *ptr) {
47554655 return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX);
47564656}
......@@ -5229,6 +5129,10 @@ bool type_has_bits(ZigType *type_entry) {
52295129// Whether you can infer the value based solely on the type.
52305130OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
52315131 assert(type_entry != nullptr);
5132
5133 if (type_entry->one_possible_value != OnePossibleValueInvalid)
5134 return type_entry->one_possible_value;
5135
52325136 Error err;
52335137 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
52345138 return OnePossibleValueInvalid;
......@@ -5276,8 +5180,14 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
52765180 case ZigTypeIdInt:
52775181 case ZigTypeIdVector:
52785182 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
5279 case ZigTypeIdPointer:
5280 return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
5183 case ZigTypeIdPointer: {
5184 ZigType *elem_type = type_entry->data.pointer.child_type;
5185 // If the recursive function call asks, then we are not one possible value.
5186 type_entry->one_possible_value = OnePossibleValueNo;
5187 // Now update it to be the value of the recursive call.
5188 type_entry->one_possible_value = type_has_one_possible_value(g, elem_type);
5189 return type_entry->one_possible_value;
5190 }
52815191 case ZigTypeIdUnion:
52825192 if (type_entry->data.unionation.src_field_count > 1)
52835193 return OnePossibleValueNo;
......@@ -6010,16 +5920,20 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const
60105920 }
60115921}
60125922
6013static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) {
6014 switch (const_val->data.x_array.special) {
5923static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) {
5924 ConstArrayValue *array = &const_val->data.x_array;
5925 switch (array->special) {
60155926 case ConstArraySpecialUndef:
60165927 buf_append_str(buf, "undefined");
60175928 return;
60185929 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
60205934 buf_append_char(buf, '"');
6021 for (size_t i = 0; i < buf_len(array_buf); i += 1) {
6022 uint8_t c = buf_ptr(array_buf)[i];
5935 for (size_t i = 0; i < len; i += 1) {
5936 uint8_t c = base[i];
60235937 if (c == '"') {
60245938 buf_append_str(buf, "\\\"");
60255939 } else {
......@@ -6030,12 +5944,13 @@ static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_v
60305944 return;
60315945 }
60325946 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));
60345951 for (uint64_t i = 0; i < len; i += 1) {
6035 if (i != 0)
6036 buf_appendf(buf, ",");
6037 ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
6038 render_const_value(g, buf, child_value);
5952 if (i != 0) buf_appendf(buf, ",");
5953 render_const_value(g, buf, &base[i]);
60395954 }
60405955 buf_appendf(buf, "}");
60415956 return;
......@@ -6124,10 +6039,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
61246039 }
61256040 case ZigTypeIdPointer:
61266041 return render_const_val_ptr(g, buf, const_val, type_entry);
6127 case ZigTypeIdVector:
6128 return render_const_val_array(g, buf, const_val, type_entry->data.vector.len);
6129 case ZigTypeIdArray:
6130 return render_const_val_array(g, buf, const_val, type_entry->data.array.len);
6042 case ZigTypeIdArray: {
6043 uint64_t len = type_entry->data.array.len;
6044 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
6045 return;
6046 }
6047 case ZigTypeIdVector: {
6048 uint32_t len = type_entry->data.vector.len;
6049 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
6050 return;
6051 }
61316052 case ZigTypeIdNull:
61326053 {
61336054 buf_appendf(buf, "null");
......@@ -6169,7 +6090,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
61696090 }
61706091 case ZigTypeIdStruct:
61716092 {
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 }
61736111 return;
61746112 }
61756113 case ZigTypeIdEnum:
......@@ -6193,8 +6131,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
61936131 }
61946132 case ZigTypeIdUnion:
61956133 {
6196 uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag);
6197 TypeUnionField *field = &type_entry->data.unionation.fields[tag];
6134 const BigInt *tag = &const_val->data.x_union.tag;
6135 TypeUnionField *field = find_union_field_by_tag(type_entry, tag);
61986136 buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
61996137 render_const_value(g, buf, const_val->data.x_union.payload);
62006138 buf_append_str(buf, "}");
......@@ -6277,6 +6215,7 @@ uint32_t type_id_hash(TypeId x) {
62776215 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
62786216 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
62796217 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
6218 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
62806219 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
62816220 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
62826221 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
......@@ -6327,6 +6266,7 @@ bool type_id_eql(TypeId a, TypeId b) {
63276266 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
63286267 a.data.pointer.is_const == b.data.pointer.is_const &&
63296268 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
6269 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
63306270 a.data.pointer.alignment == b.data.pointer.alignment &&
63316271 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
63326272 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
......@@ -6626,12 +6566,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
66266566 if (is_libc && g->libc_link_lib != nullptr)
66276567 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
66356569 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
66366570 LinkLib *existing_lib = g->link_libs_list.at(i);
66376571 if (buf_eql_buf(existing_lib->name, name)) {
......@@ -6860,3 +6794,21 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
68606794
68616795 return ErrorNone;
68626796}
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);
4040ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);
4141ZigType *get_test_fn_type(CodeGen *g);
4242bool handle_is_ptr(ZigType *type_entry);
43void find_libc_include_path(CodeGen *g);
44void find_libc_lib_path(CodeGen *g);
4543
4644bool type_has_bits(ZigType *type_entry);
47
45bool 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
4949ImportTableEntry *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);
215215X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
216216bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
217217bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
218const char *container_string(ContainerKind kind);
218219
219220uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
220221
......@@ -225,14 +226,10 @@ enum ReqCompTime {
225226};
226227ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
227228
228enum OnePossibleValue {
229 OnePossibleValueInvalid,
230 OnePossibleValueNo,
231 OnePossibleValueYes,
232};
233229OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
234230
235231Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
236232 ConstExprValue *const_val, ZigType *wanted_type);
237233
234void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
238235#endif
src/ast_render.cpp+14-13
......@@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) {
136136 return (tok == nullptr) ? "" : "threadlocal ";
137137}
138138
139const char *container_string(ContainerKind kind) {
140 switch (kind) {
141 case ContainerKindEnum: return "enum";
142 case ContainerKindStruct: return "struct";
143 case ContainerKindUnion: return "union";
139static const char *token_to_ptr_len_str(Token *tok) {
140 assert(tok != nullptr);
141 switch (tok->id) {
142 case TokenIdStar:
143 case TokenIdStarStar:
144 return "*";
145 case TokenIdBracketStarBracket:
146 return "[*]";
147 case TokenIdBracketStarCBracket:
148 return "[*c]";
149 default:
150 zig_unreachable();
144151 }
145 zig_unreachable();
146152}
147153
148154static const char *node_type_str(NodeType node_type) {
......@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
644650 case NodeTypePointerType:
645651 {
646652 if (!grouped) fprintf(ar->f, "(");
647 const char *star = "[*]";
648 if (node->data.pointer_type.star_token != nullptr &&
649 (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar))
650 {
651 star = "*";
652 }
653 fprintf(ar->f, "%s", star);
653 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
654 fprintf(ar->f, "%s", ptr_len_str);
654655 if (node->data.pointer_type.align_expr != nullptr) {
655656 fprintf(ar->f, "align(");
656657 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);
1717
1818void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
1919
20const char *container_string(ContainerKind kind);
21
2220#endif
23
src/bigint.cpp-1
......@@ -1665,7 +1665,6 @@ int64_t bigint_as_signed(const BigInt *bigint) {
16651665 return 0;
16661666 } else if (bigint->digit_count == 1) {
16671667 if (bigint->is_negative) {
1668 // TODO this code path is untested
16691668 if (bigint->data.digit <= 9223372036854775808ULL) {
16701669 return (-((int64_t)(bigint->data.digit - 1))) - 1;
16711670 } else {
src/buffer.hpp+1-3
......@@ -132,9 +132,7 @@ void buf_appendf(Buf *buf, const char *format, ...)
132132
133133static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
134134 assert(buf->list.length);
135 if (buf_len(buf) != mem_len)
136 return false;
137 return memcmp(buf_ptr(buf), mem, mem_len) == 0;
135 return mem_eql_mem(buf_ptr(buf), buf_len(buf), mem, mem_len);
138136}
139137
140138static 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) {
414414 return cache_add_file_fetch(ch, resolved_path, nullptr);
415415}
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
417450static Error write_manifest_file(CacheHash *ch) {
418451 Error err;
419452 Buf contents = BUF_INIT;
......@@ -464,3 +497,4 @@ void cache_release(CacheHash *ch) {
464497
465498 os_file_close(ch->manifest_file);
466499}
500
src/cache_hash.hpp+2
......@@ -56,6 +56,8 @@ Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
5656// If you did not get a cache hit, call this function for every file
5757// that is depended on, and then finish with cache_final.
5858Error 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
6062// This variant of cache_add_file returns the file contents.
6163// 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) {
2929
3030 // Allow conflicts among OSX and iOS, but choose the default platform.
3131 if (osx_target && ios_target) {
32 if (g->zig_target.arch.arch == ZigLLVM_arm ||
33 g->zig_target.arch.arch == ZigLLVM_aarch64 ||
34 g->zig_target.arch.arch == ZigLLVM_thumb)
32 if (g->zig_target->arch == ZigLLVM_arm ||
33 g->zig_target->arch == ZigLLVM_aarch64 ||
34 g->zig_target->arch == ZigLLVM_thumb)
3535 {
3636 osx_target = nullptr;
3737 } else {
......@@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) {
4343 g->mmacosx_version_min = buf_create_from_str(osx_target);
4444 } else if (ios_target) {
4545 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) {
4747 g->mmacosx_version_min = buf_create_from_str("10.10");
4848 }
4949}
......@@ -88,13 +88,15 @@ static const char *symbols_that_llvm_depends_on[] = {
8888};
8989
9090CodeGen *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)
9292{
9393 CodeGen *g = allocate<CodeGen>(1);
9494
9595 codegen_add_time_event(g, "Initialize");
9696
97 g->libc = libc;
9798 g->zig_lib_dir = zig_lib_dir;
99 g->zig_target = target;
98100
99101 if (override_std_dir == nullptr) {
100102 g->zig_std_dir = buf_alloc();
......@@ -149,43 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
149151 g->zig_std_special_dir = buf_alloc();
150152 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
151153
152 if (target) {
153 // cross compiling, so we can't rely on all the configured stuff since
154 // that's for native compilation
155 g->zig_target = *target;
156 resolve_target_object_format(&g->zig_target);
157 g->dynamic_linker = nullptr;
158 g->libc_lib_dir = nullptr;
159 g->libc_static_lib_dir = nullptr;
160 g->libc_include_dir = nullptr;
161 g->msvc_lib_dir = nullptr;
162 g->kernel32_lib_dir = nullptr;
154 assert(target != nullptr);
155 if (!target->is_native) {
163156 g->each_lib_rpath = false;
164157 } 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
174158 g->each_lib_rpath = true;
175159
176 if (g->zig_target.os == OsMacOSX ||
177 g->zig_target.os == OsIOS)
178 {
160 if (target_is_darwin(g->zig_target)) {
179161 init_darwin_native(g);
180162 }
181163
182164 }
183165
184 // On Darwin/MacOS/iOS, we always link libSystem which contains libc.
185 if (g->zig_target.os == OsMacOSX ||
186 g->zig_target.os == OsIOS ||
187 g->zig_target.os == OsFreeBSD)
188 {
166 if (target_requires_libc(g->zig_target)) {
189167 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
190168 g->link_libs_list.append(g->libc_link_lib);
191169 }
......@@ -197,6 +175,10 @@ void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
197175 g->out_h_path = h_path;
198176}
199177
178void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path) {
179 g->out_lib_path = lib_path;
180}
181
200182void codegen_set_output_path(CodeGen *g, Buf *path) {
201183 g->wanted_output_file_path = path;
202184}
......@@ -253,30 +235,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
253235 g->root_out_name = out_name;
254236}
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
280238void codegen_add_lib_dir(CodeGen *g, const char *dir) {
281239 g->lib_dirs.append(dir);
282240}
......@@ -389,11 +347,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
389347 case CallingConventionC: return LLVMCCallConv;
390348 case CallingConventionCold:
391349 // cold calling convention only works on x86.
392 if (g->zig_target.arch.arch == ZigLLVM_x86 ||
393 g->zig_target.arch.arch == ZigLLVM_x86_64)
350 if (g->zig_target->arch == ZigLLVM_x86 ||
351 g->zig_target->arch == ZigLLVM_x86_64)
394352 {
395353 // cold calling convention is not supported on windows
396 if (g->zig_target.os == OsWindows) {
354 if (g->zig_target->os == OsWindows) {
397355 return LLVMCCallConv;
398356 } else {
399357 return LLVMColdCallConv;
......@@ -406,7 +364,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
406364 zig_unreachable();
407365 case CallingConventionStdcall:
408366 // stdcall calling convention only works on x86.
409 if (g->zig_target.arch.arch == ZigLLVM_x86) {
367 if (g->zig_target->arch == ZigLLVM_x86) {
410368 return LLVMX86StdcallCallConv;
411369 } else {
412370 return LLVMCCallConv;
......@@ -418,7 +376,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
418376}
419377
420378static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
421 if (g->zig_target.os == OsWindows) {
379 if (g->zig_target->os == OsWindows) {
422380 addLLVMFnAttr(fn_val, "uwtable");
423381 }
424382}
......@@ -454,13 +412,13 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
454412}
455413
456414static 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) {
458416 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
459417 }
460418}
461419
462420static 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) {
464422 // TODO come up with a good explanation/understanding for why we never do
465423 // DLLImportStorageClass. Empirically it only causes problems. But let's have
466424 // this documented and then clean up the code accordingly.
......@@ -505,7 +463,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
505463 bool external_linkage = linkage != GlobalLinkageIdInternal;
506464 CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
507465 if (cc == CallingConventionStdcall && external_linkage &&
508 g->zig_target.arch.arch == ZigLLVM_x86)
466 g->zig_target->arch == ZigLLVM_x86)
509467 {
510468 // prevent llvm name mangling
511469 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) {
520478 fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));
521479 return fn_table_entry->llvm_value;
522480 } 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 }
524493 }
525494 } 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
528499 for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
529500 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) {
617588 unsigned init_gen_i = 0;
618589 if (!type_has_bits(return_type)) {
619590 // nothing to do
620 } else if (type_is_codegen_pointer(return_type)) {
591 } else if (type_is_nonnull_ptr(return_type)) {
621592 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
622593 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
594 // Sret pointers must not be address 0
623595 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
624596 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
625597 if (cc_want_sret_attr(cc)) {
......@@ -637,6 +609,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
637609
638610 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
639611 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.
640614 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
641615 }
642616
......@@ -950,6 +924,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
950924 return buf_create_from_str("invalid enum value");
951925 case PanicMsgIdFloatToInt:
952926 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");
953929 }
954930 zig_unreachable();
955931}
......@@ -1244,6 +1220,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
12441220 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
12451221 addLLVMFnAttr(fn_val, "nounwind");
12461222 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.
12471225 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
12481226 if (g->build_mode == BuildModeDebug) {
12491227 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
......@@ -1318,9 +1296,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
13181296 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
13191297 addLLVMFnAttr(fn_val, "nounwind");
13201298 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.
13211301 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
13221302 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
13231303 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.
13241306 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
13251307 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
13261308 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
......@@ -1448,6 +1430,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
14481430 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
14491431 addLLVMFnAttr(fn_val, "nounwind");
14501432 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.
14511435 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
14521436 if (g->build_mode == BuildModeDebug) {
14531437 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_
20492033 case FnWalkIdAttrs: {
20502034 ZigType *ptr_type = get_codegen_ptr_type(ty);
20512035 if (ptr_type != nullptr) {
2052 if (ty->id != ZigTypeIdOptional) {
2036 if (type_is_nonnull_ptr(ty)) {
20532037 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
20542038 }
20552039 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_
20932077 assert(handle_is_ptr(ty));
20942078 switch (fn_walk->id) {
20952079 case FnWalkIdAttrs:
2080 // arrays passed to C ABI functions may not be at address 0
20962081 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
20972082 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
20982083 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_
21232108 return true;
21242109 }
21252110
2126 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
2111 if (g->zig_target->arch == ZigLLVM_x86_64) {
21272112 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
21282113 size_t ty_size = type_size(g, ty);
21292114 if (abi_class == X64CABIClass_MEMORY) {
......@@ -2132,6 +2117,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
21322117 case FnWalkIdAttrs:
21332118 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
21342119 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2120 // Byvalue parameters must not have address 0
21352121 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
21362122 fn_walk->data.attrs.gen_i += 1;
21372123 break;
......@@ -2264,7 +2250,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
22642250 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
22652251 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
22662252 }
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)) {
22682257 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
22692258 }
22702259 break;
......@@ -2657,7 +2646,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
26572646 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
26582647 (op1->value.type->id == ZigTypeIdPointer &&
26592648 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
2660 op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
2649 op1->value.type->data.pointer.ptr_len != PtrLenSingle)
26612650 );
26622651 ZigType *operand_type = op1->value.type;
26632652 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,
27162705 AddSubMulMul;
27172706
27182707 if (scalar_type->id == ZigTypeIdPointer) {
2719 assert(scalar_type->data.pointer.ptr_len == PtrLenUnknown);
2708 assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
27202709 LLVMValueRef subscript_value;
27212710 if (operand_type->id == ZigTypeIdVector)
27222711 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
28632852 }
28642853}
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
28662925static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
28672926 IrInstructionCast *cast_instruction)
28682927{
......@@ -2877,69 +2936,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
28772936 zig_unreachable();
28782937 case CastOpNoop:
28792938 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 }
29432939 case CastOpIntToFloat:
29442940 assert(actual_type->id == ZigTypeIdInt);
29452941 if (actual_type->data.integral.is_signed) {
......@@ -3028,15 +3024,51 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
30283024 return nullptr;
30293025 }
30303026 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;
30323043}
30333044
30343045static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
3035 IrInstructionBitCast *instruction)
3046 IrInstructionBitCastGen *instruction)
30363047{
30373048 ZigType *wanted_type = instruction->base.value.type;
3038 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3039 return LLVMBuildBitCast(g->builder, value, wanted_type->type_ref, "");
3049 ZigType *actual_type = instruction->operand->value.type;
3050 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
3051
3052 bool wanted_is_ptr = handle_is_ptr(wanted_type);
3053 bool actual_is_ptr = handle_is_ptr(actual_type);
3054 if (wanted_is_ptr == actual_is_ptr) {
3055 // We either bitcast the value directly or bitcast the pointer which does a pointer cast
3056 LLVMTypeRef wanted_type_ref = wanted_is_ptr ?
3057 LLVMPointerType(wanted_type->type_ref, 0) : wanted_type->type_ref;
3058 return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
3059 } else if (actual_is_ptr) {
3060 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(wanted_type->type_ref, 0);
3061 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
3062 uint32_t alignment = get_abi_alignment(g, actual_type);
3063 return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
3064 } else {
3065 assert(instruction->tmp_ptr != nullptr);
3066 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(actual_type->type_ref, 0);
3067 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, "");
3068 uint32_t alignment = get_abi_alignment(g, wanted_type);
3069 gen_store_untyped(g, value, bitcasted_ptr, alignment, false);
3070 return instruction->tmp_ptr;
3071 }
30403072}
30413073
30423074static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
......@@ -3167,7 +3199,8 @@ static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstruc
31673199static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {
31683200 IrUnOp op_id = un_op_instruction->op_id;
31693201 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
31723205 switch (op_id) {
31733206 case IrUnOpInvalid:
......@@ -3177,16 +3210,16 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
31773210 case IrUnOpNegation:
31783211 case IrUnOpNegationWrap:
31793212 {
3180 if (expr_type->id == ZigTypeIdFloat) {
3213 if (scalar_type->id == ZigTypeIdFloat) {
31813214 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base));
31823215 return LLVMBuildFNeg(g->builder, expr, "");
3183 } else if (expr_type->id == ZigTypeIdInt) {
3216 } else if (scalar_type->id == ZigTypeIdInt) {
31843217 if (op_id == IrUnOpNegationWrap) {
31853218 return LLVMBuildNeg(g->builder, expr, "");
31863219 } else if (ir_want_runtime_safety(g, &un_op_instruction->base)) {
31873220 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
3188 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
3189 } else if (expr_type->data.integral.is_signed) {
3221 return gen_overflow_op(g, operand_type, AddSubMulSub, zero, expr);
3222 } else if (scalar_type->data.integral.is_signed) {
31903223 return LLVMBuildNSWNeg(g->builder, expr, "");
31913224 } else {
31923225 return LLVMBuildNUWNeg(g->builder, expr, "");
......@@ -3237,7 +3270,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
32373270 return nullptr;
32383271}
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) {
32413274 ZigType *child_type = instruction->base.value.type;
32423275 if (!type_has_bits(child_type))
32433276 return nullptr;
......@@ -3252,7 +3285,6 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32523285
32533286 bool big_endian = g->is_big_endian;
32543287
3255 assert(!handle_is_ptr(child_type));
32563288 LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
32573289 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
32583290 assert(host_bit_count == host_int_bytes * 8);
......@@ -3264,7 +3296,16 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32643296 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
32653297 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;
32683309}
32693310
32703311static 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) {
33073348 zig_unreachable();
33083349}
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
33103422static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
33113423 assert(type_has_bits(value_type));
33123424 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_
33193431 ZigType *usize = g->builtin_types.entry_usize;
33203432 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
33213433 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 }
33223442}
33233443
33243444static 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) {
34793599 LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);
34803600
34813601 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));
34833603 LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);
34843604 g->sp_md_node = LLVMMDNode(&str_node, 1);
34853605 }
......@@ -5337,6 +5457,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
53375457 case IrInstructionIdDeclVarSrc:
53385458 case IrInstructionIdPtrCastSrc:
53395459 case IrInstructionIdCmpxchgSrc:
5460 case IrInstructionIdLoadPtr:
5461 case IrInstructionIdBitCast:
53405462 zig_unreachable();
53415463
53425464 case IrInstructionIdDeclVarGen:
......@@ -5355,8 +5477,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
53555477 return ir_render_br(g, executable, (IrInstructionBr *)instruction);
53565478 case IrInstructionIdUnOp:
53575479 return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
5358 case IrInstructionIdLoadPtr:
5359 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);
5480 case IrInstructionIdLoadPtrGen:
5481 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);
53605482 case IrInstructionIdStorePtr:
53615483 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
53625484 case IrInstructionIdVarPtr:
......@@ -5433,8 +5555,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
54335555 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
54345556 case IrInstructionIdPtrCastGen:
54355557 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
5436 case IrInstructionIdBitCast:
5437 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
5558 case IrInstructionIdBitCastGen:
5559 return ir_render_bit_cast(g, executable, (IrInstructionBitCastGen *)instruction);
54385560 case IrInstructionIdWidenOrShorten:
54395561 return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
54405562 case IrInstructionIdPtrToInt:
......@@ -5509,6 +5631,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
55095631 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
55105632 case IrInstructionIdAssertZero:
55115633 return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);
5634 case IrInstructionIdResizeSlice:
5635 return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
55125636 }
55135637 zig_unreachable();
55145638}
......@@ -5711,8 +5835,32 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
57115835 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
57125836 return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);
57135837 }
5714 case ZigTypeIdArray:
5715 zig_panic("TODO bit pack an array");
5838 case ZigTypeIdArray: {
5839 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
5840 if (const_val->data.x_array.special == ConstArraySpecialUndef) {
5841 return val;
5842 }
5843 expand_undef_array(g, const_val);
5844 bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
5845 uint32_t packed_bits_size = type_size_bits(g, type_entry->data.array.child_type);
5846 size_t used_bits = 0;
5847 for (size_t i = 0; i < type_entry->data.array.len; i += 1) {
5848 ConstExprValue *elem_val = &const_val->data.x_array.data.s_none.elements[i];
5849 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
5850
5851 if (is_big_endian) {
5852 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
5853 val = LLVMConstShl(val, shift_amt);
5854 val = LLVMConstOr(val, child_val);
5855 } else {
5856 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
5857 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
5858 val = LLVMConstOr(val, child_val_shifted);
5859 used_bits += packed_bits_size;
5860 }
5861 }
5862 return val;
5863 }
57165864 case ZigTypeIdVector:
57175865 zig_panic("TODO bit pack a vector");
57185866 case ZigTypeIdUnion:
......@@ -6387,6 +6535,22 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
63876535 }
63886536}
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
63906554static void do_code_gen(CodeGen *g) {
63916555 assert(!g->errors.length);
63926556
......@@ -6467,21 +6631,21 @@ static void do_code_gen(CodeGen *g) {
64676631 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
64686632 // TODO debug info for the extern variable
64696633
6470 LLVMSetLinkage(global_value, LLVMExternalLinkage);
6634 LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
64716635 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
64726636 LLVMSetAlignment(global_value, var->align_bytes);
64736637 LLVMSetGlobalConstant(global_value, var->gen_is_const);
64746638 set_global_tls(g, var, global_value);
64756639 }
64766640 } else {
6477 bool exported = (var->linkage == VarLinkageExport);
6641 bool exported = (var->linkage != VarLinkageInternal);
64786642 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
64796643 render_const_val(g, var->const_value, mangled_name);
64806644 render_const_val_global(g, var->const_value, mangled_name);
64816645 global_value = var->const_value->global_refs->llvm_global;
64826646
64836647 if (exported) {
6484 LLVMSetLinkage(global_value, LLVMExternalLinkage);
6648 LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
64856649 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
64866650 }
64876651 if (tld_var->section_name) {
......@@ -6584,6 +6748,15 @@ static void do_code_gen(CodeGen *g) {
65846748 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
65856749 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
65866750 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;
65876760 } else if (instruction->id == IrInstructionIdVectorToArray) {
65886761 IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
65896762 alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
......@@ -6839,7 +7012,7 @@ static void define_builtin_types(CodeGen *g) {
68397012
68407013 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
68417014 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);
68437016 bool is_signed = info->is_signed;
68447017
68457018 ZigType *entry = new_type_table_entry(ZigTypeIdInt);
......@@ -7106,6 +7279,9 @@ static const char *build_mode_to_str(BuildMode build_mode) {
71067279Buf *codegen_generate_builtin_source(CodeGen *g) {
71077280 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
71097285 // Modifications to this struct must be coordinated with code that does anything with
71107286 // g->stack_trace_type. There are hard-coded references to the field indexes.
71117287 buf_append_str(contents,
......@@ -7114,16 +7290,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
71147290 " instruction_addresses: []usize,\n"
71157291 "};\n\n");
71167292
7293 buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
7294
71177295 const char *cur_os = nullptr;
71187296 {
71197297 buf_appendf(contents, "pub const Os = enum {\n");
71207298 uint32_t field_count = (uint32_t)target_os_count();
71217299 for (uint32_t i = 0; i < field_count; i += 1) {
7122 Os os_type = get_target_os(i);
7123 const char *name = get_target_os_name(os_type);
7300 Os os_type = target_os_enum(i);
7301 const char *name = target_os_name(os_type);
71247302 buf_appendf(contents, " %s,\n", name);
71257303
7126 if (os_type == g->zig_target.os) {
7304 if (os_type == g->zig_target->os) {
71277305 g->target_os_index = i;
71287306 cur_os = name;
71297307 }
......@@ -7134,56 +7312,81 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
71347312
71357313 const char *cur_arch = nullptr;
71367314 {
7137 buf_appendf(contents, "pub const Arch = enum {\n");
7315 buf_appendf(contents, "pub const Arch = union(enum) {\n");
71387316 uint32_t field_count = (uint32_t)target_arch_count();
7139 for (uint32_t i = 0; i < field_count; i += 1) {
7140 const ArchType *arch_type = get_target_arch(i);
7141 Buf *arch_name = buf_alloc();
7142 buf_resize(arch_name, 50);
7143 get_arch_name(buf_ptr(arch_name), arch_type);
7144 buf_resize(arch_name, strlen(buf_ptr(arch_name)));
7145
7146 buf_appendf(contents, " %s,\n", buf_ptr(arch_name));
7317 for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) {
7318 ZigLLVM_ArchType arch = target_arch_enum(arch_i);
7319 const char *arch_name = target_arch_name(arch);
7320 SubArchList sub_arch_list = target_subarch_list(arch);
7321 if (sub_arch_list == SubArchListNone) {
7322 buf_appendf(contents, " %s,\n", arch_name);
7323 if (arch == g->zig_target->arch) {
7324 g->target_arch_index = arch_i;
7325 cur_arch = buf_ptr(buf_sprintf("Arch.%s", arch_name));
7326 }
7327 } else {
7328 const char *sub_arch_list_name = target_subarch_list_name(sub_arch_list);
7329 buf_appendf(contents, " %s: %s,\n", arch_name, sub_arch_list_name);
7330 if (arch == g->zig_target->arch) {
7331 size_t sub_count = target_subarch_count(sub_arch_list);
7332 for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
7333 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
7334 if (sub == g->zig_target->sub_arch) {
7335 g->target_sub_arch_index = sub_i;
7336 cur_arch = buf_ptr(buf_sprintf("Arch{ .%s = Arch.%s.%s }",
7337 arch_name, sub_arch_list_name, target_subarch_name(sub)));
7338 }
7339 }
7340 }
7341 }
7342 }
71477343
7148 if (arch_type->arch == g->zig_target.arch.arch &&
7149 arch_type->sub_arch == g->zig_target.arch.sub_arch)
7150 {
7151 g->target_arch_index = i;
7152 cur_arch = buf_ptr(arch_name);
7344 uint32_t list_count = target_subarch_list_count();
7345 // start at index 1 to skip None
7346 for (uint32_t list_i = 1; list_i < list_count; list_i += 1) {
7347 SubArchList sub_arch_list = target_subarch_list_enum(list_i);
7348 const char *subarch_list_name = target_subarch_list_name(sub_arch_list);
7349 buf_appendf(contents, " pub const %s = enum {\n", subarch_list_name);
7350 size_t sub_count = target_subarch_count(sub_arch_list);
7351 for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
7352 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
7353 buf_appendf(contents, " %s,\n", target_subarch_name(sub));
71537354 }
7355 buf_appendf(contents, " };\n");
71547356 }
71557357 buf_appendf(contents, "};\n\n");
71567358 }
71577359 assert(cur_arch != nullptr);
71587360
7159 const char *cur_environ = nullptr;
7361 const char *cur_abi = nullptr;
71607362 {
7161 buf_appendf(contents, "pub const Environ = enum {\n");
7162 uint32_t field_count = (uint32_t)target_environ_count();
7363 buf_appendf(contents, "pub const Abi = enum {\n");
7364 uint32_t field_count = (uint32_t)target_abi_count();
71637365 for (uint32_t i = 0; i < field_count; i += 1) {
7164 ZigLLVM_EnvironmentType environ_type = get_target_environ(i);
7165 const char *name = ZigLLVMGetEnvironmentTypeName(environ_type);
7366 ZigLLVM_EnvironmentType abi = target_abi_enum(i);
7367 const char *name = target_abi_name(abi);
71667368 buf_appendf(contents, " %s,\n", name);
71677369
7168 if (environ_type == g->zig_target.env_type) {
7169 g->target_environ_index = i;
7170 cur_environ = name;
7370 if (abi == g->zig_target->abi) {
7371 g->target_abi_index = i;
7372 cur_abi = name;
71717373 }
71727374 }
71737375 buf_appendf(contents, "};\n\n");
71747376 }
7175 assert(cur_environ != nullptr);
7377 assert(cur_abi != nullptr);
71767378
71777379 const char *cur_obj_fmt = nullptr;
71787380 {
71797381 buf_appendf(contents, "pub const ObjectFormat = enum {\n");
71807382 uint32_t field_count = (uint32_t)target_oformat_count();
71817383 for (uint32_t i = 0; i < field_count; i += 1) {
7182 ZigLLVM_ObjectFormatType oformat = get_target_oformat(i);
7183 const char *name = get_target_oformat_name(oformat);
7384 ZigLLVM_ObjectFormatType oformat = target_oformat_enum(i);
7385 const char *name = target_oformat_name(oformat);
71847386 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) {
71877390 g->target_oformat_index = i;
71887391 cur_obj_fmt = name;
71897392 }
......@@ -7294,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
72947497 " One,\n"
72957498 " Many,\n"
72967499 " Slice,\n"
7500 " C,\n"
72977501 " };\n"
72987502 " };\n"
72997503 "\n"
......@@ -7466,12 +7670,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
74667670 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
74677671 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
74687672 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
7469 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
7470 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
7673 buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
7674 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
74717675 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
74727676 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
74737677 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
74747678 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
74767681 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) {
75007705 cache_int(&cache_hash, g->build_mode);
75017706 cache_bool(&cache_hash, g->is_test_build);
75027707 cache_bool(&cache_hash, g->is_single_threaded);
7503 cache_int(&cache_hash, g->zig_target.arch.arch);
7504 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
7505 cache_int(&cache_hash, g->zig_target.vendor);
7506 cache_int(&cache_hash, g->zig_target.os);
7507 cache_int(&cache_hash, g->zig_target.env_type);
7508 cache_int(&cache_hash, g->zig_target.oformat);
7708 cache_int(&cache_hash, g->zig_target->is_native);
7709 cache_int(&cache_hash, g->zig_target->arch);
7710 cache_int(&cache_hash, g->zig_target->sub_arch);
7711 cache_int(&cache_hash, g->zig_target->vendor);
7712 cache_int(&cache_hash, g->zig_target->os);
7713 cache_int(&cache_hash, g->zig_target->abi);
75097714 cache_bool(&cache_hash, g->have_err_ret_tracing);
75107715 cache_bool(&cache_hash, g->libc_link_lib != nullptr);
7716 cache_bool(&cache_hash, g->valgrind_support);
75117717
75127718 Buf digest = BUF_INIT;
75137719 buf_resize(&digest, 0);
......@@ -7576,11 +7782,11 @@ static void init(CodeGen *g) {
75767782 assert(g->root_out_name);
75777783 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
75817787 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) {
75847790 ZigLLVMAddModuleCodeViewFlag(g->module);
75857791 } else {
75867792 ZigLLVMAddModuleDebugInfoFlag(g->module);
......@@ -7608,11 +7814,11 @@ static void init(CodeGen *g) {
76087814
76097815 const char *target_specific_cpu_args;
76107816 const char *target_specific_features;
7611 if (g->is_native_target) {
7817 if (g->zig_target->is_native) {
76127818 // LLVM creates invalid binaries on Windows sometimes.
76137819 // See https://github.com/ziglang/zig/issues/508
76147820 // 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) {
76167822 target_specific_cpu_args = "";
76177823 target_specific_features = "";
76187824 } else {
......@@ -7685,9 +7891,59 @@ static void init(CodeGen *g) {
76857891 }
76867892}
76877893
7688void codegen_translate_c(CodeGen *g, Buf *full_path) {
7689 find_libc_include_path(g);
7894static void detect_libc(CodeGen *g) {
7895 Error err;
7896
7897 if (g->libc != nullptr || g->libc_link_lib == nullptr)
7898 return;
7899
7900 if (g->zig_target->is_native) {
7901 g->libc = allocate<ZigLibCInstallation>(1);
7902
7903 // Look for zig-cache/native_libc.txt
7904 Buf *native_libc_txt = buf_alloc();
7905 os_path_join(&g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt);
7906 if ((err = zig_libc_parse(g->libc, native_libc_txt, g->zig_target, false))) {
7907 if ((err = zig_libc_find_native(g->libc, true))) {
7908 fprintf(stderr,
7909 "Unable to link against libc: Unable to find libc installation: %s\n"
7910 "See `zig libc --help` for more details.\n", err_str(err));
7911 exit(1);
7912 }
7913 if ((err = os_make_path(&g->cache_dir))) {
7914 fprintf(stderr, "Unable to create %s directory: %s\n",
7915 buf_ptr(&g->cache_dir), err_str(err));
7916 exit(1);
7917 }
7918 Buf *native_libc_tmp = buf_sprintf("%s.tmp", buf_ptr(native_libc_txt));
7919 FILE *file = fopen(buf_ptr(native_libc_tmp), "wb");
7920 if (file == nullptr) {
7921 fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
7922 exit(1);
7923 }
7924 zig_libc_render(g->libc, file);
7925 if (fclose(file) != 0) {
7926 fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
7927 exit(1);
7928 }
7929 if ((err = os_rename(native_libc_tmp, native_libc_txt))) {
7930 fprintf(stderr, "Unable to create %s: %s\n", buf_ptr(native_libc_txt), err_str(err));
7931 exit(1);
7932 }
7933 }
7934 } else if ((g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) &&
7935 !target_is_darwin(g->zig_target))
7936 {
7937 // Currently darwin is the only platform that we can link libc on when not compiling natively,
7938 // without a cross compiling libc kit.
7939 fprintf(stderr,
7940 "Cannot link against libc for non-native OS '%s' without providing a libc installation file.\n"
7941 "See `zig libc --help` for more details.\n", target_os_name(g->zig_target->os));
7942 exit(1);
7943 }
7944}
76907945
7946void codegen_translate_c(CodeGen *g, Buf *full_path) {
76917947 Buf *src_basename = buf_alloc();
76927948 Buf *src_dirname = buf_alloc();
76937949 os_path_split(full_path, src_dirname, src_basename);
......@@ -7698,6 +7954,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
76987954 g->root_import = import;
76997955 import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);
77007956
7957 detect_libc(g);
7958
77017959 init(g);
77027960
77037961 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) {
78578115 }
78588116 report_errors_and_maybe_exit(g);
78598117
7860 if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
7861 g->zig_target.os != OsUefi &&
8118 if (!g->is_test_build && g->zig_target->os != OsFreestanding &&
8119 g->zig_target->os != OsUefi &&
78628120 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
78638121 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
78648122 {
78658123 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
78668124 }
7867 if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup &&
8125 if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup &&
78688126 g->out_type == OutTypeLib && !g->is_static)
78698127 {
78708128 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) {
78828140 }
78838141 }
78848142
8143 typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
8144
78858145 report_errors_and_maybe_exit(g);
78868146
78878147}
......@@ -7904,6 +8164,168 @@ static void gen_global_asm(CodeGen *g) {
79048164 }
79058165}
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
79078329void codegen_add_object(CodeGen *g, Buf *object_path) {
79088330 g->link_objects.append(object_path);
79098331}
......@@ -8410,31 +8832,39 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
84108832 }
84118833 cache_buf(ch, compiler_id);
84128834 cache_buf(ch, g->root_out_name);
8835 cache_buf(ch, g->zig_lib_dir);
8836 cache_buf(ch, g->zig_std_dir);
84138837 cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);
84148838 cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);
84158839 cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);
84168840 cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length);
84178841 cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
84188842 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 }
84198850 cache_int(ch, g->emit_file_type);
84208851 cache_int(ch, g->build_mode);
84218852 cache_int(ch, g->out_type);
8422 cache_int(ch, g->zig_target.arch.arch);
8423 cache_int(ch, g->zig_target.arch.sub_arch);
8424 cache_int(ch, g->zig_target.vendor);
8425 cache_int(ch, g->zig_target.os);
8426 cache_int(ch, g->zig_target.env_type);
8427 cache_int(ch, g->zig_target.oformat);
8853 cache_bool(ch, g->zig_target->is_native);
8854 cache_int(ch, g->zig_target->arch);
8855 cache_int(ch, g->zig_target->sub_arch);
8856 cache_int(ch, g->zig_target->vendor);
8857 cache_int(ch, g->zig_target->os);
8858 cache_int(ch, g->zig_target->abi);
84288859 cache_int(ch, g->subsystem);
84298860 cache_bool(ch, g->is_static);
84308861 cache_bool(ch, g->strip_debug_symbols);
84318862 cache_bool(ch, g->is_test_build);
84328863 cache_bool(ch, g->is_single_threaded);
8433 cache_bool(ch, g->is_native_target);
84348864 cache_bool(ch, g->linker_rdynamic);
8435 cache_bool(ch, g->no_rosegment_workaround);
84368865 cache_bool(ch, g->each_lib_rpath);
84378866 cache_bool(ch, g->disable_pic);
8867 cache_bool(ch, g->valgrind_support);
84388868 cache_buf_opt(ch, g->mmacosx_version_min);
84398869 cache_buf_opt(ch, g->mios_version_min);
84408870 cache_usize(ch, g->version_major);
......@@ -8445,6 +8875,16 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
84458875 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
84468876 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
84478877 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
84498889 buf_resize(digest, 0);
84508890 if ((err = cache_hit(ch, digest)))
......@@ -8459,19 +8899,19 @@ static void resolve_out_paths(CodeGen *g) {
84598899 switch (g->emit_file_type) {
84608900 case EmitFileTypeBinary:
84618901 {
8462 const char *o_ext = target_o_file_ext(&g->zig_target);
8902 const char *o_ext = target_o_file_ext(g->zig_target);
84638903 buf_append_str(o_basename, o_ext);
84648904 break;
84658905 }
84668906 case EmitFileTypeAssembly:
84678907 {
8468 const char *asm_ext = target_asm_file_ext(&g->zig_target);
8908 const char *asm_ext = target_asm_file_ext(g->zig_target);
84698909 buf_append_str(o_basename, asm_ext);
84708910 break;
84718911 }
84728912 case EmitFileTypeLLVMIr:
84738913 {
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);
84758915 buf_append_str(o_basename, llvm_ir_ext);
84768916 break;
84778917 }
......@@ -8497,7 +8937,7 @@ static void resolve_out_paths(CodeGen *g) {
84978937
84988938 Buf basename = BUF_INIT;
84998939 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));
85018941 if (g->enable_cache || g->is_test_build) {
85028942 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
85038943 } else {
......@@ -8510,7 +8950,7 @@ static void resolve_out_paths(CodeGen *g) {
85108950 } else {
85118951 Buf basename = BUF_INIT;
85128952 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,
85148954 g->version_major, g->version_minor, g->version_patch));
85158955 if (g->enable_cache) {
85168956 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
......@@ -8523,11 +8963,12 @@ static void resolve_out_paths(CodeGen *g) {
85238963 }
85248964}
85258965
8526
85278966void codegen_build_and_link(CodeGen *g) {
85288967 Error err;
85298968 assert(g->out_type != OutTypeUnknown);
85308969
8970 detect_libc(g);
8971
85318972 Buf *stage1_dir = get_stage1_cache_path();
85328973 Buf *artifact_dir = buf_alloc();
85338974 Buf digest = BUF_INIT;
......@@ -8559,6 +9000,7 @@ void codegen_build_and_link(CodeGen *g) {
85599000
85609001 gen_global_asm(g);
85619002 gen_root_source(g);
9003 gen_c_objects(g);
85629004
85639005 if (g->enable_cache) {
85649006 if ((err = cache_final(&g->cache_hash, &digest))) {
......@@ -8576,16 +9018,25 @@ void codegen_build_and_link(CodeGen *g) {
85769018 resolve_out_paths(g);
85779019
85789020 codegen_add_time_event(g, "Code Generation");
8579 do_code_gen(g);
8580 codegen_add_time_event(g, "LLVM Emit Output");
8581 zig_llvm_emit_output(g);
9021 if (g->out_type == OutTypeObj && g->c_source_files.length == 1) {
9022 assert(g->link_objects.length == 1);
9023 if ((err = os_rename(g->link_objects.pop(), &g->o_file_output_path))) {
9024 fprintf(stderr, "unable to move object to '%s': %s\n",
9025 buf_ptr(&g->o_file_output_path), err_str(err));
9026 exit(1);
9027 }
9028 } else {
9029 do_code_gen(g);
9030 codegen_add_time_event(g, "LLVM Emit Output");
9031 zig_llvm_emit_output(g);
85829032
8583 if (g->out_h_path != nullptr) {
8584 codegen_add_time_event(g, "Generate .h");
8585 gen_h_file(g);
8586 }
8587 if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
8588 codegen_link(g);
9033 if (g->out_h_path != nullptr) {
9034 codegen_add_time_event(g, "Generate .h");
9035 gen_h_file(g);
9036 }
9037 if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
9038 codegen_link(g);
9039 }
85899040 }
85909041 }
85919042
src/codegen.hpp+3-7
......@@ -11,11 +11,12 @@
1111#include "parser.hpp"
1212#include "errmsg.hpp"
1313#include "target.hpp"
14#include "libc_installation.hpp"
1415
1516#include <stdio.h>
1617
1718CodeGen *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
2021void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2122void 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);
2728void codegen_set_strip(CodeGen *codegen, bool strip);
2829void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
2930void 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);
3631void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
3732void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
3833LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
......@@ -46,6 +41,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter);
4641void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
4742void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
4843void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
44void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path);
4945void codegen_set_output_path(CodeGen *g, Buf *path);
5046void codegen_add_time_event(CodeGen *g, const char *name);
5147void codegen_print_timing_report(CodeGen *g, FILE *f);
src/error.cpp+9
......@@ -34,6 +34,15 @@ const char *err_str(Error err) {
3434 case ErrorPipeBusy: return "pipe busy";
3535 case ErrorPrimitiveTypeNotFound: return "primitive type not found";
3636 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";
3746 }
3847 return "(invalid error)";
3948}
src/error.hpp+9
......@@ -36,6 +36,15 @@ enum Error {
3636 ErrorPipeBusy,
3737 ErrorPrimitiveTypeNotFound,
3838 ErrorCacheUnavailable,
39 ErrorPathTooLong,
40 ErrorCCompilerCannotFindFile,
41 ErrorReadingDepFile,
42 ErrorMissingArchitecture,
43 ErrorMissingOperatingSystem,
44 ErrorUnknownArchitecture,
45 ErrorUnknownOperatingSystem,
46 ErrorUnknownABI,
47 ErrorInvalidFilename,
3948};
4049
4150const char *err_str(Error err);
src/ir.cpp+1042-367
......@@ -61,7 +61,7 @@ enum ConstCastResultId {
6161 ConstCastResultIdType,
6262 ConstCastResultIdUnresolvedInferredErrSet,
6363 ConstCastResultIdAsyncAllocatorType,
64 ConstCastResultIdNullWrapPtr
64 ConstCastResultIdBadAllowsZero,
6565};
6666
6767struct ConstCastOnly;
......@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
8383struct ConstCastErrUnionPayloadMismatch;
8484struct ConstCastErrSetMismatch;
8585struct ConstCastTypeMismatch;
86struct ConstCastBadAllowsZero;
8687
8788struct ConstCastOnly {
8889 ConstCastResultId id;
......@@ -99,6 +100,7 @@ struct ConstCastOnly {
99100 ConstCastOnly *null_wrap_ptr_child;
100101 ConstCastArg fn_arg;
101102 ConstCastArgNoAlias arg_no_alias;
103 ConstCastBadAllowsZero *bad_allows_zero;
102104 } data;
103105};
104106
......@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
141143 ZigList<ErrorTableEntry *> missing_errors;
142144};
143145
146struct ConstCastBadAllowsZero {
147 ZigType *wanted_type;
148 ZigType *actual_type;
149};
150
151
144152enum UndefAllowed {
145153 UndefOk,
146154 UndefBad,
......@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
164172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
165173 ConstExprValue *out_val, ConstExprValue *ptr_val);
166174static 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);
168176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171179static 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
173185static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
174186 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -186,10 +198,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
186198 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
187199 break;
188200 }
189 case ConstPtrSpecialBaseStruct:
190 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
191 const_val->data.x_ptr.data.base_struct.field_index];
201 case ConstPtrSpecialBaseStruct: {
202 ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
203 result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];
192204 break;
205 }
193206 case ConstPtrSpecialBaseErrorUnionCode:
194207 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
195208 break;
......@@ -218,20 +231,55 @@ static bool is_opt_err_set(ZigType *ty) {
218231 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
219232}
220233
234// This function returns true when you can change the type of a ConstExprValue and the
235// value remains meaningful.
221236static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
222237 if (a == b)
223238 return true;
224239
225 if (a->id == b->id)
226 return true;
227
228240 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
229241 return true;
230242
231243 if (is_opt_err_set(a) && is_opt_err_set(b))
232244 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();
235283}
236284
237285static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
......@@ -368,6 +416,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) {
368416 return IrInstructionIdLoadPtr;
369417}
370418
419static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtrGen *) {
420 return IrInstructionIdLoadPtrGen;
421}
422
371423static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
372424 return IrInstructionIdStorePtr;
373425}
......@@ -408,6 +460,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
408460 return IrInstructionIdCast;
409461}
410462
463static constexpr IrInstructionId ir_instruction_id(IrInstructionResizeSlice *) {
464 return IrInstructionIdResizeSlice;
465}
466
411467static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) {
412468 return IrInstructionIdContainerInitList;
413469}
......@@ -688,6 +744,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
688744 return IrInstructionIdBitCast;
689745}
690746
747static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
748 return IrInstructionIdBitCastGen;
749}
750
691751static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
692752 return IrInstructionIdWidenOrShorten;
693753}
......@@ -1291,14 +1351,23 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
12911351 return &ptr_type_of_instruction->base;
12921352}
12931353
1294static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
1295 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node);
1296 br_instruction->op_id = op_id;
1297 br_instruction->value = value;
1354static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
1355 IrInstruction *value, LVal lval)
1356{
1357 IrInstructionUnOp *instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node);
1358 instruction->op_id = op_id;
1359 instruction->value = value;
1360 instruction->lval = lval;
12981361
12991362 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);
13021371}
13031372
13041373static 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
14181487 return &decl_var_instruction->base;
14191488}
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
14211503static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
14221504 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
14231505{
......@@ -2190,12 +2272,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
21902272}
21912273
21922274static 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)
21942276{
21952277 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
21962278 irb, scope, source_node);
21972279 instruction->dest_type = dest_type;
21982280 instruction->ptr = ptr;
2281 instruction->safety_check_on = safety_check_on;
21992282
22002283 ir_ref_instruction(dest_type, irb->current_basic_block);
22012284 ir_ref_instruction(ptr, irb->current_basic_block);
......@@ -2204,12 +2287,26 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod
22042287}
22052288
22062289static 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)
22082291{
22092292 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
22102293 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
22112294 instruction->base.value.type = ptr_type;
22122295 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
22142311 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
22242321 instruction->dest_type = dest_type;
22252322 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);
22282325 ir_ref_instruction(value, irb->current_basic_block);
22292326
22302327 return &instruction->base;
22312328}
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
22332343static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,
22342344 IrInstruction *target)
22352345{
......@@ -2458,7 +2568,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
24582568
24592569 ir_ref_instruction(type_value, irb->current_basic_block);
24602570
2461 return &instruction->base;
2571 return &instruction->base;
24622572}
24632573
24642574static 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
36513761 return ir_build_const_null(irb, scope, node);
36523762}
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
36543780static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
36553781 Error err;
36563782 assert(node->type == NodeTypeSymbol);
......@@ -3704,8 +3830,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
37043830 return irb->codegen->invalid_instruction;
37053831 }
37063832
3707 // TODO put a variable of same name with invalid type in global scope
3833 // put a variable of same name with invalid type in global scope
37083834 // 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);
37093836 add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
37103837 return irb->codegen->invalid_instruction;
37113838}
......@@ -4493,7 +4620,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
44934620 if (arg1_value == irb->codegen->invalid_instruction)
44944621 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);
44974624 return ir_lval_wrap(irb, scope, ptr_cast, lval);
44984625 }
44994626 case BuiltinFnIdBitCast:
......@@ -5019,10 +5146,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
50195146 return ir_build_ref(irb, scope, value->source_node, value, false, false);
50205147}
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
50225163static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
50235164 assert(node->type == NodeTypePointerType);
5024 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||
5025 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5165 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
50265166 bool is_const = node->data.pointer_type.is_const;
50275167 bool is_volatile = node->data.pointer_type.is_volatile;
50285168 AstNode *expr_node = node->data.pointer_type.op_expr;
......@@ -6715,14 +6855,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
67156855 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
67166856
67176857 // 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);
67196860 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
67206861 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
67216862 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
67226863 atomic_state_field_name);
67236864
67246865 // 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,
67266867 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
67276868 AtomicRmwOp_or, AtomicOrderSeqCst);
67286869
......@@ -6793,14 +6934,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
67936934 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
67946935
67956936 // 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);
67976939 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
67986940 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
67996941 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
68006942 atomic_state_field_name);
68016943
68026944 // 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,
68046946 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
68056947 AtomicRmwOp_and, AtomicOrderSeqCst);
68066948
......@@ -6916,7 +7058,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69167058
69177059 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
69187060 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,
69207062 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
69217063 AtomicRmwOp_or, AtomicOrderSeqCst);
69227064
......@@ -6959,7 +7101,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69597101
69607102
69617103 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,
69637105 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
69647106 AtomicRmwOp_or, AtomicOrderSeqCst);
69657107 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
69917133
69927134 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
69937135 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,
69957137 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
69967138 AtomicRmwOp_or, AtomicOrderSeqCst);
69977139 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
71947336 if (value == irb->codegen->invalid_instruction)
71957337 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);
71987343 }
71997344 case NodeTypeUnwrapOptional: {
72007345 AstNode *expr_node = node->data.unwrap_optional.expr;
......@@ -7338,7 +7483,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73387483
73397484 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
73407485 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);
73427488 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
73437489 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
73447490 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
73627508 ir_build_return(irb, coro_scope, node, undef);
73637509
73647510 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);
73667513 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
73677514
73687515 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
74407587 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
74417588 false, false, PtrLenUnknown, 0, 0, 0));
74427589 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7443 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7444 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7445 irb->exec->coro_result_field_ptr);
7590 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7591 result_ptr, false);
7592 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node,
7593 u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false);
74467594 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
74477595 fn_entry->type_entry->data.fn.fn_type_id.return_type);
74487596 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
74927640 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
74937641 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
74947642 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);
74967645 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
74977646 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
74987647 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
86198768 return err_set_type;
86208769}
86218770
8622
86238771static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
86248772 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
86258773{
......@@ -8632,53 +8780,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86328780 if (wanted_type == actual_type)
86338781 return result;
86348782
8635 // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
8636 // but not if we want a mutable pointer
8637 // and not if the actual pointer has zero bits
8638 if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&
8639 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
8640 actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))
8641 {
8642 ConstCastOnly child = types_match_const_cast_only(ira,
8643 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
8644 if (child.id == ConstCastResultIdInvalid)
8645 return child;
8646 if (child.id != ConstCastResultIdOk) {
8647 result.id = ConstCastResultIdNullWrapPtr;
8648 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);
8649 *result.data.null_wrap_ptr_child = child;
8650 }
8651 return result;
8652 }
8653
8654 // pointer const
8655 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
8656 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8657 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8783 // If pointers have the same representation in memory, they can be "const-casted".
8784 // `const` attribute can be gained
8785 // `volatile` attribute can be gained
8786 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
8787 // but only if !wanted_is_mutable
8788 // alignment can be decreased
8789 // bit offset attributes must match exactly
8790 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
8791 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8792 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8793 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
8794 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
8795 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8796 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8797 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
8798 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
8799 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
8800 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
8801 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
8802 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8803 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
86588804 if (child.id == ConstCastResultIdInvalid)
86598805 return child;
86608806 if (child.id != ConstCastResultIdOk) {
86618807 result.id = ConstCastResultIdPointerChild;
86628808 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
86638809 result.data.pointer_mismatch->child = child;
8664 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
8665 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
8810 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
8811 result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
8812 return result;
8813 }
8814 bool ok_allows_zero = (wanted_allows_zero &&
8815 (actual_allows_zero || !wanted_is_mutable)) ||
8816 (!wanted_allows_zero && !actual_allows_zero);
8817 if (!ok_allows_zero) {
8818 result.id = ConstCastResultIdBadAllowsZero;
8819 result.data.bad_allows_zero = allocate_nonzero<ConstCastBadAllowsZero>(1);
8820 result.data.bad_allows_zero->wanted_type = wanted_type;
8821 result.data.bad_allows_zero->actual_type = actual_type;
86668822 return result;
86678823 }
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))) {
86698825 result.id = ConstCastResultIdInvalid;
86708826 return result;
86718827 }
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))) {
86738829 result.id = ConstCastResultIdInvalid;
86748830 return result;
86758831 }
8676 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8677 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8678 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8679 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
8680 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
8681 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
8832 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8833 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8834 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
8835 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8836 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8837 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
8838 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
8839 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
86828840 {
86838841 return result;
86848842 }
......@@ -8912,7 +9070,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
89129070 *errors = reallocate(*errors, old_errors_count, *errors_count);
89139071}
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{
89169076 Error err;
89179077 assert(instruction_count >= 1);
89189078 IrInstruction *prev_inst = instructions[0];
......@@ -9229,6 +9389,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
92299389 continue;
92309390 }
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
92329423 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
92339424 continue;
92349425 }
......@@ -9534,9 +9725,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
95349725 }
95359726 const_val->type = new_type;
95369727 break;
9537 case CastOpResizeSlice:
9538 // can't do it
9539 zig_unreachable();
95409728 case CastOpIntToFloat:
95419729 {
95429730 assert(new_type->id == ZigTypeIdFloat);
......@@ -9600,9 +9788,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
96009788static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
96019789 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
96029790{
9603 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
9604 cast_op != CastOpResizeSlice)
9605 {
9791 if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {
96069792 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
96079793 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
96089794 &result->value, wanted_type))
......@@ -9864,7 +10050,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
986410050 if (undef_allowed == UndefOk) {
986510051 return &value->value;
986610052 } 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"));
986810054 return nullptr;
986910055 }
987010056 }
......@@ -9874,7 +10060,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
987410060ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
987510061 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
987610062 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)
987810064{
987910065 if (expected_type != nullptr && type_is_invalid(expected_type))
988010066 return &codegen->invalid_instruction->value;
......@@ -9910,7 +10096,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
991010096 analyzed_executable->backward_branch_count = backward_branch_count;
991110097 analyzed_executable->backward_branch_quota = backward_branch_quota;
991210098 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);
991410100 if (type_is_invalid(result_type))
991510101 return &codegen->invalid_instruction->value;
991610102
......@@ -10230,49 +10416,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
1023010416 return result;
1023110417}
1023210418
10233static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr,
10234 IrInstruction *target, ZigType *wanted_type)
10235{
10419static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *union_type) {
10420 assert(union_type->id == ZigTypeIdUnion);
10421
1023610422 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;
10240 if ((err = ensure_complete_type(ira->codegen, actual_type)))
10241 return ira->codegen->invalid_instruction;
10426 AstNode *decl_node = union_type->data.unionation.decl_node;
10427 if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
10428 assert(union_type->data.unionation.tag_type != nullptr);
10429 return union_type->data.unionation.tag_type;
10430 } else {
10431 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union '%s' has no tag",
10432 buf_ptr(&union_type->name)));
10433 add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here"));
10434 return ira->codegen->builtin_types.entry_invalid;
10435 }
10436}
1024210437
10243 if (wanted_type != actual_type->data.enumeration.tag_int_type) {
10244 ir_add_error(ira, source_instr,
10245 buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'",
10246 buf_ptr(&wanted_type->name),
10247 buf_ptr(&actual_type->data.enumeration.tag_int_type->name)));
10438static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) {
10439 Error err;
10440
10441 IrInstruction *enum_target;
10442 ZigType *enum_type;
10443 if (target->value.type->id == ZigTypeIdUnion) {
10444 enum_type = ir_resolve_union_tag_type(ira, target, target->value.type);
10445 if (type_is_invalid(enum_type))
10446 return ira->codegen->invalid_instruction;
10447 enum_target = ir_implicit_cast(ira, target, enum_type);
10448 if (type_is_invalid(enum_target->value.type))
10449 return ira->codegen->invalid_instruction;
10450 } else if (target->value.type->id == ZigTypeIdEnum) {
10451 enum_target = target;
10452 enum_type = target->value.type;
10453 } else {
10454 ir_add_error(ira, target,
10455 buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
1024810456 return ira->codegen->invalid_instruction;
1024910457 }
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)) {
10254 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
10462 ZigType *tag_type = enum_type->data.enumeration.tag_int_type;
10463 assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt);
10464
10465 if (instr_is_comptime(enum_target)) {
10466 ConstExprValue *val = ir_resolve_const(ira, enum_target, UndefBad);
1025510467 if (!val)
1025610468 return ira->codegen->invalid_instruction;
10257 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10258 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
10469 IrInstruction *result = ir_const(ira, source_instr, tag_type);
10470 init_const_bigint(&result->value, tag_type, &val->data.x_enum_tag);
1025910471 return result;
1026010472 }
1026110473
1026210474 // If there is only one possible tag, then we know at comptime what it is.
10263 if (actual_type->data.enumeration.layout == ContainerLayoutAuto &&
10264 actual_type->data.enumeration.src_field_count == 1)
10475 if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&
10476 enum_type->data.enumeration.src_field_count == 1)
1026510477 {
10266 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10267 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10268 init_const_bigint(&result->value, wanted_type,
10269 &actual_type->data.enumeration.fields[0].value);
10478 assert(tag_type == ira->codegen->builtin_types.entry_num_lit_int);
10479 IrInstruction *result = ir_const(ira, source_instr, tag_type);
10480 init_const_bigint(&result->value, tag_type,
10481 &enum_type->data.enumeration.fields[0].value);
1027010482 return result;
1027110483 }
1027210484
1027310485 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
10274 source_instr->source_node, target);
10275 result->value.type = wanted_type;
10486 source_instr->source_node, enum_target);
10487 result->value.type = tag_type;
1027610488 return result;
1027710489}
1027810490
......@@ -10770,17 +10982,37 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1077010982 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
1077110983 break;
1077210984 }
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;
1077311007 case ConstCastResultIdFnAlign: // TODO
1077411008 case ConstCastResultIdFnCC: // TODO
1077511009 case ConstCastResultIdFnVarArgs: // TODO
10776 case ConstCastResultIdFnIsGeneric: // TODO
1077711010 case ConstCastResultIdFnReturnType: // TODO
1077811011 case ConstCastResultIdFnArgCount: // TODO
1077911012 case ConstCastResultIdFnGenericArgCount: // TODO
1078011013 case ConstCastResultIdFnArgNoAlias: // TODO
1078111014 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
1078211015 case ConstCastResultIdAsyncAllocatorType: // TODO
10783 case ConstCastResultIdNullWrapPtr: // TODO
1078411016 break;
1078511017 }
1078611018}
......@@ -10811,6 +11043,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
1081111043 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
1081211044}
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
1081411079static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1081511080 ZigType *wanted_type, IrInstruction *value)
1081611081{
......@@ -11182,7 +11447,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1118211447 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
1118311448 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
1118411449 {
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);
1118611451 }
1118711452 }
1118811453
......@@ -11217,6 +11482,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1121711482 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
1121811483 }
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
1122011502 // cast from undefined to anything
1122111503 if (actual_type->id == ZigTypeIdUndefined) {
1122211504 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
1128611568 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
1128711569 return ref_inst->value;
1128811570 }
11289 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
11290 source_instruction->source_node, ptr);
11291 load_ptr_instruction->value.type = child_type;
11292 return load_ptr_instruction;
11571 IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type);
11572 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
11573 ir_add_alloca(ira, result, child_type);
11574 }
11575 return result;
1129311576 } else {
1129411577 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'",
1129611579 buf_ptr(&type_entry->name)));
1129711580 return ira->codegen->invalid_instruction;
1129811581 }
......@@ -11588,28 +11871,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
1158811871}
1158911872
1159011873static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
11591 if (op_id == IrBinOpCmpEq) {
11592 return cmp == CmpEQ;
11593 } else if (op_id == IrBinOpCmpNotEq) {
11594 return cmp != CmpEQ;
11595 } else if (op_id == IrBinOpCmpLessThan) {
11596 return cmp == CmpLT;
11597 } else if (op_id == IrBinOpCmpGreaterThan) {
11598 return cmp == CmpGT;
11599 } else if (op_id == IrBinOpCmpLessOrEq) {
11600 return cmp != CmpGT;
11601 } else if (op_id == IrBinOpCmpGreaterOrEq) {
11602 return cmp != CmpLT;
11603 } else {
11604 zig_unreachable();
11874 switch (op_id) {
11875 case IrBinOpCmpEq:
11876 return cmp == CmpEQ;
11877 case IrBinOpCmpNotEq:
11878 return cmp != CmpEQ;
11879 case IrBinOpCmpLessThan:
11880 return cmp == CmpLT;
11881 case IrBinOpCmpGreaterThan:
11882 return cmp == CmpGT;
11883 case IrBinOpCmpLessOrEq:
11884 return cmp != CmpGT;
11885 case IrBinOpCmpGreaterOrEq:
11886 return cmp != CmpLT;
11887 default:
11888 zig_unreachable();
1160511889 }
1160611890}
1160711891
1160811892static bool optional_value_is_null(ConstExprValue *val) {
1160911893 assert(val->special == ConstValSpecialStatic);
1161011894 if (get_codegen_ptr_type(val->type) != nullptr) {
11611 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
11612 val->data.x_ptr.data.hard_coded_addr.addr == 0;
11895 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
11896 return true;
11897 } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
11898 return val->data.x_ptr.data.hard_coded_addr.addr == 0;
11899 } else {
11900 return false;
11901 }
1161311902 } else if (is_opt_err_set(val->type)) {
1161411903 return val->data.x_err_set == nullptr;
1161511904 } else {
......@@ -11773,7 +12062,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1177312062 case ZigTypeIdBool:
1177412063 case ZigTypeIdMetaType:
1177512064 case ZigTypeIdVoid:
11776 case ZigTypeIdPointer:
1177712065 case ZigTypeIdErrorSet:
1177812066 case ZigTypeIdFn:
1177912067 case ZigTypeIdOpaque:
......@@ -11785,6 +12073,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1178512073 operator_allowed = is_equality_cmp;
1178612074 break;
1178712075
12076 case ZigTypeIdPointer:
12077 operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
12078 break;
12079
1178812080 case ZigTypeIdUnreachable:
1178912081 case ZigTypeIdArray:
1179012082 case ZigTypeIdStruct:
......@@ -11832,15 +12124,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1183212124 if (op2_val == nullptr)
1183312125 return ira->codegen->invalid_instruction;
1183412126
11835 bool answer;
1183612127 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
1183712128 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);
1183912131 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
1184012132 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 }
1184212156 } else {
1184312157 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
12158 bool answer;
1184412159 if (op_id == IrBinOpCmpEq) {
1184512160 answer = are_equal;
1184612161 } else if (op_id == IrBinOpCmpNotEq) {
......@@ -11848,9 +12163,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1184812163 } else {
1184912164 zig_unreachable();
1185012165 }
12166 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1185112167 }
11852
11853 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1185412168 }
1185512169
1185612170 // some comparisons with unsigned numbers can be evaluated
......@@ -12245,7 +12559,29 @@ static bool ok_float_op(IrBinOp op) {
1224512559 zig_unreachable();
1224612560}
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
1224812582static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12583 Error err;
12584
1224912585 IrInstruction *op1 = instruction->op1->child;
1225012586 if (type_is_invalid(op1->value.type))
1225112587 return ira->codegen->invalid_instruction;
......@@ -12257,23 +12593,54 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1225712593 IrBinOp op_id = instruction->op_id;
1225812594
1225912595 // look for pointer math
12260 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
12261 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
12262 {
12596 if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
1226312597 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))
1226512599 return ira->codegen->invalid_instruction;
1226612600
12267 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
12268 instruction->base.source_node, op_id, op1, casted_op2, true);
12269 result->value.type = op1->value.type;
12270 return result;
12271 }
12272
12273 IrInstruction *instructions[] = {op1, op2};
12274 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);
12275 if (type_is_invalid(resolved_type))
12276 return ira->codegen->invalid_instruction;
12601 if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
12602 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12603 result->value.special = ConstValSpecialUndef;
12604 return result;
12605 }
12606 if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&
12607 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
12608 op1->value.data.x_ptr.special == ConstPtrSpecialNull))
12609 {
12610 uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?
12611 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;
12612 uint64_t elem_offset;
12613 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
12614 return ira->codegen->invalid_instruction;
12615 ZigType *elem_type = op1->value.type->data.pointer.child_type;
12616 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
12617 return ira->codegen->invalid_instruction;
12618 uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
12619 uint64_t new_addr;
12620 if (op_id == IrBinOpAdd) {
12621 new_addr = start_addr + byte_offset;
12622 } else if (op_id == IrBinOpSub) {
12623 new_addr = start_addr - byte_offset;
12624 } else {
12625 zig_unreachable();
12626 }
12627 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12628 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
12629 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
12630 result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;
12631 return result;
12632 }
12633
12634 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
12635 instruction->base.source_node, op_id, op1, casted_op2, true);
12636 result->value.type = op1->value.type;
12637 return result;
12638 }
12639
12640 IrInstruction *instructions[] = {op1, op2};
12641 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);
12642 if (type_is_invalid(resolved_type))
12643 return ira->codegen->invalid_instruction;
1227712644
1227812645 bool is_int = resolved_type->id == ZigTypeIdInt || resolved_type->id == ZigTypeIdComptimeInt;
1227912646 bool is_float = resolved_type->id == ZigTypeIdFloat || resolved_type->id == ZigTypeIdComptimeFloat;
......@@ -12878,6 +13245,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1287813245 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
1287913246}
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
1288113262static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
1288213263 IrInstruction *name = instruction->name->child;
1288313264 Buf *symbol_name = ir_resolve_str(ira, name);
......@@ -12898,14 +13279,24 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1289813279 }
1289913280 }
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);
1290213291 if (entry) {
12903 AstNode *other_export_node = entry->value;
13292 AstNode *other_export_node = entry->value->source_node;
1290413293 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
1290513294 buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name)));
1290613295 add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here"));
13296 return ira->codegen->invalid_instruction;
1290713297 }
1290813298
13299 bool want_var_export = false;
1290913300 switch (target->value.type->id) {
1291013301 case ZigTypeIdInvalid:
1291113302 case ZigTypeIdUnreachable:
......@@ -12913,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1291313304 case ZigTypeIdFn: {
1291413305 assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction);
1291513306 ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry;
13307 tld_fn->fn_entry = fn_entry;
1291613308 CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc;
1291713309 switch (cc) {
1291813310 case CallingConventionUnspecified: {
......@@ -12941,6 +13333,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1294113333 ErrorMsg *msg = ir_add_error(ira, target,
1294213334 buf_sprintf("exported struct value must be declared extern"));
1294313335 add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here"));
13336 } else {
13337 want_var_export = true;
1294413338 }
1294513339 break;
1294613340 case ZigTypeIdUnion:
......@@ -12948,6 +13342,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1294813342 ErrorMsg *msg = ir_add_error(ira, target,
1294913343 buf_sprintf("exported union value must be declared extern"));
1295013344 add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here"));
13345 } else {
13346 want_var_export = true;
1295113347 }
1295213348 break;
1295313349 case ZigTypeIdEnum:
......@@ -12955,6 +13351,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1295513351 ErrorMsg *msg = ir_add_error(ira, target,
1295613352 buf_sprintf("exported enum value must be declared extern"));
1295713353 add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here"));
13354 } else {
13355 want_var_export = true;
1295813356 }
1295913357 break;
1296013358 case ZigTypeIdMetaType: {
......@@ -13044,6 +13442,16 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1304413442 break;
1304513443 }
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
1304713455 return ir_const_void(ira, &instruction->base);
1304813456}
1304913457
......@@ -13331,9 +13739,16 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1333113739 if (var->var_type == nullptr || type_is_invalid(var->var_type))
1333213740 return ira->codegen->invalid_instruction;
1333313741
13742 ConstExprValue *mem_slot = nullptr;
13743
1333413744 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;
1333713752 if (var->const_value->special == ConstValSpecialStatic) {
1333813753 mem_slot = var->const_value;
1333913754 } else {
......@@ -13347,8 +13762,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1334713762 }
1334813763 }
1334913764
13350 bool is_const = var->src_is_const;
13351 bool is_volatile = false;
1335213765 if (mem_slot != nullptr) {
1335313766 switch (mem_slot->special) {
1335413767 case ConstValSpecialRuntime:
......@@ -13387,26 +13800,32 @@ no_mem_slot:
1338713800static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
1338813801 IrInstruction *ptr, IrInstruction *uncasted_value)
1338913802{
13390 if (ptr->value.type->id != ZigTypeIdPointer) {
13391 ir_add_error(ira, ptr,
13392 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
13393 return ira->codegen->invalid_instruction;
13394 }
13803 assert(ptr->value.type->id == ZigTypeIdPointer);
1339513804
1339613805 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
1339713806 return ir_const_void(ira, source_instr);
1339813807 }
1339913808
13809 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13810
1340013811 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
1340113812 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
1340213813 return ira->codegen->invalid_instruction;
1340313814 }
1340413815
13405 ZigType *child_type = ptr->value.type->data.pointer.child_type;
1340613816 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
1340713817 if (value == ira->codegen->invalid_instruction)
1340813818 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
1341013829 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
1341113830 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
1341213831 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
1342713846 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
1342813847 copy_const_val(dest_val, &value->value, same_global_refs);
1342913848 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13430 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13431 case OnePossibleValueInvalid:
13432 return ira->codegen->invalid_instruction;
13433 case OnePossibleValueNo:
13434 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13435 break;
13436 case OnePossibleValueYes:
13437 break;
13438 }
13849 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
1343913850 }
1344013851 return ir_const_void(ira, source_instr);
1344113852 }
......@@ -13630,7 +14041,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1363014041 AstNode *body_node = fn_entry->body_node;
1363114042 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
1363214043 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
1363514046 if (inferred_err_set_type != nullptr) {
1363614047 inferred_err_set_type->data.error_set.infer_fn = nullptr;
......@@ -13826,7 +14237,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1382614237 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
1382714238 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
1382814239 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);
1383014241 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
1383114242 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
1383214243 const_instruction->base.value = *align_result;
......@@ -14108,12 +14519,11 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1410814519 size_t src_size = type_size(codegen, pointee->type);
1410914520 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
1411614522 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 }
1411714527 Buf buf = BUF_INIT;
1411814528 buf_resize(&buf, src_size);
1411914529 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
1412914539 if (dst_size == 0)
1413014540 return ErrorNone;
1413114541 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",
1413314543 dst_size));
1413414544 return ErrorSemanticAnalyzeFail;
1413514545 case ConstPtrSpecialRef: {
1413614546 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",
1413814548 dst_size, buf_ptr(&pointee->type->name), src_size));
1413914549 return ErrorSemanticAnalyzeFail;
1414014550 }
......@@ -14148,7 +14558,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1414814558 src_size = elem_size * (array_val->type->data.array.len - elem_index);
1414914559 if (dst_size > src_size) {
1415014560 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",
1415214562 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
1415314563 return ErrorSemanticAnalyzeFail;
1415414564 }
......@@ -14220,6 +14630,41 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
1422014630 zig_unreachable();
1422114631}
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
1422314668static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) {
1422414669 IrInstruction *value = instruction->value->child;
1422514670 ZigType *expr_type = value->value.type;
......@@ -14228,47 +14673,50 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins
1422814673
1422914674 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) ||
14234 expr_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op))
14235 {
14236 if (instr_is_comptime(value)) {
14237 ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
14238 if (!target_const_val)
14239 return ira->codegen->invalid_instruction;
14678 if (instr_is_comptime(value)) {
14679 ConstExprValue *operand_val = ir_resolve_const(ira, value, UndefBad);
14680 if (!operand_val)
14681 return ira->codegen->invalid_instruction;
1424014682
14241 IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
14242 ConstExprValue *out_val = &result->value;
14243 if (is_float) {
14244 float_negate(out_val, target_const_val);
14245 } else if (is_wrap_op) {
14246 bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
14247 expr_type->data.integral.bit_count);
14248 } else {
14249 bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);
14250 }
14251 if (is_wrap_op || is_float || expr_type->id == ZigTypeIdComptimeInt) {
14252 return result;
14683 IrInstruction *result_instruction = ir_const(ira, &instruction->base, expr_type);
14684 ConstExprValue *out_val = &result_instruction->value;
14685 if (expr_type->id == ZigTypeIdVector) {
14686 expand_undef_array(ira->codegen, operand_val);
14687 out_val->special = ConstValSpecialUndef;
14688 expand_undef_array(ira->codegen, out_val);
14689 size_t len = expr_type->data.vector.len;
14690 for (size_t i = 0; i < len; i += 1) {
14691 ConstExprValue *scalar_operand_val = &operand_val->data.x_array.data.s_none.elements[i];
14692 ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
14693 assert(scalar_operand_val->type == scalar_type);
14694 assert(scalar_out_val->type == scalar_type);
14695 ErrorMsg *msg = ir_eval_negation_scalar(ira, &instruction->base, scalar_type,
14696 scalar_operand_val, scalar_out_val, is_wrap_op);
14697 if (msg != nullptr) {
14698 add_error_note(ira->codegen, msg, instruction->base.source_node,
14699 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
14700 return ira->codegen->invalid_instruction;
14701 }
1425314702 }
14254
14255 if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {
14256 ir_add_error(ira, &instruction->base, buf_sprintf("negation caused overflow"));
14703 out_val->type = expr_type;
14704 out_val->special = ConstValSpecialStatic;
14705 } else {
14706 if (ir_eval_negation_scalar(ira, &instruction->base, scalar_type, operand_val, out_val,
14707 is_wrap_op) != nullptr)
14708 {
1425714709 return ira->codegen->invalid_instruction;
1425814710 }
14259 return result;
1426014711 }
14261
14262 IrInstruction *result = ir_build_un_op(&ira->new_irb,
14263 instruction->base.scope, instruction->base.source_node,
14264 instruction->op_id, value);
14265 result->value.type = expr_type;
14266 return result;
14712 return result_instruction;
1426714713 }
1426814714
14269 const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
14270 ir_add_error(ira, &instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
14271 return ira->codegen->invalid_instruction;
14715 IrInstruction *result = ir_build_un_op(&ira->new_irb,
14716 instruction->base.scope, instruction->base.source_node,
14717 instruction->op_id, value);
14718 result->value.type = expr_type;
14719 return result;
1427214720}
1427314721
1427414722static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
......@@ -14321,11 +14769,18 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
1432114769 buf_ptr(&ptr_type->name)));
1432214770 return ira->codegen->invalid_instruction;
1432314771 }
14324 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
14325 // one of the ptr instructions
14772
1432614773 IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);
1432714774 if (result == ira->codegen->invalid_instruction)
1432814775 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
1432914784 return result;
1433014785 }
1433114786 case IrUnOpOptional:
......@@ -14958,6 +15413,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1495815413 if (bare_type->id == ZigTypeIdStruct) {
1495915414 TypeStructField *field = find_struct_type_field(bare_type, field_name);
1496015415 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 }
1496115426 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
1496215427 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
1496315428 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_
1506515530}
1506615531
1506715532static 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
1506815541 LinkLib *link_lib = add_link_lib(ira->codegen, lib_name);
1506915542 for (size_t i = 0; i < link_lib->symbols.length; i += 1) {
1507015543 Buf *existing_symbol_name = link_lib->symbols.at(i);
......@@ -15151,12 +15624,6 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1515115624 if (type_is_invalid(container_ptr->value.type))
1515215625 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 }
1516015627 ZigType *container_type = container_ptr->value.type->data.pointer.child_type;
1516115628
1516215629 Buf *field_name = field_ptr_instruction->field_name_buffer;
......@@ -15572,6 +16039,8 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
1557216039static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
1557316040 IrInstructionToPtrType *to_ptr_type_instruction)
1557416041{
16042 Error err;
16043
1557516044 IrInstruction *value = to_ptr_type_instruction->value->child;
1557616045 ZigType *type_entry = value->value.type;
1557716046 if (type_is_invalid(type_entry))
......@@ -15587,7 +16056,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
1558716056 ptr_type = get_pointer_to_type(ira->codegen,
1558816057 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
1558916058 } 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 }
1559116070 } else if (type_entry->id == ZigTypeIdArgTuple) {
1559216071 ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
1559316072 if (!arg_tuple_val)
......@@ -16355,18 +16834,13 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1635516834 return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type);
1635616835 }
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
1636316837 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
1636416838 ConstExprValue *pointee_val = nullptr;
1636516839 if (instr_is_comptime(target_value_ptr)) {
1636616840 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
1636716841 if (pointee_val == nullptr)
1636816842 return ira->codegen->invalid_instruction;
16369
16843
1637016844 if (pointee_val->special == ConstValSpecialRuntime)
1637116845 pointee_val = nullptr;
1637216846 }
......@@ -16953,9 +17427,13 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr
1695317427 }
1695417428 fprintf(stderr, "\n");
1695517429
16956 // Here we bypass higher level functions such as ir_add_error because we do not want
16957 // invalidate_exec to be called.
16958 add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
17430 auto *expr = &instruction->base.source_node->data.fn_call_expr;
17431 if (!expr->seen) {
17432 // Here we bypass higher level functions such as ir_add_error because we do not want
17433 // invalidate_exec to be called.
17434 add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
17435 }
17436 expr->seen = true;
1695917437
1696017438 return ir_const_void(ira, &instruction->base);
1696117439}
......@@ -17116,7 +17594,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
1711617594static TypeStructField *validate_byte_offset(IrAnalyze *ira,
1711717595 IrInstruction *type_value,
1711817596 IrInstruction *field_name_value,
17119 size_t *byte_offset)
17597 size_t *byte_offset)
1712017598{
1712117599 ZigType *container_type = ir_resolve_type(ira, type_value);
1712217600 if (type_is_invalid(container_type))
......@@ -17290,7 +17768,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1729017768
1729117769 // Loop through the definitions and generate info.
1729217770 decl_it = decls_scope->decl_table.entry_iterator();
17293 curr_entry = nullptr;
17771 curr_entry = nullptr;
1729417772 int definition_index = 0;
1729517773 while ((curr_entry = decl_it.next()) != nullptr) {
1729617774 // Skip comptime blocks and test functions.
......@@ -17469,6 +17947,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1746917947 return ErrorNone;
1747017948}
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
1747217962static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
1747317963 Error err;
1747417964 ZigType *attrs_type;
......@@ -17478,7 +17968,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
1747817968 size_enum_index = 2;
1747917969 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
1748017970 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);
1748217972 } else {
1748317973 zig_unreachable();
1748417974 }
......@@ -18172,12 +18662,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
1817218662static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
1817318663 IrInstructionSetEvalBranchQuota *instruction)
1817418664{
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
1818118665 uint64_t new_quota;
1818218666 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
1818318667 return ira->codegen->invalid_instruction;
......@@ -18204,12 +18688,6 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc
1820418688}
1820518689
1820618690static 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
1821318691 AstNode *node = instruction->base.source_node;
1821418692 assert(node->type == NodeTypeFnCallExpr);
1821518693 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
1822018698 ZigType *void_type = ira->codegen->builtin_types.entry_void;
1822118699 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
1822218700 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);
1822418702 if (type_is_invalid(cimport_result->type))
1822518703 return ira->codegen->invalid_instruction;
1822618704
18227 find_libc_include_path(ira->codegen);
18228
1822918705 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
1823018706 child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);
1823118707 child_import->c_import_node = node;
......@@ -18247,6 +18723,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1824718723
1824818724 if (errors.length > 0) {
1824918725 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 }
1825018730 for (size_t i = 0; i < errors.length; i += 1) {
1825118731 ErrorMsg *err_msg = errors.at(i);
1825218732 err_msg_add_note(parent_err_msg, err_msg);
......@@ -18713,7 +19193,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
1871319193 }
1871419194 }
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;
1871719199}
1871819200
1871919201static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
......@@ -18740,7 +19222,34 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
1874019222 alignment, 0, 0);
1874119223 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;
1874419253}
1874519254
1874619255static 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
1895219461 if (type_is_invalid(casted_count->value.type))
1895319462 return ira->codegen->invalid_instruction;
1895419463
19464 // TODO test this at comptime with u8 and non-u8 types
1895519465 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
1895619466 casted_byte->value.special == ConstValSpecialStatic &&
1895719467 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)
1895919470 {
1896019471 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;
1896119472
......@@ -19074,6 +19585,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
1907419585 if (type_is_invalid(casted_count->value.type))
1907519586 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
1907719590 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
1907819591 casted_src_ptr->value.special == ConstValSpecialStatic &&
1907919592 casted_count->value.special == ConstValSpecialStatic &&
......@@ -20242,7 +20755,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
2024220755 } else {
2024320756 seenFalse += 1;
2024420757 }
20245
20758
2024620759 if ((seenTrue > 1) || (seenFalse > 1)) {
2024720760 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
2024820761 return ira->codegen->invalid_instruction;
......@@ -20375,7 +20888,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
2037520888}
2037620889
2037720890static 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)
2037920892{
2038020893 Error err;
2038120894
......@@ -20385,12 +20898,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2038520898 // We have a check for zero bits later so we use get_src_ptr_type to
2038620899 // 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) {
2038920903 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
2039020904 return ira->codegen->invalid_instruction;
2039120905 }
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) {
2039420909 ir_add_error(ira, dest_type_src,
2039520910 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
2039620911 return ira->codegen->invalid_instruction;
......@@ -20400,25 +20915,44 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2040020915 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
2040120916 return ira->codegen->invalid_instruction;
2040220917 }
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
2040420926 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);
2040620930 if (!val)
2040720931 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
2040920944 IrInstruction *result = ir_const(ira, source_instr, dest_type);
2041020945 copy_const_val(&result->value, val, false);
2041120946 result->value.type = dest_type;
20412 return result;
20413 }
2041420947
20415 uint32_t src_align_bytes;
20416 if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
20417 return ira->codegen->invalid_instruction;
20948 // Keep the bigger alignment, it can only help-
20949 // unless the target is zero bits.
20950 if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
20951 result = ir_align_cast(ira, result, src_align_bytes, false);
20952 }
2041820953
20419 uint32_t dest_align_bytes;
20420 if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
20421 return ira->codegen->invalid_instruction;
20954 return result;
20955 }
2042220956
2042320957 if (dest_align_bytes > src_align_bytes) {
2042420958 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_
2042920963 return ira->codegen->invalid_instruction;
2043020964 }
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
2043420968 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
2043520969 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -20466,7 +21000,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
2046621000 if (type_is_invalid(src_type))
2046721001 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);
2047021005}
2047121006
2047221007static 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
2052921064 case ZigTypeIdVector:
2053021065 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
2053121066 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 }
2053321140 case ZigTypeIdOptional:
2053421141 zig_panic("TODO buf_write_value_bytes maybe type");
2053521142 case ZigTypeIdErrorUnion:
......@@ -20656,8 +21263,62 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2065621263 }
2065721264 return ErrorNone;
2065821265 }
20659 case ContainerLayoutPacked:
20660 zig_panic("TODO buf_read_value_bytes packed struct");
21266 case ContainerLayoutPacked: {
21267 size_t src_field_count = val->type->data.structure.src_field_count;
21268 val->data.x_struct.fields = create_const_vals(src_field_count);
21269 size_t gen_field_count = val->type->data.structure.gen_field_count;
21270 size_t gen_i = 0;
21271 size_t src_i = 0;
21272 size_t offset = 0;
21273 bool is_big_endian = codegen->is_big_endian;
21274 uint8_t child_buf_prealloc[16];
21275 size_t child_buf_len = 16;
21276 uint8_t *child_buf = child_buf_prealloc;
21277 while (gen_i < gen_field_count) {
21278 LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref,
21279 (unsigned)gen_i);
21280 size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type);
21281 size_t big_int_byte_count = big_int_bit_count / 8;
21282 if (big_int_byte_count > child_buf_len) {
21283 child_buf = allocate_nonzero<uint8_t>(big_int_byte_count);
21284 child_buf_len = big_int_byte_count;
21285 }
21286 BigInt big_int;
21287 bigint_read_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian, false);
21288 while (src_i < src_field_count) {
21289 TypeStructField *field = &val->type->data.structure.fields[src_i];
21290 assert(field->gen_index != SIZE_MAX);
21291 if (field->gen_index != gen_i)
21292 break;
21293 ConstExprValue *field_val = &val->data.x_struct.fields[src_i];
21294 field_val->special = ConstValSpecialStatic;
21295 field_val->type = field->type_entry;
21296 uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry);
21297
21298 BigInt child_val;
21299 if (is_big_endian) {
21300 zig_panic("TODO buf_read_value_bytes packed struct big endian");
21301 } else {
21302 BigInt packed_bits_size_bi;
21303 bigint_init_unsigned(&packed_bits_size_bi, packed_bits_size);
21304 bigint_truncate(&child_val, &big_int, packed_bits_size, false);
21305 BigInt tmp;
21306 bigint_shr(&tmp, &big_int, &packed_bits_size_bi);
21307 big_int = tmp;
21308 }
21309
21310 bigint_write_twos_complement(&child_val, child_buf, big_int_bit_count, is_big_endian);
21311 if ((err = buf_read_value_bytes(ira, codegen, source_node, child_buf, field_val))) {
21312 return err;
21313 }
21314
21315 src_i += 1;
21316 }
21317 offset += big_int_byte_count;
21318 gen_i += 1;
21319 }
21320 return ErrorNone;
21321 }
2066121322 }
2066221323 zig_unreachable();
2066321324 case ZigTypeIdOptional:
......@@ -20674,32 +21335,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2067421335 zig_unreachable();
2067521336}
2067621337
20677static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20678 Error err;
20679 IrInstruction *dest_type_value = instruction->dest_type->child;
20680 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20681 if (type_is_invalid(dest_type))
20682 return ira->codegen->invalid_instruction;
20683
20684 IrInstruction *value = instruction->value->child;
20685 ZigType *src_type = value->value.type;
20686 if (type_is_invalid(src_type))
20687 return ira->codegen->invalid_instruction;
20688
20689 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20690 return ira->codegen->invalid_instruction;
20691
20692 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20693 return ira->codegen->invalid_instruction;
20694
20695 if (get_codegen_ptr_type(src_type) != nullptr) {
20696 ir_add_error(ira, value,
20697 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20698 return ira->codegen->invalid_instruction;
20699 }
20700
20701 switch (src_type->id) {
21338static bool type_can_bit_cast(ZigType *t) {
21339 switch (t->id) {
2070221340 case ZigTypeIdInvalid:
21341 zig_unreachable();
2070321342 case ZigTypeIdMetaType:
2070421343 case ZigTypeIdOpaque:
2070521344 case ZigTypeIdBoundFn:
......@@ -20710,42 +21349,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2071021349 case ZigTypeIdComptimeInt:
2071121350 case ZigTypeIdUndefined:
2071221351 case ZigTypeIdNull:
20713 ir_add_error(ira, dest_type_value,
20714 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
20715 return ira->codegen->invalid_instruction;
21352 case ZigTypeIdPointer:
21353 return false;
2071621354 default:
20717 break;
21355 // TODO list these types out explicitly, there are probably some other invalid ones here
21356 return true;
2071821357 }
21358}
2071921359
20720 if (get_codegen_ptr_type(dest_type) != nullptr) {
20721 ir_add_error(ira, dest_type_value,
20722 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
21360static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
21361 ZigType *dest_type)
21362{
21363 Error err;
21364
21365 ZigType *src_type = value->value.type;
21366 assert(get_codegen_ptr_type(src_type) == nullptr);
21367 assert(type_can_bit_cast(src_type));
21368 assert(get_codegen_ptr_type(dest_type) == nullptr);
21369 assert(type_can_bit_cast(dest_type));
21370
21371 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
21372 return ira->codegen->invalid_instruction;
21373
21374 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
2072321375 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
2074521378 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
2074621379 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
2074721380 if (dest_size_bytes != src_size_bytes) {
20748 ir_add_error(ira, &instruction->base,
21381 ir_add_error(ira, source_instr,
2074921382 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
2075021383 buf_ptr(&dest_type->name), dest_size_bytes,
2075121384 buf_ptr(&src_type->name), src_size_bytes));
......@@ -20755,7 +21388,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2075521388 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
2075621389 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
2075721390 if (dest_size_bits != src_size_bits) {
20758 ir_add_error(ira, &instruction->base,
21391 ir_add_error(ira, source_instr,
2075921392 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
2076021393 buf_ptr(&dest_type->name), dest_size_bits,
2076121394 buf_ptr(&src_type->name), src_size_bits));
......@@ -20767,44 +21400,64 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2076721400 if (!val)
2076821401 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);
2077121404 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
2077221405 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)))
2077421407 return ira->codegen->invalid_instruction;
2077521408 return result;
2077621409 }
2077721410
20778 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
20779 instruction->base.source_node, nullptr, value);
20780 result->value.type = dest_type;
21411 IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
21412 if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) {
21413 ir_add_alloca(ira, result, dest_type);
21414 }
2078121415 return result;
2078221416}
2078321417
20784static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
20785 Error err;
21418static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
2078621419 IrInstruction *dest_type_value = instruction->dest_type->child;
2078721420 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
2078821421 if (type_is_invalid(dest_type))
2078921422 return ira->codegen->invalid_instruction;
2079021423
20791 // We explicitly check for the size, so we can use get_src_ptr_type
20792 if (get_src_ptr_type(dest_type) == nullptr) {
20793 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
21424 IrInstruction *value = instruction->value->child;
21425 ZigType *src_type = value->value.type;
21426 if (type_is_invalid(src_type))
21427 return ira->codegen->invalid_instruction;
21428
21429 if (get_codegen_ptr_type(src_type) != nullptr) {
21430 ir_add_error(ira, value,
21431 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
2079421432 return ira->codegen->invalid_instruction;
2079521433 }
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)));
2079821438 return ira->codegen->invalid_instruction;
20799 if (!type_has_bits(dest_type)) {
21439 }
21440
21441 if (get_codegen_ptr_type(dest_type) != nullptr) {
2080021442 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)));
2080221444 return ira->codegen->invalid_instruction;
2080321445 }
2080421446
20805 IrInstruction *target = instruction->target->child;
20806 if (type_is_invalid(target->value.type))
21447 if (!type_can_bit_cast(dest_type)) {
21448 ir_add_error(ira, dest_type_value,
21449 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
2080721450 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
2080921462 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
2081021463 if (type_is_invalid(casted_int->value.type))
......@@ -20815,19 +21468,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
2081521468 if (!val)
2081621469 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);
2081921472 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
2082021473 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
2082121474 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
2082221475 return result;
2082321476 }
2082421477
20825 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
20826 instruction->base.source_node, nullptr, casted_int);
20827 result->value.type = dest_type;
21478 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
21479 source_instr->source_node, nullptr, casted_int);
21480 result->value.type = ptr_type;
2082821481 return result;
2082921482}
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
2083121513static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2083221514 IrInstructionDeclRef *instruction)
2083321515{
......@@ -20931,6 +21613,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2093121613 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
2093221614 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
2093321615 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 }
2093421625 }
2093521626
2093621627 uint32_t align_bytes;
......@@ -21068,20 +21759,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct
2106821759
2106921760 return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);
2107021761 } else if (enum_type->id == ZigTypeIdUnion) {
21071 if ((err = ensure_complete_type(ira->codegen, enum_type)))
21072 return ira->codegen->invalid_instruction;
21073
21074 AstNode *decl_node = enum_type->data.unionation.decl_node;
21075 if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
21076 assert(enum_type->data.unionation.tag_type != nullptr);
21077
21078 return ir_const_type(ira, &instruction->base, enum_type->data.unionation.tag_type);
21079 } else {
21080 ErrorMsg *msg = ir_add_error(ira, target_inst, buf_sprintf("union '%s' has no tag",
21081 buf_ptr(&enum_type->name)));
21082 add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here"));
21762 ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target, enum_type);
21763 if (type_is_invalid(tag_type))
2108321764 return ira->codegen->invalid_instruction;
21084 }
21765 return ir_const_type(ira, &instruction->base, tag_type);
2108521766 } else {
2108621767 ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'",
2108721768 buf_ptr(&enum_type->name)));
......@@ -21662,23 +22343,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr
2166222343
2166322344
2166422345static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
21665 Error err;
2166622346 IrInstruction *target = instruction->target->child;
2166722347 if (type_is_invalid(target->value.type))
2166822348 return ira->codegen->invalid_instruction;
2166922349
21670 if (target->value.type->id != ZigTypeIdEnum) {
21671 ir_add_error(ira, instruction->target,
21672 buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
21673 return ira->codegen->invalid_instruction;
21674 }
21675
21676 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
21677 return ira->codegen->invalid_instruction;
21678
21679 ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;
21680
21681 return ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);
22350 return ir_analyze_enum_to_int(ira, &instruction->base, target);
2168222351}
2168322352
2168422353static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
......@@ -21750,6 +22419,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2175022419 case IrInstructionIdArrayToVector:
2175122420 case IrInstructionIdVectorToArray:
2175222421 case IrInstructionIdAssertZero:
22422 case IrInstructionIdResizeSlice:
22423 case IrInstructionIdLoadPtrGen:
22424 case IrInstructionIdBitCastGen:
2175322425 zig_unreachable();
2175422426
2175522427 case IrInstructionIdReturn:
......@@ -22149,12 +22821,14 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2214922821 case IrInstructionIdCmpxchgGen:
2215022822 case IrInstructionIdCmpxchgSrc:
2215122823 case IrInstructionIdAssertZero:
22824 case IrInstructionIdResizeSlice:
2215222825 return true;
2215322826
2215422827 case IrInstructionIdPhi:
2215522828 case IrInstructionIdUnOp:
2215622829 case IrInstructionIdBinOp:
2215722830 case IrInstructionIdLoadPtr:
22831 case IrInstructionIdLoadPtrGen:
2215822832 case IrInstructionIdConst:
2215922833 case IrInstructionIdCast:
2216022834 case IrInstructionIdContainerInitList:
......@@ -22205,6 +22879,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2220522879 case IrInstructionIdPtrCastSrc:
2220622880 case IrInstructionIdPtrCastGen:
2220722881 case IrInstructionIdBitCast:
22882 case IrInstructionIdBitCastGen:
2220822883 case IrInstructionIdWidenOrShorten:
2220922884 case IrInstructionIdPtrToInt:
2221022885 case IrInstructionIdIntToPtr:
src/ir.hpp+1-1
......@@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1616ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
1717 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
1818 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
2121ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
2222 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) {
336336 fprintf(irp->f, ".*");
337337}
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
339344static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
340345 fprintf(irp->f, "*");
341346 ir_print_var_instruction(irp, instruction->ptr);
......@@ -915,14 +920,18 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
915920
916921static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
917922 fprintf(irp->f, "@bitCast(");
918 if (instruction->dest_type) {
919 ir_print_other_instruction(irp, instruction->dest_type);
920 }
923 ir_print_other_instruction(irp, instruction->dest_type);
921924 fprintf(irp->f, ",");
922925 ir_print_other_instruction(irp, instruction->value);
923926 fprintf(irp->f, ")");
924927}
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
926935static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
927936 fprintf(irp->f, "WidenOrShorten(");
928937 ir_print_other_instruction(irp, instruction->target);
......@@ -990,6 +999,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct
990999 fprintf(irp->f, ")");
9911000}
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
9931008static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
9941009 fprintf(irp->f, "inttoerr ");
9951010 ir_print_other_instruction(irp, instruction->target);
......@@ -1462,6 +1477,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14621477 case IrInstructionIdLoadPtr:
14631478 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
14641479 break;
1480 case IrInstructionIdLoadPtrGen:
1481 ir_print_load_ptr_gen(irp, (IrInstructionLoadPtrGen *)instruction);
1482 break;
14651483 case IrInstructionIdStorePtr:
14661484 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
14671485 break;
......@@ -1678,6 +1696,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
16781696 case IrInstructionIdBitCast:
16791697 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
16801698 break;
1699 case IrInstructionIdBitCastGen:
1700 ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
1701 break;
16811702 case IrInstructionIdWidenOrShorten:
16821703 ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
16831704 break;
......@@ -1852,6 +1873,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
18521873 case IrInstructionIdAssertZero:
18531874 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
18541875 break;
1876 case IrInstructionIdResizeSlice:
1877 ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
1878 break;
18551879 }
18561880 fprintf(irp->f, "\n");
18571881}
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 {
1717 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
1818};
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);
2122 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);
2324 return buf_ptr(out_buf);
2425}
2526
2627static const char *get_libc_static_file(CodeGen *g, const char *file) {
28 assert(g->libc != nullptr);
2729 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);
2931 return buf_ptr(out_buf);
3032}
3133
3234static 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
3535 // The Mach-O LLD code is not well maintained, and trips an assertion
3636 // when we link compiler_rt and builtin as libraries rather than objects.
3737 // Here we workaround this by having compiler_rt and builtin be objects.
3838 // TODO write our own linker. https://github.com/ziglang/zig/issues/1535
3939 OutType child_out_type = OutTypeLib;
40 if (parent_gen->zig_target.os == OsMacOSX) {
40 if (parent_gen->zig_target->os == OsMacOSX) {
4141 child_out_type = OutTypeObj;
4242 }
4343
44 CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
45 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir);
44 CodeGen *child_gen = codegen_create(full_path, parent_gen->zig_target, child_out_type,
45 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir,
46 parent_gen->libc);
4647
4748 child_gen->out_h_path = nullptr;
4849 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)
5556 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
5657 codegen_set_is_static(child_gen, true);
5758 child_gen->disable_pic = parent_gen->disable_pic;
59 child_gen->valgrind_support = ValgrindSupportDisabled;
5860
5961 codegen_set_out_name(child_gen, buf_create_from_str(aname));
6062
......@@ -94,7 +96,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {
9496}
9597
9698static const char *get_darwin_arch_string(const ZigTarget *t) {
97 switch (t->arch.arch) {
99 switch (t->arch) {
98100 case ZigLLVM_aarch64:
99101 return "arm64";
100102 case ZigLLVM_thumb:
......@@ -107,13 +109,13 @@ static const char *get_darwin_arch_string(const ZigTarget *t) {
107109 case ZigLLVM_ppc64le:
108110 return "ppc64le";
109111 default:
110 return ZigLLVMGetArchTypeName(t->arch.arch);
112 return ZigLLVMGetArchTypeName(t->arch);
111113 }
112114}
113115
114116
115117static const char *getLDMOption(const ZigTarget *t) {
116 switch (t->arch.arch) {
118 switch (t->arch) {
117119 case ZigLLVM_x86:
118120 return "elf_i386";
119121 case ZigLLVM_aarch64:
......@@ -147,7 +149,7 @@ static const char *getLDMOption(const ZigTarget *t) {
147149 case ZigLLVM_systemz:
148150 return "elf64_s390";
149151 case ZigLLVM_x86_64:
150 if (t->env_type == ZigLLVM_GNUX32) {
152 if (t->abi == ZigLLVM_GNUX32) {
151153 return "elf32_x86_64";
152154 }
153155 // Any target elf will use the freebsd osabi if suffixed with "_fbsd".
......@@ -170,78 +172,27 @@ static void add_rpath(LinkJob *lj, Buf *rpath) {
170172 lj->rpath_table.put(rpath, true);
171173}
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
217175static void construct_linker_job_elf(LinkJob *lj) {
218176 CodeGen *g = lj->codegen;
219177
220178 lj->args.append("-error-limit=0");
221179
222 if (g->libc_link_lib != nullptr) {
223 find_libc_lib_path(g);
224 }
225
226180 if (g->linker_script) {
227181 lj->args.append("-T");
228182 lj->args.append(g->linker_script);
229183 }
230184
231 if (g->no_rosegment_workaround) {
232 lj->args.append("--no-rosegment");
233 }
234185 lj->args.append("--gc-sections");
235186
236187 lj->args.append("-m");
237 lj->args.append(getLDMOption(&g->zig_target));
188 lj->args.append(getLDMOption(g->zig_target));
238189
239190 bool is_lib = g->out_type == OutTypeLib;
240191 bool shared = !g->is_static && is_lib;
241192 Buf *soname = nullptr;
242193 if (g->is_static) {
243 if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
244 g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
194 if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||
195 g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)
245196 {
246197 lj->args.append("-Bstatic");
247198 } else {
......@@ -263,15 +214,18 @@ static void construct_linker_job_elf(LinkJob *lj) {
263214 if (lj->link_in_crt) {
264215 const char *crt1o;
265216 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) {
267221 crt1o = "crt1.o";
268222 crtbegino = "crtbeginT.o";
269223 } else {
270224 crt1o = "Scrt1.o";
271225 crtbegino = "crtbegin.o";
272226 }
273 lj->args.append(get_libc_file(g, crt1o));
274 lj->args.append(get_libc_file(g, "crti.o"));
227 lj->args.append(get_libc_crt_file(g, crt1o));
228 lj->args.append(get_libc_crt_file(g, "crti.o"));
275229 lj->args.append(get_libc_static_file(g, crtbegino));
276230 }
277231
......@@ -307,23 +261,24 @@ static void construct_linker_job_elf(LinkJob *lj) {
307261 }
308262
309263 if (g->libc_link_lib != nullptr) {
264 assert(g->libc != nullptr);
310265 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
313273 lj->args.append("-L");
314 lj->args.append(buf_ptr(g->libc_static_lib_dir));
315 }
274 lj->args.append(buf_ptr(&g->libc->static_lib_dir));
316275
317 if (!g->is_static) {
318 if (g->dynamic_linker != nullptr) {
319 assert(buf_len(g->dynamic_linker) != 0);
320 lj->args.append("-dynamic-linker");
321 lj->args.append(buf_ptr(g->dynamic_linker));
322 } else {
323 Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);
276 if (!g->is_static) {
277 assert(buf_len(&g->libc->dynamic_linker_path) != 0);
324278 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));
326280 }
281
327282 }
328283
329284 if (shared) {
......@@ -390,14 +345,14 @@ static void construct_linker_job_elf(LinkJob *lj) {
390345 // crt end
391346 if (lj->link_in_crt) {
392347 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"));
394349 }
395350
396 if (!g->is_native_target) {
351 if (!g->zig_target->is_native) {
397352 lj->args.append("--allow-shlib-undefined");
398353 }
399354
400 if (g->zig_target.os == OsZen) {
355 if (g->zig_target->os == OsZen) {
401356 lj->args.append("-e");
402357 lj->args.append("_start");
403358
......@@ -420,16 +375,16 @@ static void construct_linker_job_wasm(LinkJob *lj) {
420375}
421376
422377//static bool is_target_cyg_mingw(const ZigTarget *target) {
423// return (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_Cygnus) ||
424// (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_GNU);
378// return (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_Cygnus) ||
379// (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_GNU);
425380//}
426381
427382static 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) {
429384 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) {
431386 list->append("-MACHINE:X64");
432 } else if (g->zig_target.arch.arch == ZigLLVM_arm) {
387 } else if (g->zig_target->arch == ZigLLVM_arm) {
433388 list->append("-MACHINE:ARM");
434389 }
435390}
......@@ -515,7 +470,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
515470// lj->args.append("-Bdynamic");
516471// if (dll || shared) {
517472// lj->args.append("-e");
518// if (g->zig_target.arch.arch == ZigLLVM_x86) {
473// if (g->zig_target.arch == ZigLLVM_x86) {
519474// lj->args.append("_DllMainCRTStartup@12");
520475// } else {
521476// lj->args.append("DllMainCRTStartup");
......@@ -541,7 +496,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
541496//lj->args.append("-lmingw32");
542497
543498//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);
545500//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
546501//if (!g->is_static && !is_android) {
547502// if (!is_cyg_ming) {
......@@ -588,10 +543,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
588543
589544 lj->args.append("/ERRORLIMIT:0");
590545
591 if (g->libc_link_lib != nullptr) {
592 find_libc_lib_path(g);
593 }
594
595546 lj->args.append("/NOLOGO");
596547
597548 if (!g->strip_debug_symbols) {
......@@ -608,6 +559,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
608559 bool is_library = g->out_type == OutTypeLib;
609560 switch (g->subsystem) {
610561 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 }
611567 break;
612568 case TargetSubsystemConsole:
613569 lj->args.append("/SUBSYSTEM:console");
......@@ -646,13 +602,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
646602 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
647603
648604 if (g->libc_link_lib != nullptr) {
649 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
650 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
605 assert(g->libc != nullptr);
651606
652 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
653 if (g->libc_static_lib_dir != nullptr) {
654 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
655 }
607 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
608 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
609 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
656610 }
657611
658612 if (is_library && !g->is_static) {
......@@ -687,7 +641,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
687641 continue;
688642 }
689643 if (link_lib->provided_explicitly) {
690 if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) {
644 if (lj->codegen->zig_target->abi == ZigLLVM_GNU) {
691645 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
692646 lj->args.append(buf_ptr(arg));
693647 }
......@@ -717,7 +671,8 @@ static void construct_linker_job_coff(LinkJob *lj) {
717671 gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
718672 gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
719673 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)) {
721676 fprintf(stderr, "%s\n", buf_ptr(&diag));
722677 exit(1);
723678 }
......@@ -786,7 +741,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
786741 platform->kind = MacOS;
787742 } else if (g->mios_version_min) {
788743 platform->kind = IPhoneOS;
789 } else if (g->zig_target.os == OsMacOSX) {
744 } else if (g->zig_target->os == OsMacOSX) {
790745 platform->kind = MacOS;
791746 g->mmacosx_version_min = buf_create_from_str("10.10");
792747 } else {
......@@ -813,8 +768,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
813768 }
814769
815770 if (platform->kind == IPhoneOS &&
816 (g->zig_target.arch.arch == ZigLLVM_x86 ||
817 g->zig_target.arch.arch == ZigLLVM_x86_64))
771 (g->zig_target->arch == ZigLLVM_x86 ||
772 g->zig_target->arch == ZigLLVM_x86_64))
818773 {
819774 platform->kind = IPhoneOSSimulator;
820775 }
......@@ -878,7 +833,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
878833 }
879834
880835 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
883838 DarwinPlatform platform;
884839 get_darwin_platform(lj, &platform);
......@@ -893,7 +848,11 @@ static void construct_linker_job_macho(LinkJob *lj) {
893848 lj->args.append("-ios_simulator_version_min");
894849 break;
895850 }
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
899858 if (g->out_type == OutTypeExe) {
......@@ -914,7 +873,9 @@ static void construct_linker_job_macho(LinkJob *lj) {
914873 add_rpath(lj, &g->output_file_path);
915874
916875 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 }
918879 } else if (g->is_static) {
919880 lj->args.append("-lcrt0.o");
920881 } else {
......@@ -929,7 +890,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
929890 }
930891 break;
931892 case IPhoneOS:
932 if (g->zig_target.arch.arch == ZigLLVM_aarch64) {
893 if (g->zig_target->arch == ZigLLVM_aarch64) {
933894 // iOS does not need any crt1 files for arm64
934895 } else if (darwin_version_lt(&platform, 3, 1)) {
935896 lj->args.append("-lcrt1.o");
......@@ -959,7 +920,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
959920 lj->args.append(buf_ptr(compiler_rt_o_path));
960921 }
961922
962 if (g->is_native_target) {
923 if (g->zig_target->is_native) {
963924 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
964925 LinkLib *link_lib = g->link_libs_list.at(lib_i);
965926 if (buf_eql_str(link_lib->name, "c")) {
......@@ -1000,7 +961,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
1000961}
1001962
1002963static void construct_linker_job(LinkJob *lj) {
1003 switch (lj->codegen->zig_target.oformat) {
964 switch (target_object_format(lj->codegen->zig_target)) {
1004965 case ZigLLVM_UnknownObjectFormat:
1005966 zig_unreachable();
1006967
......@@ -1040,7 +1001,7 @@ void codegen_link(CodeGen *g) {
10401001 for (size_t i = 0; i < g->link_objects.length; i += 1) {
10411002 file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
10421003 }
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);
10441005 codegen_add_time_event(g, "LLVM Link");
10451006 if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
10461007 fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
......@@ -1065,7 +1026,7 @@ void codegen_link(CodeGen *g) {
10651026 Buf diag = BUF_INIT;
10661027
10671028 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) {
10691030 Termination term;
10701031 ZigList<const char *> args = {};
10711032 for (size_t i = 1; i < lj.args.length; i += 1) {
......@@ -1075,7 +1036,7 @@ void codegen_link(CodeGen *g) {
10751036 if (term.how != TerminationIdClean || term.code != 0) {
10761037 exit(1);
10771038 }
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)) {
10791040 fprintf(stderr, "%s\n", buf_ptr(&diag));
10801041 exit(1);
10811042 }
src/main.cpp+231-114
......@@ -13,16 +13,17 @@
1313#include "error.hpp"
1414#include "os.hpp"
1515#include "target.hpp"
16#include "libc_installation.hpp"
1617
1718#include <stdio.h>
1819
1920static 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);
2122 return EXIT_FAILURE;
2223}
2324
24static int print_full_usage(const char *arg0) {
25 fprintf(stdout,
25static int print_full_usage(const char *arg0, FILE *file, int return_code) {
26 fprintf(file,
2627 "Usage: %s [command] [options]\n"
2728 "\n"
2829 "Commands:\n"
......@@ -31,10 +32,12 @@ static int print_full_usage(const char *arg0) {
3132 " build-lib [source] create library from source or object files\n"
3233 " build-obj [source] create object from source or assembly\n"
3334 " 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"
3537 " id print the base64-encoded compiler id\n"
3638 " init-exe initialize a `zig build` application in the cwd\n"
3739 " init-lib initialize a `zig build` library in the cwd\n"
40 " libc [paths_file] Display native libc paths file or validate one\n"
3841 " run [source] create executable and run immediately\n"
3942 " translate-c [source] convert c code to zig code\n"
4043 " targets list available compilation targets\n"
......@@ -44,16 +47,20 @@ static int print_full_usage(const char *arg0) {
4447 "\n"
4548 "Compile Options:\n"
4649 " --assembly [source] add assembly file to build\n"
50 " --c-source [options] [file] compile C source code\n"
4751 " --cache-dir [path] override the cache directory\n"
4852 " --cache [auto|off|on] build in global cache, print out paths to stdout\n"
4953 " --color [auto|off|on] enable or disable colored error messages\n"
5054 " --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"
5157 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
5258 " -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"
5460 " --name [name] override output name\n"
5561 " --output [file] override destination path\n"
5662 " --output-h [file] generate header file\n"
63 " --output-lib [file] override import library path\n"
5764 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
5865 " --pkg-end pop current pkg\n"
5966 " --release-fast build with optimizations on and safety off\n"
......@@ -62,15 +69,14 @@ static int print_full_usage(const char *arg0) {
6269 " --single-threaded source may assume it is only used single-threaded\n"
6370 " --static output will be statically linked\n"
6471 " --strip exclude debug symbols\n"
65 " --target-arch [name] specify target architecture\n"
66 " --target-environ [name] specify target environment\n"
67 " --target-os [name] specify target operating system\n"
72 " -target [name] <arch><sub>-<os>-<abi> see the targets command\n"
6873 " --verbose-tokenize enable compiler debug output for tokenization\n"
6974 " --verbose-ast enable compiler debug output for AST parsing\n"
7075 " --verbose-link enable compiler debug output for linking\n"
7176 " --verbose-ir enable compiler debug output for Zig IR\n"
7277 " --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
7378 " --verbose-cimport enable compiler debug output for C imports\n"
79 " --verbose-cc enable compiler debug output for C compilation\n"
7480 " -dirafter [dir] same as -isystem but do it last\n"
7581 " -isystem [dir] add additional search path for other .h files\n"
7682 " -mllvm [arg] forward an arg to LLVM's option processing\n"
......@@ -79,10 +85,6 @@ static int print_full_usage(const char *arg0) {
7985 "Link Options:\n"
8086 " --dynamic-linker [path] set the path to ld.so\n"
8187 " --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"
8688 " --library [lib] link against lib\n"
8789 " --forbid-library [lib] make it an error to link against lib\n"
8890 " --library-path [dir] add a directory to the library search path\n"
......@@ -91,7 +93,6 @@ static int print_full_usage(const char *arg0) {
9193 " -L[dir] alias for --library-path\n"
9294 " -rdynamic add all symbols to the dynamic symbol table\n"
9395 " -rpath [path] add directory to the runtime library search path\n"
94 " --no-rosegment compromise security to workaround valgrind bug\n"
9596 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"
9697 " -framework [name] (darwin) link against framework\n"
9798 " -mios-version-min [ver] (darwin) set iOS deployment target\n"
......@@ -106,7 +107,27 @@ static int print_full_usage(const char *arg0) {
106107 " --test-cmd [arg] specify test execution command one arg at a time\n"
107108 " --test-cmd-bin appends test binary path to test cmd args\n"
108109 , 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;
110131}
111132
112133static const char *ZIG_ZEN = "\n"
......@@ -122,6 +143,14 @@ static const char *ZIG_ZEN = "\n"
122143" * Minimize energy spent on coding style.\n"
123144" * 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
125154static int print_target_list(FILE *f) {
126155 ZigTarget native;
127156 get_native_target(&native);
......@@ -129,28 +158,36 @@ static int print_target_list(FILE *f) {
129158 fprintf(f, "Architectures:\n");
130159 size_t arch_count = target_arch_count();
131160 for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) {
132 const ArchType *arch = get_target_arch(arch_i);
133 char arch_name[50];
134 get_arch_name(arch_name, arch);
135 const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ?
136 " (native)" : "";
137 fprintf(f, " %s%s\n", arch_name, native_str);
161 ZigLLVM_ArchType arch = target_arch_enum(arch_i);
162 if (!arch_available_in_llvm(arch))
163 continue;
164 const char *arch_name = target_arch_name(arch);
165 SubArchList sub_arch_list = target_subarch_list(arch);
166 size_t sub_count = target_subarch_count(sub_arch_list);
167 const char *arch_native_str = (native.arch == arch) ? " (native)" : "";
168 fprintf(stderr, " %s%s\n", arch_name, arch_native_str);
169 for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
170 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
171 const char *sub_name = target_subarch_name(sub);
172 const char *sub_native_str = (native.arch == arch && native.sub_arch == sub) ? " (native)" : "";
173 fprintf(f, " %s%s\n", sub_name, sub_native_str);
174 }
138175 }
139176
140177 fprintf(f, "\nOperating Systems:\n");
141178 size_t os_count = target_os_count();
142179 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);
144181 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);
146183 }
147184
148 fprintf(f, "\nEnvironments:\n");
149 size_t environ_count = target_environ_count();
150 for (size_t i = 0; i < environ_count; i += 1) {
151 ZigLLVM_EnvironmentType environ_type = get_target_environ(i);
152 const char *native_str = (native.env_type == environ_type) ? " (native)" : "";
153 fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str);
185 fprintf(f, "\nC ABIs:\n");
186 size_t abi_count = target_abi_count();
187 for (size_t i = 0; i < abi_count; i += 1) {
188 ZigLLVM_EnvironmentType abi = target_abi_enum(i);
189 const char *native_str = (native.abi == abi) ? " (native)" : "";
190 fprintf(f, " %s%s\n", target_abi_name(abi), native_str);
154191 }
155192
156193 return EXIT_SUCCESS;
......@@ -160,13 +197,13 @@ enum Cmd {
160197 CmdNone,
161198 CmdBuild,
162199 CmdBuiltin,
163 CmdHelp,
164200 CmdRun,
165201 CmdTargets,
166202 CmdTest,
167203 CmdTranslateC,
168204 CmdVersion,
169205 CmdZen,
206 CmdLibC,
170207};
171208
172209static const char *default_zig_cache_name = "zig-cache";
......@@ -219,6 +256,8 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
219256 zig_unreachable();
220257}
221258
259extern "C" int ZigClang_main(int argc, char **argv);
260
222261int main(int argc, char **argv) {
223262 char *arg0 = argv[0];
224263 Error err;
......@@ -236,6 +275,12 @@ int main(int argc, char **argv) {
236275 return 0;
237276 }
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
239284 // Must be before all os.hpp function calls.
240285 os_init();
241286
......@@ -345,6 +390,7 @@ int main(int argc, char **argv) {
345390 const char *in_file = nullptr;
346391 const char *out_file = nullptr;
347392 const char *out_file_h = nullptr;
393 const char *out_file_lib = nullptr;
348394 bool strip = false;
349395 bool is_static = false;
350396 OutType out_type = OutTypeUnknown;
......@@ -355,23 +401,17 @@ int main(int argc, char **argv) {
355401 bool verbose_ir = false;
356402 bool verbose_llvm_ir = false;
357403 bool verbose_cimport = false;
404 bool verbose_cc = false;
358405 ErrColor color = ErrColorAuto;
359406 CacheOpt enable_cache = CacheOptAuto;
360 const char *libc_lib_dir = nullptr;
361 const char *libc_static_lib_dir = nullptr;
362 const char *libc_include_dir = nullptr;
363 const char *msvc_lib_dir = nullptr;
364 const char *kernel32_lib_dir = nullptr;
365 const char *dynamic_linker = nullptr;
407 const char *libc_txt = nullptr;
366408 ZigList<const char *> clang_argv = {0};
367409 ZigList<const char *> llvm_argv = {0};
368410 ZigList<const char *> lib_dirs = {0};
369411 ZigList<const char *> link_libs = {0};
370412 ZigList<const char *> forbidden_link_libs = {0};
371413 ZigList<const char *> frameworks = {0};
372 const char *target_arch = nullptr;
373 const char *target_os = nullptr;
374 const char *target_environ = nullptr;
414 const char *target_string = nullptr;
375415 bool rdynamic = false;
376416 const char *mmacosx_version_min = nullptr;
377417 const char *mios_version_min = nullptr;
......@@ -379,6 +419,7 @@ int main(int argc, char **argv) {
379419 ZigList<const char *> rpath_list = {0};
380420 bool each_lib_rpath = false;
381421 ZigList<const char *> objects = {0};
422 ZigList<CFile *> c_source_files = {0};
382423 ZigList<const char *> asm_files = {0};
383424 const char *test_filter = nullptr;
384425 const char *test_name_prefix = nullptr;
......@@ -392,11 +433,11 @@ int main(int argc, char **argv) {
392433 BuildMode build_mode = BuildModeDebug;
393434 ZigList<const char *> test_exec_args = {0};
394435 int runtime_args_start = -1;
395 bool no_rosegment_workaround = false;
396436 bool system_linker_hack = false;
397437 TargetSubsystem subsystem = TargetSubsystemAuto;
398438 bool is_single_threaded = false;
399439 Buf *override_std_dir = nullptr;
440 ValgrindSupport valgrind_support = ValgrindSupportAuto;
400441
401442 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
402443 Buf zig_exe_path_buf = BUF_INIT;
......@@ -432,8 +473,11 @@ int main(int argc, char **argv) {
432473 Buf *build_runner_path = buf_alloc();
433474 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(),
436 override_std_dir);
476 ZigTarget target;
477 get_native_target(&target);
478 CodeGen *g = codegen_create(build_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
479 override_std_dir, nullptr);
480 g->valgrind_support = valgrind_support;
437481 g->enable_time_report = timing_info;
438482 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
439483 codegen_set_out_name(g, buf_create_from_str("build"));
......@@ -484,6 +528,7 @@ int main(int argc, char **argv) {
484528 " --verbose-ir Enable compiler debug output for Zig IR\n"
485529 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
486530 " --verbose-cimport Enable compiler debug output for C imports\n"
531 " --verbose-cc Enable compiler debug output for C compilation\n"
487532 "\n"
488533 , zig_exe_path);
489534 return EXIT_SUCCESS;
......@@ -493,7 +538,7 @@ int main(int argc, char **argv) {
493538 "No 'build.zig' file found.\n"
494539 "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
495540 "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"
497542 );
498543 return EXIT_FAILURE;
499544 }
......@@ -515,6 +560,37 @@ int main(int argc, char **argv) {
515560 fprintf(stderr, "\n");
516561 }
517562 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;
518594 }
519595
520596 for (int i = 1; i < argc; i += 1) {
......@@ -527,6 +603,12 @@ int main(int argc, char **argv) {
527603 build_mode = BuildModeSafeRelease;
528604 } else if (strcmp(arg, "--release-small") == 0) {
529605 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 }
530612 } else if (strcmp(arg, "--strip") == 0) {
531613 strip = true;
532614 } else if (strcmp(arg, "--static") == 0) {
......@@ -543,16 +625,20 @@ int main(int argc, char **argv) {
543625 verbose_llvm_ir = true;
544626 } else if (strcmp(arg, "--verbose-cimport") == 0) {
545627 verbose_cimport = true;
628 } else if (strcmp(arg, "--verbose-cc") == 0) {
629 verbose_cc = true;
546630 } else if (strcmp(arg, "-rdynamic") == 0) {
547631 rdynamic = true;
548 } else if (strcmp(arg, "--no-rosegment") == 0) {
549 no_rosegment_workaround = true;
550632 } else if (strcmp(arg, "--each-lib-rpath") == 0) {
551633 each_lib_rpath = true;
552634 } else if (strcmp(arg, "-ftime-report") == 0) {
553635 timing_info = true;
554636 } else if (strcmp(arg, "--disable-pic") == 0) {
555637 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;
556642 } else if (strcmp(arg, "--system-linker-hack") == 0) {
557643 system_linker_hack = true;
558644 } else if (strcmp(arg, "--single-threaded") == 0) {
......@@ -590,6 +676,8 @@ int main(int argc, char **argv) {
590676 out_file = argv[i];
591677 } else if (strcmp(arg, "--output-h") == 0) {
592678 out_file_h = argv[i];
679 } else if (strcmp(arg, "--output-lib") == 0) {
680 out_file_lib = argv[i];
593681 } else if (strcmp(arg, "--color") == 0) {
594682 if (strcmp(argv[i], "auto") == 0) {
595683 color = ErrColorAuto;
......@@ -625,18 +713,8 @@ int main(int argc, char **argv) {
625713 }
626714 } else if (strcmp(arg, "--name") == 0) {
627715 out_name = argv[i];
628 } else if (strcmp(arg, "--libc-lib-dir") == 0) {
629 libc_lib_dir = argv[i];
630 } else if (strcmp(arg, "--libc-static-lib-dir") == 0) {
631 libc_static_lib_dir = argv[i];
632 } else if (strcmp(arg, "--libc-include-dir") == 0) {
633 libc_include_dir = argv[i];
634 } else if (strcmp(arg, "--msvc-lib-dir") == 0) {
635 msvc_lib_dir = argv[i];
636 } else if (strcmp(arg, "--kernel32-lib-dir") == 0) {
637 kernel32_lib_dir = argv[i];
638 } else if (strcmp(arg, "--dynamic-linker") == 0) {
639 dynamic_linker = argv[i];
716 } else if (strcmp(arg, "--libc") == 0) {
717 libc_txt = argv[i];
640718 } else if (strcmp(arg, "-isystem") == 0) {
641719 clang_argv.append("-isystem");
642720 clang_argv.append(argv[i]);
......@@ -658,16 +736,25 @@ int main(int argc, char **argv) {
658736 forbidden_link_libs.append(argv[i]);
659737 } else if (strcmp(arg, "--object") == 0) {
660738 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 }
661752 } else if (strcmp(arg, "--assembly") == 0) {
662753 asm_files.append(argv[i]);
663754 } else if (strcmp(arg, "--cache-dir") == 0) {
664755 cache_dir = argv[i];
665 } else if (strcmp(arg, "--target-arch") == 0) {
666 target_arch = argv[i];
667 } else if (strcmp(arg, "--target-os") == 0) {
668 target_os = argv[i];
669 } else if (strcmp(arg, "--target-environ") == 0) {
670 target_environ = argv[i];
756 } else if (strcmp(arg, "-target") == 0) {
757 target_string = argv[i];
671758 } else if (strcmp(arg, "-mmacosx-version-min") == 0) {
672759 mmacosx_version_min = argv[i];
673760 } else if (strcmp(arg, "-mios-version-min") == 0) {
......@@ -736,8 +823,6 @@ int main(int argc, char **argv) {
736823 } else if (strcmp(arg, "build-lib") == 0) {
737824 cmd = CmdBuild;
738825 out_type = OutTypeLib;
739 } else if (strcmp(arg, "help") == 0) {
740 cmd = CmdHelp;
741826 } else if (strcmp(arg, "run") == 0) {
742827 cmd = CmdRun;
743828 out_type = OutTypeExe;
......@@ -745,6 +830,8 @@ int main(int argc, char **argv) {
745830 cmd = CmdVersion;
746831 } else if (strcmp(arg, "zen") == 0) {
747832 cmd = CmdZen;
833 } else if (strcmp(arg, "libc") == 0) {
834 cmd = CmdLibC;
748835 } else if (strcmp(arg, "translate-c") == 0) {
749836 cmd = CmdTranslateC;
750837 } else if (strcmp(arg, "test") == 0) {
......@@ -764,6 +851,7 @@ int main(int argc, char **argv) {
764851 case CmdRun:
765852 case CmdTranslateC:
766853 case CmdTest:
854 case CmdLibC:
767855 if (!in_file) {
768856 in_file = arg;
769857 if (cmd == CmdRun) {
......@@ -776,7 +864,6 @@ int main(int argc, char **argv) {
776864 }
777865 break;
778866 case CmdBuiltin:
779 case CmdHelp:
780867 case CmdVersion:
781868 case CmdZen:
782869 case CmdTargets:
......@@ -795,36 +882,34 @@ int main(int argc, char **argv) {
795882
796883 init_all_targets();
797884
798 ZigTarget alloc_target;
799 ZigTarget *target;
800 if (!target_arch && !target_os && !target_environ) {
801 target = nullptr;
885 ZigTarget target;
886 if (target_string == nullptr) {
887 get_native_target(&target);
802888 } else {
803 target = &alloc_target;
804 get_unknown_target(target);
805 if (target_arch) {
806 if (parse_target_arch(target_arch, &target->arch)) {
807 fprintf(stderr, "invalid --target-arch argument\n");
808 return print_error_usage(arg0);
809 }
810 }
811 if (target_os) {
812 if (parse_target_os(target_os, &target->os)) {
813 fprintf(stderr, "invalid --target-os argument\n");
814 return print_error_usage(arg0);
815 }
816 }
817 if (target_environ) {
818 if (parse_target_environ(target_environ, &target->env_type)) {
819 fprintf(stderr, "invalid --target-environ argument\n");
820 return print_error_usage(arg0);
821 }
889 if ((err = target_parse_triple(&target, target_string))) {
890 fprintf(stderr, "invalid target: %s\n", err_str(err));
891 return print_error_usage(arg0);
822892 }
823893 }
824894
825895 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 }
826909 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;
828913 g->is_single_threaded = is_single_threaded;
829914 Buf *builtin_source = codegen_generate_builtin_source(g);
830915 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) {
838923 case CmdTranslateC:
839924 case CmdTest:
840925 {
841 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
842 fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
926 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 &&
927 c_source_files.length == 0)
928 {
929 fprintf(stderr,
930 "Expected at least one of these things:\n"
931 " * Zig root source file argument\n"
932 " * --object argument\n"
933 " * --assembly argument\n"
934 " * --c-source argument\n");
843935 return print_error_usage(arg0);
844936 } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
845937 fprintf(stderr, "Expected source file argument.\n");
846938 return print_error_usage(arg0);
847 } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
848 fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
849 return print_error_usage(arg0);
939 } else if (cmd == CmdBuild && out_type == OutTypeObj) {
940 if (objects.length != 0) {
941 fprintf(stderr,
942 "When building an object file, --object arguments are invalid.\n"
943 "Consider building a static library instead.\n");
944 return print_error_usage(arg0);
945 }
946 size_t zig_root_src_count = in_file ? 1 : 0;
947 if (zig_root_src_count + c_source_files.length > 1) {
948 fprintf(stderr,
949 "When building an object file, only one of these allowed:\n"
950 " * Zig root source file argument\n"
951 " * --c-source argument\n"
952 "Consider building a static library instead.\n");
953 return print_error_usage(arg0);
954 }
955 if (c_source_files.length != 0 && asm_files.length != 0) {
956 fprintf(stderr,
957 "When building an object file, only one of these allowed:\n"
958 " * --assembly argument\n"
959 " * --c-source argument\n"
960 "Consider building a static library instead.\n");
961 return print_error_usage(arg0);
962 }
850963 }
851964
852965 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
......@@ -873,6 +986,13 @@ int main(int argc, char **argv) {
873986 }
874987 }
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
876996 if (need_name && buf_out_name == nullptr) {
877997 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
878998 return print_error_usage(arg0);
......@@ -883,8 +1003,17 @@ int main(int argc, char **argv) {
8831003 if (cmd == CmdRun && buf_out_name == nullptr) {
8841004 buf_out_name = buf_create_from_str("run");
8851005 }
886 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(),
887 override_std_dir);
1006 ZigLibCInstallation *libc = nullptr;
1007 if (libc_txt != nullptr) {
1008 libc = allocate<ZigLibCInstallation>(1);
1009 if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) {
1010 fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err));
1011 return EXIT_FAILURE;
1012 }
1013 }
1014 CodeGen *g = codegen_create(zig_root_source_file, &target, out_type, build_mode, get_zig_lib_dir(),
1015 override_std_dir, libc);
1016 g->valgrind_support = valgrind_support;
8881017 g->subsystem = subsystem;
8891018
8901019 if (disable_pic) {
......@@ -909,24 +1038,13 @@ int main(int argc, char **argv) {
9091038 codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length);
9101039 codegen_set_strip(g, strip);
9111040 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));
9241041 g->verbose_tokenize = verbose_tokenize;
9251042 g->verbose_ast = verbose_ast;
9261043 g->verbose_link = verbose_link;
9271044 g->verbose_ir = verbose_ir;
9281045 g->verbose_llvm_ir = verbose_llvm_ir;
9291046 g->verbose_cimport = verbose_cimport;
1047 g->verbose_cc = verbose_cc;
9301048 codegen_set_errmsg_color(g, color);
9311049 g->system_linker_hack = system_linker_hack;
9321050
......@@ -949,7 +1067,6 @@ int main(int argc, char **argv) {
9491067 }
9501068
9511069 codegen_set_rdynamic(g, rdynamic);
952 g->no_rosegment_workaround = no_rosegment_workaround;
9531070 if (mmacosx_version_min && mios_version_min) {
9541071 fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
9551072 return EXIT_FAILURE;
......@@ -975,11 +1092,14 @@ int main(int argc, char **argv) {
9751092 codegen_set_output_path(g, buf_create_from_str(out_file));
9761093 if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib))
9771094 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
9801099 add_package(g, cur_pkg, g->root_package);
9811100
9821101 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
1102 g->c_source_files = c_source_files;
9831103 for (size_t i = 0; i < objects.length; i += 1) {
9841104 codegen_add_object(g, buf_create_from_str(objects.at(i)));
9851105 }
......@@ -1052,7 +1172,7 @@ int main(int argc, char **argv) {
10521172 }
10531173 }
10541174
1055 if (!target_can_exec(&native, target)) {
1175 if (!target_can_exec(&native, &target)) {
10561176 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
10571177 buf_ptr(test_exe_path));
10581178 return 0;
......@@ -1079,8 +1199,6 @@ int main(int argc, char **argv) {
10791199 zig_unreachable();
10801200 }
10811201 }
1082 case CmdHelp:
1083 return print_full_usage(arg0);
10841202 case CmdVersion:
10851203 printf("%s\n", ZIG_VERSION_STRING);
10861204 return EXIT_SUCCESS;
......@@ -1090,7 +1208,6 @@ int main(int argc, char **argv) {
10901208 case CmdTargets:
10911209 return print_target_list(stdout);
10921210 case CmdNone:
1093 fprintf(stderr, "Zig programming language\n");
1094 return print_error_usage(arg0);
1211 return print_full_usage(arg0, stderr, EXIT_FAILURE);
10951212 }
10961213}
src/os.cpp+34-13
......@@ -50,11 +50,11 @@ typedef SSIZE_T ssize_t;
5050
5151#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)
5454#include <link.h>
5555#endif
5656
57#if defined(ZIG_OS_FREEBSD)
57#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
5858#include <sys/sysctl.h>
5959#endif
6060
......@@ -78,7 +78,7 @@ static clock_serv_t cclock;
7878#if defined(__APPLE__) && !defined(environ)
7979#include <crt_externs.h>
8080#define environ (*_NSGetEnviron())
81#elif defined(ZIG_OS_FREEBSD)
81#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
8282extern char **environ;
8383#endif
8484
......@@ -1099,7 +1099,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
10991099 case EINTR:
11001100 return ErrorInterrupted;
11011101 case EINVAL:
1102 zig_unreachable();
1102 return ErrorInvalidFilename;
11031103 case ENFILE:
11041104 case ENOMEM:
11051105 return ErrorSystemResources;
......@@ -1232,6 +1232,18 @@ static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_p
12321232}
12331233#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
12351247#if defined(ZIG_OS_WINDOWS)
12361248static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
12371249 char tmp_dir[MAX_PATH + 1];
......@@ -1458,6 +1470,15 @@ Error os_self_exe_path(Buf *out_path) {
14581470 }
14591471 buf_resize(out_path, cb - 1);
14601472 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;
14611482#endif
14621483 return ErrorFileNotFound;
14631484}
......@@ -1541,7 +1562,7 @@ void os_stderr_set_color(TermColor color) {
15411562#endif
15421563}
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) {
15451566#if defined(ZIG_OS_WINDOWS)
15461567 buf_resize(output_buf, 0);
15471568 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
15621583 buf_init_from_buf(tmp_buf, output_buf);
15631584 buf_append_str(tmp_buf, "ucrt.lib");
15641585 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1565 return 0;
1586 return ErrorNone;
15661587 }
15671588 else {
15681589 buf_resize(output_buf, 0);
......@@ -1573,12 +1594,12 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
15731594#endif
15741595}
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) {
15771598#if defined(ZIG_OS_WINDOWS)
15781599 buf_resize(output_buf, 0);
15791600 buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr);
15801601 if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) {
1581 return 0;
1602 return ErrorNone;
15821603 }
15831604 else {
15841605 buf_resize(output_buf, 0);
......@@ -1589,7 +1610,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
15891610#endif
15901611}
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) {
15931614#if defined(ZIG_OS_WINDOWS)
15941615 {
15951616 buf_resize(output_buf, 0);
......@@ -1611,7 +1632,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
16111632 buf_init_from_buf(tmp_buf, output_buf);
16121633 buf_append_str(tmp_buf, "kernel32.lib");
16131634 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1614 return 0;
1635 return ErrorNone;
16151636 }
16161637 }
16171638 {
......@@ -1634,7 +1655,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
16341655 buf_init_from_buf(tmp_buf, output_buf);
16351656 buf_append_str(tmp_buf, "kernel32.lib");
16361657 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1637 return 0;
1658 return ErrorNone;
16381659 }
16391660 }
16401661 return ErrorFileNotFound;
......@@ -1776,7 +1797,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
17761797}
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)
17801801static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
17811802 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
17821803 if (info->dlpi_name[0] == '/') {
......@@ -1787,7 +1808,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size,
17871808#endif
17881809
17891810Error 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)
17911812 paths.resize(0);
17921813 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
17931814 return ErrorNone;
src/os.hpp+6-3
......@@ -25,6 +25,8 @@
2525#define ZIG_OS_LINUX
2626#elif defined(__FreeBSD__)
2727#define ZIG_OS_FREEBSD
28#elif defined(__NetBSD__)
29#define ZIG_OS_NETBSD
2830#else
2931#define ZIG_OS_UNKNOWN
3032#endif
......@@ -119,6 +121,7 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
119121bool os_stderr_tty(void);
120122void os_stderr_set_color(TermColor color);
121123
124Buf *os_tmp_filename(Buf *prefix, Buf *suffix);
122125Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
123126Error os_delete_file(Buf *path);
124127
......@@ -133,9 +136,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
133136
134137Error 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);
137int 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);
139Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
140Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_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
140143Error 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) {
27392739
27402740 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async);
27412741 res->data.fn_call_expr.is_async = true;
2742 res->data.fn_call_expr.seen = false;
27422743 if (eat_token_if(pc, TokenIdCmpLessThan) != nullptr) {
27432744 AstNode *prefix_expr = ast_expect(pc, ast_parse_prefix_expr);
27442745 expect_token(pc, TokenIdCmpGreaterThan);
......@@ -2759,6 +2760,7 @@ static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
27592760
27602761 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren);
27612762 res->data.fn_call_expr.params = params;
2763 res->data.fn_call_expr.seen = false;
27622764 return res;
27632765}
27642766
......@@ -2778,7 +2780,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
27782780// PtrTypeStart
27792781// <- ASTERISK
27802782// / ASTERISK2
2781// / LBRACKET ASTERISK RBRACKET
2783// / PTRUNKNOWN
2784// / PTRC
27822785static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
27832786 Token *asterisk = eat_token_if(pc, TokenIdStar);
27842787 if (asterisk != nullptr) {
......@@ -2804,6 +2807,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
28042807 return res;
28052808 }
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
28072817 return nullptr;
28082818}
28092819
src/target.cpp+599-344
......@@ -9,127 +9,116 @@
99#include "error.hpp"
1010#include "target.hpp"
1111#include "util.hpp"
12#include "os.hpp"
1213
1314#include <stdio.h>
1415
15static const ArchType arch_list[] = {
16 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_5a},
17 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_4a},
18 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_3a},
19 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_2a},
20 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a},
21 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8},
22 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8r},
23 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_baseline},
24 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_mainline},
25 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7},
26 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7em},
27 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7m},
28 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7s},
29 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7k},
30 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7ve},
31 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6},
32 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6m},
33 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6k},
34 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6t2},
35 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5},
36 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5te},
37 {ZigLLVM_arm, ZigLLVM_ARMSubArch_v4t},
38
39 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_5a},
40 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_4a},
41 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_3a},
42 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_2a},
43 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_1a},
44 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8},
45 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8r},
46 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_baseline},
47 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_mainline},
48 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7},
49 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7em},
50 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7m},
51 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7s},
52 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7k},
53 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7ve},
54 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6},
55 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6m},
56 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6k},
57 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6t2},
58 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5},
59 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5te},
60 {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v4t},
61
62 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_5a},
63 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_4a},
64 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_3a},
65 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_2a},
66 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_1a},
67 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8},
68 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8r},
69 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_baseline},
70 {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_mainline},
71
72 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_5a},
73 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_4a},
74 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_3a},
75 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_2a},
76 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_1a},
77 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8},
78 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8r},
79 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_baseline},
80 {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_mainline},
81
82 {ZigLLVM_arc, ZigLLVM_NoSubArch},
83 {ZigLLVM_avr, ZigLLVM_NoSubArch},
84 {ZigLLVM_bpfel, ZigLLVM_NoSubArch},
85 {ZigLLVM_bpfeb, ZigLLVM_NoSubArch},
86 {ZigLLVM_hexagon, ZigLLVM_NoSubArch},
87
88 {ZigLLVM_mips, ZigLLVM_MipsSubArch_r6},
89 {ZigLLVM_mipsel, ZigLLVM_MipsSubArch_r6},
90 {ZigLLVM_mips64, ZigLLVM_MipsSubArch_r6},
91 {ZigLLVM_mips64el, ZigLLVM_MipsSubArch_r6},
92
93 {ZigLLVM_msp430, ZigLLVM_NoSubArch},
94 {ZigLLVM_ppc, ZigLLVM_NoSubArch},
95 {ZigLLVM_ppc64, ZigLLVM_NoSubArch},
96 {ZigLLVM_ppc64le, ZigLLVM_NoSubArch},
97 {ZigLLVM_r600, ZigLLVM_NoSubArch},
98 {ZigLLVM_amdgcn, ZigLLVM_NoSubArch},
99 {ZigLLVM_riscv32, ZigLLVM_NoSubArch},
100 {ZigLLVM_riscv64, ZigLLVM_NoSubArch},
101 {ZigLLVM_sparc, ZigLLVM_NoSubArch},
102 {ZigLLVM_sparcv9, ZigLLVM_NoSubArch},
103 {ZigLLVM_sparcel, ZigLLVM_NoSubArch},
104 {ZigLLVM_systemz, ZigLLVM_NoSubArch},
105 {ZigLLVM_tce, ZigLLVM_NoSubArch},
106 {ZigLLVM_tcele, ZigLLVM_NoSubArch},
107 {ZigLLVM_thumb, ZigLLVM_NoSubArch},
108 {ZigLLVM_thumbeb, ZigLLVM_NoSubArch},
109 {ZigLLVM_x86, ZigLLVM_NoSubArch},
110 {ZigLLVM_x86_64, ZigLLVM_NoSubArch},
111 {ZigLLVM_xcore, ZigLLVM_NoSubArch},
112 {ZigLLVM_nvptx, ZigLLVM_NoSubArch},
113 {ZigLLVM_nvptx64, ZigLLVM_NoSubArch},
114 {ZigLLVM_le32, ZigLLVM_NoSubArch},
115 {ZigLLVM_le64, ZigLLVM_NoSubArch},
116 {ZigLLVM_amdil, ZigLLVM_NoSubArch},
117 {ZigLLVM_amdil64, ZigLLVM_NoSubArch},
118 {ZigLLVM_hsail, ZigLLVM_NoSubArch},
119 {ZigLLVM_hsail64, ZigLLVM_NoSubArch},
120 {ZigLLVM_spir, ZigLLVM_NoSubArch},
121 {ZigLLVM_spir64, ZigLLVM_NoSubArch},
122
123 {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v3},
124 {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v4},
125 {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v5},
126
127 {ZigLLVM_shave, ZigLLVM_NoSubArch},
128 {ZigLLVM_lanai, ZigLLVM_NoSubArch},
129 {ZigLLVM_wasm32, ZigLLVM_NoSubArch},
130 {ZigLLVM_wasm64, ZigLLVM_NoSubArch},
131 {ZigLLVM_renderscript32, ZigLLVM_NoSubArch},
132 {ZigLLVM_renderscript64, ZigLLVM_NoSubArch},
16static const SubArchList subarch_list_list[] = {
17 SubArchListNone,
18 SubArchListArm32,
19 SubArchListArm64,
20 SubArchListKalimba,
21 SubArchListMips,
22};
23
24static const ZigLLVM_SubArchType subarch_list_arm32[] = {
25 ZigLLVM_ARMSubArch_v8_5a,
26 ZigLLVM_ARMSubArch_v8_4a,
27 ZigLLVM_ARMSubArch_v8_3a,
28 ZigLLVM_ARMSubArch_v8_2a,
29 ZigLLVM_ARMSubArch_v8_1a,
30 ZigLLVM_ARMSubArch_v8,
31 ZigLLVM_ARMSubArch_v8r,
32 ZigLLVM_ARMSubArch_v8m_baseline,
33 ZigLLVM_ARMSubArch_v8m_mainline,
34 ZigLLVM_ARMSubArch_v7,
35 ZigLLVM_ARMSubArch_v7em,
36 ZigLLVM_ARMSubArch_v7m,
37 ZigLLVM_ARMSubArch_v7s,
38 ZigLLVM_ARMSubArch_v7k,
39 ZigLLVM_ARMSubArch_v7ve,
40 ZigLLVM_ARMSubArch_v6,
41 ZigLLVM_ARMSubArch_v6m,
42 ZigLLVM_ARMSubArch_v6k,
43 ZigLLVM_ARMSubArch_v6t2,
44 ZigLLVM_ARMSubArch_v5,
45 ZigLLVM_ARMSubArch_v5te,
46 ZigLLVM_ARMSubArch_v4t,
47
48};
49
50static const ZigLLVM_SubArchType subarch_list_arm64[] = {
51 ZigLLVM_ARMSubArch_v8_5a,
52 ZigLLVM_ARMSubArch_v8_4a,
53 ZigLLVM_ARMSubArch_v8_3a,
54 ZigLLVM_ARMSubArch_v8_2a,
55 ZigLLVM_ARMSubArch_v8_1a,
56 ZigLLVM_ARMSubArch_v8,
57 ZigLLVM_ARMSubArch_v8r,
58 ZigLLVM_ARMSubArch_v8m_baseline,
59 ZigLLVM_ARMSubArch_v8m_mainline,
60};
61
62static const ZigLLVM_SubArchType subarch_list_kalimba[] = {
63 ZigLLVM_KalimbaSubArch_v5,
64 ZigLLVM_KalimbaSubArch_v4,
65 ZigLLVM_KalimbaSubArch_v3,
66};
67
68static const ZigLLVM_SubArchType subarch_list_mips[] = {
69 ZigLLVM_MipsSubArch_r6,
70};
71
72static const ZigLLVM_ArchType arch_list[] = {
73 ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale
74 ZigLLVM_armeb, // ARM (big endian): armeb
75 ZigLLVM_aarch64, // AArch64 (little endian): aarch64
76 ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be
77 ZigLLVM_arc, // ARC: Synopsys ARC
78 ZigLLVM_avr, // AVR: Atmel AVR microcontroller
79 ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
80 ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
81 ZigLLVM_hexagon, // Hexagon: hexagon
82 ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6
83 ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
84 ZigLLVM_mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
85 ZigLLVM_mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
86 ZigLLVM_msp430, // MSP430: msp430
87 ZigLLVM_ppc, // PPC: powerpc
88 ZigLLVM_ppc64, // PPC64: powerpc64, ppu
89 ZigLLVM_ppc64le, // PPC64LE: powerpc64le
90 ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX
91 ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs
92 ZigLLVM_riscv32, // RISC-V (32-bit): riscv32
93 ZigLLVM_riscv64, // RISC-V (64-bit): riscv64
94 ZigLLVM_sparc, // Sparc: sparc
95 ZigLLVM_sparcv9, // Sparcv9: Sparcv9
96 ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
97 ZigLLVM_systemz, // SystemZ: s390x
98 ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce
99 ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele
100 ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.*
101 ZigLLVM_thumbeb, // Thumb (big endian): thumbeb
102 ZigLLVM_x86, // X86: i[3-9]86
103 ZigLLVM_x86_64, // X86-64: amd64, x86_64
104 ZigLLVM_xcore, // XCore: xcore
105 ZigLLVM_nvptx, // NVPTX: 32-bit
106 ZigLLVM_nvptx64, // NVPTX: 64-bit
107 ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl)
108 ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl)
109 ZigLLVM_amdil, // AMDIL
110 ZigLLVM_amdil64, // AMDIL with 64-bit pointers
111 ZigLLVM_hsail, // AMD HSAIL
112 ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers
113 ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version
114 ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version
115 ZigLLVM_kalimba, // Kalimba: generic kalimba
116 ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors
117 ZigLLVM_lanai, // Lanai: Lanai 32-bit
118 ZigLLVM_wasm32, // WebAssembly with 32-bit pointers
119 ZigLLVM_wasm64, // WebAssembly with 64-bit pointers
120 ZigLLVM_renderscript32, // 32-bit RenderScript
121 ZigLLVM_renderscript64, // 64-bit RenderScript
133122};
134123
135124static const ZigLLVM_VendorType vendor_list[] = {
......@@ -190,7 +179,7 @@ static const Os os_list[] = {
190179};
191180
192181// Coordinate with zig_llvm.h
193static const ZigLLVM_EnvironmentType environ_list[] = {
182static const ZigLLVM_EnvironmentType abi_list[] = {
194183 ZigLLVM_UnknownEnvironment,
195184
196185 ZigLLVM_GNU,
......@@ -225,11 +214,12 @@ size_t target_oformat_count(void) {
225214 return array_length(oformat_list);
226215}
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));
229219 return oformat_list[index];
230220}
231221
232const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat) {
222const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) {
233223 switch (oformat) {
234224 case ZigLLVM_UnknownObjectFormat: return "unknown";
235225 case ZigLLVM_COFF: return "coff";
......@@ -244,22 +234,25 @@ size_t target_arch_count(void) {
244234 return array_length(arch_list);
245235}
246236
247const ArchType *get_target_arch(size_t index) {
248 return &arch_list[index];
237ZigLLVM_ArchType target_arch_enum(size_t index) {
238 assert(index < array_length(arch_list));
239 return arch_list[index];
249240}
250241
251242size_t target_vendor_count(void) {
252243 return array_length(vendor_list);
253244}
254245
255ZigLLVM_VendorType get_target_vendor(size_t index) {
246ZigLLVM_VendorType target_vendor_enum(size_t index) {
247 assert(index < array_length(vendor_list));
256248 return vendor_list[index];
257249}
258250
259251size_t target_os_count(void) {
260252 return array_length(os_list);
261253}
262Os get_target_os(size_t index) {
254Os target_os_enum(size_t index) {
255 assert(index < array_length(os_list));
263256 return os_list[index];
264257}
265258
......@@ -414,7 +407,7 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) {
414407 zig_unreachable();
415408}
416409
417const char *get_target_os_name(Os os_type) {
410const char *target_os_name(Os os_type) {
418411 switch (os_type) {
419412 case OsFreestanding:
420413 return "freestanding";
......@@ -460,78 +453,257 @@ const char *get_target_os_name(Os os_type) {
460453 zig_unreachable();
461454}
462455
463size_t target_environ_count(void) {
464 return array_length(environ_list);
456size_t target_abi_count(void) {
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];
465462}
466ZigLLVM_EnvironmentType get_target_environ(size_t index) {
467 return environ_list[index];
463const char *target_abi_name(ZigLLVM_EnvironmentType abi) {
464 if (abi == ZigLLVM_UnknownEnvironment)
465 return "none";
466 return ZigLLVMGetEnvironmentTypeName(abi);
468467}
469468
470469void get_native_target(ZigTarget *target) {
471470 ZigLLVM_OSType os_type;
471 ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
472472 ZigLLVMGetNativeTarget(
473 &target->arch.arch,
474 &target->arch.sub_arch,
473 &target->arch,
474 &target->sub_arch,
475475 &target->vendor,
476476 &os_type,
477 &target->env_type,
478 &target->oformat);
477 &target->abi,
478 &oformat);
479479 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 }
480484}
481485
482void get_unknown_target(ZigTarget *target) {
483 target->arch.arch = ZigLLVM_UnknownArch;
484 target->arch.sub_arch = ZigLLVM_NoSubArch;
485 target->vendor = ZigLLVM_UnknownVendor;
486 target->os = OsFreestanding;
487 target->env_type = ZigLLVM_UnknownEnvironment;
488 target->oformat = ZigLLVM_UnknownObjectFormat;
486Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,
487 const char *archsub_ptr, size_t archsub_len)
488{
489 for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
490 ZigLLVM_ArchType arch = arch_list[arch_i];
491 SubArchList sub_arch_list = target_subarch_list(arch);
492 size_t subarch_count = target_subarch_count(sub_arch_list);
493 if (subarch_count == 0) {
494 if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {
495 *out_arch = arch;
496 *out_sub = ZigLLVM_NoSubArch;
497 return ErrorNone;
498 }
499 continue;
500 }
501 for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
502 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
503 char arch_name[64];
504 int n = sprintf(arch_name, "%s%s", target_arch_name(arch), target_subarch_name(sub));
505 if (mem_eql_mem(arch_name, n, archsub_ptr, archsub_len)) {
506 *out_arch = arch;
507 *out_sub = sub;
508 return ErrorNone;
509 }
510 }
511 }
512 return ErrorUnknownArchitecture;
489513}
490514
491static void get_arch_name_raw(char *out_str, ZigLLVM_ArchType arch, ZigLLVM_SubArchType sub_arch) {
492 const char *sub_str = (sub_arch == ZigLLVM_NoSubArch) ? "" : ZigLLVMGetSubArchTypeName(sub_arch);
493 sprintf(out_str, "%s%s", ZigLLVMGetArchTypeName(arch), sub_str);
494}
515SubArchList target_subarch_list(ZigLLVM_ArchType arch) {
516 switch (arch) {
517 case ZigLLVM_UnknownArch:
518 zig_unreachable();
519 case ZigLLVM_arm:
520 case ZigLLVM_armeb:
521 case ZigLLVM_thumb:
522 case ZigLLVM_thumbeb:
523 return SubArchListArm32;
524
525 case ZigLLVM_aarch64:
526 case ZigLLVM_aarch64_be:
527 return SubArchListArm64;
495528
496void get_arch_name(char *out_str, const ArchType *arch) {
497 return get_arch_name_raw(out_str, arch->arch, arch->sub_arch);
529 case ZigLLVM_kalimba:
530 return SubArchListKalimba;
531
532 case ZigLLVM_arc:
533 case ZigLLVM_avr:
534 case ZigLLVM_bpfel:
535 case ZigLLVM_bpfeb:
536 case ZigLLVM_hexagon:
537 case ZigLLVM_mips:
538 case ZigLLVM_mipsel:
539 case ZigLLVM_mips64:
540 case ZigLLVM_mips64el:
541 case ZigLLVM_msp430:
542 case ZigLLVM_ppc:
543 case ZigLLVM_ppc64:
544 case ZigLLVM_ppc64le:
545 case ZigLLVM_r600:
546 case ZigLLVM_amdgcn:
547 case ZigLLVM_riscv32:
548 case ZigLLVM_riscv64:
549 case ZigLLVM_sparc:
550 case ZigLLVM_sparcv9:
551 case ZigLLVM_sparcel:
552 case ZigLLVM_systemz:
553 case ZigLLVM_tce:
554 case ZigLLVM_tcele:
555 case ZigLLVM_x86:
556 case ZigLLVM_x86_64:
557 case ZigLLVM_xcore:
558 case ZigLLVM_nvptx:
559 case ZigLLVM_nvptx64:
560 case ZigLLVM_le32:
561 case ZigLLVM_le64:
562 case ZigLLVM_amdil:
563 case ZigLLVM_amdil64:
564 case ZigLLVM_hsail:
565 case ZigLLVM_hsail64:
566 case ZigLLVM_spir:
567 case ZigLLVM_spir64:
568 case ZigLLVM_shave:
569 case ZigLLVM_lanai:
570 case ZigLLVM_wasm32:
571 case ZigLLVM_wasm64:
572 case ZigLLVM_renderscript32:
573 case ZigLLVM_renderscript64:
574 return SubArchListNone;
575 }
576 zig_unreachable();
498577}
499578
500int parse_target_arch(const char *str, ArchType *out_arch) {
501 for (size_t i = 0; i < array_length(arch_list); i += 1) {
502 const ArchType *arch = &arch_list[i];
503 char arch_name[50];
504 get_arch_name_raw(arch_name, arch->arch, arch->sub_arch);
505 if (strcmp(arch_name, str) == 0) {
506 *out_arch = *arch;
579size_t target_subarch_count(SubArchList sub_arch_list) {
580 switch (sub_arch_list) {
581 case SubArchListNone:
507582 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];
509611 }
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();
511642}
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) {
514645 for (size_t i = 0; i < array_length(os_list); i += 1) {
515646 Os os = os_list[i];
516 const char *os_name = get_target_os_name(os);
517 if (strcmp(os_name, str) == 0) {
647 const char *os_name = target_os_name(os);
648 if (mem_eql_str(os_ptr, os_len, os_name)) {
518649 *out_os = os;
519 return 0;
650 return ErrorNone;
520651 }
521652 }
522 return ErrorFileNotFound;
653 return ErrorUnknownOperatingSystem;
523654}
524655
525int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *out_environ) {
526 for (size_t i = 0; i < array_length(environ_list); i += 1) {
527 ZigLLVM_EnvironmentType env_type = environ_list[i];
528 const char *environ_name = ZigLLVMGetEnvironmentTypeName(env_type);
529 if (strcmp(environ_name, str) == 0) {
530 *out_environ = env_type;
531 return 0;
656Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, size_t abi_len) {
657 for (size_t i = 0; i < array_length(abi_list); i += 1) {
658 ZigLLVM_EnvironmentType abi = abi_list[i];
659 const char *abi_name = target_abi_name(abi);
660 if (mem_eql_str(abi_ptr, abi_len, abi_name)) {
661 *out_abi = abi;
662 return ErrorNone;
663 }
664 }
665 return ErrorUnknownABI;
666}
667
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;
532695 }
696 } else {
697 target->abi = target_default_abi(target->arch, target->os);
533698 }
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);
535707}
536708
537709void init_all_targets(void) {
......@@ -543,121 +715,39 @@ void init_all_targets(void) {
543715}
544716
545717void get_target_triple(Buf *triple, const ZigTarget *target) {
546 char arch_name[50];
547 get_arch_name(arch_name, &target->arch);
548
549718 buf_resize(triple, 0);
550
551 // LLVM WebAssembly output support requires the target to be activated at
552 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
553 //
554 // LLVM determines the output format based on the environment suffix,
555 // defaulting to an object based on the architecture. The default format in
556 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
557 // explicitly set this ourself in order for it to work.
558 //
559 // This is fixed in LLVM 7 and you will be able to get wasm output by
560 // using the target triple `wasm32-unknown-unknown-unknown`.
561 if (!strncmp(arch_name, "wasm", 4)) {
562 buf_appendf(triple, "%s-%s-%s-wasm", arch_name,
563 ZigLLVMGetVendorTypeName(target->vendor),
564 ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)));
565 } else {
566 buf_appendf(triple, "%s-%s-%s-%s", arch_name,
567 ZigLLVMGetVendorTypeName(target->vendor),
568 ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
569 ZigLLVMGetEnvironmentTypeName(target->env_type));
570 }
719 buf_appendf(triple, "%s%s-%s-%s-%s",
720 ZigLLVMGetArchTypeName(target->arch),
721 ZigLLVMGetSubArchTypeName(target->sub_arch),
722 ZigLLVMGetVendorTypeName(target->vendor),
723 ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
724 ZigLLVMGetEnvironmentTypeName(target->abi));
571725}
572726
573static bool is_os_darwin(ZigTarget *target) {
727bool target_is_darwin(const ZigTarget *target) {
574728 switch (target->os) {
575729 case OsMacOSX:
576730 case OsIOS:
731 case OsWatchOS:
732 case OsTvOS:
577733 return true;
578734 default:
579735 return false;
580736 }
581737}
582738
583void resolve_target_object_format(ZigTarget *target) {
584 if (target->oformat != ZigLLVM_UnknownObjectFormat) {
585 return;
739ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) {
740 if (target->os == OsUefi || target->os == OsWindows) {
741 return ZigLLVM_COFF;
742 } else if (target_is_darwin(target)) {
743 return ZigLLVM_MachO;
586744 }
587
588 switch (target->arch.arch) {
589 case ZigLLVM_UnknownArch:
590 case ZigLLVM_aarch64:
591 case ZigLLVM_arm:
592 case ZigLLVM_thumb:
593 case ZigLLVM_x86:
594 case ZigLLVM_x86_64:
595 if (is_os_darwin(target)) {
596 target->oformat = ZigLLVM_MachO;
597 } else if (target->os == OsWindows) {
598 target->oformat = ZigLLVM_COFF;
599 } else {
600 target->oformat = ZigLLVM_ELF;
601 }
602 return;
603
604 case ZigLLVM_aarch64_be:
605 case ZigLLVM_amdgcn:
606 case ZigLLVM_amdil:
607 case ZigLLVM_amdil64:
608 case ZigLLVM_armeb:
609 case ZigLLVM_arc:
610 case ZigLLVM_avr:
611 case ZigLLVM_bpfeb:
612 case ZigLLVM_bpfel:
613 case ZigLLVM_hexagon:
614 case ZigLLVM_lanai:
615 case ZigLLVM_hsail:
616 case ZigLLVM_hsail64:
617 case ZigLLVM_kalimba:
618 case ZigLLVM_le32:
619 case ZigLLVM_le64:
620 case ZigLLVM_mips:
621 case ZigLLVM_mips64:
622 case ZigLLVM_mips64el:
623 case ZigLLVM_mipsel:
624 case ZigLLVM_msp430:
625 case ZigLLVM_nvptx:
626 case ZigLLVM_nvptx64:
627 case ZigLLVM_ppc64le:
628 case ZigLLVM_r600:
629 case ZigLLVM_renderscript32:
630 case ZigLLVM_renderscript64:
631 case ZigLLVM_riscv32:
632 case ZigLLVM_riscv64:
633 case ZigLLVM_shave:
634 case ZigLLVM_sparc:
635 case ZigLLVM_sparcel:
636 case ZigLLVM_sparcv9:
637 case ZigLLVM_spir:
638 case ZigLLVM_spir64:
639 case ZigLLVM_systemz:
640 case ZigLLVM_tce:
641 case ZigLLVM_tcele:
642 case ZigLLVM_thumbeb:
643 case ZigLLVM_xcore:
644 target->oformat= ZigLLVM_ELF;
645 return;
646
647 case ZigLLVM_wasm32:
648 case ZigLLVM_wasm64:
649 target->oformat = ZigLLVM_Wasm;
650 return;
651
652 case ZigLLVM_ppc:
653 case ZigLLVM_ppc64:
654 if (is_os_darwin(target)) {
655 target->oformat = ZigLLVM_MachO;
656 } else {
657 target->oformat= ZigLLVM_ELF;
658 }
659 return;
745 if (target->arch == ZigLLVM_wasm32 ||
746 target->arch == ZigLLVM_wasm64)
747 {
748 return ZigLLVM_Wasm;
660749 }
750 return ZigLLVM_ELF;
661751}
662752
663753// 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) {
728818uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
729819 switch (target->os) {
730820 case OsFreestanding:
731 switch (target->arch.arch) {
821 switch (target->arch) {
732822 case ZigLLVM_msp430:
733823 switch (id) {
734824 case CIntTypeShort:
......@@ -756,7 +846,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
756846 return 32;
757847 case CIntTypeLong:
758848 case CIntTypeULong:
759 return get_arch_pointer_bit_width(target->arch.arch);
849 return get_arch_pointer_bit_width(target->arch);
760850 case CIntTypeLongLong:
761851 case CIntTypeULongLong:
762852 return 64;
......@@ -768,6 +858,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
768858 case OsMacOSX:
769859 case OsZen:
770860 case OsFreeBSD:
861 case OsNetBSD:
771862 case OsOpenBSD:
772863 switch (id) {
773864 case CIntTypeShort:
......@@ -778,7 +869,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
778869 return 32;
779870 case CIntTypeLong:
780871 case CIntTypeULong:
781 return get_arch_pointer_bit_width(target->arch.arch);
872 return get_arch_pointer_bit_width(target->arch);
782873 case CIntTypeLongLong:
783874 case CIntTypeULongLong:
784875 return 64;
......@@ -808,7 +899,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
808899 case OsIOS:
809900 case OsKFreeBSD:
810901 case OsLv2:
811 case OsNetBSD:
812902 case OsSolaris:
813903 case OsHaiku:
814904 case OsMinix:
......@@ -835,23 +925,27 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
835925 zig_unreachable();
836926}
837927
838const char *target_o_file_ext(ZigTarget *target) {
839 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
928bool target_allows_addr_zero(const ZigTarget *target) {
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) {
840934 return ".obj";
841935 } else {
842936 return ".o";
843937 }
844938}
845939
846const char *target_asm_file_ext(ZigTarget *target) {
940const char *target_asm_file_ext(const ZigTarget *target) {
847941 return ".s";
848942}
849943
850const char *target_llvm_ir_file_ext(ZigTarget *target) {
944const char *target_llvm_ir_file_ext(const ZigTarget *target) {
851945 return ".ll";
852946}
853947
854const char *target_exe_file_ext(ZigTarget *target) {
948const char *target_exe_file_ext(const ZigTarget *target) {
855949 if (target->os == OsWindows) {
856950 return ".exe";
857951 } else if (target->os == OsUefi) {
......@@ -861,7 +955,9 @@ const char *target_exe_file_ext(ZigTarget *target) {
861955 }
862956}
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{
865961 if (target->os == OsWindows || target->os == OsUefi) {
866962 if (is_static) {
867963 return ".lib";
......@@ -872,7 +968,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
872968 if (is_static) {
873969 return ".a";
874970 } else {
875 return buf_ptr(buf_sprintf(".so.%zu", version_major));
971 return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize, version_major));
876972 }
877973 }
878974}
......@@ -883,8 +979,8 @@ enum FloatAbi {
883979 FloatAbiSoftFp,
884980};
885981
886static FloatAbi get_float_abi(ZigTarget *target) {
887 const ZigLLVM_EnvironmentType env = target->env_type;
982static FloatAbi get_float_abi(const ZigTarget *target) {
983 const ZigLLVM_EnvironmentType env = target->abi;
888984 if (env == ZigLLVM_GNUEABIHF ||
889985 env == ZigLLVM_EABIHF ||
890986 env == ZigLLVM_MuslEABIHF)
......@@ -899,64 +995,153 @@ static bool is_64_bit(ZigLLVM_ArchType arch) {
899995 return get_arch_pointer_bit_width(arch) == 64;
900996}
901997
902Buf *target_dynamic_linker(ZigTarget *target) {
903 const ZigLLVM_ArchType arch = target->arch.arch;
904 const ZigLLVM_EnvironmentType env = target->env_type;
998const char *target_dynamic_linker(const ZigTarget *target) {
999 switch (target->os) {
1000 case OsFreeBSD:
1001 return "/libexec/ld-elf.so.1";
1002 case OsNetBSD:
1003 return "/libexec/ld.elf_so";
1004 case OsLinux: {
1005 const ZigLLVM_EnvironmentType abi = target->abi;
1006 if (abi == ZigLLVM_Android) {
1007 if (is_64_bit(target->arch)) {
1008 return "/system/bin/linker64";
1009 } else {
1010 return "/system/bin/linker";
1011 }
1012 }
9051013
906 if (env == ZigLLVM_Android) {
907 if (is_64_bit(arch)) {
908 return buf_create_from_str("/system/bin/linker64");
909 } else {
910 return buf_create_from_str("/system/bin/linker");
911 }
912 } else if (arch == ZigLLVM_x86 ||
913 arch == ZigLLVM_sparc ||
914 arch == ZigLLVM_sparcel)
915 {
916 return buf_create_from_str("/lib/ld-linux.so.2");
917 } else if (arch == ZigLLVM_aarch64) {
918 return buf_create_from_str("/lib/ld-linux-aarch64.so.1");
919 } else if (arch == ZigLLVM_aarch64_be) {
920 return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1");
921 } else if (arch == ZigLLVM_arm || arch == ZigLLVM_thumb) {
922 if (get_float_abi(target) == FloatAbiHard) {
923 return buf_create_from_str("/lib/ld-linux-armhf.so.3");
924 } else {
925 return buf_create_from_str("/lib/ld-linux.so.3");
926 }
927 } else if (arch == ZigLLVM_armeb || arch == ZigLLVM_thumbeb) {
928 if (get_float_abi(target) == FloatAbiHard) {
929 return buf_create_from_str("/lib/ld-linux-armhf.so.3");
930 } else {
931 return buf_create_from_str("/lib/ld-linux.so.3");
1014 switch (target->arch) {
1015 case ZigLLVM_UnknownArch:
1016 zig_unreachable();
1017 case ZigLLVM_x86:
1018 case ZigLLVM_sparc:
1019 case ZigLLVM_sparcel:
1020 return "/lib/ld-linux.so.2";
1021
1022 case ZigLLVM_aarch64:
1023 return "/lib/ld-linux-aarch64.so.1";
1024
1025 case ZigLLVM_aarch64_be:
1026 return "/lib/ld-linux-aarch64_be.so.1";
1027
1028 case ZigLLVM_arm:
1029 case ZigLLVM_thumb:
1030 if (get_float_abi(target) == FloatAbiHard) {
1031 return "/lib/ld-linux-armhf.so.3";
1032 } else {
1033 return "/lib/ld-linux.so.3";
1034 }
1035
1036 case ZigLLVM_armeb:
1037 case ZigLLVM_thumbeb:
1038 if (get_float_abi(target) == FloatAbiHard) {
1039 return "/lib/ld-linux-armhf.so.3";
1040 } else {
1041 return "/lib/ld-linux.so.3";
1042 }
1043
1044 case ZigLLVM_mips:
1045 case ZigLLVM_mipsel:
1046 case ZigLLVM_mips64:
1047 case ZigLLVM_mips64el:
1048 zig_panic("TODO implement target_dynamic_linker for mips");
1049
1050 case ZigLLVM_ppc:
1051 return "/lib/ld.so.1";
1052
1053 case ZigLLVM_ppc64:
1054 return "/lib64/ld64.so.2";
1055
1056 case ZigLLVM_ppc64le:
1057 return "/lib64/ld64.so.2";
1058
1059 case ZigLLVM_systemz:
1060 return "/lib64/ld64.so.1";
1061
1062 case ZigLLVM_sparcv9:
1063 return "/lib64/ld-linux.so.2";
1064
1065 case ZigLLVM_x86_64:
1066 if (abi == ZigLLVM_GNUX32) {
1067 return "/libx32/ld-linux-x32.so.2";
1068 }
1069 if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) {
1070 return "/lib/ld-musl-x86_64.so.1";
1071 }
1072 return "/lib64/ld-linux-x86-64.so.2";
1073
1074 case ZigLLVM_wasm32:
1075 case ZigLLVM_wasm64:
1076 return nullptr;
1077
1078 case ZigLLVM_arc:
1079 case ZigLLVM_avr:
1080 case ZigLLVM_bpfel:
1081 case ZigLLVM_bpfeb:
1082 case ZigLLVM_hexagon:
1083 case ZigLLVM_msp430:
1084 case ZigLLVM_r600:
1085 case ZigLLVM_amdgcn:
1086 case ZigLLVM_riscv32:
1087 case ZigLLVM_riscv64:
1088 case ZigLLVM_tce:
1089 case ZigLLVM_tcele:
1090 case ZigLLVM_xcore:
1091 case ZigLLVM_nvptx:
1092 case ZigLLVM_nvptx64:
1093 case ZigLLVM_le32:
1094 case ZigLLVM_le64:
1095 case ZigLLVM_amdil:
1096 case ZigLLVM_amdil64:
1097 case ZigLLVM_hsail:
1098 case ZigLLVM_hsail64:
1099 case ZigLLVM_spir:
1100 case ZigLLVM_spir64:
1101 case ZigLLVM_kalimba:
1102 case ZigLLVM_shave:
1103 case ZigLLVM_lanai:
1104 case ZigLLVM_renderscript32:
1105 case ZigLLVM_renderscript64:
1106 zig_panic("TODO implement target_dynamic_linker for this arch");
1107 }
1108 zig_unreachable();
9321109 }
933 } else if (arch == ZigLLVM_mips || arch == ZigLLVM_mipsel ||
934 arch == ZigLLVM_mips64 || arch == ZigLLVM_mips64el)
935 {
936 // when you want to solve this TODO, grep clang codebase for
937 // getLinuxDynamicLinker
938 zig_panic("TODO figure out MIPS dynamic linker name");
939 } else if (arch == ZigLLVM_ppc) {
940 return buf_create_from_str("/lib/ld.so.1");
941 } else if (arch == ZigLLVM_ppc64) {
942 return buf_create_from_str("/lib64/ld64.so.2");
943 } else if (arch == ZigLLVM_ppc64le) {
944 return buf_create_from_str("/lib64/ld64.so.2");
945 } else if (arch == ZigLLVM_systemz) {
946 return buf_create_from_str("/lib64/ld64.so.1");
947 } else if (arch == ZigLLVM_sparcv9) {
948 return buf_create_from_str("/lib64/ld-linux.so.2");
949 } else if (arch == ZigLLVM_x86_64 &&
950 env == ZigLLVM_GNUX32)
951 {
952 return buf_create_from_str("/libx32/ld-linux-x32.so.2");
953 } else if (arch == ZigLLVM_x86_64 &&
954 (env == ZigLLVM_Musl || env == ZigLLVM_MuslEABI || env == ZigLLVM_MuslEABIHF))
955 {
956 return buf_create_from_str("/lib/ld-musl-x86_64.so.1");
957 } else {
958 return buf_create_from_str("/lib64/ld-linux-x86-64.so.2");
1110 case OsFreestanding:
1111 case OsIOS:
1112 case OsTvOS:
1113 case OsWatchOS:
1114 case OsMacOSX:
1115 return nullptr;
1116
1117 case OsAnanas:
1118 case OsCloudABI:
1119 case OsDragonFly:
1120 case OsFuchsia:
1121 case OsKFreeBSD:
1122 case OsLv2:
1123 case OsOpenBSD:
1124 case OsSolaris:
1125 case OsWindows:
1126 case OsHaiku:
1127 case OsMinix:
1128 case OsRTEMS:
1129 case OsNaCl:
1130 case OsCNK:
1131 case OsAIX:
1132 case OsCUDA:
1133 case OsNVCL:
1134 case OsAMDHSA:
1135 case OsPS4:
1136 case OsELFIAMCU:
1137 case OsMesa3D:
1138 case OsContiki:
1139 case OsAMDPAL:
1140 case OsZen:
1141 case OsUefi:
1142 zig_panic("TODO implement target_dynamic_linker for this OS");
9591143 }
1144 zig_unreachable();
9601145}
9611146
9621147bool 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
9671152 return true;
9681153 }
9691154
970 if (guest_target->os == host_target->os && guest_target->arch.arch == host_target->arch.arch &&
971 guest_target->arch.sub_arch == host_target->arch.sub_arch)
1155 if (guest_target->os == host_target->os && guest_target->arch == host_target->arch &&
1156 guest_target->sub_arch == host_target->sub_arch)
9721157 {
9731158 // OS, arch, and sub-arch match
9741159 return true;
9751160 }
9761161
9771162 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)
9791164 {
9801165 // 64-bit windows can run 32-bit programs
9811166 return true;
......@@ -984,8 +1169,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
9841169 return false;
9851170}
9861171
987const char *arch_stack_pointer_register_name(const ArchType *arch) {
988 switch (arch->arch) {
1172const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
1173 switch (arch) {
9891174 case ZigLLVM_UnknownArch:
9901175 zig_unreachable();
9911176 case ZigLLVM_x86:
......@@ -1047,7 +1232,7 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {
10471232}
10481233
10491234bool target_is_arm(const ZigTarget *target) {
1050 switch (target->arch.arch) {
1235 switch (target->arch) {
10511236 case ZigLLVM_UnknownArch:
10521237 zig_unreachable();
10531238 case ZigLLVM_aarch64:
......@@ -1105,3 +1290,73 @@ bool target_is_arm(const ZigTarget *target) {
11051290 }
11061291 zig_unreachable();
11071292}
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 @@
1212
1313struct Buf;
1414
15struct ArchType {
16 ZigLLVM_ArchType arch;
17 ZigLLVM_SubArchType sub_arch;
18};
19
2015// Synchronize with target.cpp::os_list
2116enum Os {
2217 OsFreestanding,
......@@ -57,6 +52,15 @@ enum Os {
5752 OsUefi,
5853};
5954
55// Synchronize with target.cpp::subarch_list_list
56enum SubArchList {
57 SubArchListNone,
58 SubArchListArm32,
59 SubArchListArm64,
60 SubArchListKalimba,
61 SubArchListMips,
62};
63
6064enum TargetSubsystem {
6165 TargetSubsystemAuto, // Zig should infer the subsystem
6266 TargetSubsystemConsole,
......@@ -70,11 +74,12 @@ enum TargetSubsystem {
7074};
7175
7276struct ZigTarget {
73 ArchType arch;
77 ZigLLVM_ArchType arch;
78 ZigLLVM_SubArchType sub_arch;
7479 ZigLLVM_VendorType vendor;
7580 Os os;
76 ZigLLVM_EnvironmentType env_type;
77 ZigLLVM_ObjectFormatType oformat;
81 ZigLLVM_EnvironmentType abi;
82 bool is_native;
7883};
7984
8085enum CIntType {
......@@ -90,53 +95,71 @@ enum CIntType {
9095 CIntTypeCount,
9196};
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
93104size_t target_arch_count(void);
94const ArchType *get_target_arch(size_t index);
95void get_arch_name(char *out_str, const ArchType *arch);
105ZigLLVM_ArchType target_arch_enum(size_t index);
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
99119size_t target_vendor_count(void);
100ZigLLVM_VendorType get_target_vendor(size_t index);
120ZigLLVM_VendorType target_vendor_enum(size_t index);
101121
102122size_t target_os_count(void);
103Os get_target_os(size_t index);
104const char *get_target_os_name(Os os_type);
123Os target_os_enum(size_t index);
124const char *target_os_name(Os os_type);
105125
106size_t target_environ_count(void);
107ZigLLVM_EnvironmentType get_target_environ(size_t index);
126size_t target_abi_count(void);
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
110132size_t target_oformat_count(void);
111const ZigLLVM_ObjectFormatType get_target_oformat(size_t index);
112const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat);
133ZigLLVM_ObjectFormatType target_oformat_enum(size_t index);
134const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat);
135ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target);
113136
114137void get_native_target(ZigTarget *target);
115void get_unknown_target(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);
138void get_target_triple(Buf *triple, const ZigTarget *target);
120139
121140void init_all_targets(void);
122141
123void get_target_triple(Buf *triple, const ZigTarget *target);
124
125142void resolve_target_object_format(ZigTarget *target);
126143
127144uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
128145
129const char *target_o_file_ext(ZigTarget *target);
130const char *target_asm_file_ext(ZigTarget *target);
131const char *target_llvm_ir_file_ext(ZigTarget *target);
132const char *target_exe_file_ext(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);
146const char *target_o_file_ext(const ZigTarget *target);
147const char *target_asm_file_ext(const ZigTarget *target);
148const char *target_llvm_ir_file_ext(const ZigTarget *target);
149const char *target_exe_file_ext(const ZigTarget *target);
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
137155bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
138156ZigLLVM_OSType get_llvm_os_type(Os os_type);
139157
140158bool 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
142165#endif
src/tokenizer.cpp+18-1
......@@ -221,6 +221,7 @@ enum TokenizeState {
221221 TokenizeStateError,
222222 TokenizeStateLBracket,
223223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
224225};
225226
226227
......@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
846847 switch (c) {
847848 case '*':
848849 t.state = TokenizeStateLBracketStar;
849 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
850850 break;
851851 default:
852852 // reinterpret as just an lbracket
......@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
857857 }
858858 break;
859859 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:
860875 switch (c) {
861876 case ']':
862877 end_token(&t);
......@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
14911506 case TokenizeStateLineStringContinue:
14921507 case TokenizeStateLineStringContinueC:
14931508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
14941510 tokenize_error(&t, "unexpected EOF");
14951511 break;
14961512 case TokenizeStateLineComment:
......@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
15281544 case TokenIdBitShiftRightEq: return ">>=";
15291545 case TokenIdBitXorEq: return "^=";
15301546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
15311548 case TokenIdCharLiteral: return "CharLiteral";
15321549 case TokenIdCmpEq: return "==";
15331550 case TokenIdCmpGreaterOrEq: return ">=";
src/tokenizer.hpp+1
......@@ -29,6 +29,7 @@ enum TokenId {
2929 TokenIdBitShiftRightEq,
3030 TokenIdBitXorEq,
3131 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
3233 TokenIdCharLiteral,
3334 TokenIdCmpEq,
3435 TokenIdCmpGreaterOrEq,
src/translate_c.cpp+945-1697
......@@ -4,7 +4,6 @@
44 * This file is part of zig, which is MIT licensed.
55 * See http://opensource.org/licenses/MIT
66 */
7
87#include "all_types.hpp"
98#include "analyze.hpp"
109#include "c_tokenizer.hpp"
......@@ -13,7 +12,7 @@
1312#include "os.hpp"
1413#include "translate_c.hpp"
1514#include "parser.hpp"
16
15#include "zig_clang.h"
1716
1817#if __GNUC__ >= 8
1918#pragma GCC diagnostic push
......@@ -30,8 +29,6 @@
3029
3130#include <string.h>
3231
33using namespace clang;
34
3532struct Alias {
3633 Buf *new_name;
3734 Buf *canon_name;
......@@ -87,13 +84,13 @@ struct Context {
8784 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
8885 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
8986 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
90 SourceManager *source_manager;
87 ZigClangSourceManager *source_manager;
9188 ZigList<Alias> aliases;
9289 AstNode *source_node;
9390 bool warnings_on;
9491
9592 CodeGen *codegen;
96 ASTContext *ctx;
93 ZigClangASTContext *ctx;
9794
9895 TransScopeRoot *global_scope;
9996 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
......@@ -117,22 +114,38 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
117114
118115static TransScopeBlock *trans_scope_block_find(TransScope *scope);
119116
120static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
121static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
122static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
117static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
118static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_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,
125122 ResultUsed result_used, TransLRValue lrval,
126123 AstNode **out_node, TransScope **out_child_scope,
127124 TransScope **out_node_scope);
128static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
129static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
130static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
131static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
132static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc);
125static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
126static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
127static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
128static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
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
134147ATTRIBUTE_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, ...) {
136149 if (!c->warnings_on) {
137150 return;
138151 }
......@@ -142,16 +155,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
142155 Buf *msg = buf_vprintf(format, ap);
143156 va_end(ap);
144157
145 StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl));
146 const char *filename_bytes = (const char *)filename.bytes_begin();
158 ZigClangSourceLocation sl = bitcast(clang_sl);
159 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
160 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
147161 Buf *path;
148162 if (filename_bytes) {
149163 path = buf_create_from_str(filename_bytes);
150164 } else {
151165 path = buf_sprintf("(no file)");
152166 }
153 unsigned line = c->source_manager->getSpellingLineNumber(sl);
154 unsigned column = c->source_manager->getSpellingColumnNumber(sl);
167 unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
168 unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
155169 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
156170}
157171
......@@ -292,11 +306,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
292306 node);
293307}
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
295321static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
296322 AstNode *node = trans_create_node(c, NodeTypePointerType);
297323 node->data.pointer_type.star_token = allocate<ZigToken>(1);
298 node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;
299 node->data.pointer_type.is_const = is_const;
324 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
300325 node->data.pointer_type.is_const = is_const;
301326 node->data.pointer_type.is_volatile = is_volatile;
302327 node->data.pointer_type.op_expr = child_node;
......@@ -461,15 +486,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {
461486 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
462487}
463488
464static const char *decl_name(const Decl *decl) {
465 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
489static const char *decl_name(const clang::Decl *decl) {
490 const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
466491 return (const char *)named_decl->getName().bytes_begin();
467492}
468493
469494static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
470495 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
471496 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();
473498 if (!is_negative) {
474499 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
475500 return node;
......@@ -480,41 +505,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
480505
481506}
482507
483static const Type *qual_type_canon(QualType qt) {
508static const clang::Type *qual_type_canon(clang::QualType qt) {
484509 return qt.getCanonicalType().getTypePtr();
485510}
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) {
488513 // String literals in C are `char *` but they should really be `const char *`.
489 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
490 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
491 if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {
492 const Expr *sub_expr = cast_expr->getSubExpr();
493 if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {
494 QualType array_qt = sub_expr->getType();
495 const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr());
496 QualType pointee_qt = array_type->getElementType();
514 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
515 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
516 if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
517 const clang::Expr *sub_expr = cast_expr->getSubExpr();
518 if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
519 clang::QualType array_qt = sub_expr->getType();
520 const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr());
521 clang::QualType pointee_qt = array_type->getElementType();
497522 pointee_qt.addConst();
498 return c->ctx->getPointerType(pointee_qt);
523 return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));
499524 }
500525 }
501526 }
502527 return expr->getType();
503528}
504529
505static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {
506 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
507 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
530static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
531 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
532 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
508533 return get_expr_qual_type(c, cast_expr->getSubExpr());
509534 }
510535 return expr->getType();
511536}
512537
513static AstNode *get_expr_type(Context *c, const Expr *expr) {
538static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
514539 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc());
515540}
516541
517static bool qual_types_equal(QualType t1, QualType t2) {
542static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
518543 if (t1.isConstQualified() != t2.isConstQualified()) {
519544 return false;
520545 }
......@@ -531,37 +556,37 @@ static bool is_c_void_type(AstNode *node) {
531556 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
532557}
533558
534static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {
535 QualType t1 = get_expr_qual_type(c, expr1);
536 QualType t2 = get_expr_qual_type(c, expr2);
559static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
560 clang::QualType t1 = get_expr_qual_type(c, expr1);
561 clang::QualType t2 = get_expr_qual_type(c, expr2);
537562
538563 return qual_types_equal(t1, t2);
539564}
540565
541static bool qual_type_is_ptr(QualType qt) {
542 const Type *ty = qual_type_canon(qt);
543 return ty->getTypeClass() == Type::Pointer;
566static bool qual_type_is_ptr(clang::QualType qt) {
567 const clang::Type *ty = qual_type_canon(qt);
568 return ty->getTypeClass() == clang::Type::Pointer;
544569}
545570
546static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {
547 const Type *ty = qual_type_canon(qt);
571static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
572 const clang::Type *ty = qual_type_canon(qt);
548573 *is_ptr = false;
549574
550 if (ty->getTypeClass() == Type::Pointer) {
575 if (ty->getTypeClass() == clang::Type::Pointer) {
551576 *is_ptr = true;
552 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
553 QualType child_qt = pointer_ty->getPointeeType();
577 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
578 clang::QualType child_qt = pointer_ty->getPointeeType();
554579 ty = child_qt.getTypePtr();
555580 }
556581
557 if (ty->getTypeClass() == Type::FunctionProto) {
558 return static_cast<const FunctionProtoType*>(ty);
582 if (ty->getTypeClass() == clang::Type::FunctionProto) {
583 return static_cast<const clang::FunctionProtoType*>(ty);
559584 }
560585
561586 return nullptr;
562587}
563588
564static bool qual_type_is_fn_ptr(QualType qt) {
589static bool qual_type_is_fn_ptr(clang::QualType qt) {
565590 bool is_ptr;
566591 if (qual_type_get_fn_proto(qt, &is_ptr)) {
567592 return is_ptr;
......@@ -570,30 +595,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {
570595 return false;
571596}
572597
573static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
574 const Type *ty = qt.getTypePtr();
598static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
599 const clang::Type *ty = qt.getTypePtr();
575600 switch (ty->getTypeClass()) {
576 case Type::Builtin:
601 case clang::Type::Builtin:
577602 {
578 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
603 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
579604 switch (builtin_ty->getKind()) {
580 case BuiltinType::Char_U:
581 case BuiltinType::UChar:
582 case BuiltinType::Char_S:
583 case BuiltinType::SChar:
605 case clang::BuiltinType::Char_U:
606 case clang::BuiltinType::UChar:
607 case clang::BuiltinType::Char_S:
608 case clang::BuiltinType::SChar:
584609 return 8;
585 case BuiltinType::UInt128:
586 case BuiltinType::Int128:
610 case clang::BuiltinType::UInt128:
611 case clang::BuiltinType::Int128:
587612 return 128;
588613 default:
589614 return 0;
590615 }
591616 zig_unreachable();
592617 }
593 case Type::Typedef:
618 case clang::Type::Typedef:
594619 {
595 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
596 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
620 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
621 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
597622 const char *type_name = decl_name(typedef_decl);
598623 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
599624 return 8;
......@@ -614,8 +639,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So
614639}
615640
616641
617static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
618 const SourceLocation &source_loc)
642static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
643 const clang::SourceLocation &source_loc)
619644{
620645 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
621646 if (int_bit_width != 0) {
......@@ -633,7 +658,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
633658// FieldAccess
634659// FnCall (.builtin = true)
635660// Symbol "import"
636// StringLiteral "std"
661// clang::StringLiteral "std"
637662// Symbol "math"
638663// Symbol "Log2Int"
639664// zig_type_node
......@@ -647,21 +672,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
647672 return log2int_fn_call;
648673}
649674
650static bool qual_type_child_is_fn_proto(const QualType &qt) {
651 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
652 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
653 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
675static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
676 if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
677 const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr());
678 if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
654679 return true;
655680 }
656 } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
657 const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());
681 } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
682 const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr());
658683 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
659684 }
660685 return false;
661686}
662687
663static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type,
664 QualType src_type, AstNode *expr)
688static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
689 clang::QualType src_type, AstNode *expr)
665690{
666691 if (qual_types_equal(dest_type, src_type)) {
667692 return expr;
......@@ -678,72 +703,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
678703 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
679704}
680705
681static bool c_is_signed_integer(Context *c, QualType qt) {
682 const Type *c_type = qual_type_canon(qt);
683 if (c_type->getTypeClass() != Type::Builtin)
706static bool c_is_signed_integer(Context *c, clang::QualType qt) {
707 const clang::Type *c_type = qual_type_canon(qt);
708 if (c_type->getTypeClass() != clang::Type::Builtin)
684709 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);
686711 switch (builtin_ty->getKind()) {
687 case BuiltinType::SChar:
688 case BuiltinType::Short:
689 case BuiltinType::Int:
690 case BuiltinType::Long:
691 case BuiltinType::LongLong:
692 case BuiltinType::Int128:
693 case BuiltinType::WChar_S:
712 case clang::BuiltinType::SChar:
713 case clang::BuiltinType::Short:
714 case clang::BuiltinType::Int:
715 case clang::BuiltinType::Long:
716 case clang::BuiltinType::LongLong:
717 case clang::BuiltinType::Int128:
718 case clang::BuiltinType::WChar_S:
694719 return true;
695720 default:
696721 return false;
697722 }
698723}
699724
700static bool c_is_unsigned_integer(Context *c, QualType qt) {
701 const Type *c_type = qual_type_canon(qt);
702 if (c_type->getTypeClass() != Type::Builtin)
725static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
726 const clang::Type *c_type = qual_type_canon(qt);
727 if (c_type->getTypeClass() != clang::Type::Builtin)
703728 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);
705730 switch (builtin_ty->getKind()) {
706 case BuiltinType::Char_U:
707 case BuiltinType::UChar:
708 case BuiltinType::Char_S:
709 case BuiltinType::UShort:
710 case BuiltinType::UInt:
711 case BuiltinType::ULong:
712 case BuiltinType::ULongLong:
713 case BuiltinType::UInt128:
714 case BuiltinType::WChar_U:
731 case clang::BuiltinType::Char_U:
732 case clang::BuiltinType::UChar:
733 case clang::BuiltinType::Char_S:
734 case clang::BuiltinType::UShort:
735 case clang::BuiltinType::UInt:
736 case clang::BuiltinType::ULong:
737 case clang::BuiltinType::ULongLong:
738 case clang::BuiltinType::UInt128:
739 case clang::BuiltinType::WChar_U:
715740 return true;
716741 default:
717742 return false;
718743 }
719744}
720745
721static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {
722 const Type *c_type = qual_type_canon(qt);
723 if (c_type->getTypeClass() != Type::Builtin)
746static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
747 const clang::Type *c_type = qual_type_canon(qt);
748 if (c_type->getTypeClass() != clang::Type::Builtin)
724749 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);
726751 return builtin_ty->getKind() == kind;
727752}
728753
729static bool c_is_float(Context *c, QualType qt) {
730 const Type *c_type = qt.getTypePtr();
731 if (c_type->getTypeClass() != Type::Builtin)
754static bool c_is_float(Context *c, clang::QualType qt) {
755 const clang::Type *c_type = qt.getTypePtr();
756 if (c_type->getTypeClass() != clang::Type::Builtin)
732757 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);
734759 switch (builtin_ty->getKind()) {
735 case BuiltinType::Half:
736 case BuiltinType::Float:
737 case BuiltinType::Double:
738 case BuiltinType::Float128:
739 case BuiltinType::LongDouble:
760 case clang::BuiltinType::Half:
761 case clang::BuiltinType::Float:
762 case clang::BuiltinType::Double:
763 case clang::BuiltinType::Float128:
764 case clang::BuiltinType::LongDouble:
740765 return true;
741766 default:
742767 return false;
743768 }
744769}
745770
746static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
771static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
747772 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
748773 // float and signed integer overflow is undefined behavior.
749774 return false;
......@@ -753,23 +778,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
753778 }
754779}
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) {
757782 switch (ty->getTypeClass()) {
758 case Type::Builtin: {
759 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
760 return builtin_ty->getKind() == BuiltinType::Void;
783 case clang::Type::Builtin: {
784 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
785 return builtin_ty->getKind() == clang::BuiltinType::Void;
761786 }
762 case Type::Record: {
763 const RecordType *record_ty = static_cast<const RecordType*>(ty);
787 case clang::Type::Record: {
788 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
764789 return record_ty->getDecl()->getDefinition() == nullptr;
765790 }
766 case Type::Elaborated: {
767 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
791 case clang::Type::Elaborated: {
792 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
768793 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
769794 }
770 case Type::Typedef: {
771 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
772 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
795 case clang::Type::Typedef: {
796 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
797 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
773798 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
774799 }
775800 default:
......@@ -777,136 +802,136 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou
777802 }
778803}
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) {
781806 switch (ty->getTypeClass()) {
782 case Type::Builtin:
807 case clang::Type::Builtin:
783808 {
784 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
809 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
785810 switch (builtin_ty->getKind()) {
786 case BuiltinType::Void:
811 case clang::BuiltinType::Void:
787812 return trans_create_node_symbol_str(c, "c_void");
788 case BuiltinType::Bool:
813 case clang::BuiltinType::Bool:
789814 return trans_create_node_symbol_str(c, "bool");
790 case BuiltinType::Char_U:
791 case BuiltinType::UChar:
792 case BuiltinType::Char_S:
793 case BuiltinType::Char8:
815 case clang::BuiltinType::Char_U:
816 case clang::BuiltinType::UChar:
817 case clang::BuiltinType::Char_S:
818 case clang::BuiltinType::Char8:
794819 return trans_create_node_symbol_str(c, "u8");
795 case BuiltinType::SChar:
820 case clang::BuiltinType::SChar:
796821 return trans_create_node_symbol_str(c, "i8");
797 case BuiltinType::UShort:
822 case clang::BuiltinType::UShort:
798823 return trans_create_node_symbol_str(c, "c_ushort");
799 case BuiltinType::UInt:
824 case clang::BuiltinType::UInt:
800825 return trans_create_node_symbol_str(c, "c_uint");
801 case BuiltinType::ULong:
826 case clang::BuiltinType::ULong:
802827 return trans_create_node_symbol_str(c, "c_ulong");
803 case BuiltinType::ULongLong:
828 case clang::BuiltinType::ULongLong:
804829 return trans_create_node_symbol_str(c, "c_ulonglong");
805 case BuiltinType::Short:
830 case clang::BuiltinType::Short:
806831 return trans_create_node_symbol_str(c, "c_short");
807 case BuiltinType::Int:
832 case clang::BuiltinType::Int:
808833 return trans_create_node_symbol_str(c, "c_int");
809 case BuiltinType::Long:
834 case clang::BuiltinType::Long:
810835 return trans_create_node_symbol_str(c, "c_long");
811 case BuiltinType::LongLong:
836 case clang::BuiltinType::LongLong:
812837 return trans_create_node_symbol_str(c, "c_longlong");
813 case BuiltinType::UInt128:
838 case clang::BuiltinType::UInt128:
814839 return trans_create_node_symbol_str(c, "u128");
815 case BuiltinType::Int128:
840 case clang::BuiltinType::Int128:
816841 return trans_create_node_symbol_str(c, "i128");
817 case BuiltinType::Float:
842 case clang::BuiltinType::Float:
818843 return trans_create_node_symbol_str(c, "f32");
819 case BuiltinType::Double:
844 case clang::BuiltinType::Double:
820845 return trans_create_node_symbol_str(c, "f64");
821 case BuiltinType::Float128:
846 case clang::BuiltinType::Float128:
822847 return trans_create_node_symbol_str(c, "f128");
823 case BuiltinType::Float16:
848 case clang::BuiltinType::Float16:
824849 return trans_create_node_symbol_str(c, "f16");
825 case BuiltinType::LongDouble:
850 case clang::BuiltinType::LongDouble:
826851 return trans_create_node_symbol_str(c, "c_longdouble");
827 case BuiltinType::WChar_U:
828 case BuiltinType::Char16:
829 case BuiltinType::Char32:
830 case BuiltinType::WChar_S:
831 case BuiltinType::Half:
832 case BuiltinType::NullPtr:
833 case BuiltinType::ObjCId:
834 case BuiltinType::ObjCClass:
835 case BuiltinType::ObjCSel:
836 case BuiltinType::OMPArraySection:
837 case BuiltinType::Dependent:
838 case BuiltinType::Overload:
839 case BuiltinType::BoundMember:
840 case BuiltinType::PseudoObject:
841 case BuiltinType::UnknownAny:
842 case BuiltinType::BuiltinFn:
843 case BuiltinType::ARCUnbridgedCast:
844 case BuiltinType::ShortAccum:
845 case BuiltinType::Accum:
846 case BuiltinType::LongAccum:
847 case BuiltinType::UShortAccum:
848 case BuiltinType::UAccum:
849 case BuiltinType::ULongAccum:
850
851 case BuiltinType::OCLImage1dRO:
852 case BuiltinType::OCLImage1dArrayRO:
853 case BuiltinType::OCLImage1dBufferRO:
854 case BuiltinType::OCLImage2dRO:
855 case BuiltinType::OCLImage2dArrayRO:
856 case BuiltinType::OCLImage2dDepthRO:
857 case BuiltinType::OCLImage2dArrayDepthRO:
858 case BuiltinType::OCLImage2dMSAARO:
859 case BuiltinType::OCLImage2dArrayMSAARO:
860 case BuiltinType::OCLImage2dMSAADepthRO:
861 case BuiltinType::OCLImage2dArrayMSAADepthRO:
862 case BuiltinType::OCLImage3dRO:
863 case BuiltinType::OCLImage1dWO:
864 case BuiltinType::OCLImage1dArrayWO:
865 case BuiltinType::OCLImage1dBufferWO:
866 case BuiltinType::OCLImage2dWO:
867 case BuiltinType::OCLImage2dArrayWO:
868 case BuiltinType::OCLImage2dDepthWO:
869 case BuiltinType::OCLImage2dArrayDepthWO:
870 case BuiltinType::OCLImage2dMSAAWO:
871 case BuiltinType::OCLImage2dArrayMSAAWO:
872 case BuiltinType::OCLImage2dMSAADepthWO:
873 case BuiltinType::OCLImage2dArrayMSAADepthWO:
874 case BuiltinType::OCLImage3dWO:
875 case BuiltinType::OCLImage1dRW:
876 case BuiltinType::OCLImage1dArrayRW:
877 case BuiltinType::OCLImage1dBufferRW:
878 case BuiltinType::OCLImage2dRW:
879 case BuiltinType::OCLImage2dArrayRW:
880 case BuiltinType::OCLImage2dDepthRW:
881 case BuiltinType::OCLImage2dArrayDepthRW:
882 case BuiltinType::OCLImage2dMSAARW:
883 case BuiltinType::OCLImage2dArrayMSAARW:
884 case BuiltinType::OCLImage2dMSAADepthRW:
885 case BuiltinType::OCLImage2dArrayMSAADepthRW:
886 case BuiltinType::OCLImage3dRW:
887 case BuiltinType::OCLSampler:
888 case BuiltinType::OCLEvent:
889 case BuiltinType::OCLClkEvent:
890 case BuiltinType::OCLQueue:
891 case BuiltinType::OCLReserveID:
892 case BuiltinType::ShortFract:
893 case BuiltinType::Fract:
894 case BuiltinType::LongFract:
895 case BuiltinType::UShortFract:
896 case BuiltinType::UFract:
897 case BuiltinType::ULongFract:
898 case BuiltinType::SatShortAccum:
899 case BuiltinType::SatAccum:
900 case BuiltinType::SatLongAccum:
901 case BuiltinType::SatUShortAccum:
902 case BuiltinType::SatUAccum:
903 case BuiltinType::SatULongAccum:
904 case BuiltinType::SatShortFract:
905 case BuiltinType::SatFract:
906 case BuiltinType::SatLongFract:
907 case BuiltinType::SatUShortFract:
908 case BuiltinType::SatUFract:
909 case BuiltinType::SatULongFract:
852 case clang::BuiltinType::WChar_U:
853 case clang::BuiltinType::Char16:
854 case clang::BuiltinType::Char32:
855 case clang::BuiltinType::WChar_S:
856 case clang::BuiltinType::Half:
857 case clang::BuiltinType::NullPtr:
858 case clang::BuiltinType::ObjCId:
859 case clang::BuiltinType::ObjCClass:
860 case clang::BuiltinType::ObjCSel:
861 case clang::BuiltinType::OMPArraySection:
862 case clang::BuiltinType::Dependent:
863 case clang::BuiltinType::Overload:
864 case clang::BuiltinType::BoundMember:
865 case clang::BuiltinType::PseudoObject:
866 case clang::BuiltinType::UnknownAny:
867 case clang::BuiltinType::BuiltinFn:
868 case clang::BuiltinType::ARCUnbridgedCast:
869 case clang::BuiltinType::ShortAccum:
870 case clang::BuiltinType::Accum:
871 case clang::BuiltinType::LongAccum:
872 case clang::BuiltinType::UShortAccum:
873 case clang::BuiltinType::UAccum:
874 case clang::BuiltinType::ULongAccum:
875
876 case clang::BuiltinType::OCLImage1dRO:
877 case clang::BuiltinType::OCLImage1dArrayRO:
878 case clang::BuiltinType::OCLImage1dBufferRO:
879 case clang::BuiltinType::OCLImage2dRO:
880 case clang::BuiltinType::OCLImage2dArrayRO:
881 case clang::BuiltinType::OCLImage2dDepthRO:
882 case clang::BuiltinType::OCLImage2dArrayDepthRO:
883 case clang::BuiltinType::OCLImage2dMSAARO:
884 case clang::BuiltinType::OCLImage2dArrayMSAARO:
885 case clang::BuiltinType::OCLImage2dMSAADepthRO:
886 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
887 case clang::BuiltinType::OCLImage3dRO:
888 case clang::BuiltinType::OCLImage1dWO:
889 case clang::BuiltinType::OCLImage1dArrayWO:
890 case clang::BuiltinType::OCLImage1dBufferWO:
891 case clang::BuiltinType::OCLImage2dWO:
892 case clang::BuiltinType::OCLImage2dArrayWO:
893 case clang::BuiltinType::OCLImage2dDepthWO:
894 case clang::BuiltinType::OCLImage2dArrayDepthWO:
895 case clang::BuiltinType::OCLImage2dMSAAWO:
896 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
897 case clang::BuiltinType::OCLImage2dMSAADepthWO:
898 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
899 case clang::BuiltinType::OCLImage3dWO:
900 case clang::BuiltinType::OCLImage1dRW:
901 case clang::BuiltinType::OCLImage1dArrayRW:
902 case clang::BuiltinType::OCLImage1dBufferRW:
903 case clang::BuiltinType::OCLImage2dRW:
904 case clang::BuiltinType::OCLImage2dArrayRW:
905 case clang::BuiltinType::OCLImage2dDepthRW:
906 case clang::BuiltinType::OCLImage2dArrayDepthRW:
907 case clang::BuiltinType::OCLImage2dMSAARW:
908 case clang::BuiltinType::OCLImage2dArrayMSAARW:
909 case clang::BuiltinType::OCLImage2dMSAADepthRW:
910 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
911 case clang::BuiltinType::OCLImage3dRW:
912 case clang::BuiltinType::OCLSampler:
913 case clang::BuiltinType::OCLEvent:
914 case clang::BuiltinType::OCLClkEvent:
915 case clang::BuiltinType::OCLQueue:
916 case clang::BuiltinType::OCLReserveID:
917 case clang::BuiltinType::ShortFract:
918 case clang::BuiltinType::Fract:
919 case clang::BuiltinType::LongFract:
920 case clang::BuiltinType::UShortFract:
921 case clang::BuiltinType::UFract:
922 case clang::BuiltinType::ULongFract:
923 case clang::BuiltinType::SatShortAccum:
924 case clang::BuiltinType::SatAccum:
925 case clang::BuiltinType::SatLongAccum:
926 case clang::BuiltinType::SatUShortAccum:
927 case clang::BuiltinType::SatUAccum:
928 case clang::BuiltinType::SatULongAccum:
929 case clang::BuiltinType::SatShortFract:
930 case clang::BuiltinType::SatFract:
931 case clang::BuiltinType::SatLongFract:
932 case clang::BuiltinType::SatUShortFract:
933 case clang::BuiltinType::SatUFract:
934 case clang::BuiltinType::SatULongFract:
910935 case BuiltinType::OCLIntelSubgroupAVCMcePayload:
911936 case BuiltinType::OCLIntelSubgroupAVCImePayload:
912937 case BuiltinType::OCLIntelSubgroupAVCRefPayload:
......@@ -924,10 +949,10 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
924949 }
925950 break;
926951 }
927 case Type::Pointer:
952 case clang::Type::Pointer:
928953 {
929 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
930 QualType child_qt = pointer_ty->getPointeeType();
954 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
955 clang::QualType child_qt = pointer_ty->getPointeeType();
931956 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
932957 if (child_node == nullptr) {
933958 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
938963 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
939964 }
940965
941 PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;
942
943 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
944 child_qt.isVolatileQualified(), child_node, ptr_len);
945 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
966 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
967 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
968 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
969 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
970 } else {
971 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
972 child_qt.isVolatileQualified(), child_node, PtrLenC);
973 }
946974 }
947 case Type::Typedef:
975 case clang::Type::Typedef:
948976 {
949 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
950 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
977 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
978 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
951979 return resolve_typedef_decl(c, typedef_decl);
952980 }
953 case Type::Elaborated:
981 case clang::Type::Elaborated:
954982 {
955 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
983 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
956984 switch (elaborated_ty->getKeyword()) {
957 case ETK_Struct:
958 case ETK_Enum:
959 case ETK_Union:
985 case clang::ETK_Struct:
986 case clang::ETK_Enum:
987 case clang::ETK_Union:
960988 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
961 case ETK_Interface:
962 case ETK_Class:
963 case ETK_Typename:
964 case ETK_None:
989 case clang::ETK_Interface:
990 case clang::ETK_Class:
991 case clang::ETK_Typename:
992 case clang::ETK_None:
965993 emit_warning(c, source_loc, "unsupported elaborated type");
966994 return nullptr;
967995 }
968996 }
969 case Type::FunctionProto:
997 case clang::Type::FunctionProto:
998 case clang::Type::FunctionNoProto:
970999 {
971 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
1000 const clang::FunctionType *fn_ty = static_cast<const clang::FunctionType*>(ty);
9721001
9731002 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
974 switch (fn_proto_ty->getCallConv()) {
975 case CC_C: // __attribute__((cdecl))
1003 switch (fn_ty->getCallConv()) {
1004 case clang::CC_C: // __attribute__((cdecl))
9761005 proto_node->data.fn_proto.cc = CallingConventionC;
9771006 proto_node->data.fn_proto.is_extern = true;
9781007 break;
979 case CC_X86StdCall: // __attribute__((stdcall))
1008 case clang::CC_X86StdCall: // __attribute__((stdcall))
9801009 proto_node->data.fn_proto.cc = CallingConventionStdcall;
9811010 break;
982 case CC_X86FastCall: // __attribute__((fastcall))
1011 case clang::CC_X86FastCall: // __attribute__((fastcall))
9831012 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
9841013 return nullptr;
985 case CC_X86ThisCall: // __attribute__((thiscall))
1014 case clang::CC_X86ThisCall: // __attribute__((thiscall))
9861015 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
9871016 return nullptr;
988 case CC_X86VectorCall: // __attribute__((vectorcall))
1017 case clang::CC_X86VectorCall: // __attribute__((vectorcall))
9891018 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
9901019 return nullptr;
991 case CC_X86Pascal: // __attribute__((pascal))
1020 case clang::CC_X86Pascal: // __attribute__((pascal))
9921021 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
9931022 return nullptr;
994 case CC_Win64: // __attribute__((ms_abi))
1023 case clang::CC_Win64: // __attribute__((ms_abi))
9951024 emit_warning(c, source_loc, "unsupported calling convention: win64");
9961025 return nullptr;
997 case CC_X86_64SysV: // __attribute__((sysv_abi))
1026 case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
9981027 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
9991028 return nullptr;
1000 case CC_X86RegCall:
1029 case clang::CC_X86RegCall:
10011030 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
10021031 return nullptr;
1003 case CC_AAPCS: // __attribute__((pcs("aapcs")))
1032 case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
10041033 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
10051034 return nullptr;
1006 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
1035 case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
10071036 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
10081037 return nullptr;
1009 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
1038 case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
10101039 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
10111040 return nullptr;
1012 case CC_SpirFunction: // default for OpenCL functions on SPIR target
1041 case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
10131042 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
10141043 return nullptr;
1015 case CC_OpenCLKernel:
1044 case clang::CC_OpenCLKernel:
10161045 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
10171046 return nullptr;
1018 case CC_Swift:
1047 case clang::CC_Swift:
10191048 emit_warning(c, source_loc, "unsupported calling convention: Swift");
10201049 return nullptr;
1021 case CC_PreserveMost:
1050 case clang::CC_PreserveMost:
10221051 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
10231052 return nullptr;
1024 case CC_PreserveAll:
1053 case clang::CC_PreserveAll:
10251054 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
10261055 return nullptr;
10271056 case CC_AArch64VectorCall:
......@@ -1029,20 +1058,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10291058 return nullptr;
10301059 }
10311060
1032 proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
1033 size_t param_count = fn_proto_ty->getNumParams();
1034
1035 if (fn_proto_ty->getNoReturnAttr()) {
1061 if (fn_ty->getNoReturnAttr()) {
10361062 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
10371063 } 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(),
10391065 source_loc);
10401066 if (proto_node->data.fn_proto.return_type == nullptr) {
10411067 emit_warning(c, source_loc, "unsupported function proto return type");
10421068 return nullptr;
10431069 }
10441070 // convert c_void to actual void (only for return type)
1045 // we do want to look at the AstNode instead of QualType, because
1071 // we do want to look at the AstNode instead of clang::QualType, because
10461072 // if they do something like:
10471073 // typedef Foo void;
10481074 // void foo(void) -> Foo;
......@@ -1058,8 +1084,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10581084 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
10591085 }
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
10611096 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);
10631098 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
10641099
10651100 if (param_type_node == nullptr) {
......@@ -1082,19 +1117,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10821117
10831118 return proto_node;
10841119 }
1085 case Type::Record:
1120 case clang::Type::Record:
10861121 {
1087 const RecordType *record_ty = static_cast<const RecordType*>(ty);
1122 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
10881123 return resolve_record_decl(c, record_ty->getDecl());
10891124 }
1090 case Type::Enum:
1125 case clang::Type::Enum:
10911126 {
1092 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
1127 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
10931128 return resolve_enum_decl(c, enum_ty->getDecl());
10941129 }
1095 case Type::ConstantArray:
1130 case clang::Type::ConstantArray:
10961131 {
1097 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
1132 const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty);
10981133 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
10991134 if (child_type_node == nullptr) {
11001135 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
11041139 AstNode *size_node = trans_create_node_unsigned(c, size);
11051140 return trans_create_node_array_type(c, size_node, child_type_node);
11061141 }
1107 case Type::Paren:
1142 case clang::Type::Paren:
11081143 {
1109 const ParenType *paren_ty = static_cast<const ParenType *>(ty);
1144 const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty);
11101145 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
11111146 }
1112 case Type::Decayed:
1147 case clang::Type::Decayed:
11131148 {
1114 const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
1149 const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty);
11151150 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
11161151 }
1117 case Type::Attributed:
1152 case clang::Type::Attributed:
11181153 {
1119 const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
1154 const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty);
11201155 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
11211156 }
1122 case Type::IncompleteArray:
1157 case clang::Type::IncompleteArray:
11231158 {
1124 const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty);
1125 QualType child_qt = incomplete_array_ty->getElementType();
1159 const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty);
1160 clang::QualType child_qt = incomplete_array_ty->getElementType();
11261161 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
11271162 if (child_type_node == nullptr) {
11281163 emit_warning(c, source_loc, "unresolved array element type");
11291164 return nullptr;
11301165 }
11311166 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);
11331168 return pointer_node;
11341169 }
1135 case Type::BlockPointer:
1136 case Type::LValueReference:
1137 case Type::RValueReference:
1138 case Type::MemberPointer:
1139 case Type::VariableArray:
1140 case Type::DependentSizedArray:
1141 case Type::DependentSizedExtVector:
1142 case Type::Vector:
1143 case Type::ExtVector:
1144 case Type::FunctionNoProto:
1145 case Type::UnresolvedUsing:
1146 case Type::Adjusted:
1147 case Type::TypeOfExpr:
1148 case Type::TypeOf:
1149 case Type::Decltype:
1150 case Type::UnaryTransform:
1151 case Type::TemplateTypeParm:
1152 case Type::SubstTemplateTypeParm:
1153 case Type::SubstTemplateTypeParmPack:
1154 case Type::TemplateSpecialization:
1155 case Type::Auto:
1156 case Type::InjectedClassName:
1157 case Type::DependentName:
1158 case Type::DependentTemplateSpecialization:
1159 case Type::PackExpansion:
1160 case Type::ObjCObject:
1161 case Type::ObjCInterface:
1162 case Type::Complex:
1163 case Type::ObjCObjectPointer:
1164 case Type::Atomic:
1165 case Type::Pipe:
1166 case Type::ObjCTypeParam:
1167 case Type::DeducedTemplateSpecialization:
1168 case Type::DependentAddressSpace:
1169 case Type::DependentVector:
1170 case clang::Type::BlockPointer:
1171 case clang::Type::LValueReference:
1172 case clang::Type::RValueReference:
1173 case clang::Type::MemberPointer:
1174 case clang::Type::VariableArray:
1175 case clang::Type::DependentSizedArray:
1176 case clang::Type::DependentSizedExtVector:
1177 case clang::Type::Vector:
1178 case clang::Type::ExtVector:
1179 case clang::Type::UnresolvedUsing:
1180 case clang::Type::Adjusted:
1181 case clang::Type::TypeOfExpr:
1182 case clang::Type::TypeOf:
1183 case clang::Type::Decltype:
1184 case clang::Type::UnaryTransform:
1185 case clang::Type::TemplateTypeParm:
1186 case clang::Type::SubstTemplateTypeParm:
1187 case clang::Type::SubstTemplateTypeParmPack:
1188 case clang::Type::TemplateSpecialization:
1189 case clang::Type::Auto:
1190 case clang::Type::InjectedClassName:
1191 case clang::Type::DependentName:
1192 case clang::Type::DependentTemplateSpecialization:
1193 case clang::Type::PackExpansion:
1194 case clang::Type::ObjCObject:
1195 case clang::Type::ObjCInterface:
1196 case clang::Type::Complex:
1197 case clang::Type::ObjCObjectPointer:
1198 case clang::Type::Atomic:
1199 case clang::Type::Pipe:
1200 case clang::Type::ObjCTypeParam:
1201 case clang::Type::DeducedTemplateSpecialization:
1202 case clang::Type::DependentAddressSpace:
1203 case clang::Type::DependentVector:
11701204 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
11711205 return nullptr;
11721206 }
11731207 zig_unreachable();
11741208}
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) {
11771211 return trans_type(c, qt.getTypePtr(), source_loc);
11781212}
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,
11811215 AstNode *block_node, TransScope **out_node_scope)
11821216{
11831217 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) {
11851219 AstNode *child_node;
11861220 scope = trans_stmt(c, scope, *it, &child_node);
11871221 if (scope == nullptr)
......@@ -1195,7 +1229,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo
11951229 return ErrorNone;
11961230}
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,
11991233 TransScope **out_node_scope)
12001234{
12011235 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
12041238 return child_scope_block->node;
12051239}
12061240
1207static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) {
1208 const Expr *value_expr = stmt->getRetValue();
1241static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
1242 const clang::Expr *value_expr = stmt->getRetValue();
12091243 if (value_expr == nullptr) {
12101244 return trans_create_node(c, NodeTypeReturnExpr);
12111245 } else {
......@@ -1217,18 +1251,18 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm
12171251 }
12181252}
12191253
1220static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
1254static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
12211255 Expr::EvalResult result;
1222 if (!stmt->EvaluateAsInt(result, *c->ctx)) {
1256 if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
12231257 emit_warning(c, stmt->getBeginLoc(), "invalid integer literal");
12241258 return nullptr;
12251259 }
12261260 return trans_create_node_apint(c, result.Val.getInt());
12271261}
12281262
1229static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {
1263static AstNode *trans_constant_expr(Context *c, const clang::ConstantExpr *expr) {
12301264 Expr::EvalResult result;
1231 if (!expr->EvaluateAsConstantExpr(result, Expr::EvaluateForCodeGen, *c->ctx)) {
1265 if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, *c->ctx)) {
12321266 emit_warning(c, expr->getBeginLoc(), "invalid constant expression");
12331267 return nullptr;
12341268 }
......@@ -1236,13 +1270,13 @@ static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {
12361270}
12371271
12381272static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
1239 const ConditionalOperator *stmt)
1273 const clang::ConditionalOperator *stmt)
12401274{
12411275 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
12421276
1243 Expr *cond_expr = stmt->getCond();
1244 Expr *true_expr = stmt->getTrueExpr();
1245 Expr *false_expr = stmt->getFalseExpr();
1277 clang::Expr *cond_expr = stmt->getCond();
1278 clang::Expr *true_expr = stmt->getTrueExpr();
1279 clang::Expr *false_expr = stmt->getFalseExpr();
12461280
12471281 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
12481282 if (node->data.if_bool_expr.condition == nullptr)
......@@ -1259,7 +1293,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
12591293 return maybe_suppress_result(c, result_used, node);
12601294}
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) {
12631297 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
12641298 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
12741308 return node;
12751309}
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) {
12781312 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
12791313 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
12801314 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
12901324 return node;
12911325}
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) {
12941328 if (result_used == ResultUsedNo) {
12951329 // common case
12961330 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
......@@ -1341,10 +1375,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
13411375 }
13421376}
13431377
1344static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type,
1345 Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr)
1378static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
1379 clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)
13461380{
1347 const SourceLocation &rhs_location = rhs_expr->getBeginLoc();
1381 const clang::SourceLocation &rhs_location = rhs_expr->getBeginLoc();
13481382 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
13491383 // lhs >> u5(rh)
13501384
......@@ -1358,22 +1392,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re
13581392 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
13591393}
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) {
13621396 switch (stmt->getOpcode()) {
1363 case BO_PtrMemD:
1397 case clang::BO_PtrMemD:
13641398 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD");
13651399 return nullptr;
1366 case BO_PtrMemI:
1400 case clang::BO_PtrMemI:
13671401 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI");
13681402 return nullptr;
1369 case BO_Cmp:
1403 case clang::BO_Cmp:
13701404 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp");
13711405 return nullptr;
1372 case BO_Mul:
1406 case clang::BO_Mul:
13731407 return trans_create_bin_op(c, scope, stmt->getLHS(),
13741408 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
13751409 stmt->getRHS());
1376 case BO_Div:
1410 case clang::BO_Div:
13771411 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
13781412 // unsigned/float division uses the operator
13791413 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
13881422 fn_call->data.fn_call_expr.params.append(rhs);
13891423 return fn_call;
13901424 }
1391 case BO_Rem:
1425 case clang::BO_Rem:
13921426 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
13931427 // unsigned/float division uses the operator
13941428 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
14031437 fn_call->data.fn_call_expr.params.append(rhs);
14041438 return fn_call;
14051439 }
1406 case BO_Add:
1440 case clang::BO_Add:
14071441 return trans_create_bin_op(c, scope, stmt->getLHS(),
14081442 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
14091443 stmt->getRHS());
1410 case BO_Sub:
1444 case clang::BO_Sub:
14111445 return trans_create_bin_op(c, scope, stmt->getLHS(),
14121446 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
14131447 stmt->getRHS());
1414 case BO_Shl:
1448 case clang::BO_Shl:
14151449 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
1416 case BO_Shr:
1450 case clang::BO_Shr:
14171451 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
1418 case BO_LT:
1452 case clang::BO_LT:
14191453 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
1420 case BO_GT:
1454 case clang::BO_GT:
14211455 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
1422 case BO_LE:
1456 case clang::BO_LE:
14231457 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
1424 case BO_GE:
1458 case clang::BO_GE:
14251459 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
1426 case BO_EQ:
1460 case clang::BO_EQ:
14271461 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
1428 case BO_NE:
1462 case clang::BO_NE:
14291463 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
1430 case BO_And:
1464 case clang::BO_And:
14311465 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
1432 case BO_Xor:
1466 case clang::BO_Xor:
14331467 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
1434 case BO_Or:
1468 case clang::BO_Or:
14351469 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1436 case BO_LAnd:
1470 case clang::BO_LAnd:
14371471 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1438 case BO_LOr:
1472 case clang::BO_LOr:
14391473 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1440 case BO_Assign:
1474 case clang::BO_Assign:
14411475 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
1442 case BO_Comma:
1476 case clang::BO_Comma:
14431477 {
14441478 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
14451479 Buf *label_name = buf_create_from_str("x");
......@@ -1456,16 +1490,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
14561490 scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
14571491 return scope_block->node;
14581492 }
1459 case BO_MulAssign:
1460 case BO_DivAssign:
1461 case BO_RemAssign:
1462 case BO_AddAssign:
1463 case BO_SubAssign:
1464 case BO_ShlAssign:
1465 case BO_ShrAssign:
1466 case BO_AndAssign:
1467 case BO_XorAssign:
1468 case BO_OrAssign:
1493 case clang::BO_MulAssign:
1494 case clang::BO_DivAssign:
1495 case clang::BO_RemAssign:
1496 case clang::BO_AddAssign:
1497 case clang::BO_SubAssign:
1498 case clang::BO_ShlAssign:
1499 case clang::BO_ShrAssign:
1500 case clang::BO_AndAssign:
1501 case clang::BO_XorAssign:
1502 case clang::BO_OrAssign:
14691503 zig_unreachable();
14701504 }
14711505
......@@ -1473,9 +1507,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
14731507}
14741508
14751509static 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)
14771511{
1478 const SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc();
1512 const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc();
14791513 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
14801514
14811515 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
15551589}
15561590
15571591static 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)
15591593{
15601594 if (result_used == ResultUsedNo) {
15611595 // 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,
16151649
16161650
16171651static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
1618 const CompoundAssignOperator *stmt)
1652 const clang::CompoundAssignOperator *stmt)
16191653{
16201654 switch (stmt->getOpcode()) {
1621 case BO_MulAssign:
1655 case clang::BO_MulAssign:
16221656 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
16231657 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
16241658 else
16251659 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1626 case BO_DivAssign:
1660 case clang::BO_DivAssign:
16271661 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign");
16281662 return nullptr;
1629 case BO_RemAssign:
1663 case clang::BO_RemAssign:
16301664 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign");
16311665 return nullptr;
1632 case BO_Cmp:
1666 case clang::BO_Cmp:
16331667 emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp");
16341668 return nullptr;
1635 case BO_AddAssign:
1669 case clang::BO_AddAssign:
16361670 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
16371671 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
16381672 else
16391673 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1640 case BO_SubAssign:
1674 case clang::BO_SubAssign:
16411675 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
16421676 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
16431677 else
16441678 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1645 case BO_ShlAssign:
1679 case clang::BO_ShlAssign:
16461680 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1647 case BO_ShrAssign:
1681 case clang::BO_ShrAssign:
16481682 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1649 case BO_AndAssign:
1683 case clang::BO_AndAssign:
16501684 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1651 case BO_XorAssign:
1685 case clang::BO_XorAssign:
16521686 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1653 case BO_OrAssign:
1687 case clang::BO_OrAssign:
16541688 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1655 case BO_PtrMemD:
1656 case BO_PtrMemI:
1657 case BO_Assign:
1658 case BO_Mul:
1659 case BO_Div:
1660 case BO_Rem:
1661 case BO_Add:
1662 case BO_Sub:
1663 case BO_Shl:
1664 case BO_Shr:
1665 case BO_LT:
1666 case BO_GT:
1667 case BO_LE:
1668 case BO_GE:
1669 case BO_EQ:
1670 case BO_NE:
1671 case BO_And:
1672 case BO_Xor:
1673 case BO_Or:
1674 case BO_LAnd:
1675 case BO_LOr:
1676 case BO_Comma:
1689 case clang::BO_PtrMemD:
1690 case clang::BO_PtrMemI:
1691 case clang::BO_Assign:
1692 case clang::BO_Mul:
1693 case clang::BO_Div:
1694 case clang::BO_Rem:
1695 case clang::BO_Add:
1696 case clang::BO_Sub:
1697 case clang::BO_Shl:
1698 case clang::BO_Shr:
1699 case clang::BO_LT:
1700 case clang::BO_GT:
1701 case clang::BO_LE:
1702 case clang::BO_GE:
1703 case clang::BO_EQ:
1704 case clang::BO_NE:
1705 case clang::BO_And:
1706 case clang::BO_Xor:
1707 case clang::BO_Or:
1708 case clang::BO_LAnd:
1709 case clang::BO_LOr:
1710 case clang::BO_Comma:
16771711 zig_unreachable();
16781712 }
16791713
16801714 zig_unreachable();
16811715}
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) {
16841718 switch (stmt->getCastKind()) {
1685 case CK_LValueToRValue:
1719 case clang::CK_LValueToRValue:
16861720 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1687 case CK_IntegralCast:
1721 case clang::CK_IntegralCast:
16881722 {
16891723 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
16901724 if (target_node == nullptr)
......@@ -1692,15 +1726,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
16921726 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
16931727 stmt->getSubExpr()->getType(), target_node);
16941728 }
1695 case CK_FunctionToPointerDecay:
1696 case CK_ArrayToPointerDecay:
1729 case clang::CK_FunctionToPointerDecay:
1730 case clang::CK_ArrayToPointerDecay:
16971731 {
16981732 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
16991733 if (target_node == nullptr)
17001734 return nullptr;
17011735 return target_node;
17021736 }
1703 case CK_BitCast:
1737 case clang::CK_BitCast:
17041738 {
17051739 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
17061740 if (target_node == nullptr)
......@@ -1717,172 +1751,55 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
17171751 node->data.fn_call_expr.params.append(target_node);
17181752 return node;
17191753 }
1720 case CK_NullToPointer:
1721 return trans_create_node(c, NodeTypeNullLiteral);
1722 case CK_Dependent:
1754 case clang::CK_NullToPointer:
1755 return trans_create_node_unsigned(c, 0);
1756 case clang::CK_NoOp:
1757 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1758 case clang::CK_Dependent:
17231759 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent");
17241760 return nullptr;
1725 case CK_LValueBitCast:
1761 case clang::CK_LValueBitCast:
17261762 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast");
17271763 return nullptr;
1728 case CK_NoOp:
1729 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1730 case CK_BaseToDerived:
1764 case clang::CK_BaseToDerived:
17311765 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived");
17321766 return nullptr;
1733 case CK_DerivedToBase:
1767 case clang::CK_DerivedToBase:
17341768 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase");
17351769 return nullptr;
1736 case CK_UncheckedDerivedToBase:
1770 case clang::CK_UncheckedDerivedToBase:
17371771 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
17381772 return nullptr;
1739 case CK_Dynamic:
1773 case clang::CK_Dynamic:
17401774 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic");
17411775 return nullptr;
1742 case CK_ToUnion:
1776 case clang::CK_ToUnion:
17431777 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion");
17441778 return nullptr;
1745 case CK_NullToMemberPointer:
1779 case clang::CK_NullToMemberPointer:
17461780 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer");
17471781 return nullptr;
1748 case CK_BaseToDerivedMemberPointer:
1782 case clang::CK_BaseToDerivedMemberPointer:
17491783 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
17501784 return nullptr;
1751 case CK_DerivedToBaseMemberPointer:
1785 case clang::CK_DerivedToBaseMemberPointer:
17521786 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
17531787 return nullptr;
1754 case CK_MemberPointerToBoolean:
1788 case clang::CK_MemberPointerToBoolean:
17551789 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean");
17561790 return nullptr;
1757 case CK_ReinterpretMemberPointer:
1791 case clang::CK_ReinterpretMemberPointer:
17581792 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
17591793 return nullptr;
1760 case CK_UserDefinedConversion:
1794 case clang::CK_UserDefinedConversion:
17611795 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion");
17621796 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;
18801797 }
18811798 zig_unreachable();
18821799}
18831800
1884static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) {
1885 const ValueDecl *value_decl = stmt->getDecl();
1801static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
1802 const clang::ValueDecl *value_decl = stmt->getDecl();
18861803 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
18871804 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
18881805 if (lrval == TransLValue) {
......@@ -1892,9 +1809,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef
18921809}
18931810
18941811static 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)
18961813{
1897 Expr *op_expr = stmt->getSubExpr();
1814 clang::Expr *op_expr = stmt->getSubExpr();
18981815
18991816 if (result_used == ResultUsedNo) {
19001817 // common case
......@@ -1948,9 +1865,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
19481865}
19491866
19501867static 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)
19521869{
1953 Expr *op_expr = stmt->getSubExpr();
1870 clang::Expr *op_expr = stmt->getSubExpr();
19541871
19551872 if (result_used == ResultUsedNo) {
19561873 // common case
......@@ -1997,36 +1914,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
19971914 return child_scope->node;
19981915}
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) {
20011918 switch (stmt->getOpcode()) {
2002 case UO_PostInc:
1919 case clang::UO_PostInc:
20031920 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
20041921 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
20051922 else
20061923 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2007 case UO_PostDec:
1924 case clang::UO_PostDec:
20081925 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
20091926 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
20101927 else
20111928 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2012 case UO_PreInc:
1929 case clang::UO_PreInc:
20131930 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
20141931 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
20151932 else
20161933 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2017 case UO_PreDec:
1934 case clang::UO_PreDec:
20181935 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
20191936 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
20201937 else
20211938 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2022 case UO_AddrOf:
1939 case clang::UO_AddrOf:
20231940 {
20241941 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
20251942 if (value_node == nullptr)
20261943 return value_node;
20271944 return trans_create_node_addr_of(c, value_node);
20281945 }
2029 case UO_Deref:
1946 case clang::UO_Deref:
20301947 {
20311948 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
20321949 if (value_node == nullptr)
......@@ -2037,12 +1954,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
20371954 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
20381955 return trans_create_node_ptr_deref(c, unwrapped);
20391956 }
2040 case UO_Plus:
1957 case clang::UO_Plus:
20411958 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus");
20421959 return nullptr;
2043 case UO_Minus:
1960 case clang::UO_Minus:
20441961 {
2045 Expr *op_expr = stmt->getSubExpr();
1962 clang::Expr *op_expr = stmt->getSubExpr();
20461963 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
20471964 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
20481965 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
......@@ -2068,41 +1985,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
20681985 return nullptr;
20691986 }
20701987 }
2071 case UO_Not:
1988 case clang::UO_Not:
20721989 {
2073 Expr *op_expr = stmt->getSubExpr();
1990 clang::Expr *op_expr = stmt->getSubExpr();
20741991 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
20751992 if (sub_node == nullptr)
20761993 return nullptr;
20771994
20781995 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
20791996 }
2080 case UO_LNot:
1997 case clang::UO_LNot:
20811998 {
2082 Expr *op_expr = stmt->getSubExpr();
1999 clang::Expr *op_expr = stmt->getSubExpr();
20832000 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
20842001 if (sub_node == nullptr)
20852002 return nullptr;
20862003
20872004 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
20882005 }
2089 case UO_Real:
2006 case clang::UO_Real:
20902007 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real");
20912008 return nullptr;
2092 case UO_Imag:
2009 case clang::UO_Imag:
20932010 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag");
20942011 return nullptr;
2095 case UO_Extension:
2012 case clang::UO_Extension:
20962013 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Extension");
20972014 return nullptr;
2098 case UO_Coawait:
2015 case clang::UO_Coawait:
20992016 emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait");
21002017 return nullptr;
21012018 }
21022019 zig_unreachable();
21032020}
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,
21062023 AstNode **out_node, TransScope **out_scope)
21072024{
21082025 // declarations are added via the scope
......@@ -2112,11 +2029,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
21122029 assert(scope_block != nullptr);
21132030
21142031 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
2115 Decl *decl = *iter;
2032 clang::Decl *decl = *iter;
21162033 switch (decl->getKind()) {
2117 case Decl::Var: {
2118 VarDecl *var_decl = (VarDecl *)decl;
2119 QualType qual_type = var_decl->getTypeSourceInfo()->getType();
2034 case clang::Decl::Var: {
2035 clang::VarDecl *var_decl = (clang::VarDecl *)decl;
2036 clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
21202037 AstNode *init_node = nullptr;
21212038 if (var_decl->hasInit()) {
21222039 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
21412058 scope_block->node->data.block.statements.append(node);
21422059 continue;
21432060 }
2144 case Decl::AccessSpec:
2061 case clang::Decl::AccessSpec:
21452062 emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec");
21462063 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;
23632064 }
23642065 zig_unreachable();
23652066 }
......@@ -2384,7 +2085,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
23842085 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
23852086}
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) {
23882089 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
23892090 if (res == nullptr)
23902091 return nullptr;
......@@ -2421,143 +2122,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
24212122 }
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();
24252126 auto classs = ty->getTypeClass();
24262127 switch (classs) {
2427 case Type::Builtin:
2128 case clang::Type::Builtin:
24282129 {
2429 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
2130 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
24302131 switch (builtin_ty->getKind()) {
2431 case BuiltinType::Bool:
2432 case BuiltinType::Char_U:
2433 case BuiltinType::UChar:
2434 case BuiltinType::Char_S:
2435 case BuiltinType::SChar:
2436 case BuiltinType::UShort:
2437 case BuiltinType::UInt:
2438 case BuiltinType::ULong:
2439 case BuiltinType::ULongLong:
2440 case BuiltinType::Short:
2441 case BuiltinType::Int:
2442 case BuiltinType::Long:
2443 case BuiltinType::LongLong:
2444 case BuiltinType::UInt128:
2445 case BuiltinType::Int128:
2446 case BuiltinType::Float:
2447 case BuiltinType::Double:
2448 case BuiltinType::Float128:
2449 case BuiltinType::LongDouble:
2450 case BuiltinType::WChar_U:
2451 case BuiltinType::Char8:
2452 case BuiltinType::Char16:
2453 case BuiltinType::Char32:
2454 case BuiltinType::WChar_S:
2455 case BuiltinType::Float16:
2132 case clang::BuiltinType::Bool:
2133 case clang::BuiltinType::Char_U:
2134 case clang::BuiltinType::UChar:
2135 case clang::BuiltinType::Char_S:
2136 case clang::BuiltinType::SChar:
2137 case clang::BuiltinType::UShort:
2138 case clang::BuiltinType::UInt:
2139 case clang::BuiltinType::ULong:
2140 case clang::BuiltinType::ULongLong:
2141 case clang::BuiltinType::Short:
2142 case clang::BuiltinType::Int:
2143 case clang::BuiltinType::Long:
2144 case clang::BuiltinType::LongLong:
2145 case clang::BuiltinType::UInt128:
2146 case clang::BuiltinType::Int128:
2147 case clang::BuiltinType::Float:
2148 case clang::BuiltinType::Double:
2149 case clang::BuiltinType::Float128:
2150 case clang::BuiltinType::LongDouble:
2151 case clang::BuiltinType::WChar_U:
2152 case clang::BuiltinType::Char8:
2153 case clang::BuiltinType::Char16:
2154 case clang::BuiltinType::Char32:
2155 case clang::BuiltinType::WChar_S:
2156 case clang::BuiltinType::Float16:
24562157 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2457 case BuiltinType::NullPtr:
2458 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2459
2460 case BuiltinType::Void:
2461 case BuiltinType::Half:
2462 case BuiltinType::ObjCId:
2463 case BuiltinType::ObjCClass:
2464 case BuiltinType::ObjCSel:
2465 case BuiltinType::OMPArraySection:
2466 case BuiltinType::Dependent:
2467 case BuiltinType::Overload:
2468 case BuiltinType::BoundMember:
2469 case BuiltinType::PseudoObject:
2470 case BuiltinType::UnknownAny:
2471 case BuiltinType::BuiltinFn:
2472 case BuiltinType::ARCUnbridgedCast:
2473 case BuiltinType::OCLImage1dRO:
2474 case BuiltinType::OCLImage1dArrayRO:
2475 case BuiltinType::OCLImage1dBufferRO:
2476 case BuiltinType::OCLImage2dRO:
2477 case BuiltinType::OCLImage2dArrayRO:
2478 case BuiltinType::OCLImage2dDepthRO:
2479 case BuiltinType::OCLImage2dArrayDepthRO:
2480 case BuiltinType::OCLImage2dMSAARO:
2481 case BuiltinType::OCLImage2dArrayMSAARO:
2482 case BuiltinType::OCLImage2dMSAADepthRO:
2483 case BuiltinType::OCLImage2dArrayMSAADepthRO:
2484 case BuiltinType::OCLImage3dRO:
2485 case BuiltinType::OCLImage1dWO:
2486 case BuiltinType::OCLImage1dArrayWO:
2487 case BuiltinType::OCLImage1dBufferWO:
2488 case BuiltinType::OCLImage2dWO:
2489 case BuiltinType::OCLImage2dArrayWO:
2490 case BuiltinType::OCLImage2dDepthWO:
2491 case BuiltinType::OCLImage2dArrayDepthWO:
2492 case BuiltinType::OCLImage2dMSAAWO:
2493 case BuiltinType::OCLImage2dArrayMSAAWO:
2494 case BuiltinType::OCLImage2dMSAADepthWO:
2495 case BuiltinType::OCLImage2dArrayMSAADepthWO:
2496 case BuiltinType::OCLImage3dWO:
2497 case BuiltinType::OCLImage1dRW:
2498 case BuiltinType::OCLImage1dArrayRW:
2499 case BuiltinType::OCLImage1dBufferRW:
2500 case BuiltinType::OCLImage2dRW:
2501 case BuiltinType::OCLImage2dArrayRW:
2502 case BuiltinType::OCLImage2dDepthRW:
2503 case BuiltinType::OCLImage2dArrayDepthRW:
2504 case BuiltinType::OCLImage2dMSAARW:
2505 case BuiltinType::OCLImage2dArrayMSAARW:
2506 case BuiltinType::OCLImage2dMSAADepthRW:
2507 case BuiltinType::OCLImage2dArrayMSAADepthRW:
2508 case BuiltinType::OCLImage3dRW:
2509 case BuiltinType::OCLSampler:
2510 case BuiltinType::OCLEvent:
2511 case BuiltinType::OCLClkEvent:
2512 case BuiltinType::OCLQueue:
2513 case BuiltinType::OCLReserveID:
2514 case BuiltinType::ShortAccum:
2515 case BuiltinType::Accum:
2516 case BuiltinType::LongAccum:
2517 case BuiltinType::UShortAccum:
2518 case BuiltinType::UAccum:
2519 case BuiltinType::ULongAccum:
2520 case BuiltinType::ShortFract:
2521 case BuiltinType::Fract:
2522 case BuiltinType::LongFract:
2523 case BuiltinType::UShortFract:
2524 case BuiltinType::UFract:
2525 case BuiltinType::ULongFract:
2526 case BuiltinType::SatShortAccum:
2527 case BuiltinType::SatAccum:
2528 case BuiltinType::SatLongAccum:
2529 case BuiltinType::SatUShortAccum:
2530 case BuiltinType::SatUAccum:
2531 case BuiltinType::SatULongAccum:
2532 case BuiltinType::SatShortFract:
2533 case BuiltinType::SatFract:
2534 case BuiltinType::SatLongFract:
2535 case BuiltinType::SatUShortFract:
2536 case BuiltinType::SatUFract:
2537 case BuiltinType::SatULongFract:
2538 case BuiltinType::OCLIntelSubgroupAVCMcePayload:
2539 case BuiltinType::OCLIntelSubgroupAVCImePayload:
2540 case BuiltinType::OCLIntelSubgroupAVCRefPayload:
2541 case BuiltinType::OCLIntelSubgroupAVCSicPayload:
2542 case BuiltinType::OCLIntelSubgroupAVCMceResult:
2543 case BuiltinType::OCLIntelSubgroupAVCImeResult:
2544 case BuiltinType::OCLIntelSubgroupAVCRefResult:
2545 case BuiltinType::OCLIntelSubgroupAVCSicResult:
2546 case BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
2547 case BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
2548 case BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
2549 case BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
2158 case clang::BuiltinType::NullPtr:
2159 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2160 trans_create_node_unsigned(c, 0));
2161
2162 case clang::BuiltinType::Void:
2163 case clang::BuiltinType::Half:
2164 case clang::BuiltinType::ObjCId:
2165 case clang::BuiltinType::ObjCClass:
2166 case clang::BuiltinType::ObjCSel:
2167 case clang::BuiltinType::OMPArraySection:
2168 case clang::BuiltinType::Dependent:
2169 case clang::BuiltinType::Overload:
2170 case clang::BuiltinType::BoundMember:
2171 case clang::BuiltinType::PseudoObject:
2172 case clang::BuiltinType::UnknownAny:
2173 case clang::BuiltinType::BuiltinFn:
2174 case clang::BuiltinType::ARCUnbridgedCast:
2175 case clang::BuiltinType::OCLImage1dRO:
2176 case clang::BuiltinType::OCLImage1dArrayRO:
2177 case clang::BuiltinType::OCLImage1dBufferRO:
2178 case clang::BuiltinType::OCLImage2dRO:
2179 case clang::BuiltinType::OCLImage2dArrayRO:
2180 case clang::BuiltinType::OCLImage2dDepthRO:
2181 case clang::BuiltinType::OCLImage2dArrayDepthRO:
2182 case clang::BuiltinType::OCLImage2dMSAARO:
2183 case clang::BuiltinType::OCLImage2dArrayMSAARO:
2184 case clang::BuiltinType::OCLImage2dMSAADepthRO:
2185 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
2186 case clang::BuiltinType::OCLImage3dRO:
2187 case clang::BuiltinType::OCLImage1dWO:
2188 case clang::BuiltinType::OCLImage1dArrayWO:
2189 case clang::BuiltinType::OCLImage1dBufferWO:
2190 case clang::BuiltinType::OCLImage2dWO:
2191 case clang::BuiltinType::OCLImage2dArrayWO:
2192 case clang::BuiltinType::OCLImage2dDepthWO:
2193 case clang::BuiltinType::OCLImage2dArrayDepthWO:
2194 case clang::BuiltinType::OCLImage2dMSAAWO:
2195 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
2196 case clang::BuiltinType::OCLImage2dMSAADepthWO:
2197 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
2198 case clang::BuiltinType::OCLImage3dWO:
2199 case clang::BuiltinType::OCLImage1dRW:
2200 case clang::BuiltinType::OCLImage1dArrayRW:
2201 case clang::BuiltinType::OCLImage1dBufferRW:
2202 case clang::BuiltinType::OCLImage2dRW:
2203 case clang::BuiltinType::OCLImage2dArrayRW:
2204 case clang::BuiltinType::OCLImage2dDepthRW:
2205 case clang::BuiltinType::OCLImage2dArrayDepthRW:
2206 case clang::BuiltinType::OCLImage2dMSAARW:
2207 case clang::BuiltinType::OCLImage2dArrayMSAARW:
2208 case clang::BuiltinType::OCLImage2dMSAADepthRW:
2209 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
2210 case clang::BuiltinType::OCLImage3dRW:
2211 case clang::BuiltinType::OCLSampler:
2212 case clang::BuiltinType::OCLEvent:
2213 case clang::BuiltinType::OCLClkEvent:
2214 case clang::BuiltinType::OCLQueue:
2215 case clang::BuiltinType::OCLReserveID:
2216 case clang::BuiltinType::ShortAccum:
2217 case clang::BuiltinType::Accum:
2218 case clang::BuiltinType::LongAccum:
2219 case clang::BuiltinType::UShortAccum:
2220 case clang::BuiltinType::UAccum:
2221 case clang::BuiltinType::ULongAccum:
2222 case clang::BuiltinType::ShortFract:
2223 case clang::BuiltinType::Fract:
2224 case clang::BuiltinType::LongFract:
2225 case clang::BuiltinType::UShortFract:
2226 case clang::BuiltinType::UFract:
2227 case clang::BuiltinType::ULongFract:
2228 case clang::BuiltinType::SatShortAccum:
2229 case clang::BuiltinType::SatAccum:
2230 case clang::BuiltinType::SatLongAccum:
2231 case clang::BuiltinType::SatUShortAccum:
2232 case clang::BuiltinType::SatUAccum:
2233 case clang::BuiltinType::SatULongAccum:
2234 case clang::BuiltinType::SatShortFract:
2235 case clang::BuiltinType::SatFract:
2236 case clang::BuiltinType::SatLongFract:
2237 case clang::BuiltinType::SatUShortFract:
2238 case clang::BuiltinType::SatUFract:
2239 case clang::BuiltinType::SatULongFract:
2240 case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
2241 case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
2242 case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
2243 case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
2244 case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
2245 case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
2246 case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
2247 case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
2248 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
2249 case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
2250 case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
2251 case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
25502252 return res;
25512253 }
25522254 break;
25532255 }
2554 case Type::Pointer:
2555 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2256 case clang::Type::Pointer:
2257 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2258 trans_create_node_unsigned(c, 0));
25562259
2557 case Type::Typedef:
2260 case clang::Type::Typedef:
25582261 {
2559 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
2560 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
2262 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
2263 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
25612264 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
25622265 if (existing_entry) {
25632266 return existing_entry->value;
......@@ -2566,79 +2269,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
25662269 return res;
25672270 }
25682271
2569 case Type::Enum:
2272 case clang::Type::Enum:
25702273 {
2571 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
2274 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
25722275 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
25732276 return to_enum_zero_cmp(c, res, enum_type);
25742277 }
25752278
2576 case Type::Elaborated:
2279 case clang::Type::Elaborated:
25772280 {
2578 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
2281 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
25792282 switch (elaborated_ty->getKeyword()) {
2580 case ETK_Enum: {
2581 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc());
2283 case clang::ETK_Enum: {
2284 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginloc());
25822285 return to_enum_zero_cmp(c, res, enum_type);
25832286 }
2584 case ETK_Struct:
2585 case ETK_Union:
2586 case ETK_Interface:
2587 case ETK_Class:
2588 case ETK_Typename:
2589 case ETK_None:
2287 case clang::ETK_Struct:
2288 case clang::ETK_Union:
2289 case clang::ETK_Interface:
2290 case clang::ETK_Class:
2291 case clang::ETK_Typename:
2292 case clang::ETK_None:
25902293 return res;
25912294 }
25922295 }
25932296
2594 case Type::FunctionProto:
2595 case Type::Record:
2596 case Type::ConstantArray:
2597 case Type::Paren:
2598 case Type::Decayed:
2599 case Type::Attributed:
2600 case Type::IncompleteArray:
2601 case Type::BlockPointer:
2602 case Type::LValueReference:
2603 case Type::RValueReference:
2604 case Type::MemberPointer:
2605 case Type::VariableArray:
2606 case Type::DependentSizedArray:
2607 case Type::DependentSizedExtVector:
2608 case Type::Vector:
2609 case Type::ExtVector:
2610 case Type::FunctionNoProto:
2611 case Type::UnresolvedUsing:
2612 case Type::Adjusted:
2613 case Type::TypeOfExpr:
2614 case Type::TypeOf:
2615 case Type::Decltype:
2616 case Type::UnaryTransform:
2617 case Type::TemplateTypeParm:
2618 case Type::SubstTemplateTypeParm:
2619 case Type::SubstTemplateTypeParmPack:
2620 case Type::TemplateSpecialization:
2621 case Type::Auto:
2622 case Type::InjectedClassName:
2623 case Type::DependentName:
2624 case Type::DependentTemplateSpecialization:
2625 case Type::PackExpansion:
2626 case Type::ObjCObject:
2627 case Type::ObjCInterface:
2628 case Type::Complex:
2629 case Type::ObjCObjectPointer:
2630 case Type::Atomic:
2631 case Type::Pipe:
2632 case Type::ObjCTypeParam:
2633 case Type::DeducedTemplateSpecialization:
2634 case Type::DependentAddressSpace:
2635 case Type::DependentVector:
2297 case clang::Type::FunctionProto:
2298 case clang::Type::Record:
2299 case clang::Type::ConstantArray:
2300 case clang::Type::Paren:
2301 case clang::Type::Decayed:
2302 case clang::Type::Attributed:
2303 case clang::Type::IncompleteArray:
2304 case clang::Type::BlockPointer:
2305 case clang::Type::LValueReference:
2306 case clang::Type::RValueReference:
2307 case clang::Type::MemberPointer:
2308 case clang::Type::VariableArray:
2309 case clang::Type::DependentSizedArray:
2310 case clang::Type::DependentSizedExtVector:
2311 case clang::Type::Vector:
2312 case clang::Type::ExtVector:
2313 case clang::Type::FunctionNoProto:
2314 case clang::Type::UnresolvedUsing:
2315 case clang::Type::Adjusted:
2316 case clang::Type::TypeOfExpr:
2317 case clang::Type::TypeOf:
2318 case clang::Type::Decltype:
2319 case clang::Type::UnaryTransform:
2320 case clang::Type::TemplateTypeParm:
2321 case clang::Type::SubstTemplateTypeParm:
2322 case clang::Type::SubstTemplateTypeParmPack:
2323 case clang::Type::TemplateSpecialization:
2324 case clang::Type::Auto:
2325 case clang::Type::InjectedClassName:
2326 case clang::Type::DependentName:
2327 case clang::Type::DependentTemplateSpecialization:
2328 case clang::Type::PackExpansion:
2329 case clang::Type::ObjCObject:
2330 case clang::Type::ObjCInterface:
2331 case clang::Type::Complex:
2332 case clang::Type::ObjCObjectPointer:
2333 case clang::Type::Atomic:
2334 case clang::Type::Pipe:
2335 case clang::Type::ObjCTypeParam:
2336 case clang::Type::DeducedTemplateSpecialization:
2337 case clang::Type::DependentAddressSpace:
2338 case clang::Type::DependentVector:
26362339 return res;
26372340 }
26382341 zig_unreachable();
26392342}
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) {
26422345 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
26432346
26442347 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
26532356 return while_scope->node;
26542357}
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) {
26572360 // if (c) t
26582361 // if (c) t else e
26592362 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
......@@ -2675,7 +2378,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
26752378 return if_node;
26762379}
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) {
26792382 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
26802383
26812384 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 *
26832386 return nullptr;
26842387
26852388 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);
26872390 AstNode *callee_node = nullptr;
26882391 if (is_ptr && fn_ty) {
2689 if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {
2690 const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee());
2691 if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {
2692 if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) {
2693 const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr());
2694 const Decl *decl = decl_ref->getFoundDecl();
2695 if (decl->getKind() == Decl::Function) {
2392 if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
2393 const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());
2394 if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
2395 if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
2396 const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());
2397 const clang::Decl *decl = decl_ref->getFoundDecl();
2398 if (decl->getKind() == clang::Decl::Function) {
26962399 callee_node = callee_raw_node;
26972400 }
26982401 }
......@@ -2708,7 +2411,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
27082411 node->data.fn_call_expr.fn_ref_expr = callee_node;
27092412
27102413 unsigned num_args = stmt->getNumArgs();
2711 const Expr * const* args = stmt->getArgs();
2414 const clang::Expr * const* args = stmt->getArgs();
27122415 for (unsigned i = 0; i < num_args; i += 1) {
27132416 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
27142417 if (arg_node == nullptr)
......@@ -2724,7 +2427,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
27242427 return node;
27252428}
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) {
27282431 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
27292432 if (container_node == nullptr)
27302433 return nullptr;
......@@ -2739,7 +2442,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp
27392442 return node;
27402443}
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) {
27432446 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
27442447 if (container_node == nullptr)
27452448 return nullptr;
......@@ -2756,7 +2459,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
27562459}
27572460
27582461static 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)
27602463{
27612464 AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
27622465 if (sub_expr_node == nullptr)
......@@ -2766,7 +2469,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
27662469}
27672470
27682471static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
2769 const UnaryExprOrTypeTraitExpr *stmt)
2472 const clang::UnaryExprOrTypeTraitExpr *stmt)
27702473{
27712474 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc());
27722475 if (type_node == nullptr)
......@@ -2777,14 +2480,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
27772480 return node;
27782481}
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) {
27812484 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
27822485
27832486 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
27842487
27852488 AstNode *body_node;
27862489 TransScope *child_scope;
2787 if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {
2490 if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
27882491 // there's already a block in C, so we'll append our condition to it.
27892492 // c: do {
27902493 // c: a;
......@@ -2837,11 +2540,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
28372540 return while_scope->node;
28382541}
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) {
28412544 AstNode *loop_block_node;
28422545 TransScopeWhile *while_scope;
28432546 TransScope *cond_scope;
2844 const Stmt *init_stmt = stmt->getInit();
2547 const clang::Stmt *init_stmt = stmt->getInit();
28452548 if (init_stmt == nullptr) {
28462549 while_scope = trans_scope_while_create(c, parent_scope);
28472550 loop_block_node = while_scope->node;
......@@ -2862,12 +2565,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
28622565 child_scope->node->data.block.statements.append(while_scope->node);
28632566 }
28642567
2865 const Stmt *cond_stmt = stmt->getCond();
2568 const clang::Stmt *cond_stmt = stmt->getCond();
28662569 if (cond_stmt == nullptr) {
28672570 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
28682571 } else {
2869 if (Expr::classof(cond_stmt)) {
2870 const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);
2572 if (clang::Expr::classof(cond_stmt)) {
2573 const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt);
28712574 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
28722575
28732576 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
28802583 }
28812584 }
28822585
2883 const Stmt *inc_stmt = stmt->getInc();
2586 const clang::Stmt *inc_stmt = stmt->getInc();
28842587 if (inc_stmt != nullptr) {
28852588 AstNode *inc_node;
28862589 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
29032606 return loop_block_node;
29042607}
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) {
29072610 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
29082611
29092612 TransScopeSwitch *switch_scope;
29102613
2911 const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
2614 const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
29122615 if (var_decl_stmt == nullptr) {
29132616 switch_scope = trans_scope_switch_create(c, &block_scope->base);
29142617 } else {
......@@ -2927,7 +2630,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
29272630 switch_scope->end_label_name = end_label_name;
29282631 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();
29312634 assert(cond_expr != nullptr);
29322635
29332636 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
29362639 switch_scope->switch_node->data.switch_expr.expr = expr_node;
29372640
29382641 AstNode *body_node;
2939 const Stmt *body_stmt = stmt->getBody();
2940 if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {
2941 if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,
2642 const clang::Stmt *body_stmt = stmt->getBody();
2643 if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
2644 if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
29422645 block_scope->node, nullptr))
29432646 {
29442647 return nullptr;
......@@ -2970,7 +2673,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
29702673 return nullptr;
29712674}
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,
29742677 TransScope **out_scope) {
29752678 *out_node = nullptr;
29762679
......@@ -3015,7 +2718,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm
30152718 return ErrorNone;
30162719}
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,
30192722 TransScope **out_scope)
30202723{
30212724 *out_node = nullptr;
......@@ -3052,25 +2755,27 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa
30522755 return ErrorNone;
30532756}
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) {
30562759 switch (stmt->getKind()) {
3057 case StringLiteral::Ascii:
3058 case StringLiteral::UTF8:
2760 case clang::StringLiteral::Ascii:
2761 case clang::StringLiteral::UTF8:
30592762 return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
3060 case StringLiteral::UTF16:
2763 case clang::StringLiteral::UTF16:
30612764 emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals");
30622765 return nullptr;
3063 case StringLiteral::UTF32:
2766 case clang::StringLiteral::UTF32:
30642767 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");
30652770 return nullptr;
3066 case StringLiteral::Wide:
2771 case clang::StringLiteral::Wide:
30672772 emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals");
30682773 return nullptr;
30692774 }
30702775 zig_unreachable();
30712776}
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) {
30742779 TransScope *cur_scope = scope;
30752780 while (cur_scope != nullptr) {
30762781 if (cur_scope->id == TransScopeIdWhile) {
......@@ -3084,7 +2789,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt
30842789 zig_unreachable();
30852790}
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) {
30882793 return trans_create_node(c, NodeTypeContinue);
30892794}
30902795
......@@ -3097,47 +2802,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
30972802 return ErrorNone;
30982803}
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,
31012806 ResultUsed result_used, TransLRValue lrvalue,
31022807 AstNode **out_node, TransScope **out_child_scope,
31032808 TransScope **out_node_scope)
31042809{
3105 Stmt::StmtClass sc = stmt->getStmtClass();
2810 clang::Stmt::StmtClass sc = stmt->getStmtClass();
31062811 switch (sc) {
3107 case Stmt::ReturnStmtClass:
2812 case clang::Stmt::ReturnStmtClass:
31082813 return wrap_stmt(out_node, out_child_scope, scope,
3109 trans_return_stmt(c, scope, (const ReturnStmt *)stmt));
3110 case Stmt::CompoundStmtClass:
2814 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
2815 case clang::Stmt::CompoundStmtClass:
31112816 return wrap_stmt(out_node, out_child_scope, scope,
3112 trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope));
3113 case Stmt::IntegerLiteralClass:
2817 trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
2818 case clang::Stmt::IntegerLiteralClass:
31142819 return wrap_stmt(out_node, out_child_scope, scope,
3115 trans_integer_literal(c, (const IntegerLiteral *)stmt));
3116 case Stmt::ConditionalOperatorClass:
2820 trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
2821 case clang::Stmt::ConditionalOperatorClass:
31172822 return wrap_stmt(out_node, out_child_scope, scope,
3118 trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt));
3119 case Stmt::BinaryOperatorClass:
2823 trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
2824 case clang::Stmt::BinaryOperatorClass:
31202825 return wrap_stmt(out_node, out_child_scope, scope,
3121 trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt));
3122 case Stmt::CompoundAssignOperatorClass:
2826 trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
2827 case clang::Stmt::CompoundAssignOperatorClass:
31232828 return wrap_stmt(out_node, out_child_scope, scope,
3124 trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt));
3125 case Stmt::ImplicitCastExprClass:
2829 trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
2830 case clang::Stmt::ImplicitCastExprClass:
31262831 return wrap_stmt(out_node, out_child_scope, scope,
3127 trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt));
3128 case Stmt::DeclRefExprClass:
2832 trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
2833 case clang::Stmt::DeclRefExprClass:
31292834 return wrap_stmt(out_node, out_child_scope, scope,
3130 trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue));
3131 case Stmt::UnaryOperatorClass:
2835 trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
2836 case clang::Stmt::UnaryOperatorClass:
31322837 return wrap_stmt(out_node, out_child_scope, scope,
3133 trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt));
3134 case Stmt::DeclStmtClass:
3135 return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope);
3136 case Stmt::DoStmtClass:
3137 case Stmt::WhileStmtClass: {
3138 AstNode *while_node = sc == Stmt::DoStmtClass
3139 ? trans_do_loop(c, scope, (const DoStmt *)stmt)
3140 : trans_while_loop(c, scope, (const WhileStmt *)stmt);
2838 trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
2839 case clang::Stmt::DeclStmtClass:
2840 return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
2841 case clang::Stmt::DoStmtClass:
2842 case clang::Stmt::WhileStmtClass: {
2843 AstNode *while_node = sc == clang::Stmt::DoStmtClass
2844 ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
2845 : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
31412846
31422847 if (while_node == nullptr)
31432848 return ErrorUnexpected;
......@@ -3148,567 +2853,63 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
31482853
31492854 return wrap_stmt(out_node, out_child_scope, scope, while_node);
31502855 }
3151 case Stmt::IfStmtClass:
2856 case clang::Stmt::IfStmtClass:
31522857 return wrap_stmt(out_node, out_child_scope, scope,
3153 trans_if_statement(c, scope, (const IfStmt *)stmt));
3154 case Stmt::CallExprClass:
2858 trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
2859 case clang::Stmt::CallExprClass:
31552860 return wrap_stmt(out_node, out_child_scope, scope,
3156 trans_call_expr(c, result_used, scope, (const CallExpr *)stmt));
3157 case Stmt::NullStmtClass:
2861 trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
2862 case clang::Stmt::NullStmtClass:
31582863 *out_node = nullptr;
31592864 *out_child_scope = scope;
31602865 return ErrorNone;
3161 case Stmt::MemberExprClass:
2866 case clang::Stmt::MemberExprClass:
31622867 return wrap_stmt(out_node, out_child_scope, scope,
3163 trans_member_expr(c, scope, (const MemberExpr *)stmt));
3164 case Stmt::ArraySubscriptExprClass:
2868 trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
2869 case clang::Stmt::ArraySubscriptExprClass:
31652870 return wrap_stmt(out_node, out_child_scope, scope,
3166 trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt));
3167 case Stmt::CStyleCastExprClass:
2871 trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
2872 case clang::Stmt::CStyleCastExprClass:
31682873 return wrap_stmt(out_node, out_child_scope, scope,
3169 trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue));
3170 case Stmt::UnaryExprOrTypeTraitExprClass:
2874 trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
2875 case clang::Stmt::UnaryExprOrTypeTraitExprClass:
31712876 return wrap_stmt(out_node, out_child_scope, scope,
3172 trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt));
3173 case Stmt::ForStmtClass: {
3174 AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt);
2877 trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
2878 case clang::Stmt::ForStmtClass: {
2879 AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
31752880 return wrap_stmt(out_node, out_child_scope, scope, node);
31762881 }
3177 case Stmt::StringLiteralClass:
2882 case clang::Stmt::StringLiteralClass:
31782883 return wrap_stmt(out_node, out_child_scope, scope,
3179 trans_string_literal(c, scope, (const StringLiteral *)stmt));
3180 case Stmt::BreakStmtClass:
2884 trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
2885 case clang::Stmt::BreakStmtClass:
31812886 return wrap_stmt(out_node, out_child_scope, scope,
3182 trans_break_stmt(c, scope, (const BreakStmt *)stmt));
3183 case Stmt::ContinueStmtClass:
2887 trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
2888 case clang::Stmt::ContinueStmtClass:
31842889 return wrap_stmt(out_node, out_child_scope, scope,
3185 trans_continue_stmt(c, scope, (const ContinueStmt *)stmt));
3186 case Stmt::ParenExprClass:
2890 trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
2891 case clang::Stmt::ParenExprClass:
31872892 return wrap_stmt(out_node, out_child_scope, scope,
3188 trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));
3189 case Stmt::SwitchStmtClass:
2893 trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
2894 case clang::Stmt::SwitchStmtClass:
31902895 return wrap_stmt(out_node, out_child_scope, scope,
3191 trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));
3192 case Stmt::CaseStmtClass:
3193 return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);
3194 case Stmt::DefaultStmtClass:
3195 return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);
3196 case Stmt::ConstantExprClass:
2896 trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
2897 case clang::Stmt::CaseStmtClass:
2898 return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
2899 case clang::Stmt::DefaultStmtClass:
2900 return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
2901 case clang::Stmt::ConstantExprClass:
31972902 return wrap_stmt(out_node, out_child_scope, scope,
3198 trans_constant_expr(c, (const ConstantExpr *)stmt));
3199 case Stmt::NoStmtClass:
2903 trans_constant_expr(c, (const clang::ConstantExpr *)stmt));
2904 case clang::Stmt::NoStmtClass:
32002905 emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass");
32012906 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;
37062907 }
37072908 zig_unreachable();
37082909}
37092910
37102911// 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,
37122913 TransLRValue lrval)
37132914{
37142915 AstNode *result_node;
......@@ -3721,7 +2922,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
37212922
37222923// Statements have no result and no concept of L or R value.
37232924// 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) {
37252926 TransScope *child_scope;
37262927 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
37272928 return nullptr;
......@@ -3729,7 +2930,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A
37292930 return child_scope;
37302931}
37312932
3732static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
2933static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
37332934 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
37342935
37352936 if (get_global(c, fn_name)) {
......@@ -3746,13 +2947,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37462947 proto_node->data.fn_proto.name = fn_name;
37472948 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
37482949
3749 StorageClass sc = fn_decl->getStorageClass();
3750 if (sc == SC_None) {
2950 clang::StorageClass sc = fn_decl->getStorageClass();
2951 if (sc == clang::SC_None) {
37512952 proto_node->data.fn_proto.visib_mod = c->visib_mod;
37522953 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) {
37542955 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3755 } else if (sc == SC_PrivateExtern) {
2956 } else if (sc == clang::SC_PrivateExtern) {
37562957 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
37572958 return;
37582959 } else {
......@@ -3764,7 +2965,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37642965
37652966 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
37662967 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);
37682969 const char *name = decl_name(param);
37692970
37702971 Buf *proto_param_name;
......@@ -3791,7 +2992,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37912992
37922993 // actual function definition with body
37932994 c->ptr_params.clear();
3794 Stmt *body = fn_decl->getBody();
2995 clang::Stmt *body = fn_decl->getBody();
37952996 AstNode *actual_body_node;
37962997 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
37972998 if (result_scope == nullptr) {
......@@ -3833,19 +3034,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
38333034 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
38343035}
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) {
38373038 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
38383039 c->decl_table.put(typedef_decl, node);
38393040 return node;
38403041}
38413042
3842static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
3043static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
38433044 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
38443045 if (existing_entry) {
38453046 return existing_entry->value;
38463047 }
38473048
3848 QualType child_qt = typedef_decl->getUnderlyingType();
3049 clang::QualType child_qt = typedef_decl->getUnderlyingType();
38493050 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
38503051
38513052 if (buf_eql_str(type_name, "uint8_t")) {
......@@ -3894,7 +3095,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_
38943095 return symbol_node;
38953096}
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,
38983099 Buf *full_type_name, Buf *bare_name)
38993100{
39003101 AstNode *opaque_node = trans_create_node_opaque(c);
......@@ -3909,7 +3110,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
39093110 return symbol_node;
39103111}
39113112
3912static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3113static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
39133114 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
39143115 if (existing_entry) {
39153116 return existing_entry->value;
......@@ -3920,7 +3121,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39203121 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
39213122 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();
39243125 if (!enum_def) {
39253126 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
39263127 }
......@@ -3932,7 +3133,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39323133 it_end = enum_def->enumerator_end();
39333134 it != it_end; ++it, field_count += 1)
39343135 {
3935 const EnumConstantDecl *enum_const = *it;
3136 const clang::EnumConstantDecl *enum_const = *it;
39363137 if (enum_const->getInitExpr()) {
39373138 pure_enum = false;
39383139 }
......@@ -3946,8 +3147,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39463147 // TODO only emit this tag type if the enum tag type is not the default.
39473148 // I don't know what the default is, need to figure out how clang is deciding.
39483149 // it appears to at least be different across gcc/msvc
3949 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&
3950 !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))
3150 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&
3151 !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
39513152 {
39523153 enum_node->data.container_decl.init_arg_expr = tag_int_type;
39533154 }
......@@ -3957,7 +3158,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39573158 it_end = enum_def->enumerator_end();
39583159 it != it_end; ++it, i += 1)
39593160 {
3960 const EnumConstantDecl *enum_const = *it;
3161 const clang::EnumConstantDecl *enum_const = *it;
39613162
39623163 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
39633164 Buf *field_name;
......@@ -3998,7 +3199,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39983199 }
39993200}
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,
40023203 Buf *full_type_name, Buf *bare_name)
40033204{
40043205 AstNode *opaque_node = trans_create_node_opaque(c);
......@@ -4013,7 +3214,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec
40133214 return symbol_node;
40143215}
40153216
4016static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
3217static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
40173218 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
40183219 if (existing_entry) {
40193220 return existing_entry->value;
......@@ -4039,7 +3240,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
40393240 Buf *full_type_name = (bare_name == nullptr) ?
40403241 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();
40433244 if (record_def == nullptr) {
40443245 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
40453246 }
......@@ -4050,7 +3251,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
40503251 it_end = record_def->field_end();
40513252 it != it_end; ++it, field_count += 1)
40523253 {
4053 const FieldDecl *field_decl = *it;
3254 const clang::FieldDecl *field_decl = *it;
40543255
40553256 if (field_decl->isBitField()) {
40563257 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) {
40803281 it_end = record_def->field_end();
40813282 it != it_end; ++it, i += 1)
40823283 {
4083 const FieldDecl *field_decl = *it;
3284 const clang::FieldDecl *field_decl = *it;
40843285
40853286 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
40863287 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) {
41073308 }
41083309}
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) {
41113312 switch (ap_value->getKind()) {
4112 case APValue::Int:
3313 case clang::APValue::Int:
41133314 return trans_create_node_apint(c, ap_value->getInt());
4114 case APValue::Uninitialized:
3315 case clang::APValue::Uninitialized:
41153316 return trans_create_node(c, NodeTypeUndefinedLiteral);
4116 case APValue::Array: {
3317 case clang::APValue::Array: {
41173318 emit_warning(c, source_loc, "TODO add a test case for this code");
41183319
41193320 unsigned init_count = ap_value->getArrayInitializedElts();
......@@ -4121,13 +3322,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
41213322 unsigned leftover_count = all_count - init_count;
41223323 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
41233324 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 }
41243328 init_node->data.container_init_expr.type = arr_type_node;
41253329 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
41293333 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);
41313335 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
41323336 if (elem_node == nullptr)
41333337 return nullptr;
......@@ -4137,15 +3341,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
41373341 return init_node;
41383342 }
41393343
4140 APValue &filler_ap_val = ap_value->getArrayFiller();
3344 clang::APValue &filler_ap_val = ap_value->getArrayFiller();
41413345 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
41423346 if (filler_node == nullptr)
41433347 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
41453353 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
4146 init_node->data.container_init_expr.type = arr_type_node;
4147 init_node->data.container_init_expr.kind = ContainerInitKindArray;
4148 init_node->data.container_init_expr.entries.append(filler_node);
3354 filler_arr_1->data.container_init_expr.type = filler_arr_type;
3355 filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
3356 filler_arr_1->data.container_init_expr.entries.append(filler_node);
41493357
41503358 AstNode *rhs_node;
41513359 if (leftover_count == 1) {
......@@ -4155,62 +3363,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
41553363 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
41563364 }
41573365
3366 if (init_count == 0) {
3367 return rhs_node;
3368 }
3369
41583370 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
41593371 }
4160 case APValue::LValue: {
4161 const APValue::LValueBase lval_base = ap_value->getLValueBase();
4162 if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) {
3372 case clang::APValue::LValue: {
3373 const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
3374 if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) {
41633375 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
41643376 }
4165 //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>();
4166 emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");
3377 //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();
3378 emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
41673379 return nullptr;
41683380 }
4169 case APValue::Float:
3381 case clang::APValue::Float:
41703382 emit_warning(c, source_loc, "unsupported initializer value kind: Float");
41713383 return nullptr;
4172 case APValue::ComplexInt:
3384 case clang::APValue::ComplexInt:
41733385 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
41743386 return nullptr;
4175 case APValue::ComplexFloat:
3387 case clang::APValue::ComplexFloat:
41763388 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
41773389 return nullptr;
4178 case APValue::Vector:
3390 case clang::APValue::Vector:
41793391 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
41803392 return nullptr;
4181 case APValue::Struct:
3393 case clang::APValue::Struct:
41823394 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
41833395 return nullptr;
4184 case APValue::Union:
3396 case clang::APValue::Union:
41853397 emit_warning(c, source_loc, "unsupported initializer value kind: Union");
41863398 return nullptr;
4187 case APValue::MemberPointer:
3399 case clang::APValue::MemberPointer:
41883400 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
41893401 return nullptr;
4190 case APValue::AddrLabelDiff:
3402 case clang::APValue::AddrLabelDiff:
41913403 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
41923404 return nullptr;
41933405 }
41943406 zig_unreachable();
41953407}
41963408
4197static void visit_var_decl(Context *c, const VarDecl *var_decl) {
3409static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
41983410 Buf *name = buf_create_from_str(decl_name(var_decl));
41993411
42003412 switch (var_decl->getTLSKind()) {
4201 case VarDecl::TLS_None:
3413 case clang::VarDecl::TLS_None:
42023414 break;
4203 case VarDecl::TLS_Static:
3415 case clang::VarDecl::TLS_Static:
42043416 emit_warning(c, var_decl->getLocation(),
42053417 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
42063418 return;
4207 case VarDecl::TLS_Dynamic:
3419 case clang::VarDecl::TLS_Dynamic:
42083420 emit_warning(c, var_decl->getLocation(),
42093421 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
42103422 return;
42113423 }
42123424
4213 QualType qt = var_decl->getType();
3425 clang::QualType qt = var_decl->getType();
42143426 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
42153427 if (var_type == nullptr) {
42163428 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) {
42243436 if (is_static && !is_extern) {
42253437 AstNode *init_node;
42263438 if (var_decl->hasInit()) {
4227 APValue *ap_value = var_decl->evaluateValue();
3439 clang::APValue *ap_value = var_decl->evaluateValue();
42283440 if (ap_value == nullptr) {
42293441 emit_warning(c, var_decl->getLocation(),
42303442 "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) {
42543466 return;
42553467}
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);
42583471 Context *c = (Context*)context;
42593472
42603473 switch (decl->getKind()) {
4261 case Decl::Function:
4262 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));
3474 case clang::Decl::Function:
3475 visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));
42633476 break;
4264 case Decl::Typedef:
4265 resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
3477 case clang::Decl::Typedef:
3478 resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl));
42663479 break;
4267 case Decl::Enum:
4268 resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));
3480 case clang::Decl::Enum:
3481 resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl));
42693482 break;
4270 case Decl::Record:
4271 resolve_record_decl(c, static_cast<const RecordDecl *>(decl));
3483 case clang::Decl::Record:
3484 resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl));
42723485 break;
4273 case Decl::Var:
4274 visit_var_decl(c, static_cast<const VarDecl *>(decl));
3486 case clang::Decl::Var:
3487 visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));
42753488 break;
42763489 default:
42773490 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
46133826 } else if (first_tok->id == CTokIdAsterisk) {
46143827 *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);
46173830 } else {
46183831 return node;
46193832 }
......@@ -4692,24 +3905,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
46923905 c->macro_table.put(name, result_node);
46933906}
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);
46963910 CTokenize ctok = {{0}};
46973911
46983912 // TODO if we see #undef, delete it from the table
46993913
4700 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
3914 for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) {
47013915 switch (entity->getKind()) {
4702 case PreprocessedEntity::InvalidKind:
4703 case PreprocessedEntity::InclusionDirectiveKind:
4704 case PreprocessedEntity::MacroExpansionKind:
3916 case clang::PreprocessedEntity::InvalidKind:
3917 case clang::PreprocessedEntity::InclusionDirectiveKind:
3918 case clang::PreprocessedEntity::MacroExpansionKind:
47053919 continue;
4706 case PreprocessedEntity::MacroDefinitionKind:
3920 case clang::PreprocessedEntity::MacroDefinitionKind:
47073921 {
4708 MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity);
3922 clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity);
47093923 const char *raw_name = macro->getName()->getNameStart();
4710 SourceRange range = macro->getSourceRange();
4711 SourceLocation begin_loc = range.getBegin();
4712 SourceLocation end_loc = range.getEnd();
3924 clang::SourceRange range = macro->getSourceRange();
3925 clang::SourceLocation begin_loc = range.getBegin();
3926 clang::SourceLocation end_loc = range.getEnd();
47133927
47143928 if (begin_loc == end_loc) {
47153929 // this means it is a macro without a value
......@@ -4721,7 +3935,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
47213935 continue;
47223936 }
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));
47253939 process_macro(c, &ctok, name, begin_c);
47263940 }
47273941 }
......@@ -4772,7 +3986,16 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47723986 clang_argv.append("-x");
47733987 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) {
47763999 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
47774000 if (ZIG_PARSEC_CFLAGS) {
47784001 Buf tmp_buf = BUF_INIT;
......@@ -4791,12 +4014,24 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47914014 }
47924015 }
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
47944024 clang_argv.append("-isystem");
47954025 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
47964026
4797 if (codegen->libc_include_dir != nullptr) {
4027 if (codegen->libc != nullptr) {
47984028 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 }
48004035 }
48014036
48024037 // windows c runtime requires -D_DEBUG if using debug libraries
......@@ -4816,7 +4051,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48164051 clang_argv.append("-Xclang");
48174052 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 {
48204057 clang_argv.append("-target");
48214058 clang_argv.append(buf_ptr(&c->codegen->triple_str));
48224059 }
......@@ -4834,9 +4071,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48344071 // to make the [start...end] argument work
48354072 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
48414078 bool only_local_decls = true;
48424079 bool capture_diagnostics = true;
......@@ -4845,13 +4082,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48454082 bool single_file_parse = false;
48464083 bool for_serialization = false;
48474084 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
4848 std::unique_ptr<ASTUnit> err_unit;
4849 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
4085 std::unique_ptr<clang::ASTUnit> err_unit;
4086 ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
48504087 &clang_argv.at(0), &clang_argv.last(),
48514088 pch_container_ops, diags, resources_path,
4852 only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,
4853 false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None,
4854 single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
4089 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
4090 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
4091 single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
48554092 nullptr));
48564093
48574094 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
......@@ -4861,29 +4098,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48614098
48624099 if (diags->getClient()->getNumErrors() > 0) {
48634100 if (ast_unit) {
4864 err_unit = std::move(ast_unit);
4101 err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit));
48654102 }
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(),
48684105 it_end = err_unit->stored_diag_end();
48694106 it != it_end; ++it)
48704107 {
48714108 switch (it->getLevel()) {
4872 case DiagnosticsEngine::Ignored:
4873 case DiagnosticsEngine::Note:
4874 case DiagnosticsEngine::Remark:
4875 case DiagnosticsEngine::Warning:
4109 case clang::DiagnosticsEngine::Ignored:
4110 case clang::DiagnosticsEngine::Note:
4111 case clang::DiagnosticsEngine::Remark:
4112 case clang::DiagnosticsEngine::Warning:
48764113 continue;
4877 case DiagnosticsEngine::Error:
4878 case DiagnosticsEngine::Fatal:
4114 case clang::DiagnosticsEngine::Error:
4115 case clang::DiagnosticsEngine::Fatal:
48794116 break;
48804117 }
48814118 StringRef msg_str_ref = it->getMessage();
48824119 Buf *msg = string_ref_to_buf(msg_str_ref);
4883 FullSourceLoc fsl = it->getLocation();
4120 clang::FullSourceLoc fsl = it->getLocation();
48844121 if (fsl.hasManager()) {
4885 FileID file_id = fsl.getFileID();
4886 StringRef filename = fsl.getManager().getFilename(fsl);
4122 clang::FileID file_id = fsl.getFileID();
4123 clang::StringRef filename = fsl.getManager().getFilename(fsl);
48874124 unsigned line = fsl.getSpellingLineNumber() - 1;
48884125 unsigned column = fsl.getSpellingColumnNumber() - 1;
48894126 unsigned offset = fsl.getManager().getFileOffset(fsl);
......@@ -4908,14 +4145,25 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
49084145 return ErrorCCompileErrors;
49094146 }
49104147
4911 c->ctx = &ast_unit->getASTContext();
4912 c->source_manager = &ast_unit->getSourceManager();
4148 if (codegen->enable_cache) {
4149 Error err;
4150 assert(out_dep_path != nullptr);
4151 if ((err = cache_add_dep_file(&codegen->cache_hash, out_dep_path, codegen->verbose_cimport))) {
4152 if (codegen->verbose_cimport) {
4153 fprintf(stderr, "translate-c: aborting due to failed cache operation: %s\n", err_str(err));
4154 }
4155 return err;
4156 }
4157 }
4158
4159 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
4160 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
49134161 c->root = trans_create_node(c, NodeTypeContainerDecl);
49144162 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
49204168 render_macros(c);
49214169 render_aliases(c);
src/util.hpp+7-4
......@@ -147,11 +147,14 @@ static inline T clamp(T min_value, T value, T max_value) {
147147 return max(min(value, max_value), min_value);
148148}
149149
150static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {
151 size_t str_len = strlen(str);
152 if (str_len != mem_len)
150static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
151 if (a_len != b_len)
153152 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));
155158}
156159
157160static 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
732732const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
733733 switch (sub_arch) {
734734 case ZigLLVM_NoSubArch:
735 return "(none)";
735 return "";
736736 case ZigLLVM_ARMSubArch_v8_5a:
737737 return "v8_5a";
738738 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
215215
216216
217217// copied from include/llvm/ADT/Triple.h
218
218// synchronize with target.cpp::arch_list
219219enum ZigLLVM_ArchType {
220220 ZigLLVM_UnknownArch,
221221
......@@ -272,6 +272,7 @@ enum ZigLLVM_ArchType {
272272 ZigLLVM_LastArchType = ZigLLVM_renderscript64
273273};
274274
275// synchronize with lists in target.cpp
275276enum ZigLLVM_SubArchType {
276277 ZigLLVM_NoSubArch,
277278
......@@ -409,7 +410,7 @@ ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
409410ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);
410411ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
411412ZIG_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
414415ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
415416 void (*append_diagnostic)(void *, const char *, size_t), void *context);
std/buf_set.zig+4
......@@ -32,6 +32,10 @@ pub const BufSet = struct {
3232 }
3333 }
3434
35 pub fn exists(self: BufSet, key: []const u8) bool {
36 return self.hash_map.get(key) != null;
37 }
38
3539 pub fn delete(self: *BufSet, key: []const u8) void {
3640 const entry = self.hash_map.remove(key) orelse return;
3741 self.free(entry.key);
std/build.zig+205-724
......@@ -15,6 +15,8 @@ const BufSet = std.BufSet;
1515const BufMap = std.BufMap;
1616const fmt_lib = std.fmt;
1717
18pub const FmtStep = @import("build/fmt.zig").FmtStep;
19
1820pub const Builder = struct {
1921 uninstall_tls: TopLevelStep,
2022 install_tls: TopLevelStep,
......@@ -31,6 +33,7 @@ pub const Builder = struct {
3133 verbose_tokenize: bool,
3234 verbose_ast: bool,
3335 verbose_link: bool,
36 verbose_cc: bool,
3437 verbose_ir: bool,
3538 verbose_llvm_ir: bool,
3639 verbose_cimport: bool,
......@@ -99,6 +102,7 @@ pub const Builder = struct {
99102 .verbose_tokenize = false,
100103 .verbose_ast = false,
101104 .verbose_link = false,
105 .verbose_cc = false,
102106 .verbose_ir = false,
103107 .verbose_llvm_ir = false,
104108 .verbose_cimport = false,
......@@ -157,7 +161,7 @@ pub const Builder = struct {
157161 return LibExeObjStep.createExecutable(self, name, root_src, true);
158162 }
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 {
161165 return LibExeObjStep.createObject(self, name, root_src);
162166 }
163167
......@@ -169,10 +173,8 @@ pub const Builder = struct {
169173 return LibExeObjStep.createStaticLibrary(self, name, root_src);
170174 }
171175
172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {
173 const test_step = self.allocator.create(TestStep) catch unreachable;
174 test_step.* = TestStep.init(self, root_src);
175 return test_step;
176 pub fn addTest(self: *Builder, root_src: []const u8) *LibExeObjStep {
177 return LibExeObjStep.createTest(self, "test", root_src);
176178 }
177179
178180 pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
......@@ -181,22 +183,6 @@ pub const Builder = struct {
181183 return obj_step;
182184 }
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
200186 /// ::argv is copied.
201187 pub fn addCommand(self: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {
202188 return CommandStep.create(self, cwd, env_map, argv);
......@@ -221,6 +207,10 @@ pub const Builder = struct {
221207 return remove_dir_step;
222208 }
223209
210 pub fn addFmt(self: *Builder, paths: []const []const u8) *FmtStep {
211 return FmtStep.create(self, paths);
212 }
213
224214 pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version {
225215 return Version{
226216 .major = major,
......@@ -663,14 +653,6 @@ pub const Builder = struct {
663653 return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;
664654 }
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
674656 pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
675657 // TODO report error for ambiguous situations
676658 const exe_extension = (Target{ .Native = {} }).exeFileExt();
......@@ -755,20 +737,40 @@ const Version = struct {
755737const CrossTarget = struct {
756738 arch: builtin.Arch,
757739 os: builtin.Os,
758 environ: builtin.Environ,
740 abi: builtin.Abi,
759741};
760742
761743pub const Target = union(enum) {
762744 Native: void,
763745 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
765767 pub fn oFileExt(self: *const Target) []const u8 {
766 const environ = switch (self.*) {
767 Target.Native => builtin.environ,
768 Target.Cross => |t| t.environ,
768 const abi = switch (self.*) {
769 Target.Native => builtin.abi,
770 Target.Cross => |t| t.abi,
769771 };
770 return switch (environ) {
771 builtin.Environ.msvc => ".obj",
772 return switch (abi) {
773 builtin.Abi.msvc => ".obj",
772774 else => ".o",
773775 };
774776 }
......@@ -825,6 +827,11 @@ const Pkg = struct {
825827 path: []const u8,
826828};
827829
830const CSourceFile = struct {
831 source_path: []const u8,
832 args: []const []const u8,
833};
834
828835pub const LibExeObjStep = struct {
829836 step: Step,
830837 builder: *Builder,
......@@ -834,6 +841,7 @@ pub const LibExeObjStep = struct {
834841 linker_script: ?[]const u8,
835842 out_filename: []const u8,
836843 output_path: ?[]const u8,
844 output_lib_path: ?[]const u8,
837845 static: bool,
838846 version: Version,
839847 object_files: ArrayList([]const u8),
......@@ -844,33 +852,34 @@ pub const LibExeObjStep = struct {
844852 strip: bool,
845853 full_path_libs: ArrayList([]const u8),
846854 need_flat_namespace_hack: bool,
847 is_zig: bool,
848 cflags: ArrayList([]const u8),
849855 include_dirs: ArrayList([]const u8),
850856 lib_paths: ArrayList([]const u8),
851 disable_libc: bool,
852857 frameworks: BufSet,
853858 verbose_link: bool,
854 no_rosegment: bool,
859 verbose_cc: bool,
855860 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
858866 root_src: ?[]const u8,
859867 output_h_path: ?[]const u8,
860868 out_h_filename: []const u8,
869 out_lib_filename: []const u8,
861870 assembly_files: ArrayList([]const u8),
862871 packages: ArrayList(Pkg),
863872 build_options_contents: std.Buffer,
864873 system_linker_hack: bool,
865874
866 // C only stuff
867 source_files: ArrayList([]const u8),
875 c_source_files: ArrayList(*CSourceFile),
868876 object_src: []const u8,
869877
870878 const Kind = enum {
871879 Exe,
872880 Lib,
873881 Obj,
882 Test,
874883 };
875884
876885 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {
......@@ -879,55 +888,36 @@ pub const LibExeObjStep = struct {
879888 return self;
880889 }
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
888891 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
889892 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
890893 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
891894 return self;
892895 }
893896
894 pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep {
895 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
896 self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
897 return self;
898 }
899
900 pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
897 pub fn createObject(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
901898 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
902899 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
903900 return self;
904901 }
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
913903 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
914904 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
915905 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0));
916906 return self;
917907 }
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 {
920910 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));
922912 return self;
923913 }
924914
925915 fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: Version) LibExeObjStep {
926916 var self = LibExeObjStep{
927 .no_rosegment = false,
928917 .strip = false,
929918 .builder = builder,
930919 .verbose_link = false,
920 .verbose_cc = false,
931921 .build_mode = builtin.Mode.Debug,
932922 .static = static,
933923 .kind = kind,
......@@ -939,80 +929,35 @@ pub const LibExeObjStep = struct {
939929 .frameworks = BufSet.init(builder.allocator),
940930 .step = Step.init(name, builder.allocator, make),
941931 .output_path = null,
932 .output_lib_path = null,
942933 .output_h_path = null,
943934 .version = ver,
944935 .out_filename = undefined,
945936 .out_h_filename = builder.fmt("{}.h", name),
937 .out_lib_filename = undefined,
946938 .major_only_filename = undefined,
947939 .name_only_filename = undefined,
948940 .object_files = ArrayList([]const u8).init(builder.allocator),
949941 .assembly_files = ArrayList([]const u8).init(builder.allocator),
950942 .packages = ArrayList(Pkg).init(builder.allocator),
951 .is_zig = true,
952943 .full_path_libs = ArrayList([]const u8).init(builder.allocator),
953944 .need_flat_namespace_hack = false,
954 .cflags = ArrayList([]const u8).init(builder.allocator),
955 .source_files = undefined,
945 .c_source_files = ArrayList(*CSourceFile).init(builder.allocator),
956946 .include_dirs = ArrayList([]const u8).init(builder.allocator),
957947 .lib_paths = ArrayList([]const u8).init(builder.allocator),
958948 .object_src = undefined,
959 .disable_libc = true,
960949 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
961950 .c_std = Builder.CStd.C99,
962951 .system_linker_hack = false,
952 .override_std_dir = null,
953 .exec_cmd_args = null,
954 .name_prefix = "",
955 .filter = null,
963956 };
964957 self.computeOutFileNames();
965958 return self;
966959 }
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
1016961 fn computeOutFileNames(self: *LibExeObjStep) void {
1017962 switch (self.kind) {
1018963 Kind.Obj => {
......@@ -1021,23 +966,37 @@ pub const LibExeObjStep = struct {
1021966 Kind.Exe => {
1022967 self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());
1023968 },
969 Kind.Test => {
970 self.out_filename = self.builder.fmt("test{}", self.target.exeFileExt());
971 },
1024972 Kind.Lib => {
1025973 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;
1027983 } else {
1028984 switch (self.target.getOs()) {
1029985 builtin.Os.ios, builtin.Os.macosx => {
1030986 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);
1031987 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);
1032988 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
989 self.out_lib_filename = self.out_filename;
1033990 },
1034991 builtin.Os.windows => {
1035992 self.out_filename = self.builder.fmt("{}.dll", self.name);
993 self.out_lib_filename = self.builder.fmt("{}.lib", self.name);
1036994 },
1037995 else => {
1038996 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch);
1039997 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);
1040998 self.name_only_filename = self.builder.fmt("lib{}.so", self.name);
999 self.out_lib_filename = self.out_filename;
10411000 },
10421001 }
10431002 }
......@@ -1045,12 +1004,17 @@ pub const LibExeObjStep = struct {
10451004 }
10461005 }
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 {
10491013 self.target = Target{
10501014 .Cross = CrossTarget{
10511015 .arch = target_arch,
10521016 .os = target_os,
1053 .environ = target_environ,
1017 .abi = target_abi,
10541018 },
10551019 };
10561020 self.computeOutFileNames();
......@@ -1072,7 +1036,15 @@ pub const LibExeObjStep = struct {
10721036
10731037 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
10771049 // TODO should be some kind of isolated directory that only has this header in it
10781050 self.include_dirs.append(self.builder.cache_root) catch unreachable;
......@@ -1088,24 +1060,44 @@ pub const LibExeObjStep = struct {
10881060 }
10891061
10901062 pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {
1091 assert(self.kind != Kind.Obj);
10921063 self.link_libs.put(name) catch unreachable;
10931064 }
10941065
1095 pub fn addSourceFile(self: *LibExeObjStep, file: []const u8) void {
1096 assert(self.kind != Kind.Obj);
1097 assert(!self.is_zig);
1098 self.source_files.append(file) catch unreachable;
1066 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
1067 assert(self.kind == Kind.Test);
1068 self.name_prefix = text;
1069 }
1070
1071 pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void {
1072 assert(self.kind == Kind.Test);
1073 self.filter = text;
1074 }
1075
1076 pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void {
1077 const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable;
1078 c_source_file.* = CSourceFile{
1079 .source_path = file,
1080 .args = args,
1081 };
1082 self.c_source_files.append(c_source_file) catch unreachable;
10991083 }
11001084
11011085 pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {
11021086 self.verbose_link = value;
11031087 }
11041088
1089 pub fn setVerboseCC(self: *LibExeObjStep, value: bool) void {
1090 self.verbose_cc = value;
1091 }
1092
11051093 pub fn setBuildMode(self: *LibExeObjStep, mode: builtin.Mode) void {
11061094 self.build_mode = mode;
11071095 }
11081096
1097 pub fn overrideStdDir(self: *LibExeObjStep, dir_path: []const u8) void {
1098 self.override_std_dir = dir_path;
1099 }
1100
11091101 pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void {
11101102 self.output_path = file_path;
11111103
......@@ -1122,6 +1114,22 @@ pub const LibExeObjStep = struct {
11221114 ) catch unreachable;
11231115 }
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
11251133 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {
11261134 self.output_h_path = file_path;
11271135
......@@ -1156,17 +1164,15 @@ pub const LibExeObjStep = struct {
11561164
11571165 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
11641167 // TODO should be some kind of isolated directory that only has this header in it
11651168 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 }
11661173 }
11671174
11681175 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
1169 assert(self.is_zig);
11701176 const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream;
11711177 out.print("pub const {} = {};\n", name, value) catch unreachable;
11721178 }
......@@ -1180,23 +1186,15 @@ pub const LibExeObjStep = struct {
11801186 }
11811187
11821188 pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
1183 assert(self.is_zig);
1184
11851189 self.packages.append(Pkg{
11861190 .name = name,
11871191 .path = pkg_index_path,
11881192 }) catch unreachable;
11891193 }
11901194
1191 pub fn addCompileFlags(self: *LibExeObjStep, flags: []const []const u8) void {
1192 for (flags) |flag| {
1193 self.cflags.append(flag) catch unreachable;
1194 }
1195 }
1196
1197 pub fn setNoStdLib(self: *LibExeObjStep, disable: bool) void {
1198 assert(!self.is_zig);
1199 self.disable_libc = disable;
1195 pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void {
1196 assert(self.kind == Kind.Test);
1197 self.exec_cmd_args = args;
12001198 }
12011199
12021200 pub fn enableSystemLinkerHack(self: *LibExeObjStep) void {
......@@ -1205,15 +1203,11 @@ pub const LibExeObjStep = struct {
12051203
12061204 fn make(step: *Step) !void {
12071205 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 {
12121206 const builder = self.builder;
12131207
1214 assert(self.is_zig);
1215
1216 if (self.root_src == null and self.object_files.len == 0 and self.assembly_files.len == 0) {
1208 if (self.root_src == null and self.object_files.len == 0 and
1209 self.assembly_files.len == 0 and self.c_source_files.len == 0)
1210 {
12171211 warn("{}: linker needs 1 or more objects to link\n", self.step.name);
12181212 return error.NeedAnObject;
12191213 }
......@@ -1227,6 +1221,7 @@ pub const LibExeObjStep = struct {
12271221 Kind.Lib => "build-lib",
12281222 Kind.Exe => "build-exe",
12291223 Kind.Obj => "build-obj",
1224 Kind.Test => "test",
12301225 };
12311226 zig_args.append(cmd) catch unreachable;
12321227
......@@ -1234,6 +1229,14 @@ pub const LibExeObjStep = struct {
12341229 zig_args.append(builder.pathFromRoot(root_src)) catch unreachable;
12351230 }
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
12371240 if (self.build_options_contents.len() > 0) {
12381241 const build_options_file = try os.path.join(
12391242 builder.allocator,
......@@ -1246,6 +1249,16 @@ pub const LibExeObjStep = struct {
12461249 try zig_args.append("--pkg-end");
12471250 }
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
12491262 for (self.object_files.toSliceConst()) |object_file| {
12501263 zig_args.append("--object") catch unreachable;
12511264 zig_args.append(builder.pathFromRoot(object_file)) catch unreachable;
......@@ -1262,6 +1275,7 @@ pub const LibExeObjStep = struct {
12621275 if (builder.verbose_ir) zig_args.append("--verbose-ir") catch unreachable;
12631276 if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;
12641277 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
12661280 if (self.strip) {
12671281 zig_args.append("--strip") catch unreachable;
......@@ -1281,7 +1295,13 @@ pub const LibExeObjStep = struct {
12811295 zig_args.append("--output") catch unreachable;
12821296 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) {
12851305 const output_h_path = self.getOutputHPath();
12861306 zig_args.append("--output-h") catch unreachable;
12871307 zig_args.append(builder.pathFromRoot(output_h_path)) catch unreachable;
......@@ -1300,21 +1320,23 @@ pub const LibExeObjStep = struct {
13001320 zig_args.append("--ver-patch") catch unreachable;
13011321 zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;
13021322 }
1303 if (self.kind == Kind.Exe and self.static) {
1323 if ((self.kind == Kind.Exe or self.kind == Kind.Test) and self.static) {
13041324 zig_args.append("--static") catch unreachable;
13051325 }
13061326
13071327 switch (self.target) {
13081328 Target.Native => {},
13091329 Target.Cross => |cross_target| {
1310 zig_args.append("--target-arch") catch unreachable;
1311 zig_args.append(@tagName(cross_target.arch)) catch unreachable;
1312
1313 zig_args.append("--target-os") catch unreachable;
1314 zig_args.append(@tagName(cross_target.os)) catch unreachable;
1315
1316 zig_args.append("--target-environ") catch unreachable;
1317 zig_args.append(@tagName(cross_target.environ)) catch unreachable;
1330 const triple = builder.fmt(
1331 "{}{}-{}-{}",
1332 @tagName(cross_target.arch),
1333 Target.archSubArchName(cross_target.arch),
1334 @tagName(cross_target.os),
1335 @tagName(cross_target.abi),
1336 );
1337
1338 try zig_args.append("-target");
1339 try zig_args.append(triple);
13181340 },
13191341 }
13201342
......@@ -1332,11 +1354,16 @@ pub const LibExeObjStep = struct {
13321354 }
13331355 }
13341356
1335 if (!self.disable_libc) {
1336 zig_args.append("--library") catch unreachable;
1337 zig_args.append("c") catch unreachable;
1357 if (self.exec_cmd_args) |exec_cmd_args| {
1358 for (exec_cmd_args) |cmd_arg| {
1359 if (cmd_arg) |arg| {
1360 try zig_args.append("--test-cmd");
1361 try zig_args.append(arg);
1362 } else {
1363 try zig_args.append("--test-cmd-bin");
1364 }
1365 }
13381366 }
1339
13401367 for (self.packages.toSliceConst()) |pkg| {
13411368 zig_args.append("--pkg-begin") catch unreachable;
13421369 zig_args.append(pkg.name) catch unreachable;
......@@ -1370,8 +1397,14 @@ pub const LibExeObjStep = struct {
13701397 }
13711398
13721399 for (self.full_path_libs.toSliceConst()) |full_path_lib| {
1373 zig_args.append("--library") catch unreachable;
1374 zig_args.append(builder.pathFromRoot(full_path_lib)) catch unreachable;
1400 try zig_args.append("--library");
1401 try zig_args.append(builder.pathFromRoot(full_path_lib));
1402
1403 const full_path_lib_abs = builder.pathFromRoot(full_path_lib);
1404 if (os.path.dirname(full_path_lib_abs)) |dirname| {
1405 try zig_args.append("-rpath");
1406 try zig_args.append(dirname);
1407 }
13751408 }
13761409
13771410 if (self.target.isDarwin()) {
......@@ -1382,574 +1415,20 @@ pub const LibExeObjStep = struct {
13821415 }
13831416 }
13841417
1385 if (self.no_rosegment) {
1386 try zig_args.append("--no-rosegment");
1387 }
13881418 if (self.system_linker_hack) {
13891419 try zig_args.append("--system-linker-hack");
13901420 }
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 }
19471422 if (self.override_std_dir) |dir| {
19481423 try zig_args.append("--override-std-dir");
19491424 try zig_args.append(builder.pathFromRoot(dir));
19501425 }
19511426
19521427 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 }
19531432 }
19541433};
19551434
......@@ -1995,6 +1474,7 @@ const InstallArtifactStep = struct {
19951474 pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {
19961475 const dest_dir = switch (artifact.kind) {
19971476 LibExeObjStep.Kind.Obj => unreachable,
1477 LibExeObjStep.Kind.Test => unreachable,
19981478 LibExeObjStep.Kind.Exe => builder.exe_dir,
19991479 LibExeObjStep.Kind.Lib => builder.lib_dir,
20001480 };
......@@ -2031,6 +1511,7 @@ const InstallArtifactStep = struct {
20311511 builtin.Os.windows => {},
20321512 else => switch (self.artifact.kind) {
20331513 LibExeObjStep.Kind.Obj => unreachable,
1514 LibExeObjStep.Kind.Test => unreachable,
20341515 LibExeObjStep.Kind.Exe => u32(0o755),
20351516 LibExeObjStep.Kind.Lib => if (self.artifact.static) u32(0o666) else u32(0o755),
20361517 },
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
3636pub extern "c" fn bind(socket: c_int, address: ?*const sockaddr, address_len: socklen_t) c_int;
3737pub 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
3941/// The value of the link editor defined symbol _MH_EXECUTE_SYM is the address
4042/// of the mach header in a Mach-O executable file type. It does not appear in
4143/// any file type other than a MH_EXECUTE file type. The type of the symbol is
4244/// 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
4554pub const mach_header_64 = macho.mach_header_64;
4655pub const mach_header = macho.mach_header;
std/c/index.zig+1
......@@ -6,6 +6,7 @@ pub use switch (builtin.os) {
66 Os.windows => @import("windows.zig"),
77 Os.macosx, Os.ios => @import("darwin.zig"),
88 Os.freebsd => @import("freebsd.zig"),
9 Os.netbsd => @import("netbsd.zig"),
910 else => empty_import,
1011};
1112const 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 {
9090 };
9191}
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
93144/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
94145/// TODO multithreaded awareness
95pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {
146pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void {
96147 const stderr = getStderrStream() catch return;
97148 const debug_info = getSelfDebugInfo() catch |err| {
98149 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
141192 const stderr = getStderrStream() catch os.abort();
142193 stderr.print(format ++ "\n", args) catch os.abort();
143194 if (trace) |t| {
144 dumpStackTrace(t);
195 dumpStackTrace(t.*);
145196 }
146197 dumpCurrentStackTrace(first_trace_addr);
147198
......@@ -155,16 +206,15 @@ const WHITE = "\x1b[37;1m";
155206const DIM = "\x1b[2m";
156207const 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 {
159 var frame_index: usize = undefined;
160 var frames_left: usize = undefined;
161 if (stack_trace.index < stack_trace.instruction_addresses.len) {
162 frame_index = 0;
163 frames_left = stack_trace.index;
164 } else {
165 frame_index = (stack_trace.index + 1) % stack_trace.instruction_addresses.len;
166 frames_left = stack_trace.instruction_addresses.len;
167 }
209pub fn writeStackTrace(
210 stack_trace: builtin.StackTrace,
211 out_stream: var,
212 allocator: *mem.Allocator,
213 debug_info: *DebugInfo,
214 tty_color: bool,
215) !void {
216 var frame_index: usize = 0;
217 var frames_left: usize = stack_trace.index;
168218
169219 while (frames_left != 0) : ({
170220 frames_left -= 1;
......@@ -240,7 +290,7 @@ pub fn writeCurrentStackTraceWindows(
240290pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
241291 switch (builtin.os) {
242292 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),
244294 builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),
245295 else => return error.UnsupportedOperatingSystem,
246296 }
......@@ -574,7 +624,7 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
574624}
575625
576626fn 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();
578628 const adjusted_addr = 0x100000000 + (address - base_addr);
579629
580630 const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
......@@ -717,7 +767,7 @@ pub const OpenSelfDebugInfoError = error{
717767
718768pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
719769 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),
721771 builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),
722772 builtin.Os.windows => return openSelfDebugInfoWindows(allocator),
723773 else => return error.UnsupportedOperatingSystem,
......@@ -1141,7 +1191,7 @@ pub const DebugInfo = switch (builtin.os) {
11411191 sect_contribs: []pdb.SectionContribEntry,
11421192 modules: []Module,
11431193 },
1144 builtin.Os.linux, builtin.Os.freebsd => DwarfInfo,
1194 builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => DwarfInfo,
11451195 else => @compileError("Unsupported OS"),
11461196};
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
8585 builtin.Os.macosx,
8686 builtin.Os.linux,
8787 builtin.Os.freebsd,
88 builtin.Os.netbsd,
8889 => {
8990 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
9091 defer loop.allocator.free(iovecs);
......@@ -222,6 +223,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:
222223 builtin.Os.macosx,
223224 builtin.Os.linux,
224225 builtin.Os.freebsd,
226 builtin.Os.netbsd,
225227 => {
226228 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
227229 defer loop.allocator.free(iovecs);
......@@ -402,7 +404,11 @@ pub async fn openPosix(
402404
403405pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {
404406 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 => {
406412 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
407413 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
408414 },
......@@ -431,6 +437,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
431437 builtin.Os.macosx,
432438 builtin.Os.linux,
433439 builtin.Os.freebsd,
440 builtin.Os.netbsd,
434441 => {
435442 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
436443 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
......@@ -453,7 +460,7 @@ pub async fn openReadWrite(
453460 mode: os.File.Mode,
454461) os.File.OpenError!os.FileHandle {
455462 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 => {
457464 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
458465 return await (async openPosix(loop, path, flags, mode) catch unreachable);
459466 },
......@@ -481,7 +488,7 @@ pub const CloseOperation = struct {
481488 os_data: OsData,
482489
483490 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
486493 builtin.Os.windows => struct {
487494 handle: ?os.FileHandle,
......@@ -500,7 +507,7 @@ pub const CloseOperation = struct {
500507 self.* = CloseOperation{
501508 .loop = loop,
502509 .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),
504511 builtin.Os.windows => OsData{ .handle = null },
505512 else => @compileError("Unsupported OS"),
506513 },
......@@ -530,6 +537,7 @@ pub const CloseOperation = struct {
530537 builtin.Os.linux,
531538 builtin.Os.macosx,
532539 builtin.Os.freebsd,
540 builtin.Os.netbsd,
533541 => {
534542 if (self.os_data.have_fd) {
535543 self.loop.posixFsRequest(&self.os_data.close_req_node);
......@@ -552,6 +560,7 @@ pub const CloseOperation = struct {
552560 builtin.Os.linux,
553561 builtin.Os.macosx,
554562 builtin.Os.freebsd,
563 builtin.Os.netbsd,
555564 => {
556565 self.os_data.close_req_node.data.msg.Close.fd = handle;
557566 self.os_data.have_fd = true;
......@@ -569,6 +578,7 @@ pub const CloseOperation = struct {
569578 builtin.Os.linux,
570579 builtin.Os.macosx,
571580 builtin.Os.freebsd,
581 builtin.Os.netbsd,
572582 => {
573583 self.os_data.have_fd = false;
574584 },
......@@ -584,6 +594,7 @@ pub const CloseOperation = struct {
584594 builtin.Os.linux,
585595 builtin.Os.macosx,
586596 builtin.Os.freebsd,
597 builtin.Os.netbsd,
587598 => {
588599 assert(self.os_data.have_fd);
589600 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,
608619 builtin.Os.linux,
609620 builtin.Os.macosx,
610621 builtin.Os.freebsd,
622 builtin.Os.netbsd,
611623 => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),
612624 builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),
613625 else => @compileError("Unsupported OS"),
......@@ -713,7 +725,7 @@ pub fn Watch(comptime V: type) type {
713725 os_data: OsData,
714726
715727 const OsData = switch (builtin.os) {
716 builtin.Os.macosx, builtin.Os.freebsd => struct {
728 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => struct {
717729 file_table: FileTable,
718730 table_lock: event.Lock,
719731
......@@ -802,7 +814,7 @@ pub fn Watch(comptime V: type) type {
802814 return self;
803815 },
804816
805 builtin.Os.macosx, builtin.Os.freebsd => {
817 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
806818 const self = try loop.allocator.create(Self);
807819 errdefer loop.allocator.destroy(self);
808820
......@@ -822,7 +834,7 @@ pub fn Watch(comptime V: type) type {
822834 /// All addFile calls and removeFile calls must have completed.
823835 pub fn destroy(self: *Self) void {
824836 switch (builtin.os) {
825 builtin.Os.macosx, builtin.Os.freebsd => {
837 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
826838 // TODO we need to cancel the coroutines before destroying the lock
827839 self.os_data.table_lock.deinit();
828840 var it = self.os_data.file_table.iterator();
......@@ -864,7 +876,10 @@ pub fn Watch(comptime V: type) type {
864876
865877 pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
866878 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),
868883 builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),
869884 builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),
870885 else => @compileError("Unsupported OS"),
std/event/loop.zig+11-10
......@@ -50,7 +50,7 @@ pub const Loop = struct {
5050 };
5151
5252 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,
5454 builtin.Os.linux => struct {
5555 base: ResumeNode,
5656 epoll_op: u32,
......@@ -69,7 +69,7 @@ pub const Loop = struct {
6969 };
7070
7171 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,
7373 builtin.Os.linux => struct {
7474 base: ResumeNode,
7575 },
......@@ -221,7 +221,7 @@ pub const Loop = struct {
221221 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
222222 }
223223 },
224 builtin.Os.macosx, builtin.Os.freebsd => {
224 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
225225 self.os_data.kqfd = try os.bsdKQueue();
226226 errdefer os.close(self.os_data.kqfd);
227227
......@@ -386,7 +386,7 @@ pub const Loop = struct {
386386 os.close(self.os_data.epollfd);
387387 self.allocator.free(self.eventfd_resume_nodes);
388388 },
389 builtin.Os.macosx, builtin.Os.freebsd => {
389 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
390390 os.close(self.os_data.kqfd);
391391 os.close(self.os_data.fs_kqfd);
392392 },
......@@ -501,7 +501,7 @@ pub const Loop = struct {
501501 const eventfd_node = &resume_stack_node.data;
502502 eventfd_node.base.handle = next_tick_node.data;
503503 switch (builtin.os) {
504 builtin.Os.macosx, builtin.Os.freebsd => {
504 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
505505 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
506506 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
507507 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
......@@ -564,6 +564,7 @@ pub const Loop = struct {
564564 builtin.Os.linux,
565565 builtin.Os.macosx,
566566 builtin.Os.freebsd,
567 builtin.Os.netbsd,
567568 => self.os_data.fs_thread.wait(),
568569 else => {},
569570 }
......@@ -628,7 +629,7 @@ pub const Loop = struct {
628629 os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
629630 return;
630631 },
631 builtin.Os.macosx, builtin.Os.freebsd => {
632 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
632633 self.posixFsRequest(&self.os_data.fs_end_request);
633634 const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
634635 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
......@@ -686,7 +687,7 @@ pub const Loop = struct {
686687 }
687688 }
688689 },
689 builtin.Os.macosx, builtin.Os.freebsd => {
690 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
690691 var eventlist: [1]posix.Kevent = undefined;
691692 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
692693 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
......@@ -749,7 +750,7 @@ pub const Loop = struct {
749750 self.beginOneEvent(); // finished in posixFsRun after processing the msg
750751 self.os_data.fs_queue.put(request_node);
751752 switch (builtin.os) {
752 builtin.Os.macosx, builtin.Os.freebsd => {
753 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
753754 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
754755 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
755756 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
......@@ -819,7 +820,7 @@ pub const Loop = struct {
819820 else => unreachable,
820821 }
821822 },
822 builtin.Os.macosx, builtin.Os.freebsd => {
823 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
823824 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
824825 var out_kevs: [1]posix.Kevent = undefined;
825826 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
......@@ -831,7 +832,7 @@ pub const Loop = struct {
831832
832833 const OsData = switch (builtin.os) {
833834 builtin.Os.linux => LinuxOsData,
834 builtin.Os.macosx, builtin.Os.freebsd => KEventData,
835 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventData,
835836 builtin.Os.windows => struct {
836837 io_port: windows.HANDLE,
837838 extra_thread_count: usize,
std/fmt/index.zig+11-2
......@@ -236,6 +236,9 @@ pub fn formatType(
236236 const casted_value = ([]const u8)(value);
237237 return output(context, casted_value);
238238 },
239 builtin.TypeInfo.Pointer.Size.C => {
240 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
241 },
239242 },
240243 builtin.TypeId.Array => |info| {
241244 if (info.child == u8) {
......@@ -828,7 +831,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
828831 return x;
829832}
830833
831test "parseUnsigned" {
834test "fmt.parseUnsigned" {
832835 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
833836 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
834837 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
......@@ -855,6 +858,12 @@ test "parseUnsigned" {
855858 testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
856859}
857860
861pub const parseFloat = @import("parse_float.zig").parseFloat;
862
863test "fmt.parseFloat" {
864 _ = @import("parse_float.zig");
865}
866
858867pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
859868 const value = switch (c) {
860869 '0'...'9' => c - '0',
......@@ -1109,7 +1118,7 @@ test "fmt.format" {
11091118 const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);
11101119 testing.expect(mem.eql(u8, result, "f64: nan\n"));
11111120 }
1112 if (builtin.arch != builtin.Arch.armv8) {
1121 if (builtin.arch != builtin.Arch.arm) {
11131122 // negative nan is not defined by IEE 754,
11141123 // and ARM thus normalizes it to positive nan
11151124 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
496496 builtin.TypeId.Pointer => |info| switch (info.size) {
497497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
498498 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"),
499500 builtin.TypeInfo.Pointer.Size.Slice => {
500501 const interval = std.math.max(1, key.len / 256);
501502 var i: usize = 0;
......@@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
543544 builtin.TypeId.Pointer => |info| switch (info.size) {
544545 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
545546 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"),
546548 builtin.TypeInfo.Pointer.Size.Slice => {
547549 if (a.len != b.len) return false;
548550 for (a) |a_item, i| {
std/heap.zig+3-3
......@@ -71,7 +71,7 @@ pub const DirectAllocator = struct {
7171 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
7272
7373 switch (builtin.os) {
74 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
74 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
7575 const p = os.posix;
7676 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
7777 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 {
120120 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
121121
122122 switch (builtin.os) {
123 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
123 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
124124 if (new_size <= old_mem.len) {
125125 const base_addr = @ptrToInt(old_mem.ptr);
126126 const old_addr_end = base_addr + old_mem.len;
......@@ -164,7 +164,7 @@ pub const DirectAllocator = struct {
164164 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
165165
166166 switch (builtin.os) {
167 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
167 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
168168 _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
169169 },
170170 Os.windows => {
std/index.zig+3-1
......@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
99pub const HashMap = @import("hash_map.zig").HashMap;
1010pub const LinkedList = @import("linked_list.zig").LinkedList;
1111pub const Mutex = @import("mutex.zig").Mutex;
12pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;
1213pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
1314pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
1415pub const SpinLock = @import("spinlock.zig").SpinLock;
......@@ -59,7 +60,7 @@ test "std" {
5960 _ = @import("statically_initialized_mutex.zig");
6061 _ = @import("segmented_list.zig");
6162 _ = @import("spinlock.zig");
62
63
6364 _ = @import("base64.zig");
6465 _ = @import("build.zig");
6566 _ = @import("c/index.zig");
......@@ -85,6 +86,7 @@ test "std" {
8586 _ = @import("net.zig");
8687 _ = @import("os/index.zig");
8788 _ = @import("pdb.zig");
89 _ = @import("priority_queue.zig");
8890 _ = @import("rand/index.zig");
8991 _ = @import("sort.zig");
9092 _ = @import("testing.zig");
std/io.zig+61-22
......@@ -343,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
343343 const amt_buffered = self.end_index - self.start_index;
344344 if (amt_buffered == 0) {
345345 assert(self.end_index <= buffer_size);
346 if (self.end_index == buffer_size) {
347 // we can read more data from the unbuffered stream
348 if (dest_space < buffer_size) {
349 self.start_index = 0;
350 self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
351 } else {
352 // asking for so much data that buffering is actually less efficient.
353 // forward the request directly to the unbuffered stream
354 const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
355 return dest_index + amt_read;
356 }
357 } else {
358 // reading from the unbuffered stream returned less than we asked for
359 // so we cannot read any more data.
346 // Make sure the last read actually gave us some data
347 if (self.end_index == 0) {
348 // reading from the unbuffered stream returned nothing
349 // so we have nothing left to read.
360350 return dest_index;
361351 }
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 }
362362 }
363
363364 const copy_amount = math.min(dest_space, amt_buffered);
364365 const copy_end_index = self.start_index + copy_amount;
365366 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)
370371 };
371372}
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
373414/// Creates a stream which supports 'un-reading' data, so that it can be read again.
374415/// This makes look-ahead style parsing much easier.
375416pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
......@@ -935,8 +976,6 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
935976 };
936977}
937978
938
939
940979pub const BufferedAtomicFile = struct {
941980 atomic_file: os.AtomicFile,
942981 file_stream: os.File.OutStream,
......@@ -978,7 +1017,6 @@ pub const BufferedAtomicFile = struct {
9781017 }
9791018};
9801019
981
9821020pub fn readLine(buf: *std.Buffer) ![]u8 {
9831021 var stdin = try getStdIn();
9841022 var stdin_stream = stdin.inStream();
......@@ -1073,13 +1111,13 @@ pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime E
10731111 else => in_stream,
10741112 } };
10751113 }
1076
1114
10771115 pub fn alignToByte(self: *Self) void {
1078 if(!is_packed) return;
1116 if (!is_packed) return;
10791117 self.in_stream.alignToByte();
10801118 }
10811119
1082 //@BUG: inferred error issue. See: #1386
1120 //@BUG: inferred error issue. See: #1386
10831121 fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
10841122 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
10881126
10891127 const U = @IntType(false, t_bit_count);
10901128 const Log2U = math.Log2Int(U);
1091 const int_size = @sizeOf(U);
1129 const int_size = (U.bit_count + 7) / 8;
10921130
10931131 if (is_packed) {
10941132 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
13011339
13021340 const U = @IntType(false, t_bit_count);
13031341 const Log2U = math.Log2Int(U);
1304 const int_size = @sizeOf(U);
1342 const int_size = (U.bit_count + 7) / 8;
13051343
13061344 const u_value = @bitCast(U, value);
13071345
......@@ -1414,3 +1452,4 @@ test "import io tests" {
14141452 _ = @import("io_test.zig");
14151453 }
14161454}
1455
std/io_test.zig+11
......@@ -29,6 +29,17 @@ test "write a file, read it, then delete it" {
2929 try st.print("end");
3030 try buf_stream.flush();
3131 }
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
3243 {
3344 var file = try os.File.openRead(tmp_file_name);
3445 defer file.close();
std/json.zig+6-2
......@@ -1345,7 +1345,7 @@ pub const Parser = struct {
13451345 return if (token.number_is_integer)
13461346 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
13471347 else
1348 @panic("TODO: fmt.parseFloat not yet implemented");
1348 Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) };
13491349 }
13501350};
13511351
......@@ -1366,7 +1366,8 @@ test "json.parser.dynamic" {
13661366 \\ },
13671367 \\ "Animated" : false,
13681368 \\ "IDs": [116, 943, 234, 38793],
1369 \\ "ArrayOfObject": [{"n": "m"}]
1369 \\ "ArrayOfObject": [{"n": "m"}],
1370 \\ "double": 1.3412
13701371 \\ }
13711372 \\}
13721373 ;
......@@ -1395,4 +1396,7 @@ test "json.parser.dynamic" {
13951396
13961397 const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
13971398 testing.expect(mem.eql(u8, obj0.String, "m"));
1399
1400 const double = image.Object.get("double").?.value;
1401 testing.expect(double.Float == 1.3412);
13981402}
std/math/fabs.zig+19
......@@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) {
1414 f16 => fabs16(x),
1515 f32 => fabs32(x),
1616 f64 => fabs64(x),
17 f128 => fabs128(x),
1718 else => @compileError("fabs not implemented for " ++ @typeName(T)),
1819 };
1920}
......@@ -36,10 +37,17 @@ fn fabs64(x: f64) f64 {
3637 return @bitCast(f64, u);
3738}
3839
40fn fabs128(x: f128) f128 {
41 var u = @bitCast(u128, x);
42 u &= maxInt(u128) >> 1;
43 return @bitCast(f128, u);
44}
45
3946test "math.fabs" {
4047 expect(fabs(f16(1.0)) == fabs16(1.0));
4148 expect(fabs(f32(1.0)) == fabs32(1.0));
4249 expect(fabs(f64(1.0)) == fabs64(1.0));
50 expect(fabs(f128(1.0)) == fabs128(1.0));
4351}
4452
4553test "math.fabs16" {
......@@ -57,6 +65,11 @@ test "math.fabs64" {
5765 expect(fabs64(-1.0) == 1.0);
5866}
5967
68test "math.fabs128" {
69 expect(fabs128(1.0) == 1.0);
70 expect(fabs128(-1.0) == 1.0);
71}
72
6073test "math.fabs16.special" {
6174 expect(math.isPositiveInf(fabs(math.inf(f16))));
6275 expect(math.isPositiveInf(fabs(-math.inf(f16))));
......@@ -74,3 +87,9 @@ test "math.fabs64.special" {
7487 expect(math.isPositiveInf(fabs(-math.inf(f64))));
7588 expect(math.isNan(fabs(math.nan(f64))));
7689}
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);
5151pub const inf_u64 = u64(0x7FF << 52);
5252pub 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
5460pub const nan = @import("nan.zig").nan;
5561pub const snan = @import("nan.zig").snan;
5662pub const inf = @import("inf.zig").inf;
......@@ -379,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
379385 return u0;
380386 }
381387 const is_signed = from < 0;
382 const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement
388 const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
383389 const base = log2(largest_positive_integer);
384390 const upper = (1 << base) - 1;
385391 var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
......@@ -752,6 +758,7 @@ test "minInt and maxInt" {
752758 testing.expect(maxInt(u16) == 65535);
753759 testing.expect(maxInt(u32) == 4294967295);
754760 testing.expect(maxInt(u64) == 18446744073709551615);
761 testing.expect(maxInt(u128) == 340282366920938463463374607431768211455);
755762
756763 testing.expect(maxInt(i0) == 0);
757764 testing.expect(maxInt(i1) == 0);
......@@ -760,6 +767,7 @@ test "minInt and maxInt" {
760767 testing.expect(maxInt(i32) == 2147483647);
761768 testing.expect(maxInt(i63) == 4611686018427387903);
762769 testing.expect(maxInt(i64) == 9223372036854775807);
770 testing.expect(maxInt(i128) == 170141183460469231731687303715884105727);
763771
764772 testing.expect(minInt(u0) == 0);
765773 testing.expect(minInt(u1) == 0);
......@@ -768,6 +776,7 @@ test "minInt and maxInt" {
768776 testing.expect(minInt(u32) == 0);
769777 testing.expect(minInt(u63) == 0);
770778 testing.expect(minInt(u64) == 0);
779 testing.expect(minInt(u128) == 0);
771780
772781 testing.expect(minInt(i0) == 0);
773782 testing.expect(minInt(i1) == -1);
......@@ -776,6 +785,7 @@ test "minInt and maxInt" {
776785 testing.expect(minInt(i32) == -2147483648);
777786 testing.expect(minInt(i63) == -4611686018427387904);
778787 testing.expect(minInt(i64) == -9223372036854775808);
788 testing.expect(minInt(i128) == -170141183460469231731687303715884105728);
779789}
780790
781791test "max value type" {
std/math/inf.zig+4-3
......@@ -3,9 +3,10 @@ const math = std.math;
33
44pub fn inf(comptime T: type) T {
55 return switch (T) {
6 f16 => @bitCast(f16, math.inf_u16),
7 f32 => @bitCast(f32, math.inf_u32),
8 f64 => @bitCast(f64, math.inf_u64),
6 f16 => math.inf_f16,
7 f32 => math.inf_f32,
8 f64 => math.inf_f64,
9 f128 => math.inf_f128,
910 else => @compileError("inf not implemented for " ++ @typeName(T)),
1011 };
1112}
std/math/isinf.zig+22
......@@ -18,6 +18,10 @@ pub fn isInf(x: var) bool {
1818 const bits = @bitCast(u64, x);
1919 return bits & (maxInt(u64) >> 1) == (0x7FF << 52);
2020 },
21 f128 => {
22 const bits = @bitCast(u128, x);
23 return bits & (maxInt(u128) >> 1) == (0x7FFF << 112);
24 },
2125 else => {
2226 @compileError("isInf not implemented for " ++ @typeName(T));
2327 },
......@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {
3640 f64 => {
3741 return @bitCast(u64, x) == 0x7FF << 52;
3842 },
43 f128 => {
44 return @bitCast(u128, x) == 0x7FFF << 112;
45 },
3946 else => {
4047 @compileError("isPositiveInf not implemented for " ++ @typeName(T));
4148 },
......@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {
5461 f64 => {
5562 return @bitCast(u64, x) == 0xFFF << 52;
5663 },
64 f128 => {
65 return @bitCast(u128, x) == 0xFFFF << 112;
66 },
5767 else => {
5868 @compileError("isNegativeInf not implemented for " ++ @typeName(T));
5969 },
......@@ -67,12 +77,16 @@ test "math.isInf" {
6777 expect(!isInf(f32(-0.0)));
6878 expect(!isInf(f64(0.0)));
6979 expect(!isInf(f64(-0.0)));
80 expect(!isInf(f128(0.0)));
81 expect(!isInf(f128(-0.0)));
7082 expect(isInf(math.inf(f16)));
7183 expect(isInf(-math.inf(f16)));
7284 expect(isInf(math.inf(f32)));
7385 expect(isInf(-math.inf(f32)));
7486 expect(isInf(math.inf(f64)));
7587 expect(isInf(-math.inf(f64)));
88 expect(isInf(math.inf(f128)));
89 expect(isInf(-math.inf(f128)));
7690}
7791
7892test "math.isPositiveInf" {
......@@ -82,12 +96,16 @@ test "math.isPositiveInf" {
8296 expect(!isPositiveInf(f32(-0.0)));
8397 expect(!isPositiveInf(f64(0.0)));
8498 expect(!isPositiveInf(f64(-0.0)));
99 expect(!isPositiveInf(f128(0.0)));
100 expect(!isPositiveInf(f128(-0.0)));
85101 expect(isPositiveInf(math.inf(f16)));
86102 expect(!isPositiveInf(-math.inf(f16)));
87103 expect(isPositiveInf(math.inf(f32)));
88104 expect(!isPositiveInf(-math.inf(f32)));
89105 expect(isPositiveInf(math.inf(f64)));
90106 expect(!isPositiveInf(-math.inf(f64)));
107 expect(isPositiveInf(math.inf(f128)));
108 expect(!isPositiveInf(-math.inf(f128)));
91109}
92110
93111test "math.isNegativeInf" {
......@@ -97,10 +115,14 @@ test "math.isNegativeInf" {
97115 expect(!isNegativeInf(f32(-0.0)));
98116 expect(!isNegativeInf(f64(0.0)));
99117 expect(!isNegativeInf(f64(-0.0)));
118 expect(!isNegativeInf(f128(0.0)));
119 expect(!isNegativeInf(f128(-0.0)));
100120 expect(!isNegativeInf(math.inf(f16)));
101121 expect(isNegativeInf(-math.inf(f16)));
102122 expect(!isNegativeInf(math.inf(f32)));
103123 expect(isNegativeInf(-math.inf(f32)));
104124 expect(!isNegativeInf(math.inf(f64)));
105125 expect(isNegativeInf(-math.inf(f64)));
126 expect(!isNegativeInf(math.inf(f128)));
127 expect(isNegativeInf(-math.inf(f128)));
106128}
std/math/isnan.zig+6
......@@ -18,6 +18,10 @@ pub fn isNan(x: var) bool {
1818 const bits = @bitCast(u64, x);
1919 return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52);
2020 },
21 f128 => {
22 const bits = @bitCast(u128, x);
23 return (bits & (maxInt(u128) >> 1)) > (u128(0x7FFF) << 112);
24 },
2125 else => {
2226 @compileError("isNan not implemented for " ++ @typeName(T));
2327 },
......@@ -34,7 +38,9 @@ test "math.isNan" {
3438 expect(isNan(math.nan(f16)));
3539 expect(isNan(math.nan(f32)));
3640 expect(isNan(math.nan(f64)));
41 expect(isNan(math.nan(f128)));
3742 expect(!isNan(f16(1.0)));
3843 expect(!isNan(f32(1.0)));
3944 expect(!isNan(f64(1.0)));
45 expect(!isNan(f128(1.0)));
4046}
std/math/nan.zig+4-3
......@@ -2,9 +2,10 @@ const math = @import("index.zig");
22
33pub fn nan(comptime T: type) T {
44 return switch (T) {
5 f16 => @bitCast(f16, math.nan_u16),
6 f32 => @bitCast(f32, math.nan_u32),
7 f64 => @bitCast(f64, math.nan_u64),
5 f16 => math.nan_f16,
6 f32 => math.nan_f32,
7 f64 => math.nan_f64,
8 f128 => math.nan_f128,
89 else => @compileError("nan not implemented for " ++ @typeName(T)),
910 };
1011}
std/math/powi.zig+8-1
......@@ -25,7 +25,7 @@ pub fn powi(comptime T: type, x: T, y: T) (error{
2525
2626 // powi(x, +-0) = 1 for any x
2727 if (y == 0 or y == -0) {
28 return 0;
28 return 1;
2929 }
3030
3131 switch (x) {
......@@ -174,4 +174,11 @@ test "math.powi.special" {
174174 testing.expectError(error.Overflow, powi(u64, 2, 64));
175175 testing.expectError(error.Overflow, powi(u17, 2, 17));
176176 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);
177184}
std/mem.zig+20-29
......@@ -423,8 +423,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.
423423/// This function cannot fail and cannot cause undefined behavior.
424424/// Assumes the endianness of memory is native. This means the function can
425425/// simply pointer cast memory.
426pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
427 comptime assert(T.bit_count % 8 == 0);
426pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
428427 return @ptrCast(*align(1) const T, bytes).*;
429428}
430429
......@@ -432,7 +431,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
432431/// The bit count of T must be evenly divisible by 8.
433432/// This function cannot fail and cannot cause undefined behavior.
434433/// 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 {
436435 return @bswap(T, readIntNative(T, bytes));
437436}
438437
......@@ -446,22 +445,20 @@ pub const readIntBig = switch (builtin.endian) {
446445 builtin.Endian.Big => readIntNative,
447446};
448447
449/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
448/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
450449/// and ignores extra bytes.
451/// Note that @sizeOf(u24) is 3.
452450/// The bit count of T must be evenly divisible by 8.
453451/// Assumes the endianness of memory is native. This means the function can
454452/// simply pointer cast memory.
455453pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
456 assert(@sizeOf(u24) == 3);
457 assert(bytes.len >= @sizeOf(T));
454 const n = @divExact(T.bit_count, 8);
455 assert(bytes.len >= n);
458456 // 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));
460458}
461459
462/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
460/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
463461/// and ignores extra bytes.
464/// Note that @sizeOf(u24) is 3.
465462/// The bit count of T must be evenly divisible by 8.
466463/// Assumes the endianness of memory is foreign, so it must byte-swap.
467464pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
......@@ -481,7 +478,7 @@ pub const readIntSliceBig = switch (builtin.endian) {
481478/// Reads an integer from memory with bit count specified by T.
482479/// The bit count of T must be evenly divisible by 8.
483480/// 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 {
485482 if (endian == builtin.endian) {
486483 return readIntNative(T, bytes);
487484 } else {
......@@ -489,15 +486,14 @@ pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.E
489486 }
490487}
491488
492/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
489/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
493490/// and ignores extra bytes.
494/// Note that @sizeOf(u24) is 3.
495491/// The bit count of T must be evenly divisible by 8.
496492pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
497 assert(@sizeOf(u24) == 3);
498 assert(bytes.len >= @sizeOf(T));
493 const n = @divExact(T.bit_count, 8);
494 assert(bytes.len >= n);
499495 // 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);
501497}
502498
503499test "comptime read/write int" {
......@@ -540,7 +536,7 @@ test "readIntBig and readIntLittle" {
540536/// accepts any integer bit width.
541537/// This function stores in native endian, which means it is implemented as a simple
542538/// 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 {
544540 @ptrCast(*align(1) T, buf).* = value;
545541}
546542
......@@ -548,7 +544,7 @@ pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
548544/// This function always succeeds, has defined behavior for all inputs, but
549545/// the integer bit width must be divisible by 8.
550546/// 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 {
552548 writeIntNative(T, buf, @bswap(T, value));
553549}
554550
......@@ -565,8 +561,7 @@ pub const writeIntBig = switch (builtin.endian) {
565561/// Writes an integer to memory, storing it in twos-complement.
566562/// This function always succeeds, has defined behavior for all inputs, but
567563/// 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 {
569 comptime assert(T.bit_count % 8 == 0);
564pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void {
570565 if (endian == builtin.endian) {
571566 return writeIntNative(T, buffer, value);
572567 } else {
......@@ -575,15 +570,13 @@ pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: bui
575570}
576571
577572/// 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.
579574/// The bit count of T must be divisible by 8.
580575/// Any extra bytes in buffer after writing the integer are set to zero. To
581576/// avoid the branch to check for extra buffer bytes, use writeIntLittle
582577/// instead.
583578pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
584 comptime assert(@sizeOf(u24) == 3);
585 comptime assert(T.bit_count % 8 == 0);
586 assert(buffer.len >= @sizeOf(T));
579 assert(buffer.len >= @divExact(T.bit_count, 8));
587580
588581 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
589582 const uint = @IntType(false, T.bit_count);
......@@ -595,14 +588,12 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
595588}
596589
597590/// 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.
599592/// The bit count of T must be divisible by 8.
600593/// Any extra bytes in buffer before writing the integer are set to zero. To
601594/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
602595pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
603 comptime assert(@sizeOf(u24) == 3);
604 comptime assert(T.bit_count % 8 == 0);
605 assert(buffer.len >= @sizeOf(T));
596 assert(buffer.len >= @divExact(T.bit_count, 8));
606597
607598 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
608599 const uint = @IntType(false, T.bit_count);
......@@ -626,7 +617,7 @@ pub const writeIntSliceForeign = switch (builtin.endian) {
626617};
627618
628619/// 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.
630621/// The bit count of T must be evenly divisible by 8.
631622/// Any extra bytes in buffer not part of the integer are set to zero, with
632623/// 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 {
463463 builtin.TypeId.Pointer => {
464464 const info = @typeInfo(T).Pointer;
465465 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,
467470 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
468471 }
469472 },
470473 builtin.TypeId.Optional => {
471 if(a == null and b == null) return true;
472 if(a == null or b == null) return false;
474 if (a == null and b == null) return true;
475 if (a == null or b == null) return false;
473476 return eql(a.?, b.?);
474477 },
475478 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 {
665665
666666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
667667 const ptr_result = c.mmap(
668 @ptrCast(*c_void, address),
668 @ptrCast(?*c_void, address),
669669 length,
670670 @bitCast(c_int, @intCast(c_uint, prot)),
671671 @bitCast(c_int, c_uint(flags)),
std/os/file.zig+4-4
......@@ -105,7 +105,7 @@ pub const File = struct {
105105 pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
106106 if (is_posix) {
107107 const path_c = try os.toPosixPath(path);
108 return openWriteNoClobberC(path_c, file_mode);
108 return openWriteNoClobberC(&path_c, file_mode);
109109 } else if (is_windows) {
110110 const path_w = try windows_util.sliceToPrefixedFileW(path);
111111 return openWriteNoClobberW(&path_w, file_mode);
......@@ -237,7 +237,7 @@ pub const File = struct {
237237
238238 pub fn seekForward(self: File, amount: isize) SeekError!void {
239239 switch (builtin.os) {
240 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
240 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
241241 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
242242 const err = posix.getErrno(result);
243243 if (err > 0) {
......@@ -268,7 +268,7 @@ pub const File = struct {
268268
269269 pub fn seekTo(self: File, pos: usize) SeekError!void {
270270 switch (builtin.os) {
271 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
271 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
272272 const ipos = try math.cast(isize, pos);
273273 const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);
274274 const err = posix.getErrno(result);
......@@ -309,7 +309,7 @@ pub const File = struct {
309309
310310 pub fn getPos(self: File) GetSeekPosError!usize {
311311 switch (builtin.os) {
312 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
312 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
313313 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
314314 const err = posix.getErrno(result);
315315 if (err > 0) {
std/os/freebsd/index.zig+1-1
......@@ -617,7 +617,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
617617
618618pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
619619 const ptr_result = c.mmap(
620 @ptrCast(*c_void, address),
620 @ptrCast(?*c_void, address),
621621 length,
622622 @bitCast(c_int, @intCast(c_uint, prot)),
623623 @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
4343 };
4444 return os.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname });
4545 },
46 builtin.Os.linux, builtin.Os.freebsd => {
46 builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
4747 const home_dir = os.getEnvPosix("HOME") orelse {
4848 // TODO look in /etc/passwd
4949 return error.AppDataDirUnavailable;
std/os/get_user_id.zig+1-1
......@@ -11,7 +11,7 @@ pub const UserInfo = struct {
1111/// POSIX function which gets a uid from username.
1212pub fn getUserInfo(name: []const u8) !UserInfo {
1313 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),
1515 else => @compileError("Unsupported OS"),
1616 };
1717}
std/os/index.zig+34-16
......@@ -3,7 +3,7 @@ const builtin = @import("builtin");
33const Os = builtin.Os;
44const is_windows = builtin.os == Os.windows;
55const 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,
77 else => false,
88};
99const os = @This();
......@@ -30,6 +30,7 @@ pub const windows = @import("windows/index.zig");
3030pub const darwin = @import("darwin.zig");
3131pub const linux = @import("linux/index.zig");
3232pub const freebsd = @import("freebsd/index.zig");
33pub const netbsd = @import("netbsd/index.zig");
3334pub const zen = @import("zen.zig");
3435pub const uefi = @import("uefi.zig");
3536
......@@ -37,6 +38,7 @@ pub const posix = switch (builtin.os) {
3738 Os.linux => linux,
3839 Os.macosx, Os.ios => darwin,
3940 Os.freebsd => freebsd,
41 Os.netbsd => netbsd,
4042 Os.zen => zen,
4143 else => @compileError("Unsupported OS"),
4244};
......@@ -50,7 +52,7 @@ pub const time = @import("time.zig");
5052
5153pub const page_size = 4 * 1024;
5254pub 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,
5456 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
5557 // If it would require 4 UTF-8 bytes, then there would be a surrogate
5658 // 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 {
125127 else => return unexpectedErrorPosix(errno),
126128 }
127129 },
128 Os.macosx, Os.ios, Os.freebsd => return getRandomBytesDevURandom(buf),
130 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => return getRandomBytesDevURandom(buf),
129131 Os.windows => {
130132 // Call RtlGenRandom() instead of CryptGetRandom() on Windows
131133 // https://github.com/rust-lang-nursery/rand/issues/111
......@@ -185,7 +187,7 @@ pub fn abort() noreturn {
185187 c.abort();
186188 }
187189 switch (builtin.os) {
188 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
190 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
189191 _ = posix.raise(posix.SIGABRT);
190192 _ = posix.raise(posix.SIGKILL);
191193 while (true) {}
......@@ -211,7 +213,7 @@ pub fn exit(status: u8) noreturn {
211213 c.exit(status);
212214 }
213215 switch (builtin.os) {
214 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
216 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
215217 posix.exit(status);
216218 },
217219 Os.windows => {
......@@ -327,7 +329,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
327329 }
328330 }
329331 },
330 builtin.Os.linux, builtin.Os.freebsd => while (true) {
332 builtin.Os.linux, builtin.Os.freebsd, Os.netbsd => while (true) {
331333 const rc = posix.preadv(fd, iov, count, offset);
332334 const err = posix.getErrno(rc);
333335 switch (err) {
......@@ -434,7 +436,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off
434436 }
435437 }
436438 },
437 builtin.Os.linux, builtin.Os.freebsd => while (true) {
439 builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => while (true) {
438440 const rc = posix.pwritev(fd, iov, count, offset);
439441 const err = posix.getErrno(rc);
440442 switch (err) {
......@@ -699,7 +701,9 @@ pub fn getBaseAddress() usize {
699701 const phdr = linuxGetAuxVal(std.elf.AT_PHDR);
700702 return phdr - @sizeOf(std.elf.Ehdr);
701703 },
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 },
703707 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
704708 else => @compileError("Unsupported OS"),
705709 }
......@@ -1339,7 +1343,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
13391343 const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);
13401344 return deleteDirW(&dir_path_w);
13411345 },
1342 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
1346 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
13431347 const err = posix.getErrno(posix.rmdir(dir_path));
13441348 switch (err) {
13451349 0 => return,
......@@ -1382,7 +1386,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
13821386 const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);
13831387 return deleteDirW(&dir_path_w);
13841388 },
1385 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
1389 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
13861390 const dir_path_c = try toPosixPath(dir_path);
13871391 return deleteDirC(&dir_path_c);
13881392 },
......@@ -1501,7 +1505,7 @@ pub const Dir = struct {
15011505 allocator: *Allocator,
15021506
15031507 pub const Handle = switch (builtin.os) {
1504 Os.macosx, Os.ios, Os.freebsd => struct {
1508 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => struct {
15051509 fd: i32,
15061510 seek: i64,
15071511 buf: []u8,
......@@ -1578,7 +1582,7 @@ pub const Dir = struct {
15781582 .name_data = undefined,
15791583 };
15801584 },
1581 Os.macosx, Os.ios, Os.freebsd => Handle{
1585 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => Handle{
15821586 .fd = try posixOpen(
15831587 dir_path,
15841588 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
......@@ -1609,7 +1613,7 @@ pub const Dir = struct {
16091613 Os.windows => {
16101614 _ = windows.FindClose(self.handle.handle);
16111615 },
1612 Os.macosx, Os.ios, Os.linux, Os.freebsd => {
1616 Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => {
16131617 self.allocator.free(self.handle.buf);
16141618 os.close(self.handle.fd);
16151619 },
......@@ -1625,6 +1629,7 @@ pub const Dir = struct {
16251629 Os.macosx, Os.ios => return self.nextDarwin(),
16261630 Os.windows => return self.nextWindows(),
16271631 Os.freebsd => return self.nextFreebsd(),
1632 Os.netbsd => return self.nextFreebsd(),
16281633 else => @compileError("unimplemented"),
16291634 }
16301635 }
......@@ -2256,7 +2261,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
22562261pub fn openSelfExe() !os.File {
22572262 switch (builtin.os) {
22582263 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 => {
22602265 var buf: [MAX_PATH_BYTES]u8 = undefined;
22612266 const self_exe_path = try selfExePath(&buf);
22622267 buf[self_exe_path.len] = 0;
......@@ -2317,6 +2322,19 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
23172322 else => unexpectedErrorPosix(err),
23182323 };
23192324 },
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 },
23202338 Os.windows => {
23212339 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
23222340 const utf16le_slice = try selfExePathW(&utf16le_buf);
......@@ -2355,7 +2373,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
23552373 // will not return null.
23562374 return path.dirname(full_exe_path).?;
23572375 },
2358 Os.windows, Os.macosx, Os.ios, Os.freebsd => {
2376 Os.windows, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
23592377 const self_exe_path = try selfExePath(out_buffer);
23602378 // Assume that the OS APIs return absolute paths, and therefore dirname
23612379 // will not return null.
......@@ -3227,7 +3245,7 @@ pub const CpuCountError = error{
32273245
32283246pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
32293247 switch (builtin.os) {
3230 builtin.Os.macosx, builtin.Os.freebsd => {
3248 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
32313249 var count: c_int = undefined;
32323250 var count_len: usize = @sizeOf(c_int);
32333251 const rc = posix.sysctlbyname(switch (builtin.os) {
std/os/linux/index.zig+1-1
......@@ -6,7 +6,7 @@ const vdso = @import("vdso.zig");
66pub use switch (builtin.arch) {
77 builtin.Arch.x86_64 => @import("x86_64.zig"),
88 builtin.Arch.i386 => @import("i386.zig"),
9 builtin.Arch.aarch64v8 => @import("arm64.zig"),
9 builtin.Arch.aarch64 => @import("arm64.zig"),
1010 else => @compileError("unsupported arch"),
1111};
1212pub 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
12261226 const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);
12271227 return realW(out_buffer, pathname_w);
12281228 },
1229 Os.freebsd, Os.macosx, Os.ios => {
1229 Os.freebsd, Os.netbsd, Os.macosx, Os.ios => {
12301230 // TODO instead of calling the libc function here, port the implementation to Zig
12311231 const err = posix.getErrno(posix.realpath(pathname, out_buffer));
12321232 switch (err) {
......@@ -1267,7 +1267,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!
12671267 const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);
12681268 return realW(out_buffer, &pathname_w);
12691269 },
1270 Os.macosx, Os.ios, Os.linux, Os.freebsd => {
1270 Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => {
12711271 const pathname_c = try os.toPosixPath(pathname);
12721272 return realC(out_buffer, &pathname_c);
12731273 },
std/os/time.zig+5-5
......@@ -14,7 +14,7 @@ pub const epoch = @import("epoch.zig");
1414/// Sleep for the specified duration
1515pub fn sleep(nanoseconds: u64) void {
1616 switch (builtin.os) {
17 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
17 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
1818 const s = nanoseconds / ns_per_s;
1919 const ns = nanoseconds % ns_per_s;
2020 posixSleep(@intCast(u63, s), @intCast(u63, ns));
......@@ -62,7 +62,7 @@ pub fn timestamp() u64 {
6262/// Get the posix timestamp, UTC, in milliseconds
6363pub const milliTimestamp = switch (builtin.os) {
6464 Os.windows => milliTimestampWindows,
65 Os.linux, Os.freebsd => milliTimestampPosix,
65 Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
6666 Os.macosx, Os.ios => milliTimestampDarwin,
6767 else => @compileError("Unsupported OS"),
6868};
......@@ -178,7 +178,7 @@ pub const Timer = struct {
178178 debug.assert(err != windows.FALSE);
179179 self.start_time = @intCast(u64, start_time);
180180 },
181 Os.linux, Os.freebsd => {
181 Os.linux, Os.freebsd, Os.netbsd => {
182182 //On Linux, seccomp can do arbitrary things to our ability to call
183183 // syscalls, including return any errno value it wants and
184184 // inconsistently throwing errors. Since we can't account for
......@@ -214,7 +214,7 @@ pub const Timer = struct {
214214 var clock = clockNative() - self.start_time;
215215 return switch (builtin.os) {
216216 Os.windows => @divFloor(clock * ns_per_s, self.frequency),
217 Os.linux, Os.freebsd => clock,
217 Os.linux, Os.freebsd, Os.netbsd => clock,
218218 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
219219 else => @compileError("Unsupported OS"),
220220 };
......@@ -235,7 +235,7 @@ pub const Timer = struct {
235235
236236 const clockNative = switch (builtin.os) {
237237 Os.windows => clockWindows,
238 Os.linux, Os.freebsd => clockLinux,
238 Os.linux, Os.freebsd, Os.netbsd => clockLinux,
239239 Os.macosx, Os.ios => clockDarwin,
240240 else => @compileError("Unsupported OS"),
241241 };
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 {
2323 switch (builtin.arch) {
2424 builtin.Arch.x86_64 => {
2525 argc_ptr = asm ("lea (%%rsp), %[argc]"
26 : [argc] "=r" (-> [*]usize)
27 );
26 : [argc] "=r" (-> [*]usize)
27 );
2828 },
2929 builtin.Arch.i386 => {
3030 argc_ptr = asm ("lea (%%esp), %[argc]"
3131 : [argc] "=r" (-> [*]usize)
3232 );
3333 },
34 builtin.Arch.aarch64v8 => {
34 builtin.Arch.aarch64, builtin.Arch.aarch64_be => {
3535 argc_ptr = asm ("mov %[argc], sp"
3636 : [argc] "=r" (-> [*]usize)
3737 );
......@@ -123,7 +123,7 @@ inline fn callMain() u8 {
123123 std.debug.warn("error: {}\n", @errorName(err));
124124 if (builtin.os != builtin.Os.zen) {
125125 if (@errorReturnTrace()) |trace| {
126 std.debug.dumpStackTrace(trace);
126 std.debug.dumpStackTrace(trace.*);
127127 }
128128 }
129129 return 1;
......@@ -142,7 +142,10 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent:
142142 var phdr_addr = at_phdr;
143143 var n = at_phnum;
144144 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 }) {
146149 const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);
147150 // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
148151 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 {
2121
2222 @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
2427 @export("__floattitf", @import("floattitf.zig").__floattitf, linkage);
2528 @export("__floattidf", @import("floattidf.zig").__floattidf, linkage);
2629 @export("__floattisf", @import("floattisf.zig").__floattisf, linkage);
......@@ -37,6 +40,7 @@ comptime {
3740 @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);
3841
3942 @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);
43 @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage);
4044 @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);
4145 @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);
4246
......@@ -180,60 +184,10 @@ const is_arm_64 = switch (builtin.arch) {
180184};
181185
182186const is_arm_arch = switch (builtin.arch) {
183 builtin.Arch.armv8_3a,
184 builtin.Arch.armv8_2a,
185 builtin.Arch.armv8_1a,
186 builtin.Arch.armv8,
187 builtin.Arch.armv8r,
188 builtin.Arch.armv8m_baseline,
189 builtin.Arch.armv8m_mainline,
190 builtin.Arch.armv7,
191 builtin.Arch.armv7em,
192 builtin.Arch.armv7m,
193 builtin.Arch.armv7s,
194 builtin.Arch.armv7k,
195 builtin.Arch.armv7ve,
196 builtin.Arch.armv6,
197 builtin.Arch.armv6m,
198 builtin.Arch.armv6k,
199 builtin.Arch.armv6t2,
200 builtin.Arch.armv5,
201 builtin.Arch.armv5te,
202 builtin.Arch.armv4t,
203 builtin.Arch.armebv8_3a,
204 builtin.Arch.armebv8_2a,
205 builtin.Arch.armebv8_1a,
206 builtin.Arch.armebv8,
207 builtin.Arch.armebv8r,
208 builtin.Arch.armebv8m_baseline,
209 builtin.Arch.armebv8m_mainline,
210 builtin.Arch.armebv7,
211 builtin.Arch.armebv7em,
212 builtin.Arch.armebv7m,
213 builtin.Arch.armebv7s,
214 builtin.Arch.armebv7k,
215 builtin.Arch.armebv7ve,
216 builtin.Arch.armebv6,
217 builtin.Arch.armebv6m,
218 builtin.Arch.armebv6k,
219 builtin.Arch.armebv6t2,
220 builtin.Arch.armebv5,
221 builtin.Arch.armebv5te,
222 builtin.Arch.armebv4t,
223 builtin.Arch.aarch64v8_3a,
224 builtin.Arch.aarch64v8_2a,
225 builtin.Arch.aarch64v8_1a,
226 builtin.Arch.aarch64v8,
227 builtin.Arch.aarch64v8r,
228 builtin.Arch.aarch64v8m_baseline,
229 builtin.Arch.aarch64v8m_mainline,
230 builtin.Arch.aarch64_bev8_3a,
231 builtin.Arch.aarch64_bev8_2a,
232 builtin.Arch.aarch64_bev8_1a,
233 builtin.Arch.aarch64_bev8,
234 builtin.Arch.aarch64_bev8r,
235 builtin.Arch.aarch64_bev8m_baseline,
236 builtin.Arch.aarch64_bev8m_mainline,
187 builtin.Arch.arm,
188 builtin.Arch.armeb,
189 builtin.Arch.aarch64,
190 builtin.Arch.aarch64_be,
237191 builtin.Arch.thumb,
238192 builtin.Arch.thumbeb,
239193 => true,
std/special/compiler_rt/truncXfYf2.zig+4
......@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {
44 return @bitCast(u16, truncXfYf2(f16, f32, a));
55}
66
7pub extern fn __truncdfhf2(a: f64) u16 {
8 return @bitCast(u16, truncXfYf2(f16, f64, a));
9}
10
711pub extern fn __trunctfsf2(a: f128) f32 {
812 return truncXfYf2(f32, f128, a);
913}
std/special/compiler_rt/truncXfYf2_test.zig+68
......@@ -63,6 +63,74 @@ test "truncsfhf2" {
6363 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
6464}
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
66134const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
67135
68136fn 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 {
5959 switch (pointer.size) {
6060 builtin.TypeInfo.Pointer.Size.One,
6161 builtin.TypeInfo.Pointer.Size.Many,
62 builtin.TypeInfo.Pointer.Size.C,
6263 => {
6364 if (actual != expected) {
6465 std.debug.panic("expected {}, found {}", expected, actual);
6566 }
6667 },
6768
68 builtin.TypeInfo.Pointer.Size.Slice => {
69 builtin.TypeInfo.Pointer.Size.Slice => {
6970 if (actual.ptr != expected.ptr) {
7071 std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);
7172 }
......@@ -118,7 +119,6 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
118119 }
119120 }
120121 },
121
122122 }
123123}
124124
std/zig/parse.zig+6-1
......@@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
35253525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
35263526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
35273527 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{
35293534 .PtrType = ast.Node.PrefixOp.PtrInfo{
35303535 .align_info = null,
35313536 .const_token = null,
std/zig/parser_test.zig+16
......@@ -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
117test "zig fmt: threadlocal" {
218 try testCanonical(
319 \\threadlocal var x: i32 = 1234;
std/zig/render.zig+3-2
......@@ -340,7 +340,6 @@ fn renderExpression(
340340 ast.Node.Id.InfixOp => {
341341 const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);
342342
343 const op_token = tree.tokens.at(infix_op_node.op_token);
344343 const op_space = switch (infix_op_node.op) {
345344 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
346345 else => Space.Space,
......@@ -353,7 +352,9 @@ fn renderExpression(
353352 };
354353
355354 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 {
357358 try stream.writeByteNTimes(' ', indent + indent_delta);
358359 start_col.* = indent + indent_delta;
359360 }
std/zig/tokenizer.zig+22-1
......@@ -141,6 +141,7 @@ pub const Token = struct {
141141 LineComment,
142142 DocComment,
143143 BracketStarBracket,
144 BracketStarCBracket,
144145 ShebangLine,
145146 Keyword_align,
146147 Keyword_and,
......@@ -279,6 +280,7 @@ pub const Tokenizer = struct {
279280 SawAtSign,
280281 LBracket,
281282 LBracketStar,
283 LBracketStarC,
282284 };
283285
284286 pub fn next(self: *Tokenizer) Token {
......@@ -456,6 +458,9 @@ pub const Tokenizer = struct {
456458 },
457459
458460 State.LBracketStar => switch (c) {
461 'c' => {
462 state = State.LBracketStarC;
463 },
459464 ']' => {
460465 result.id = Token.Id.BracketStarBracket;
461466 self.index += 1;
......@@ -467,6 +472,18 @@ pub const Tokenizer = struct {
467472 },
468473 },
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
470487 State.Ampersand => switch (c) {
471488 '=' => {
472489 result.id = Token.Id.AmpersandEqual;
......@@ -1035,6 +1052,7 @@ pub const Tokenizer = struct {
10351052 State.CharLiteralEnd,
10361053 State.StringLiteralBackslash,
10371054 State.LBracketStar,
1055 State.LBracketStarC,
10381056 => {
10391057 result.id = Token.Id.Invalid;
10401058 },
......@@ -1169,12 +1187,15 @@ test "tokenizer" {
11691187 testTokenize("test", []Token.Id{Token.Id.Keyword_test});
11701188}
11711189
1172test "tokenizer - unknown length pointer" {
1190test "tokenizer - unknown length pointer and then c pointer" {
11731191 testTokenize(
11741192 \\[*]u8
1193 \\[*c]u8
11751194 , []Token.Id{
11761195 Token.Id.BracketStarBracket,
11771196 Token.Id.Identifier,
1197 Token.Id.BracketStarCBracket,
1198 Token.Id.Identifier,
11781199 });
11791200}
11801201
test/build_examples.zig+2-6
......@@ -7,12 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
77 cases.addC("example/hello_world/hello_libc.zig");
88 cases.add("example/cat/main.zig");
99 cases.add("example/guess_number/main.zig");
10 if (!is_windows) {
11 // TODO get this test passing on windows
12 // See https://github.com/ziglang/zig/issues/538
13 cases.addBuildFile("example/shared_library/build.zig");
14 cases.addBuildFile("example/mix_o_files/build.zig");
15 }
10 cases.addBuildFile("example/shared_library/build.zig");
11 cases.addBuildFile("example/mix_o_files/build.zig");
1612 if (builtin.os != builtin.Os.macosx) {
1713 // TODO https://github.com/ziglang/zig/issues/1126
1814 cases.addBuildFile("test/standalone/issue_339/build.zig");
test/compile_errors.zig+405-69
......@@ -1,13 +1,330 @@
11const tests = @import("tests.zig");
2const builtin = @import("builtin");
23
34pub 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
4321 cases.addTest(
5322 "@truncate undefined value",
6323 \\export fn entry() void {
7324 \\ var z = @truncate(u8, u16(undefined));
8325 \\}
9326 ,
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",
11328 );
12329
13330 cases.addTest(
......@@ -121,12 +438,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
121438 "reading past end of pointer casted array",
122439 \\comptime {
123440 \\ const array = "aoeu";
124 \\ const slice = array[2..];
441 \\ const slice = array[1..];
125442 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
126443 \\ const deref = int_ptr.*;
127444 \\}
128445 ,
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",
130447 );
131448
132449 cases.add(
......@@ -210,13 +527,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
210527 );
211528
212529 cases.add(
213 "Panic declared with wrong type signature in tests",
530 "wrong panic signature, runtime function",
214531 \\test "" {}
215532 \\
216533 \\pub fn panic() void {}
217534 \\
218535 ,
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",
220547 );
221548
222549 cases.add(
......@@ -301,7 +628,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
301628 \\ _ = a.*.len;
302629 \\}
303630 ,
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'",
305632 );
306633
307634 cases.add(
......@@ -368,7 +695,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
368695 \\ f(i32);
369696 \\}
370697 ,
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",
372699 );
373700
374701 cases.add(
......@@ -768,7 +1095,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7681095 \\ command.exec();
7691096 \\}
7701097 ,
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",
7721099 );
7731100
7741101 cases.add(
......@@ -781,7 +1108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7811108 \\ command.exec();
7821109 \\}
7831110 ,
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",
7851112 );
7861113
7871114 cases.add(
......@@ -1012,7 +1339,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10121339 \\ Filled,
10131340 \\};
10141341 ,
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'",
10161343 );
10171344
10181345 cases.add(
......@@ -2089,7 +2416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
20892416 \\}
20902417 ,
20912418 ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'",
2092 ".tmp_source.zig:2:12: error: use of undeclared identifier 'i'",
20932419 );
20942420
20952421 cases.add(
......@@ -2752,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27523078 \\
27533079 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }
27543080 ,
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",
27563082 );
27573083
27583084 cases.add(
......@@ -2762,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27623088 \\ _ = a / a;
27633089 \\}
27643090 ,
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",
27663092 );
27673093
27683094 cases.add(
......@@ -2772,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27723098 \\ a /= a;
27733099 \\}
27743100 ,
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",
27763102 );
27773103
27783104 cases.add(
......@@ -2782,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27823108 \\ _ = a % a;
27833109 \\}
27843110 ,
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",
27863112 );
27873113
27883114 cases.add(
......@@ -2792,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27923118 \\ a %= a;
27933119 \\}
27943120 ,
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",
27963122 );
27973123
27983124 cases.add(
......@@ -2802,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28023128 \\ _ = a + a;
28033129 \\}
28043130 ,
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",
28063132 );
28073133
28083134 cases.add(
......@@ -2812,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28123138 \\ a += a;
28133139 \\}
28143140 ,
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",
28163142 );
28173143
28183144 cases.add(
......@@ -2822,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28223148 \\ _ = a +% a;
28233149 \\}
28243150 ,
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",
28263152 );
28273153
28283154 cases.add(
......@@ -2832,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28323158 \\ a +%= a;
28333159 \\}
28343160 ,
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",
28363162 );
28373163
28383164 cases.add(
......@@ -2842,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28423168 \\ _ = a - a;
28433169 \\}
28443170 ,
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",
28463172 );
28473173
28483174 cases.add(
......@@ -2852,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28523178 \\ a -= a;
28533179 \\}
28543180 ,
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",
28563182 );
28573183
28583184 cases.add(
......@@ -2862,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28623188 \\ _ = a -% a;
28633189 \\}
28643190 ,
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",
28663192 );
28673193
28683194 cases.add(
......@@ -2872,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28723198 \\ a -%= a;
28733199 \\}
28743200 ,
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",
28763202 );
28773203
28783204 cases.add(
......@@ -2882,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28823208 \\ _ = a * a;
28833209 \\}
28843210 ,
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",
28863212 );
28873213
28883214 cases.add(
......@@ -2892,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28923218 \\ a *= a;
28933219 \\}
28943220 ,
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",
28963222 );
28973223
28983224 cases.add(
......@@ -2902,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29023228 \\ _ = a *% a;
29033229 \\}
29043230 ,
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",
29063232 );
29073233
29083234 cases.add(
......@@ -2912,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29123238 \\ a *%= a;
29133239 \\}
29143240 ,
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",
29163242 );
29173243
29183244 cases.add(
......@@ -2922,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29223248 \\ _ = a << 2;
29233249 \\}
29243250 ,
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",
29263252 );
29273253
29283254 cases.add(
......@@ -2932,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29323258 \\ a <<= 2;
29333259 \\}
29343260 ,
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",
29363262 );
29373263
29383264 cases.add(
......@@ -2942,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29423268 \\ _ = a >> 2;
29433269 \\}
29443270 ,
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",
29463272 );
29473273
29483274 cases.add(
......@@ -2952,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29523278 \\ a >>= 2;
29533279 \\}
29543280 ,
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",
29563282 );
29573283
29583284 cases.add(
......@@ -2962,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29623288 \\ _ = a & a;
29633289 \\}
29643290 ,
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",
29663292 );
29673293
29683294 cases.add(
......@@ -2972,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29723298 \\ a &= a;
29733299 \\}
29743300 ,
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",
29763302 );
29773303
29783304 cases.add(
......@@ -2982,7 +3308,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29823308 \\ _ = a | a;
29833309 \\}
29843310 ,
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",
29863312 );
29873313
29883314 cases.add(
......@@ -2992,7 +3318,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29923318 \\ a |= a;
29933319 \\}
29943320 ,
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",
29963322 );
29973323
29983324 cases.add(
......@@ -3002,7 +3328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30023328 \\ _ = a ^ a;
30033329 \\}
30043330 ,
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",
30063332 );
30073333
30083334 cases.add(
......@@ -3012,7 +3338,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30123338 \\ a ^= a;
30133339 \\}
30143340 ,
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",
30163342 );
30173343
30183344 cases.add(
......@@ -3022,7 +3348,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30223348 \\ _ = a == a;
30233349 \\}
30243350 ,
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",
30263352 );
30273353
30283354 cases.add(
......@@ -3032,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30323358 \\ _ = a != a;
30333359 \\}
30343360 ,
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",
30363362 );
30373363
30383364 cases.add(
......@@ -3042,7 +3368,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30423368 \\ _ = a > a;
30433369 \\}
30443370 ,
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",
30463372 );
30473373
30483374 cases.add(
......@@ -3052,7 +3378,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30523378 \\ _ = a >= a;
30533379 \\}
30543380 ,
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",
30563382 );
30573383
30583384 cases.add(
......@@ -3062,7 +3388,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30623388 \\ _ = a < a;
30633389 \\}
30643390 ,
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",
30663392 );
30673393
30683394 cases.add(
......@@ -3072,7 +3398,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30723398 \\ _ = a <= a;
30733399 \\}
30743400 ,
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",
30763402 );
30773403
30783404 cases.add(
......@@ -3082,7 +3408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30823408 \\ _ = a and a;
30833409 \\}
30843410 ,
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",
30863412 );
30873413
30883414 cases.add(
......@@ -3092,7 +3418,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30923418 \\ _ = a or a;
30933419 \\}
30943420 ,
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",
30963422 );
30973423
30983424 cases.add(
......@@ -3102,7 +3428,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31023428 \\ _ = -a;
31033429 \\}
31043430 ,
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",
31063432 );
31073433
31083434 cases.add(
......@@ -3112,7 +3438,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31123438 \\ _ = -%a;
31133439 \\}
31143440 ,
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",
31163442 );
31173443
31183444 cases.add(
......@@ -3122,7 +3448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31223448 \\ _ = ~a;
31233449 \\}
31243450 ,
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",
31263452 );
31273453
31283454 cases.add(
......@@ -3132,7 +3458,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31323458 \\ _ = !a;
31333459 \\}
31343460 ,
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",
31363462 );
31373463
31383464 cases.add(
......@@ -3142,7 +3468,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31423468 \\ _ = a orelse false;
31433469 \\}
31443470 ,
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",
31463472 );
31473473
31483474 cases.add(
......@@ -3152,7 +3478,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31523478 \\ _ = a catch |err| false;
31533479 \\}
31543480 ,
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",
31563482 );
31573483
31583484 cases.add(
......@@ -3854,7 +4180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
38544180 \\
38554181 \\export fn entry() usize { return @sizeOf(@typeOf(pass)); }
38564182 ,
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'",
38584184 );
38594185
38604186 cases.add(
......@@ -4554,20 +4880,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
45544880 ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",
45554881 );
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
45714883 cases.add(
45724884 "wrong pointer implicitly casted to pointer to @OpaqueType()",
45734885 \\const Derp = @OpaqueType();
......@@ -4788,7 +5100,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
47885100
47895101 cases.add(
47905102 "non-printable invalid character",
4791 "\xff\xfe" ++
5103 "\xff\xfe" ++
47925104 \\fn test() bool {\r
47935105 \\ true\r
47945106 \\}
......@@ -5348,7 +5660,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
53485660 \\ Baz: void,
53495661 \\};
53505662 \\comptime {
5351 \\ var foo = Foo {.Baz = {}};
5663 \\ var foo = Foo {.Baz = {}};
53525664 \\ const bar_val = foo.Bar;
53535665 \\}
53545666 ,
......@@ -5430,4 +5742,28 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
54305742 ,
54315743 ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
54325744 );
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");
54335769}
test/runtime_safety.zig+51
......@@ -1,6 +1,16 @@
11const tests = @import("tests.zig");
22
33pub 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
414 cases.addRuntimeSafety("@intToEnum - no matching tag value",
515 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
616 \\ @import("std").os.exit(126);
......@@ -108,6 +118,47 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
108118 \\}
109119 );
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
111162 cases.addRuntimeSafety("integer subtraction overflow",
112163 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
113164 \\ @import("std").os.exit(126);
test/stage1/behavior.zig+8
......@@ -11,15 +11,22 @@ comptime {
1111 _ = @import("behavior/bswap.zig");
1212 _ = @import("behavior/bugs/1076.zig");
1313 _ = @import("behavior/bugs/1111.zig");
14 _ = @import("behavior/bugs/1120.zig");
1415 _ = @import("behavior/bugs/1277.zig");
1516 _ = @import("behavior/bugs/1322.zig");
1617 _ = @import("behavior/bugs/1381.zig");
1718 _ = @import("behavior/bugs/1421.zig");
1819 _ = @import("behavior/bugs/1442.zig");
1920 _ = @import("behavior/bugs/1486.zig");
21 _ = @import("behavior/bugs/1851.zig");
22 _ = @import("behavior/bugs/2006.zig");
2023 _ = @import("behavior/bugs/394.zig");
24 _ = @import("behavior/bugs/421.zig");
25 _ = @import("behavior/bugs/529.zig");
2126 _ = @import("behavior/bugs/655.zig");
2227 _ = @import("behavior/bugs/656.zig");
28 _ = @import("behavior/bugs/704.zig");
29 _ = @import("behavior/bugs/718.zig");
2330 _ = @import("behavior/bugs/726.zig");
2431 _ = @import("behavior/bugs/828.zig");
2532 _ = @import("behavior/bugs/920.zig");
......@@ -59,6 +66,7 @@ comptime {
5966 _ = @import("behavior/reflection.zig");
6067 _ = @import("behavior/sizeof_and_typeof.zig");
6168 _ = @import("behavior/slice.zig");
69 _ = @import("behavior/slicetobytes.zig");
6270 _ = @import("behavior/struct.zig");
6371 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
6472 _ = @import("behavior/struct_contains_slice_of_itself.zig");
test/stage1/behavior/bitcast.zig+78
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const builtin = @import("builtin");
23const expect = std.testing.expect;
34const maxInt = std.math.maxInt;
45
......@@ -34,3 +35,80 @@ test "@bitCast extern enum to its integer type" {
3435 SOCK.testBitCastExternEnum();
3536 comptime SOCK.testBitCastExternEnum();
3637}
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 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const expectError = std.testing.expectError;
34
45test "dereference pointer" {
56 comptime testDerefPtr();
......@@ -42,3 +43,84 @@ test "double pointer parsing" {
4243fn PtrOf(comptime T: type) type {
4344 return *T;
4445}
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 {
5050 return res;
5151 }
5252};
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 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
34const builtin = @import("builtin");
45const maxInt = std.math.maxInt;
56
......@@ -103,19 +104,20 @@ fn structInitializer() void {
103104}
104105
105106test "fn call of struct field" {
106 expect(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
107 const Foo = struct {
108 ptr: fn () i32,
109 };
110 const S = struct {
111 fn aFunc() i32 {
112 return 13;
113 }
112114
113fn aFunc() i32 {
114 return 13;
115}
115 fn callStructField(foo: Foo) i32 {
116 return foo.ptr();
117 }
118 };
116119
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
120 expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
119121}
120122
121123test "store member function in variable" {
......@@ -468,3 +470,32 @@ test "pointer to packed struct member in a stack variable" {
468470 b_ptr.* = 2;
469471 expect(s.b == 2);
470472}
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" {
2929 var result = @truncate(i8, x);
3030 expect(result == 10);
3131}
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 {
6161 expect(u32_ptr_info.Pointer.child == f64);
6262}
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
6479test "type info: slice type info" {
6580 testSlice();
6681 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
350350 expect(@enumToInt(t) == 33);
351351 comptime expect(@enumToInt(t) == 33);
352352}
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;
55test "vector wrap operators" {
66 const S = struct {
77 fn doTheTest() void {
8 const v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
9 const x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
10 expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ 11, 22, 33, 44 }));
11 expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 9, 18, 27, 36 }));
12 expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 10, 40, 90, 160 }));
8 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
9 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
10 expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ -2147483648, 2147483645, 33, 44 }));
11 expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 2147483646, 2147483647, 27, 36 }));
12 expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 2147483647, 2, 90, 160 }));
13 var z: @Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 };
14 expect(mem.eql(i32, ([4]i32)(-%z), [4]i32{ -1, -2, -3, -2147483648 }));
15 }
16 };
17 S.doTheTest();
18 comptime S.doTheTest();
19}
20
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 }));
1359 }
1460 };
1561 S.doTheTest();
test/stage1/c_abi/build.zig+3-2
......@@ -3,9 +3,10 @@ const Builder = @import("std").build.Builder;
33pub fn build(b: *Builder) void {
44 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"});
78 c_obj.setBuildMode(rel_opts);
8 c_obj.setNoStdLib(true);
9 c_obj.linkSystemLibrary("c");
910
1011 const main = b.addTest("main.zig");
1112 main.setBuildMode(rel_opts);
test/tests.zig+66-16
......@@ -24,24 +24,24 @@ const gen_h = @import("gen_h.zig");
2424const TestTarget = struct {
2525 os: builtin.Os,
2626 arch: builtin.Arch,
27 environ: builtin.Environ,
27 abi: builtin.Abi,
2828};
2929
3030const test_targets = []TestTarget{
3131 TestTarget{
3232 .os = builtin.Os.linux,
3333 .arch = builtin.Arch.x86_64,
34 .environ = builtin.Environ.gnu,
34 .abi = builtin.Abi.gnu,
3535 },
3636 TestTarget{
3737 .os = builtin.Os.macosx,
3838 .arch = builtin.Arch.x86_64,
39 .environ = builtin.Environ.unknown,
39 .abi = builtin.Abi.gnu,
4040 },
4141 TestTarget{
4242 .os = builtin.Os.windows,
4343 .arch = builtin.Arch.x86_64,
44 .environ = builtin.Environ.msvc,
44 .abi = builtin.Abi.msvc,
4545 },
4646};
4747
......@@ -189,7 +189,7 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
189189 these_tests.setFilter(test_filter);
190190 these_tests.setBuildMode(mode);
191191 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);
193193 }
194194 if (link_libc) {
195195 these_tests.linkSystemLibrary("c");
......@@ -536,6 +536,7 @@ pub const CompileErrorContext = struct {
536536 name: []const u8,
537537 sources: ArrayList(SourceFile),
538538 expected_errors: ArrayList([]const u8),
539 expect_exact: bool,
539540 link_libc: bool,
540541 is_exe: bool,
541542 is_test: bool,
......@@ -565,6 +566,24 @@ pub const CompileErrorContext = struct {
565566 case: *const TestCase,
566567 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
568587 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
569588 const allocator = context.b.allocator;
570589 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
......@@ -674,19 +693,49 @@ pub const CompileErrorContext = struct {
674693 return error.TestFailed;
675694 }
676695
677 for (self.case.expected_errors.toSliceConst()) |expected_error| {
678 if (mem.indexOf(u8, stderr, expected_error) == null) {
679 warn(
680 \\
681 \\========= Expected this compile error: =========
682 \\{}
683 \\================================================
684 \\{}
685 \\
686 , expected_error, stderr);
687 return error.TestFailed;
696 var ok = true;
697 if (self.case.expect_exact) {
698 var err_iter = ErrLineIter.init(stderr);
699 var i: usize = 0;
700 ok = while (err_iter.next()) |line| : (i += 1) {
701 if (i >= self.case.expected_errors.len) break false;
702 const expected = self.case.expected_errors.at(i);
703 if (mem.indexOf(u8, line, expected) == null) break false;
704 continue;
705 } else true;
706
707 ok = ok and i == self.case.expected_errors.len;
708
709 if (!ok) {
710 warn("\n======== Expected these compile errors: ========\n");
711 for (self.case.expected_errors.toSliceConst()) |expected| {
712 warn("{}\n", expected);
713 }
714 }
715 } else {
716 for (self.case.expected_errors.toSliceConst()) |expected| {
717 if (mem.indexOf(u8, stderr, expected) == null) {
718 warn(
719 \\
720 \\=========== Expected compile error: ============
721 \\{}
722 \\
723 , expected);
724 ok = false;
725 break;
726 }
688727 }
689728 }
729
730 if (!ok) {
731 warn(
732 \\================= Full output: =================
733 \\{}
734 \\
735 , stderr);
736 return error.TestFailed;
737 }
738
690739 warn("OK\n");
691740 }
692741 };
......@@ -704,6 +753,7 @@ pub const CompileErrorContext = struct {
704753 .name = name,
705754 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
706755 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
756 .expect_exact = false,
707757 .link_libc = false,
708758 .is_exe = false,
709759 .is_test = false,
test/translate_c.zig+69-31
......@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
117117 \\};
118118 ,
119119 \\pub const struct_Foo = extern struct {
120 \\ a: ?[*]Foo,
120 \\ a: [*c]Foo,
121121 \\};
122122 \\pub const Foo = struct_Foo;
123123 \\pub const struct_Bar = extern struct {
124 \\ a: ?[*]Foo,
124 \\ a: [*c]Foo,
125125 \\};
126126 );
127127
......@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213213 ,
214214 \\const struct_Foo = extern struct {
215215 \\ x: c_int,
216 \\ y: ?[*]u8,
216 \\ y: [*c]u8,
217217 \\};
218218 ,
219219 \\pub const Foo = struct_Foo;
......@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
244244 ,
245245 \\pub const BarB = enum_Bar.B;
246246 ,
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;
248248 ,
249249 \\pub const Foo = struct_Foo;
250250 ,
......@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
254254 cases.add("constant size array",
255255 \\void func(int array[20]);
256256 ,
257 \\pub extern fn func(array: ?[*]c_int) void;
257 \\pub extern fn func(array: [*c]c_int) void;
258258 );
259259
260260 cases.add("self referential struct with function pointer",
......@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263263 \\};
264264 ,
265265 \\pub const struct_Foo = extern struct {
266 \\ derp: ?extern fn(?[*]struct_Foo) void,
266 \\ derp: ?extern fn([*c]struct_Foo) void,
267267 \\};
268268 ,
269269 \\pub const Foo = struct_Foo;
......@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
322322 \\};
323323 ,
324324 \\pub const struct_Bar = extern struct {
325 \\ next: ?[*]struct_Foo,
325 \\ next: [*c]struct_Foo,
326326 \\};
327327 ,
328328 \\pub const struct_Foo = extern struct {
329 \\ next: ?[*]struct_Bar,
329 \\ next: [*c]struct_Bar,
330330 \\};
331331 );
332332
......@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
610610 ,
611611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != null)) return 1;
614 \\ if ((a != 0) and (c != null)) return 2;
613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != 0)) return 2;
615615 \\ if ((a != 0) or (b != 0)) return 3;
616 \\ if ((b != 0) or (c != null)) return 4;
617 \\ if ((a != 0) or (c != null)) return 5;
616 \\ if ((b != 0) or (c != 0)) return 4;
617 \\ if ((a != 0) or (c != 0)) return 5;
618618 \\ return 6;
619619 \\}
620620 );
......@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
710710 \\pub const struct_Foo = extern struct {
711711 \\ field: c_int,
712712 \\};
713 \\pub export fn read_field(foo: ?[*]struct_Foo) c_int {
713 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
714714 \\ return foo.?.field;
715715 \\}
716716 );
......@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756756 \\ return x;
757757 \\}
758758 ,
759 \\pub export fn foo(x: ?[*]c_ushort) ?*c_void {
759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760760 \\ return @ptrCast(?*c_void, x);
761761 \\}
762762 );
......@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
777777 \\ return 0;
778778 \\}
779779 ,
780 \\pub export fn foo() ?[*]c_int {
781 \\ return null;
780 \\pub export fn foo() [*c]c_int {
781 \\ return 0;
782782 \\}
783783 );
784784
......@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10861086 \\ *x = 1;
10871087 \\}
10881088 ,
1089 \\pub export fn foo(x: ?[*]c_int) void {
1089 \\pub export fn foo(x: [*c]c_int) void {
10901090 \\ x.?.* = 1;
10911091 \\}
10921092 );
......@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11141114 ,
11151115 \\pub fn foo() c_int {
11161116 \\ var x: c_int = 1234;
1117 \\ var ptr: ?[*]c_int = &x;
1117 \\ var ptr: [*c]c_int = &x;
11181118 \\ return ptr.?.*;
11191119 \\}
11201120 );
......@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11241124 \\ return "bar";
11251125 \\}
11261126 ,
1127 \\pub fn foo() ?[*]const u8 {
1127 \\pub fn foo() [*c]const u8 {
11281128 \\ return c"bar";
11291129 \\}
11301130 );
......@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12531253 \\ return (float *)a;
12541254 \\}
12551255 ,
1256 \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {
1257 \\ return @ptrCast(?[*]f32, a);
1256 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1257 \\ return @ptrCast([*c]f32, a);
12581258 \\}
12591259 );
12601260
......@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12801280 \\ return !(a == 0);
12811281 \\ return !(a != 0);
12821282 \\ return !(b != 0);
1283 \\ return !(c != null);
1283 \\ return !(c != 0);
12841284 \\}
12851285 );
12861286
......@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12971297 cases.add("const ptr initializer",
12981298 \\static const char *v0 = "0.0.0";
12991299 ,
1300 \\pub var v0: ?[*]const u8 = c"0.0.0";
1300 \\pub var v0: [*c]const u8 = c"0.0.0";
13011301 );
13021302
13031303 cases.add("static incomplete array inside function",
......@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13061306 \\}
13071307 ,
13081308 \\pub fn foo() void {
1309 \\ const v2: [*]const u8 = c"2.2.2";
1309 \\ const v2: [*c]const u8 = c"2.2.2";
13101310 \\}
13111311 );
13121312
13131313 cases.add("macro pointer cast",
13141314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
13151315 ,
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);
13171317 );
13181318
1319 cases.add("if on none bool",
1319 cases.add("if on non-bool",
13201320 \\enum SomeEnum { A, B, C };
13211321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
13221322 \\ if (a) return 0;
......@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13371337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
13381338 \\ if (a != 0) return 0;
13391339 \\ if (b != 0) return 1;
1340 \\ if (c != null) return 2;
1340 \\ if (c != 0) return 2;
13411341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
13421342 \\ return 4;
13431343 \\}
13441344 );
13451345
1346 cases.add("while on none bool",
1346 cases.add("while on non-bool",
13471347 \\int while_none_bool(int a, float b, void *c) {
13481348 \\ while (a) return 0;
13491349 \\ while (b) return 1;
......@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13541354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13551355 \\ while (a != 0) return 0;
13561356 \\ while (b != 0) return 1;
1357 \\ while (c != null) return 2;
1357 \\ while (c != 0) return 2;
13581358 \\ return 3;
13591359 \\}
13601360 );
13611361
1362 cases.add("for on none bool",
1362 cases.add("for on non-bool",
13631363 \\int for_none_bool(int a, float b, void *c) {
13641364 \\ for (;a;) return 0;
13651365 \\ for (;b;) return 1;
......@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13701370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13711371 \\ while (a != 0) return 0;
13721372 \\ while (b != 0) return 1;
1373 \\ while (c != null) return 2;
1373 \\ while (c != 0) return 2;
13741374 \\ return 3;
13751375 \\}
13761376 );
......@@ -1416,4 +1416,42 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14161416 \\ }
14171417 \\}
14181418 );
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 // );
14191457}