| author | |
| committer | |
| log | 6bfaf262d5a1d18482a813c7022ffb03a18f52a8 |
| tree | 7f432e8f386aed17df3f1bccdff34ec58b3ff2af |
| parent | 8b716f941dbd43936a994a008aec9cd21d0b08f2 |
| parent | 08dd1b553b37de24eaf24a37558b0f9993d4ca42 |
98 files changed, 2293 insertions(+), 1690 deletions(-)
CMakeLists.txt+14-14| ... | ... | @@ -49,6 +49,8 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead |
| 49 | 49 | find_package(llvm) |
| 50 | 50 | find_package(clang) |
| 51 | 51 | |
| 52 | set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp") | |
| 53 | ||
| 52 | 54 | if(ZIG_FORCE_EXTERNAL_LLD) |
| 53 | 55 | find_package(lld) |
| 54 | 56 | include_directories(${LLVM_INCLUDE_DIRS}) |
| ... | ... | @@ -192,6 +194,7 @@ else() |
| 192 | 194 | embedded_lld_coff |
| 193 | 195 | embedded_lld_lib |
| 194 | 196 | ) |
| 197 | install(TARGETS embedded_lld_elf embedded_lld_coff embedded_lld_lib DESTINATION "${ZIG_CPP_LIB_DIR}") | |
| 195 | 198 | endif() |
| 196 | 199 | |
| 197 | 200 | # No patches have been applied to SoftFloat-3d |
| ... | ... | @@ -345,6 +348,8 @@ set(ZIG_SOURCES |
| 345 | 348 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" |
| 346 | 349 | "${CMAKE_SOURCE_DIR}/src/util.cpp" |
| 347 | 350 | "${CMAKE_SOURCE_DIR}/src/translate_c.cpp" |
| 351 | ) | |
| 352 | set(ZIG_CPP_SOURCES | |
| 348 | 353 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" |
| 349 | 354 | ) |
| 350 | 355 | |
| ... | ... | @@ -390,6 +395,11 @@ if(ZIG_TEST_COVERAGE) |
| 390 | 395 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage") |
| 391 | 396 | endif() |
| 392 | 397 | |
| 398 | add_library(zig_cpp STATIC ${ZIG_CPP_SOURCES}) | |
| 399 | set_target_properties(zig_cpp PROPERTIES | |
| 400 | COMPILE_FLAGS ${EXE_CFLAGS} | |
| 401 | ) | |
| 402 | ||
| 393 | 403 | add_executable(zig ${ZIG_SOURCES}) |
| 394 | 404 | set_target_properties(zig PROPERTIES |
| 395 | 405 | COMPILE_FLAGS ${EXE_CFLAGS} |
| ... | ... | @@ -397,6 +407,7 @@ set_target_properties(zig PROPERTIES |
| 397 | 407 | ) |
| 398 | 408 | |
| 399 | 409 | target_link_libraries(zig LINK_PUBLIC |
| 410 | zig_cpp | |
| 400 | 411 | ${SOFTFLOAT_LIBRARIES} |
| 401 | 412 | ${CLANG_LIBRARIES} |
| 402 | 413 | ${LLD_LIBRARIES} |
| ... | ... | @@ -407,6 +418,7 @@ if(MSVC OR MINGW) |
| 407 | 418 | target_link_libraries(zig LINK_PUBLIC version) |
| 408 | 419 | endif() |
| 409 | 420 | install(TARGETS zig DESTINATION bin) |
| 421 | install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}") | |
| 410 | 422 | |
| 411 | 423 | install(FILES "${CMAKE_SOURCE_DIR}/c_headers/__clang_cuda_builtin_vars.h" DESTINATION "${C_HEADERS_DEST}") |
| 412 | 424 | install(FILES "${CMAKE_SOURCE_DIR}/c_headers/__clang_cuda_cmath.h" DESTINATION "${C_HEADERS_DEST}") |
| ... | ... | @@ -516,7 +528,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/c/index.zig" DESTINATION "${ZIG_STD_DEST} |
| 516 | 528 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/linux.zig" DESTINATION "${ZIG_STD_DEST}/c") |
| 517 | 529 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/windows.zig" DESTINATION "${ZIG_STD_DEST}/c") |
| 518 | 530 | install(FILES "${CMAKE_SOURCE_DIR}/std/cstr.zig" DESTINATION "${ZIG_STD_DEST}") |
| 519 | install(FILES "${CMAKE_SOURCE_DIR}/std/debug.zig" DESTINATION "${ZIG_STD_DEST}") | |
| 531 | install(FILES "${CMAKE_SOURCE_DIR}/std/debug/index.zig" DESTINATION "${ZIG_STD_DEST}/debug") | |
| 532 | install(FILES "${CMAKE_SOURCE_DIR}/std/debug/failing_allocator.zig" DESTINATION "${ZIG_STD_DEST}/debug") | |
| 520 | 533 | install(FILES "${CMAKE_SOURCE_DIR}/std/dwarf.zig" DESTINATION "${ZIG_STD_DEST}") |
| 521 | 534 | install(FILES "${CMAKE_SOURCE_DIR}/std/elf.zig" DESTINATION "${ZIG_STD_DEST}") |
| 522 | 535 | install(FILES "${CMAKE_SOURCE_DIR}/std/empty.zig" DESTINATION "${ZIG_STD_DEST}") |
| ... | ... | @@ -618,16 +631,3 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/udivti3.zig" DESTINAT |
| 618 | 631 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/umodti3.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") |
| 619 | 632 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/panic.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 620 | 633 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 621 | ||
| 622 | if (ZIG_TEST_COVERAGE) | |
| 623 | add_custom_target(coverage | |
| 624 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
| 625 | COMMAND lcov --directory . --zerocounters --rc lcov_branch_coverage=1 | |
| 626 | COMMAND ./zig build --build-file ../build.zig test | |
| 627 | COMMAND lcov --directory . --capture --output-file coverage.info --rc lcov_branch_coverage=1 | |
| 628 | COMMAND lcov --remove coverage.info '/usr/*' --output-file coverage.info.cleaned --rc lcov_branch_coverage=1 | |
| 629 | COMMAND genhtml -o coverage coverage.info.cleaned --rc lcov_branch_coverage=1 | |
| 630 | COMMAND rm coverage.info coverage.info.cleaned | |
| 631 | ) | |
| 632 | endif() | |
| 633 |
README.md+10-20| ... | ... | @@ -26,7 +26,7 @@ clarity. |
| 26 | 26 | always compiled against statically in source form. Compile units do not |
| 27 | 27 | depend on libc unless explicitly linked. |
| 28 | 28 | * Nullable type instead of null pointers. |
| 29 | * Tagged union type instead of raw unions. | |
| 29 | * Safe unions, tagged unions, and C ABI compatible unions. | |
| 30 | 30 | * Generics so that one can write efficient data structures that work for any |
| 31 | 31 | data type. |
| 32 | 32 | * No header files required. Top level declarations are entirely |
| ... | ... | @@ -35,7 +35,7 @@ clarity. |
| 35 | 35 | * Partial compile-time function evaluation with eliminates the need for |
| 36 | 36 | a preprocessor or macros. |
| 37 | 37 | * The binaries produced by Zig have complete debugging information so you can, |
| 38 | for example, use GDB to debug your software. | |
| 38 | for example, use GDB or MSVC to debug your software. | |
| 39 | 39 | * Built-in unit tests with `zig test`. |
| 40 | 40 | * Friendly toward package maintainers. Reproducible build, bootstrapping |
| 41 | 41 | process carefully documented. Issues filed by package maintainers are |
| ... | ... | @@ -78,10 +78,10 @@ that counts as "freestanding" for the purposes of this table. |
| 78 | 78 | |
| 79 | 79 | ### Wanted: Windows Developers |
| 80 | 80 | |
| 81 | Help get the tests passing on Windows, flesh out the standard library for | |
| 82 | Windows, streamline Zig installation and distribution for Windows. Work with | |
| 83 | LLVM and LLD teams to improve PDB/CodeView/MSVC debugging. Implement stack traces | |
| 84 | for Windows in the MinGW environment and the MSVC environment. | |
| 81 | Flesh out the standard library for Windows, streamline Zig installation and | |
| 82 | distribution for Windows. Work with LLVM and LLD teams to improve | |
| 83 | PDB/CodeView/MSVC debugging. Implement stack traces for Windows in the MinGW | |
| 84 | environment and the MSVC environment. | |
| 85 | 85 | |
| 86 | 86 | ### Wanted: MacOS and iOS Developers |
| 87 | 87 | |
| ... | ... | @@ -178,6 +178,10 @@ Dependencies are the same as Stage 1, except now you have a working zig compiler |
| 178 | 178 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install |
| 179 | 179 | ``` |
| 180 | 180 | |
| 181 | This produces `./stage2/bin/zig` which can be used for testing and development. | |
| 182 | Once it is feature complete, it will be used to build stage 3 - the final compiler | |
| 183 | binary. | |
| 184 | ||
| 181 | 185 | ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler |
| 182 | 186 | |
| 183 | 187 | This is the actual compiler binary that we will install to the system. |
| ... | ... | @@ -194,20 +198,6 @@ This is the actual compiler binary that we will install to the system. |
| 194 | 198 | ./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast |
| 195 | 199 | ``` |
| 196 | 200 | |
| 197 | ### Test Coverage | |
| 198 | ||
| 199 | To see test coverage in Zig, configure with `-DZIG_TEST_COVERAGE=ON` as an | |
| 200 | additional parameter to the Debug build. | |
| 201 | ||
| 202 | You must have `lcov` installed and available. | |
| 203 | ||
| 204 | Then `make coverage`. | |
| 205 | ||
| 206 | With GCC you will get a nice HTML view of the coverage data. With clang, | |
| 207 | the last step will fail, but you can execute | |
| 208 | `llvm-cov gcov $(find CMakeFiles/ -name "*.gcda")` and then inspect the | |
| 209 | produced .gcov files. | |
| 210 | ||
| 211 | 201 | ### Related Projects |
| 212 | 202 | |
| 213 | 203 | * [zig-mode](https://github.com/AndreaOrru/zig-mode) - Emacs integration |
build.zig+30-2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("std"); |
| 2 | 3 | const Builder = std.build.Builder; |
| 3 | 4 | const tests = @import("test/tests.zig"); |
| ... | ... | @@ -33,11 +34,32 @@ pub fn build(b: &Builder) { |
| 33 | 34 | docs_step.dependOn(&docgen_home_cmd.step); |
| 34 | 35 | |
| 35 | 36 | if (findLLVM(b)) |llvm| { |
| 37 | // find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library | |
| 38 | const build_info = b.exec([][]const u8{b.zig_exe, "BUILD_INFO"}); | |
| 39 | var build_info_it = mem.split(build_info, "\n"); | |
| 40 | const cmake_binary_dir = ??build_info_it.next(); | |
| 41 | const cxx_compiler = ??build_info_it.next(); | |
| 42 | ||
| 36 | 43 | var exe = b.addExecutable("zig", "src-self-hosted/main.zig"); |
| 37 | 44 | exe.setBuildMode(mode); |
| 38 | exe.linkSystemLibrary("c"); | |
| 45 | exe.addIncludeDir("src"); | |
| 46 | exe.addIncludeDir(cmake_binary_dir); | |
| 47 | addCppLib(b, exe, cmake_binary_dir, "libzig_cpp"); | |
| 48 | addCppLib(b, exe, cmake_binary_dir, "libembedded_lld_elf"); | |
| 49 | addCppLib(b, exe, cmake_binary_dir, "libembedded_lld_coff"); | |
| 50 | addCppLib(b, exe, cmake_binary_dir, "libembedded_lld_lib"); | |
| 39 | 51 | dependOnLib(exe, llvm); |
| 40 | 52 | |
| 53 | if (!exe.target.isWindows()) { | |
| 54 | const libstdcxx_path_padded = b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"}); | |
| 55 | const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\n").next(); | |
| 56 | exe.addObjectFile(libstdcxx_path); | |
| 57 | ||
| 58 | exe.linkSystemLibrary("pthread"); | |
| 59 | } | |
| 60 | ||
| 61 | exe.linkSystemLibrary("c"); | |
| 62 | ||
| 41 | 63 | b.default_step.dependOn(&exe.step); |
| 42 | 64 | b.default_step.dependOn(docs_step); |
| 43 | 65 | |
| ... | ... | @@ -91,6 +113,11 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) { |
| 91 | 113 | } |
| 92 | 114 | } |
| 93 | 115 | |
| 116 | fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) { | |
| 117 | lib_exe_obj.addObjectFile(%%os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", | |
| 118 | b.fmt("{}{}", lib_name, lib_exe_obj.target.libFileExt()))); | |
| 119 | } | |
| 120 | ||
| 94 | 121 | const LibraryDep = struct { |
| 95 | 122 | libdirs: ArrayList([]const u8), |
| 96 | 123 | libs: ArrayList([]const u8), |
| ... | ... | @@ -172,7 +199,8 @@ pub fn installStdLib(b: &Builder) { |
| 172 | 199 | "c/linux.zig", |
| 173 | 200 | "c/windows.zig", |
| 174 | 201 | "cstr.zig", |
| 175 | "debug.zig", | |
| 202 | "debug/failing_allocator.zig", | |
| 203 | "debug/index.zig", | |
| 176 | 204 | "dwarf.zig", |
| 177 | 205 | "elf.zig", |
| 178 | 206 | "empty.zig", |
doc/langref.html.in+9| ... | ... | @@ -291,6 +291,15 @@ pub fn main() -> %void { |
| 291 | 291 | <li><a href="#errors">Errors</a></li> |
| 292 | 292 | <li><a href="#root-source-file">Root Source File</a></li> |
| 293 | 293 | </ul> |
| 294 | <h2 id="values">Source encoding</h2> | |
| 295 | <p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p> | |
| 296 | <p>Throughout all zig source code (including in comments), some codepoints are never allowed:</p> | |
| 297 | <ul> | |
| 298 | <li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li> | |
| 299 | <li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li> | |
| 300 | </ul> | |
| 301 | <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code. A non-empty zig source must end with the line terminator character.</p> | |
| 302 | <p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/zig-lang/zig/issues/663">issue #663</a></p> | |
| 294 | 303 | <h2 id="values">Values</h2> |
| 295 | 304 | <pre><code class="zig">const warn = @import("std").debug.warn; |
| 296 | 305 | const os = @import("std").os; |
src-self-hosted/c.zig+2-5| ... | ... | @@ -1,7 +1,4 @@ |
| 1 | 1 | pub use @cImport({ |
| 2 | @cInclude("llvm-c/Core.h"); | |
| 3 | @cInclude("llvm-c/Analysis.h"); | |
| 4 | @cInclude("llvm-c/Target.h"); | |
| 5 | @cInclude("llvm-c/Initialization.h"); | |
| 6 | @cInclude("llvm-c/TargetMachine.h"); | |
| 2 | @cInclude("config.h"); | |
| 3 | @cInclude("zig_llvm.h"); | |
| 7 | 4 | }); |
src-self-hosted/ir.zig created+112| ... | ... | @@ -0,0 +1,112 @@ |
| 1 | const Scope = @import("scope.zig").Scope; | |
| 2 | ||
| 3 | pub const Instruction = struct { | |
| 4 | id: Id, | |
| 5 | scope: &Scope, | |
| 6 | ||
| 7 | pub const Id = enum { | |
| 8 | Br, | |
| 9 | CondBr, | |
| 10 | SwitchBr, | |
| 11 | SwitchVar, | |
| 12 | SwitchTarget, | |
| 13 | Phi, | |
| 14 | UnOp, | |
| 15 | BinOp, | |
| 16 | DeclVar, | |
| 17 | LoadPtr, | |
| 18 | StorePtr, | |
| 19 | FieldPtr, | |
| 20 | StructFieldPtr, | |
| 21 | UnionFieldPtr, | |
| 22 | ElemPtr, | |
| 23 | VarPtr, | |
| 24 | Call, | |
| 25 | Const, | |
| 26 | Return, | |
| 27 | Cast, | |
| 28 | ContainerInitList, | |
| 29 | ContainerInitFields, | |
| 30 | StructInit, | |
| 31 | UnionInit, | |
| 32 | Unreachable, | |
| 33 | TypeOf, | |
| 34 | ToPtrType, | |
| 35 | PtrTypeChild, | |
| 36 | SetDebugSafety, | |
| 37 | SetFloatMode, | |
| 38 | ArrayType, | |
| 39 | SliceType, | |
| 40 | Asm, | |
| 41 | SizeOf, | |
| 42 | TestNonNull, | |
| 43 | UnwrapMaybe, | |
| 44 | MaybeWrap, | |
| 45 | UnionTag, | |
| 46 | Clz, | |
| 47 | Ctz, | |
| 48 | Import, | |
| 49 | CImport, | |
| 50 | CInclude, | |
| 51 | CDefine, | |
| 52 | CUndef, | |
| 53 | ArrayLen, | |
| 54 | Ref, | |
| 55 | MinValue, | |
| 56 | MaxValue, | |
| 57 | CompileErr, | |
| 58 | CompileLog, | |
| 59 | ErrName, | |
| 60 | EmbedFile, | |
| 61 | Cmpxchg, | |
| 62 | Fence, | |
| 63 | Truncate, | |
| 64 | IntType, | |
| 65 | BoolNot, | |
| 66 | Memset, | |
| 67 | Memcpy, | |
| 68 | Slice, | |
| 69 | MemberCount, | |
| 70 | MemberType, | |
| 71 | MemberName, | |
| 72 | Breakpoint, | |
| 73 | ReturnAddress, | |
| 74 | FrameAddress, | |
| 75 | AlignOf, | |
| 76 | OverflowOp, | |
| 77 | TestErr, | |
| 78 | UnwrapErrCode, | |
| 79 | UnwrapErrPayload, | |
| 80 | ErrWrapCode, | |
| 81 | ErrWrapPayload, | |
| 82 | FnProto, | |
| 83 | TestComptime, | |
| 84 | PtrCast, | |
| 85 | BitCast, | |
| 86 | WidenOrShorten, | |
| 87 | IntToPtr, | |
| 88 | PtrToInt, | |
| 89 | IntToEnum, | |
| 90 | IntToErr, | |
| 91 | ErrToInt, | |
| 92 | CheckSwitchProngs, | |
| 93 | CheckStatementIsVoid, | |
| 94 | TypeName, | |
| 95 | CanImplicitCast, | |
| 96 | DeclRef, | |
| 97 | Panic, | |
| 98 | TagName, | |
| 99 | TagType, | |
| 100 | FieldParentPtr, | |
| 101 | OffsetOf, | |
| 102 | TypeId, | |
| 103 | SetEvalBranchQuota, | |
| 104 | PtrTypeOf, | |
| 105 | AlignCast, | |
| 106 | OpaqueType, | |
| 107 | SetAlignStack, | |
| 108 | ArgType, | |
| 109 | Export, | |
| 110 | }; | |
| 111 | ||
| 112 | }; |
src-self-hosted/main.zig+6-1| ... | ... | @@ -12,6 +12,7 @@ const ErrColor = Module.ErrColor; |
| 12 | 12 | const Emit = Module.Emit; |
| 13 | 13 | const builtin = @import("builtin"); |
| 14 | 14 | const ArrayList = std.ArrayList; |
| 15 | const c = @import("c.zig"); | |
| 15 | 16 | |
| 16 | 17 | error InvalidCommandLineArguments; |
| 17 | 18 | error ZigLibDirNotFound; |
| ... | ... | @@ -462,7 +463,11 @@ pub fn main2() -> %void { |
| 462 | 463 | else => unreachable, |
| 463 | 464 | } |
| 464 | 465 | }, |
| 465 | Cmd.Version => @panic("TODO zig version"), | |
| 466 | Cmd.Version => { | |
| 467 | var stdout_file = %return io.getStdErr(); | |
| 468 | %return stdout_file.write(std.cstr.toSliceConst(c.ZIG_VERSION_STRING)); | |
| 469 | %return stdout_file.write("\n"); | |
| 470 | }, | |
| 466 | 471 | Cmd.Targets => @panic("TODO zig targets"), |
| 467 | 472 | } |
| 468 | 473 | } |
src-self-hosted/module.zig+7| ... | ... | @@ -199,6 +199,13 @@ pub const Module = struct { |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | 201 | pub fn build(self: &Module) -> %void { |
| 202 | if (self.llvm_argv.len != 0) { | |
| 203 | var c_compatible_args = %return std.cstr.NullTerminated2DArray.fromSlices(self.allocator, | |
| 204 | [][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, }); | |
| 205 | defer c_compatible_args.deinit(); | |
| 206 | c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr); | |
| 207 | } | |
| 208 | ||
| 202 | 209 | const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path"); |
| 203 | 210 | const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| { |
| 204 | 211 | %return printError("unable to open '{}': {}", root_src_path, err); |
src-self-hosted/parser.zig+18-12| ... | ... | @@ -1119,18 +1119,24 @@ fn testCanonical(source: []const u8) { |
| 1119 | 1119 | break :x failing_allocator.index; |
| 1120 | 1120 | }; |
| 1121 | 1121 | |
| 1122 | // TODO make this pass | |
| 1123 | //var fail_index = needed_alloc_count; | |
| 1124 | //while (fail_index != 0) { | |
| 1125 | // fail_index -= 1; | |
| 1126 | // var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]); | |
| 1127 | // var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index); | |
| 1128 | // if (testParse(source, &failing_allocator.allocator)) |_| { | |
| 1129 | // @panic("non-deterministic memory usage"); | |
| 1130 | // } else |err| { | |
| 1131 | // assert(err == error.OutOfMemory); | |
| 1132 | // } | |
| 1133 | //} | |
| 1122 | var fail_index: usize = 0; | |
| 1123 | while (fail_index < needed_alloc_count) : (fail_index += 1) { | |
| 1124 | var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]); | |
| 1125 | var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index); | |
| 1126 | if (testParse(source, &failing_allocator.allocator)) |_| { | |
| 1127 | @panic("non-deterministic memory usage"); | |
| 1128 | } else |err| { | |
| 1129 | assert(err == error.OutOfMemory); | |
| 1130 | // TODO make this pass | |
| 1131 | //if (failing_allocator.allocated_bytes != failing_allocator.freed_bytes) { | |
| 1132 | // warn("\nfail_index: {}/{}\nallocated bytes: {}\nfreed bytes: {}\nallocations: {}\ndeallocations: {}\n", | |
| 1133 | // fail_index, needed_alloc_count, | |
| 1134 | // failing_allocator.allocated_bytes, failing_allocator.freed_bytes, | |
| 1135 | // failing_allocator.index, failing_allocator.deallocations); | |
| 1136 | // @panic("memory leak detected"); | |
| 1137 | //} | |
| 1138 | } | |
| 1139 | } | |
| 1134 | 1140 | } |
| 1135 | 1141 | |
| 1136 | 1142 | test "zig fmt" { |
src-self-hosted/scope.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | pub const Scope = struct { | |
| 2 | id: Id, | |
| 3 | parent: &Scope, | |
| 4 | ||
| 5 | pub const Id = enum { | |
| 6 | Decls, | |
| 7 | Block, | |
| 8 | Defer, | |
| 9 | DeferExpr, | |
| 10 | VarDecl, | |
| 11 | CImport, | |
| 12 | Loop, | |
| 13 | FnDef, | |
| 14 | CompTime, | |
| 15 | }; | |
| 16 | }; |
src-self-hosted/tokenizer.zig+217-4| ... | ... | @@ -70,6 +70,7 @@ pub const Token = struct { |
| 70 | 70 | Identifier, |
| 71 | 71 | StringLiteral: StrLitKind, |
| 72 | 72 | Eof, |
| 73 | NoEolAtEof, | |
| 73 | 74 | Builtin, |
| 74 | 75 | Bang, |
| 75 | 76 | Equal, |
| ... | ... | @@ -139,6 +140,8 @@ pub const Token = struct { |
| 139 | 140 | pub const Tokenizer = struct { |
| 140 | 141 | buffer: []const u8, |
| 141 | 142 | index: usize, |
| 143 | actual_file_end: usize, | |
| 144 | pending_invalid_token: ?Token, | |
| 142 | 145 | |
| 143 | 146 | pub const Location = struct { |
| 144 | 147 | line: usize, |
| ... | ... | @@ -177,9 +180,17 @@ pub const Tokenizer = struct { |
| 177 | 180 | } |
| 178 | 181 | |
| 179 | 182 | pub fn init(buffer: []const u8) -> Tokenizer { |
| 183 | var source_len = buffer.len; | |
| 184 | while (source_len > 0) : (source_len -= 1) { | |
| 185 | if (buffer[source_len - 1] == '\n') break; | |
| 186 | // last line is incomplete, so skip it, and give an error when we get there. | |
| 187 | } | |
| 188 | ||
| 180 | 189 | return Tokenizer { |
| 181 | .buffer = buffer, | |
| 190 | .buffer = buffer[0..source_len], | |
| 182 | 191 | .index = 0, |
| 192 | .actual_file_end = buffer.len, | |
| 193 | .pending_invalid_token = null, | |
| 183 | 194 | }; |
| 184 | 195 | } |
| 185 | 196 | |
| ... | ... | @@ -207,6 +218,10 @@ pub const Tokenizer = struct { |
| 207 | 218 | }; |
| 208 | 219 | |
| 209 | 220 | pub fn next(self: &Tokenizer) -> Token { |
| 221 | if (self.pending_invalid_token) |token| { | |
| 222 | self.pending_invalid_token = null; | |
| 223 | return token; | |
| 224 | } | |
| 210 | 225 | var state = State.Start; |
| 211 | 226 | var result = Token { |
| 212 | 227 | .id = Token.Id.Eof, |
| ... | ... | @@ -352,7 +367,7 @@ pub const Tokenizer = struct { |
| 352 | 367 | break; |
| 353 | 368 | }, |
| 354 | 369 | '\n' => break, // Look for this error later. |
| 355 | else => {}, | |
| 370 | else => self.checkLiteralCharacter(), | |
| 356 | 371 | }, |
| 357 | 372 | |
| 358 | 373 | State.StringLiteralBackslash => switch (c) { |
| ... | ... | @@ -439,7 +454,7 @@ pub const Tokenizer = struct { |
| 439 | 454 | .end = undefined, |
| 440 | 455 | }; |
| 441 | 456 | }, |
| 442 | else => {}, | |
| 457 | else => self.checkLiteralCharacter(), | |
| 443 | 458 | }, |
| 444 | 459 | State.Zero => switch (c) { |
| 445 | 460 | 'b', 'o', 'x' => { |
| ... | ... | @@ -497,13 +512,211 @@ pub const Tokenizer = struct { |
| 497 | 512 | } |
| 498 | 513 | } |
| 499 | 514 | result.end = self.index; |
| 500 | // TODO check state when returning EOF | |
| 515 | if (result.id == Token.Id.Eof) { | |
| 516 | if (self.pending_invalid_token) |token| { | |
| 517 | self.pending_invalid_token = null; | |
| 518 | return token; | |
| 519 | } | |
| 520 | if (self.actual_file_end != self.buffer.len) { | |
| 521 | // instead of an Eof, give an error token | |
| 522 | result.id = Token.Id.NoEolAtEof; | |
| 523 | result.end = self.actual_file_end; | |
| 524 | } | |
| 525 | } | |
| 501 | 526 | return result; |
| 502 | 527 | } |
| 503 | 528 | |
| 504 | 529 | pub fn getTokenSlice(self: &const Tokenizer, token: &const Token) -> []const u8 { |
| 505 | 530 | return self.buffer[token.start..token.end]; |
| 506 | 531 | } |
| 532 | ||
| 533 | fn checkLiteralCharacter(self: &Tokenizer) { | |
| 534 | if (self.pending_invalid_token != null) return; | |
| 535 | const invalid_length = self.getInvalidCharacterLength(); | |
| 536 | if (invalid_length == 0) return; | |
| 537 | self.pending_invalid_token = Token { | |
| 538 | .id = Token.Id.Invalid, | |
| 539 | .start = self.index, | |
| 540 | .end = self.index + invalid_length, | |
| 541 | }; | |
| 542 | } | |
| 543 | ||
| 544 | fn getInvalidCharacterLength(self: &Tokenizer) -> u3 { | |
| 545 | const c0 = self.buffer[self.index]; | |
| 546 | if (c0 < 0x80) { | |
| 547 | if (c0 < 0x20 or c0 == 0x7f) { | |
| 548 | // ascii control codes are never allowed | |
| 549 | // (note that \n was checked before we got here) | |
| 550 | return 1; | |
| 551 | } | |
| 552 | // looks fine to me. | |
| 553 | return 0; | |
| 554 | } else { | |
| 555 | // check utf8-encoded character. | |
| 556 | // remember that the last byte in the buffer is guaranteed to be '\n', | |
| 557 | // which means we really don't need to do bounds checks here, | |
| 558 | // as long as we check one byte at a time for being a continuation byte. | |
| 559 | var value: u32 = undefined; | |
| 560 | var length: u3 = undefined; | |
| 561 | if (c0 & 0b11100000 == 0b11000000) {value = c0 & 0b00011111; length = 2;} | |
| 562 | else if (c0 & 0b11110000 == 0b11100000) {value = c0 & 0b00001111; length = 3;} | |
| 563 | else if (c0 & 0b11111000 == 0b11110000) {value = c0 & 0b00000111; length = 4;} | |
| 564 | else return 1; // unexpected continuation or too many leading 1's | |
| 565 | ||
| 566 | const c1 = self.buffer[self.index + 1]; | |
| 567 | if (c1 & 0b11000000 != 0b10000000) return 1; // expected continuation | |
| 568 | value <<= 6; | |
| 569 | value |= c1 & 0b00111111; | |
| 570 | if (length == 2) { | |
| 571 | if (value < 0x80) return length; // overlong | |
| 572 | if (value == 0x85) return length; // U+0085 (NEL) | |
| 573 | self.index += length - 1; | |
| 574 | return 0; | |
| 575 | } | |
| 576 | const c2 = self.buffer[self.index + 2]; | |
| 577 | if (c2 & 0b11000000 != 0b10000000) return 2; // expected continuation | |
| 578 | value <<= 6; | |
| 579 | value |= c2 & 0b00111111; | |
| 580 | if (length == 3) { | |
| 581 | if (value < 0x800) return length; // overlong | |
| 582 | if (value == 0x2028) return length; // U+2028 (LS) | |
| 583 | if (value == 0x2029) return length; // U+2029 (PS) | |
| 584 | if (0xd800 <= value and value <= 0xdfff) return length; // surrogate halves not allowed in utf8 | |
| 585 | self.index += length - 1; | |
| 586 | return 0; | |
| 587 | } | |
| 588 | const c3 = self.buffer[self.index + 3]; | |
| 589 | if (c3 & 0b11000000 != 0b10000000) return 3; // expected continuation | |
| 590 | value <<= 6; | |
| 591 | value |= c3 & 0b00111111; | |
| 592 | if (length == 4) { | |
| 593 | if (value < 0x10000) return length; // overlong | |
| 594 | if (value > 0x10FFFF) return length; // out of bounds | |
| 595 | self.index += length - 1; | |
| 596 | return 0; | |
| 597 | } | |
| 598 | unreachable; | |
| 599 | } | |
| 600 | } | |
| 507 | 601 | }; |
| 508 | 602 | |
| 509 | 603 | |
| 604 | ||
| 605 | test "tokenizer - source must end with eol" { | |
| 606 | testTokenizeWithEol("", []Token.Id { | |
| 607 | }, true); | |
| 608 | testTokenizeWithEol("no newline", []Token.Id { | |
| 609 | }, false); | |
| 610 | testTokenizeWithEol("test\n", []Token.Id { | |
| 611 | Token.Id.Keyword_test, | |
| 612 | }, true); | |
| 613 | testTokenizeWithEol("test\nno newline", []Token.Id { | |
| 614 | Token.Id.Keyword_test, | |
| 615 | }, false); | |
| 616 | } | |
| 617 | ||
| 618 | test "tokenizer - invalid token characters" { | |
| 619 | testTokenize("#\n", []Token.Id{Token.Id.Invalid}); | |
| 620 | testTokenize("`\n", []Token.Id{Token.Id.Invalid}); | |
| 621 | } | |
| 622 | ||
| 623 | test "tokenizer - invalid literal/comment characters" { | |
| 624 | testTokenize("\"\x00\"\n", []Token.Id { | |
| 625 | Token.Id { .StringLiteral = Token.StrLitKind.Normal }, | |
| 626 | Token.Id.Invalid, | |
| 627 | }); | |
| 628 | testTokenize("//\x00\n", []Token.Id { | |
| 629 | Token.Id.Invalid, | |
| 630 | }); | |
| 631 | testTokenize("//\x1f\n", []Token.Id { | |
| 632 | Token.Id.Invalid, | |
| 633 | }); | |
| 634 | testTokenize("//\x7f\n", []Token.Id { | |
| 635 | Token.Id.Invalid, | |
| 636 | }); | |
| 637 | } | |
| 638 | ||
| 639 | test "tokenizer - valid unicode" { | |
| 640 | testTokenize("//\xc2\x80\n", []Token.Id{}); | |
| 641 | testTokenize("//\xdf\xbf\n", []Token.Id{}); | |
| 642 | testTokenize("//\xe0\xa0\x80\n", []Token.Id{}); | |
| 643 | testTokenize("//\xe1\x80\x80\n", []Token.Id{}); | |
| 644 | testTokenize("//\xef\xbf\xbf\n", []Token.Id{}); | |
| 645 | testTokenize("//\xf0\x90\x80\x80\n", []Token.Id{}); | |
| 646 | testTokenize("//\xf1\x80\x80\x80\n", []Token.Id{}); | |
| 647 | testTokenize("//\xf3\xbf\xbf\xbf\n", []Token.Id{}); | |
| 648 | testTokenize("//\xf4\x8f\xbf\xbf\n", []Token.Id{}); | |
| 649 | } | |
| 650 | ||
| 651 | test "tokenizer - invalid unicode continuation bytes" { | |
| 652 | // unexpected continuation | |
| 653 | testTokenize("//\x80\n", []Token.Id{Token.Id.Invalid}); | |
| 654 | testTokenize("//\xbf\n", []Token.Id{Token.Id.Invalid}); | |
| 655 | // too many leading 1's | |
| 656 | testTokenize("//\xf8\n", []Token.Id{Token.Id.Invalid}); | |
| 657 | testTokenize("//\xff\n", []Token.Id{Token.Id.Invalid}); | |
| 658 | // expected continuation for 2 byte sequences | |
| 659 | testTokenize("//\xc2\x00\n", []Token.Id{Token.Id.Invalid}); | |
| 660 | testTokenize("//\xc2\xc0\n", []Token.Id{Token.Id.Invalid}); | |
| 661 | // expected continuation for 3 byte sequences | |
| 662 | testTokenize("//\xe0\x00\n", []Token.Id{Token.Id.Invalid}); | |
| 663 | testTokenize("//\xe0\xc0\n", []Token.Id{Token.Id.Invalid}); | |
| 664 | testTokenize("//\xe0\xa0\n", []Token.Id{Token.Id.Invalid}); | |
| 665 | testTokenize("//\xe0\xa0\x00\n", []Token.Id{Token.Id.Invalid}); | |
| 666 | testTokenize("//\xe0\xa0\xc0\n", []Token.Id{Token.Id.Invalid}); | |
| 667 | // expected continuation for 4 byte sequences | |
| 668 | testTokenize("//\xf0\x00\n", []Token.Id{Token.Id.Invalid}); | |
| 669 | testTokenize("//\xf0\xc0\n", []Token.Id{Token.Id.Invalid}); | |
| 670 | testTokenize("//\xf0\x90\x00\n", []Token.Id{Token.Id.Invalid}); | |
| 671 | testTokenize("//\xf0\x90\xc0\n", []Token.Id{Token.Id.Invalid}); | |
| 672 | testTokenize("//\xf0\x90\x80\x00\n", []Token.Id{Token.Id.Invalid}); | |
| 673 | testTokenize("//\xf0\x90\x80\xc0\n", []Token.Id{Token.Id.Invalid}); | |
| 674 | } | |
| 675 | ||
| 676 | test "tokenizer - overlong utf8 codepoint" { | |
| 677 | testTokenize("//\xc0\x80\n", []Token.Id{Token.Id.Invalid}); | |
| 678 | testTokenize("//\xc1\xbf\n", []Token.Id{Token.Id.Invalid}); | |
| 679 | testTokenize("//\xe0\x80\x80\n", []Token.Id{Token.Id.Invalid}); | |
| 680 | testTokenize("//\xe0\x9f\xbf\n", []Token.Id{Token.Id.Invalid}); | |
| 681 | testTokenize("//\xf0\x80\x80\x80\n", []Token.Id{Token.Id.Invalid}); | |
| 682 | testTokenize("//\xf0\x8f\xbf\xbf\n", []Token.Id{Token.Id.Invalid}); | |
| 683 | } | |
| 684 | ||
| 685 | test "tokenizer - misc invalid utf8" { | |
| 686 | // codepoint out of bounds | |
| 687 | testTokenize("//\xf4\x90\x80\x80\n", []Token.Id{Token.Id.Invalid}); | |
| 688 | testTokenize("//\xf7\xbf\xbf\xbf\n", []Token.Id{Token.Id.Invalid}); | |
| 689 | // unicode newline characters.U+0085, U+2028, U+2029 | |
| 690 | testTokenize("//\xc2\x84\n", []Token.Id{}); | |
| 691 | testTokenize("//\xc2\x85\n", []Token.Id{Token.Id.Invalid}); | |
| 692 | testTokenize("//\xc2\x86\n", []Token.Id{}); | |
| 693 | testTokenize("//\xe2\x80\xa7\n", []Token.Id{}); | |
| 694 | testTokenize("//\xe2\x80\xa8\n", []Token.Id{Token.Id.Invalid}); | |
| 695 | testTokenize("//\xe2\x80\xa9\n", []Token.Id{Token.Id.Invalid}); | |
| 696 | testTokenize("//\xe2\x80\xaa\n", []Token.Id{}); | |
| 697 | // surrogate halves | |
| 698 | testTokenize("//\xed\x9f\x80\n", []Token.Id{}); | |
| 699 | testTokenize("//\xed\xa0\x80\n", []Token.Id{Token.Id.Invalid}); | |
| 700 | testTokenize("//\xed\xbf\xbf\n", []Token.Id{Token.Id.Invalid}); | |
| 701 | testTokenize("//\xee\x80\x80\n", []Token.Id{}); | |
| 702 | // surrogate halves are invalid, even in surrogate pairs | |
| 703 | testTokenize("//\xed\xa0\xad\xed\xb2\xa9\n", []Token.Id{Token.Id.Invalid}); | |
| 704 | } | |
| 705 | ||
| 706 | fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) { | |
| 707 | testTokenizeWithEol(source, expected_tokens, true); | |
| 708 | } | |
| 709 | fn testTokenizeWithEol(source: []const u8, expected_tokens: []const Token.Id, expected_eol_at_eof: bool) { | |
| 710 | var tokenizer = Tokenizer.init(source); | |
| 711 | for (expected_tokens) |expected_token_id| { | |
| 712 | const token = tokenizer.next(); | |
| 713 | std.debug.assert(@TagType(Token.Id)(token.id) == @TagType(Token.Id)(expected_token_id)); | |
| 714 | switch (expected_token_id) { | |
| 715 | Token.Id.StringLiteral => |expected_kind| { | |
| 716 | std.debug.assert(expected_kind == switch (token.id) { Token.Id.StringLiteral => |kind| kind, else => unreachable }); | |
| 717 | }, | |
| 718 | else => {}, | |
| 719 | } | |
| 720 | } | |
| 721 | std.debug.assert(tokenizer.next().id == if (expected_eol_at_eof) Token.Id.Eof else Token.Id.NoEolAtEof); | |
| 722 | } |
src/all_types.hpp+1-1| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | |
| 11 | 11 | #include "list.hpp" |
| 12 | 12 | #include "buffer.hpp" |
| 13 | #include "zig_llvm.hpp" | |
| 13 | #include "zig_llvm.h" | |
| 14 | 14 | #include "hash_map.hpp" |
| 15 | 15 | #include "errmsg.hpp" |
| 16 | 16 | #include "bigint.hpp" |
src/analyze.cpp+1-1| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | #include "os.hpp" |
| 15 | 15 | #include "parser.hpp" |
| 16 | 16 | #include "softfloat.hpp" |
| 17 | #include "zig_llvm.hpp" | |
| 17 | #include "zig_llvm.h" | |
| 18 | 18 | |
| 19 | 19 | |
| 20 | 20 | static const size_t default_backward_branch_quota = 1000; |
src/codegen.cpp+20-8| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | #include "os.hpp" |
| 18 | 18 | #include "translate_c.hpp" |
| 19 | 19 | #include "target.hpp" |
| 20 | #include "zig_llvm.hpp" | |
| 20 | #include "zig_llvm.h" | |
| 21 | 21 | |
| 22 | 22 | #include <stdio.h> |
| 23 | 23 | #include <errno.h> |
| ... | ... | @@ -3705,12 +3705,24 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar |
| 3705 | 3705 | ConstParent *parent = &array_const_val->data.x_array.s_none.parent; |
| 3706 | 3706 | LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); |
| 3707 | 3707 | |
| 3708 | TypeTableEntry *usize = g->builtin_types.entry_usize; | |
| 3709 | LLVMValueRef indices[] = { | |
| 3710 | LLVMConstNull(usize->type_ref), | |
| 3711 | LLVMConstInt(usize->type_ref, index, false), | |
| 3712 | }; | |
| 3713 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | |
| 3708 | LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); | |
| 3709 | if (el_type == LLVMArrayTypeKind) { | |
| 3710 | TypeTableEntry *usize = g->builtin_types.entry_usize; | |
| 3711 | LLVMValueRef indices[] = { | |
| 3712 | LLVMConstNull(usize->type_ref), | |
| 3713 | LLVMConstInt(usize->type_ref, index, false), | |
| 3714 | }; | |
| 3715 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | |
| 3716 | } else if (el_type == LLVMStructTypeKind) { | |
| 3717 | TypeTableEntry *u32 = g->builtin_types.entry_u32; | |
| 3718 | LLVMValueRef indices[] = { | |
| 3719 | LLVMConstNull(u32->type_ref), | |
| 3720 | LLVMConstInt(u32->type_ref, index, false), | |
| 3721 | }; | |
| 3722 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | |
| 3723 | } else { | |
| 3724 | zig_unreachable(); | |
| 3725 | } | |
| 3714 | 3726 | } |
| 3715 | 3727 | |
| 3716 | 3728 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) { |
| ... | ... | @@ -3732,7 +3744,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un |
| 3732 | 3744 | TypeTableEntry *u32 = g->builtin_types.entry_u32; |
| 3733 | 3745 | LLVMValueRef indices[] = { |
| 3734 | 3746 | LLVMConstNull(u32->type_ref), |
| 3735 | LLVMConstInt(u32->type_ref, 0, false), | |
| 3747 | LLVMConstInt(u32->type_ref, 0, false), // TODO test const union with more aligned tag type than payload | |
| 3736 | 3748 | }; |
| 3737 | 3749 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 3738 | 3750 | } |
src/config.h.in+4| ... | ... | @@ -24,4 +24,8 @@ |
| 24 | 24 | // Only used for running tests before installing. |
| 25 | 25 | #define ZIG_TEST_DIR "@CMAKE_SOURCE_DIR@/test" |
| 26 | 26 | |
| 27 | // Used for communicating build information to self hosted build. | |
| 28 | #define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@" | |
| 29 | #define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@" | |
| 30 | ||
| 27 | 31 | #endif |
src/link.cpp+12-2| ... | ... | @@ -351,6 +351,16 @@ static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) { |
| 351 | 351 | } |
| 352 | 352 | } |
| 353 | 353 | |
| 354 | static void link_diag_callback(void *context, const char *ptr, size_t len) { | |
| 355 | Buf *diag = reinterpret_cast<Buf *>(context); | |
| 356 | buf_append_mem(diag, ptr, len); | |
| 357 | } | |
| 358 | ||
| 359 | static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, Buf *diag) { | |
| 360 | buf_resize(diag, 0); | |
| 361 | return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag); | |
| 362 | } | |
| 363 | ||
| 354 | 364 | static void construct_linker_job_coff(LinkJob *lj) { |
| 355 | 365 | CodeGen *g = lj->codegen; |
| 356 | 366 | |
| ... | ... | @@ -515,7 +525,7 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 515 | 525 | gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path)))); |
| 516 | 526 | gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path)))); |
| 517 | 527 | Buf diag = BUF_INIT; |
| 518 | if (!ZigLLDLink(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) { | |
| 528 | if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) { | |
| 519 | 529 | fprintf(stderr, "%s\n", buf_ptr(&diag)); |
| 520 | 530 | exit(1); |
| 521 | 531 | } |
| ... | ... | @@ -930,7 +940,7 @@ void codegen_link(CodeGen *g, const char *out_file) { |
| 930 | 940 | Buf diag = BUF_INIT; |
| 931 | 941 | |
| 932 | 942 | codegen_add_time_event(g, "LLVM Link"); |
| 933 | if (!ZigLLDLink(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) { | |
| 943 | if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) { | |
| 934 | 944 | fprintf(stderr, "%s\n", buf_ptr(&diag)); |
| 935 | 945 | exit(1); |
| 936 | 946 | } |
src/main.cpp+5| ... | ... | @@ -266,6 +266,11 @@ static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) { |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | 268 | int main(int argc, char **argv) { |
| 269 | if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) { | |
| 270 | printf("%s\n%s\n", ZIG_CMAKE_BINARY_DIR, ZIG_CXX_COMPILER); | |
| 271 | return 0; | |
| 272 | } | |
| 273 | ||
| 269 | 274 | os_init(); |
| 270 | 275 | |
| 271 | 276 | char *arg0 = argv[0]; |
src/os.hpp+1-1| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | #include "list.hpp" |
| 12 | 12 | #include "buffer.hpp" |
| 13 | 13 | #include "error.hpp" |
| 14 | #include "zig_llvm.hpp" | |
| 14 | #include "zig_llvm.h" | |
| 15 | 15 | |
| 16 | 16 | #include <stdio.h> |
| 17 | 17 | #include <inttypes.h> |
src/target.hpp+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | #ifndef ZIG_TARGET_HPP |
| 9 | 9 | #define ZIG_TARGET_HPP |
| 10 | 10 | |
| 11 | #include <zig_llvm.hpp> | |
| 11 | #include <zig_llvm.h> | |
| 12 | 12 | |
| 13 | 13 | struct Buf; |
| 14 | 14 |
src/util.hpp-2| ... | ... | @@ -13,8 +13,6 @@ |
| 13 | 13 | #include <string.h> |
| 14 | 14 | #include <assert.h> |
| 15 | 15 | |
| 16 | #include <new> | |
| 17 | ||
| 18 | 16 | #if defined(_MSC_VER) |
| 19 | 17 | |
| 20 | 18 | #include <intrin.h> |
src/zig_llvm.cpp+65-29| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | * 3. Prevent C++ from infecting the rest of the project. |
| 14 | 14 | */ |
| 15 | 15 | |
| 16 | #include "zig_llvm.hpp" | |
| 16 | #include "zig_llvm.h" | |
| 17 | 17 | |
| 18 | 18 | #include <llvm/Analysis/TargetLibraryInfo.h> |
| 19 | 19 | #include <llvm/Analysis/TargetTransformInfo.h> |
| ... | ... | @@ -39,8 +39,35 @@ |
| 39 | 39 | |
| 40 | 40 | #include <lld/Common/Driver.h> |
| 41 | 41 | |
| 42 | #include <new> | |
| 43 | ||
| 44 | #include <stdlib.h> | |
| 45 | ||
| 46 | #if defined(_MSC_VER) | |
| 47 | #define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) | |
| 48 | #else | |
| 49 | #define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) | |
| 50 | #endif | |
| 51 | ||
| 42 | 52 | using namespace llvm; |
| 43 | 53 | |
| 54 | template<typename T, typename... Args> | |
| 55 | ATTRIBUTE_RETURNS_NOALIAS static inline T * create(Args... args) { | |
| 56 | T * ptr = reinterpret_cast<T*>(malloc(sizeof(T))); | |
| 57 | if (ptr == nullptr) | |
| 58 | return nullptr; | |
| 59 | new (ptr) T(args...); | |
| 60 | return ptr; | |
| 61 | } | |
| 62 | ||
| 63 | template<typename T> | |
| 64 | static inline void destroy(T * ptr) { | |
| 65 | if (ptr != nullptr) { | |
| 66 | ptr[0].~T(); | |
| 67 | } | |
| 68 | free(ptr); | |
| 69 | } | |
| 70 | ||
| 44 | 71 | void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) { |
| 45 | 72 | initializeLoopStrengthReducePass(*unwrap(R)); |
| 46 | 73 | } |
| ... | ... | @@ -50,8 +77,7 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) { |
| 50 | 77 | } |
| 51 | 78 | |
| 52 | 79 | char *ZigLLVMGetHostCPUName(void) { |
| 53 | std::string str = sys::getHostCPUName(); | |
| 54 | return strdup(str.c_str()); | |
| 80 | return strdup((const char *)sys::getHostCPUName().bytes_begin()); | |
| 55 | 81 | } |
| 56 | 82 | |
| 57 | 83 | char *ZigLLVMGetNativeFeatures(void) { |
| ... | ... | @@ -63,11 +89,11 @@ char *ZigLLVMGetNativeFeatures(void) { |
| 63 | 89 | features.AddFeature(F.first(), F.second); |
| 64 | 90 | } |
| 65 | 91 | |
| 66 | return strdup(features.getString().c_str()); | |
| 92 | return strdup((const char *)StringRef(features.getString()).bytes_begin()); | |
| 67 | 93 | } |
| 68 | 94 | |
| 69 | 95 | static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { |
| 70 | PM.add(createAddDiscriminatorsPass()); | |
| 96 | PM.add(createAddDiscriminatorsPass()); | |
| 71 | 97 | } |
| 72 | 98 | |
| 73 | 99 | #ifndef NDEBUG |
| ... | ... | @@ -82,7 +108,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 82 | 108 | std::error_code EC; |
| 83 | 109 | raw_fd_ostream dest(filename, EC, sys::fs::F_None); |
| 84 | 110 | if (EC) { |
| 85 | *error_message = strdup(EC.message().c_str()); | |
| 111 | *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); | |
| 86 | 112 | return true; |
| 87 | 113 | } |
| 88 | 114 | TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref); |
| ... | ... | @@ -90,7 +116,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 90 | 116 | |
| 91 | 117 | Module* module = unwrap(module_ref); |
| 92 | 118 | |
| 93 | PassManagerBuilder *PMBuilder = new PassManagerBuilder(); | |
| 119 | PassManagerBuilder *PMBuilder = create<PassManagerBuilder>(); | |
| 94 | 120 | PMBuilder->OptLevel = target_machine->getOptLevel(); |
| 95 | 121 | PMBuilder->SizeLevel = 0; |
| 96 | 122 | |
| ... | ... | @@ -123,7 +149,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 123 | 149 | |
| 124 | 150 | // Set up the per-function pass manager. |
| 125 | 151 | legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module); |
| 126 | FPM.add(new TargetLibraryInfoWrapperPass(tlii)); | |
| 152 | FPM.add(create<TargetLibraryInfoWrapperPass>(tlii)); | |
| 127 | 153 | FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); |
| 128 | 154 | if (assertions_on) { |
| 129 | 155 | FPM.add(createVerifierPass()); |
| ... | ... | @@ -415,7 +441,10 @@ unsigned ZigLLVMTag_DW_union_type(void) { |
| 415 | 441 | } |
| 416 | 442 | |
| 417 | 443 | ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) { |
| 418 | DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved); | |
| 444 | DIBuilder *di_builder = reinterpret_cast<DIBuilder*>(malloc(sizeof(DIBuilder))); | |
| 445 | if (di_builder == nullptr) | |
| 446 | return nullptr; | |
| 447 | new (di_builder) DIBuilder(*unwrap(module), allow_unresolved); | |
| 419 | 448 | return reinterpret_cast<ZigLLVMDIBuilder *>(di_builder); |
| 420 | 449 | } |
| 421 | 450 | |
| ... | ... | @@ -617,7 +646,7 @@ void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn_ref) { |
| 617 | 646 | func->setAttributes(new_attr_set); |
| 618 | 647 | } |
| 619 | 648 | |
| 620 | void ZigLLVMParseCommandLineOptions(int argc, const char *const *argv) { | |
| 649 | void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { | |
| 621 | 650 | llvm::cl::ParseCommandLineOptions(argc, argv); |
| 622 | 651 | } |
| 623 | 652 | |
| ... | ... | @@ -775,29 +804,35 @@ LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLV |
| 775 | 804 | } |
| 776 | 805 | |
| 777 | 806 | |
| 778 | #include "buffer.hpp" | |
| 807 | class MyOStream: public raw_ostream { | |
| 808 | public: | |
| 809 | MyOStream(void (*_append_diagnostic)(void *, const char *, size_t), void *_context) : | |
| 810 | raw_ostream(true), append_diagnostic(_append_diagnostic), context(_context), pos(0) { | |
| 811 | ||
| 812 | } | |
| 813 | void write_impl(const char *ptr, size_t len) override { | |
| 814 | append_diagnostic(context, ptr, len); | |
| 815 | pos += len; | |
| 816 | } | |
| 817 | uint64_t current_pos() const override { | |
| 818 | return pos; | |
| 819 | } | |
| 820 | void (*append_diagnostic)(void *, const char *, size_t); | |
| 821 | void *context; | |
| 822 | size_t pos; | |
| 823 | }; | |
| 824 | ||
| 779 | 825 | |
| 780 | bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, Buf *diag_buf) { | |
| 826 | bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, | |
| 827 | void (*append_diagnostic)(void *, const char *, size_t), void *context) | |
| 828 | { | |
| 781 | 829 | ArrayRef<const char *> array_ref_args(args, arg_count); |
| 782 | 830 | |
| 783 | buf_resize(diag_buf, 0); | |
| 784 | class MyOStream: public raw_ostream { | |
| 785 | public: | |
| 786 | MyOStream(Buf *_diag_buf) : raw_ostream(true), diag_buf(_diag_buf) { | |
| 787 | ||
| 788 | } | |
| 789 | void write_impl(const char *ptr, size_t len) override { | |
| 790 | buf_append_mem(diag_buf, ptr, len); | |
| 791 | } | |
| 792 | uint64_t current_pos() const override { | |
| 793 | return buf_len(diag_buf); | |
| 794 | } | |
| 795 | Buf *diag_buf; | |
| 796 | } diag(diag_buf); | |
| 831 | MyOStream diag(append_diagnostic, context); | |
| 797 | 832 | |
| 798 | 833 | switch (oformat) { |
| 799 | 834 | case ZigLLVM_UnknownObjectFormat: |
| 800 | zig_unreachable(); | |
| 835 | assert(false); // unreachable | |
| 801 | 836 | |
| 802 | 837 | case ZigLLVM_COFF: |
| 803 | 838 | return lld::coff::link(array_ref_args, false, diag); |
| ... | ... | @@ -809,7 +844,8 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_ |
| 809 | 844 | return lld::mach_o::link(array_ref_args, diag); |
| 810 | 845 | |
| 811 | 846 | case ZigLLVM_Wasm: |
| 812 | zig_panic("ZigLLDLink for Wasm"); | |
| 847 | assert(false); // TODO ZigLLDLink for Wasm | |
| 813 | 848 | } |
| 814 | zig_unreachable(); | |
| 849 | assert(false); // unreachable | |
| 850 | abort(); | |
| 815 | 851 | } |
src/zig_llvm.h created+398| ... | ... | @@ -0,0 +1,398 @@ |
| 1 | /* | |
| 2 | * Copyright (c) 2015 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_LLVM_HPP | |
| 9 | #define ZIG_ZIG_LLVM_HPP | |
| 10 | ||
| 11 | #include <stdbool.h> | |
| 12 | #include <stddef.h> | |
| 13 | #include <llvm-c/Core.h> | |
| 14 | #include <llvm-c/Analysis.h> | |
| 15 | #include <llvm-c/Target.h> | |
| 16 | #include <llvm-c/Initialization.h> | |
| 17 | #include <llvm-c/TargetMachine.h> | |
| 18 | ||
| 19 | #ifdef __cplusplus | |
| 20 | #define ZIG_EXTERN_C extern "C" | |
| 21 | #else | |
| 22 | #define ZIG_EXTERN_C | |
| 23 | #endif | |
| 24 | ||
| 25 | struct ZigLLVMDIType; | |
| 26 | struct ZigLLVMDIBuilder; | |
| 27 | struct ZigLLVMDICompileUnit; | |
| 28 | struct ZigLLVMDIScope; | |
| 29 | struct ZigLLVMDIFile; | |
| 30 | struct ZigLLVMDILexicalBlock; | |
| 31 | struct ZigLLVMDISubprogram; | |
| 32 | struct ZigLLVMDISubroutineType; | |
| 33 | struct ZigLLVMDILocalVariable; | |
| 34 | struct ZigLLVMDIGlobalVariable; | |
| 35 | struct ZigLLVMDILocation; | |
| 36 | struct ZigLLVMDIEnumerator; | |
| 37 | struct ZigLLVMInsertionPoint; | |
| 38 | ||
| 39 | ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); | |
| 40 | ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); | |
| 41 | ||
| 42 | /// Caller must free memory. | |
| 43 | ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); | |
| 44 | ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); | |
| 45 | ||
| 46 | // We use a custom enum here since LLVM does not expose LLVMIr as an emit | |
| 47 | // output through the same mechanism as assembly/binary. | |
| 48 | enum ZigLLVM_EmitOutputType { | |
| 49 | ZigLLVM_EmitAssembly, | |
| 50 | ZigLLVM_EmitBinary, | |
| 51 | ZigLLVM_EmitLLVMIr, | |
| 52 | }; | |
| 53 | ||
| 54 | ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | |
| 55 | const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug); | |
| 56 | ||
| 57 | enum ZigLLVM_FnInline { | |
| 58 | ZigLLVM_FnInlineAuto, | |
| 59 | ZigLLVM_FnInlineAlways, | |
| 60 | ZigLLVM_FnInlineNever, | |
| 61 | }; | |
| 62 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | |
| 63 | unsigned NumArgs, unsigned CC, enum ZigLLVM_FnInline fn_inline, const char *Name); | |
| 64 | ||
| 65 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, | |
| 66 | LLVMValueRef new_val, LLVMAtomicOrdering success_ordering, | |
| 67 | LLVMAtomicOrdering failure_ordering); | |
| 68 | ||
| 69 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 70 | const char *name); | |
| 71 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 72 | const char *name); | |
| 73 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 74 | const char *name); | |
| 75 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 76 | const char *name); | |
| 77 | ||
| 78 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugPointerType(struct ZigLLVMDIBuilder *dibuilder, | |
| 79 | struct ZigLLVMDIType *pointee_type, uint64_t size_in_bits, uint64_t align_in_bits, const char *name); | |
| 80 | ||
| 81 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugBasicType(struct ZigLLVMDIBuilder *dibuilder, const char *name, | |
| 82 | uint64_t size_in_bits, unsigned encoding); | |
| 83 | ||
| 84 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugArrayType(struct ZigLLVMDIBuilder *dibuilder, | |
| 85 | uint64_t size_in_bits, uint64_t align_in_bits, struct ZigLLVMDIType *elem_type, | |
| 86 | int elem_count); | |
| 87 | ||
| 88 | ZIG_EXTERN_C struct ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(struct ZigLLVMDIBuilder *dibuilder, | |
| 89 | const char *name, int64_t val); | |
| 90 | ||
| 91 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(struct ZigLLVMDIBuilder *dibuilder, | |
| 92 | struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number, | |
| 93 | uint64_t size_in_bits, uint64_t align_in_bits, struct ZigLLVMDIEnumerator **enumerator_array, | |
| 94 | int enumerator_array_len, struct ZigLLVMDIType *underlying_type, const char *unique_id); | |
| 95 | ||
| 96 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugStructType(struct ZigLLVMDIBuilder *dibuilder, | |
| 97 | struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number, | |
| 98 | uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, struct ZigLLVMDIType *derived_from, | |
| 99 | struct ZigLLVMDIType **types_array, int types_array_len, unsigned run_time_lang, | |
| 100 | struct ZigLLVMDIType *vtable_holder, const char *unique_id); | |
| 101 | ||
| 102 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugUnionType(struct ZigLLVMDIBuilder *dibuilder, | |
| 103 | struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number, | |
| 104 | uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, struct ZigLLVMDIType **types_array, | |
| 105 | int types_array_len, unsigned run_time_lang, const char *unique_id); | |
| 106 | ||
| 107 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugMemberType(struct ZigLLVMDIBuilder *dibuilder, | |
| 108 | struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line, | |
| 109 | uint64_t size_in_bits, uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, | |
| 110 | struct ZigLLVMDIType *type); | |
| 111 | ||
| 112 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateReplaceableCompositeType(struct ZigLLVMDIBuilder *dibuilder, | |
| 113 | unsigned tag, const char *name, struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line); | |
| 114 | ||
| 115 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugForwardDeclType(struct ZigLLVMDIBuilder *dibuilder, unsigned tag, | |
| 116 | const char *name, struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line); | |
| 117 | ||
| 118 | ZIG_EXTERN_C void ZigLLVMReplaceTemporary(struct ZigLLVMDIBuilder *dibuilder, struct ZigLLVMDIType *type, | |
| 119 | struct ZigLLVMDIType *replacement); | |
| 120 | ||
| 121 | ZIG_EXTERN_C void ZigLLVMReplaceDebugArrays(struct ZigLLVMDIBuilder *dibuilder, struct ZigLLVMDIType *type, | |
| 122 | struct ZigLLVMDIType **types_array, int types_array_len); | |
| 123 | ||
| 124 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateSubroutineType(struct ZigLLVMDIBuilder *dibuilder_wrapped, | |
| 125 | struct ZigLLVMDIType **types_array, int types_array_len, unsigned flags); | |
| 126 | ||
| 127 | ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_unsigned(void); | |
| 128 | ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed(void); | |
| 129 | ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_float(void); | |
| 130 | ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_boolean(void); | |
| 131 | ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_unsigned_char(void); | |
| 132 | ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed_char(void); | |
| 133 | ZIG_EXTERN_C unsigned ZigLLVMLang_DW_LANG_C99(void); | |
| 134 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_variable(void); | |
| 135 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_structure_type(void); | |
| 136 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void); | |
| 137 | ||
| 138 | ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); | |
| 139 | ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module); | |
| 140 | ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module); | |
| 141 | ||
| 142 | ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, | |
| 143 | struct ZigLLVMDIScope *scope); | |
| 144 | ZIG_EXTERN_C void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder); | |
| 145 | ||
| 146 | ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(struct ZigLLVMDILexicalBlock *lexical_block); | |
| 147 | ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMCompileUnitToScope(struct ZigLLVMDICompileUnit *compile_unit); | |
| 148 | ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *difile); | |
| 149 | ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram); | |
| 150 | ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type); | |
| 151 | ||
| 152 | ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder, | |
| 153 | struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no, | |
| 154 | struct ZigLLVMDIType *type, bool always_preserve, unsigned flags); | |
| 155 | ||
| 156 | ZIG_EXTERN_C struct ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(struct ZigLLVMDIBuilder *dbuilder, | |
| 157 | struct ZigLLVMDIScope *scope, const char *name, const char *linkage_name, struct ZigLLVMDIFile *file, | |
| 158 | unsigned line_no, struct ZigLLVMDIType *di_type, bool is_local_to_unit); | |
| 159 | ||
| 160 | ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(struct ZigLLVMDIBuilder *dbuilder, | |
| 161 | struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no, | |
| 162 | struct ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no); | |
| 163 | ||
| 164 | ZIG_EXTERN_C struct ZigLLVMDILexicalBlock *ZigLLVMCreateLexicalBlock(struct ZigLLVMDIBuilder *dbuilder, | |
| 165 | struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line, unsigned col); | |
| 166 | ||
| 167 | ZIG_EXTERN_C struct ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(struct ZigLLVMDIBuilder *dibuilder, | |
| 168 | unsigned lang, struct ZigLLVMDIFile *difile, const char *producer, | |
| 169 | bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name, | |
| 170 | uint64_t dwo_id, bool emit_debug_info); | |
| 171 | ||
| 172 | ZIG_EXTERN_C struct ZigLLVMDIFile *ZigLLVMCreateFile(struct ZigLLVMDIBuilder *dibuilder, const char *filename, | |
| 173 | const char *directory); | |
| 174 | ||
| 175 | ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIBuilder *dibuilder, | |
| 176 | struct ZigLLVMDIScope *scope, const char *name, const char *linkage_name, struct ZigLLVMDIFile *file, | |
| 177 | unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, | |
| 178 | unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram); | |
| 179 | ||
| 180 | ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram); | |
| 181 | ||
| 182 | ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder); | |
| 183 | ||
| 184 | ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclareAtEnd(struct ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage, | |
| 185 | struct ZigLLVMDILocalVariable *var_info, struct ZigLLVMDILocation *debug_loc, | |
| 186 | LLVMBasicBlockRef basic_block_ref); | |
| 187 | ||
| 188 | ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclare(struct ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage, | |
| 189 | struct ZigLLVMDILocalVariable *var_info, struct ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr); | |
| 190 | ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, struct ZigLLVMDIScope *scope); | |
| 191 | ||
| 192 | ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); | |
| 193 | ||
| 194 | ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); | |
| 195 | ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); | |
| 196 | ||
| 197 | ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); | |
| 198 | ||
| 199 | ||
| 200 | // copied from include/llvm/ADT/Triple.h | |
| 201 | ||
| 202 | enum ZigLLVM_ArchType { | |
| 203 | ZigLLVM_UnknownArch, | |
| 204 | ||
| 205 | ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale | |
| 206 | ZigLLVM_armeb, // ARM (big endian): armeb | |
| 207 | ZigLLVM_aarch64, // AArch64 (little endian): aarch64 | |
| 208 | ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be | |
| 209 | ZigLLVM_arc, // ARC: Synopsys ARC | |
| 210 | ZigLLVM_avr, // AVR: Atmel AVR microcontroller | |
| 211 | ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) | |
| 212 | ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) | |
| 213 | ZigLLVM_hexagon, // Hexagon: hexagon | |
| 214 | ZigLLVM_mips, // MIPS: mips, mipsallegrex | |
| 215 | ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexel | |
| 216 | ZigLLVM_mips64, // MIPS64: mips64 | |
| 217 | ZigLLVM_mips64el, // MIPS64EL: mips64el | |
| 218 | ZigLLVM_msp430, // MSP430: msp430 | |
| 219 | ZigLLVM_nios2, // NIOSII: nios2 | |
| 220 | ZigLLVM_ppc, // PPC: powerpc | |
| 221 | ZigLLVM_ppc64, // PPC64: powerpc64, ppu | |
| 222 | ZigLLVM_ppc64le, // PPC64LE: powerpc64le | |
| 223 | ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX | |
| 224 | ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs | |
| 225 | ZigLLVM_riscv32, // RISC-V (32-bit): riscv32 | |
| 226 | ZigLLVM_riscv64, // RISC-V (64-bit): riscv64 | |
| 227 | ZigLLVM_sparc, // Sparc: sparc | |
| 228 | ZigLLVM_sparcv9, // Sparcv9: Sparcv9 | |
| 229 | ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant | |
| 230 | ZigLLVM_systemz, // SystemZ: s390x | |
| 231 | ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce | |
| 232 | ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele | |
| 233 | ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.* | |
| 234 | ZigLLVM_thumbeb, // Thumb (big endian): thumbeb | |
| 235 | ZigLLVM_x86, // X86: i[3-9]86 | |
| 236 | ZigLLVM_x86_64, // X86-64: amd64, x86_64 | |
| 237 | ZigLLVM_xcore, // XCore: xcore | |
| 238 | ZigLLVM_nvptx, // NVPTX: 32-bit | |
| 239 | ZigLLVM_nvptx64, // NVPTX: 64-bit | |
| 240 | ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl) | |
| 241 | ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl) | |
| 242 | ZigLLVM_amdil, // AMDIL | |
| 243 | ZigLLVM_amdil64, // AMDIL with 64-bit pointers | |
| 244 | ZigLLVM_hsail, // AMD HSAIL | |
| 245 | ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers | |
| 246 | ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version | |
| 247 | ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version | |
| 248 | ZigLLVM_kalimba, // Kalimba: generic kalimba | |
| 249 | ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors | |
| 250 | ZigLLVM_lanai, // Lanai: Lanai 32-bit | |
| 251 | ZigLLVM_wasm32, // WebAssembly with 32-bit pointers | |
| 252 | ZigLLVM_wasm64, // WebAssembly with 64-bit pointers | |
| 253 | ZigLLVM_renderscript32, // 32-bit RenderScript | |
| 254 | ZigLLVM_renderscript64, // 64-bit RenderScript | |
| 255 | ||
| 256 | ZigLLVM_LastArchType = ZigLLVM_renderscript64 | |
| 257 | }; | |
| 258 | ||
| 259 | enum ZigLLVM_SubArchType { | |
| 260 | ZigLLVM_NoSubArch, | |
| 261 | ||
| 262 | ZigLLVM_ARMSubArch_v8_3a, | |
| 263 | ZigLLVM_ARMSubArch_v8_2a, | |
| 264 | ZigLLVM_ARMSubArch_v8_1a, | |
| 265 | ZigLLVM_ARMSubArch_v8, | |
| 266 | ZigLLVM_ARMSubArch_v8r, | |
| 267 | ZigLLVM_ARMSubArch_v8m_baseline, | |
| 268 | ZigLLVM_ARMSubArch_v8m_mainline, | |
| 269 | ZigLLVM_ARMSubArch_v7, | |
| 270 | ZigLLVM_ARMSubArch_v7em, | |
| 271 | ZigLLVM_ARMSubArch_v7m, | |
| 272 | ZigLLVM_ARMSubArch_v7s, | |
| 273 | ZigLLVM_ARMSubArch_v7k, | |
| 274 | ZigLLVM_ARMSubArch_v7ve, | |
| 275 | ZigLLVM_ARMSubArch_v6, | |
| 276 | ZigLLVM_ARMSubArch_v6m, | |
| 277 | ZigLLVM_ARMSubArch_v6k, | |
| 278 | ZigLLVM_ARMSubArch_v6t2, | |
| 279 | ZigLLVM_ARMSubArch_v5, | |
| 280 | ZigLLVM_ARMSubArch_v5te, | |
| 281 | ZigLLVM_ARMSubArch_v4t, | |
| 282 | ||
| 283 | ZigLLVM_KalimbaSubArch_v3, | |
| 284 | ZigLLVM_KalimbaSubArch_v4, | |
| 285 | ZigLLVM_KalimbaSubArch_v5, | |
| 286 | }; | |
| 287 | ||
| 288 | enum ZigLLVM_VendorType { | |
| 289 | ZigLLVM_UnknownVendor, | |
| 290 | ||
| 291 | ZigLLVM_Apple, | |
| 292 | ZigLLVM_PC, | |
| 293 | ZigLLVM_SCEI, | |
| 294 | ZigLLVM_BGP, | |
| 295 | ZigLLVM_BGQ, | |
| 296 | ZigLLVM_Freescale, | |
| 297 | ZigLLVM_IBM, | |
| 298 | ZigLLVM_ImaginationTechnologies, | |
| 299 | ZigLLVM_MipsTechnologies, | |
| 300 | ZigLLVM_NVIDIA, | |
| 301 | ZigLLVM_CSR, | |
| 302 | ZigLLVM_Myriad, | |
| 303 | ZigLLVM_AMD, | |
| 304 | ZigLLVM_Mesa, | |
| 305 | ZigLLVM_SUSE, | |
| 306 | ||
| 307 | ZigLLVM_LastVendorType = ZigLLVM_SUSE | |
| 308 | }; | |
| 309 | ||
| 310 | enum ZigLLVM_OSType { | |
| 311 | ZigLLVM_UnknownOS, | |
| 312 | ||
| 313 | ZigLLVM_Ananas, | |
| 314 | ZigLLVM_CloudABI, | |
| 315 | ZigLLVM_Darwin, | |
| 316 | ZigLLVM_DragonFly, | |
| 317 | ZigLLVM_FreeBSD, | |
| 318 | ZigLLVM_Fuchsia, | |
| 319 | ZigLLVM_IOS, | |
| 320 | ZigLLVM_KFreeBSD, | |
| 321 | ZigLLVM_Linux, | |
| 322 | ZigLLVM_Lv2, // PS3 | |
| 323 | ZigLLVM_MacOSX, | |
| 324 | ZigLLVM_NetBSD, | |
| 325 | ZigLLVM_OpenBSD, | |
| 326 | ZigLLVM_Solaris, | |
| 327 | ZigLLVM_Win32, | |
| 328 | ZigLLVM_Haiku, | |
| 329 | ZigLLVM_Minix, | |
| 330 | ZigLLVM_RTEMS, | |
| 331 | ZigLLVM_NaCl, // Native Client | |
| 332 | ZigLLVM_CNK, // BG/P Compute-Node Kernel | |
| 333 | ZigLLVM_Bitrig, | |
| 334 | ZigLLVM_AIX, | |
| 335 | ZigLLVM_CUDA, // NVIDIA CUDA | |
| 336 | ZigLLVM_NVCL, // NVIDIA OpenCL | |
| 337 | ZigLLVM_AMDHSA, // AMD HSA Runtime | |
| 338 | ZigLLVM_PS4, | |
| 339 | ZigLLVM_ELFIAMCU, | |
| 340 | ZigLLVM_TvOS, // Apple tvOS | |
| 341 | ZigLLVM_WatchOS, // Apple watchOS | |
| 342 | ZigLLVM_Mesa3D, | |
| 343 | ZigLLVM_Contiki, | |
| 344 | ||
| 345 | ZigLLVM_LastOSType = ZigLLVM_Contiki | |
| 346 | }; | |
| 347 | ||
| 348 | enum ZigLLVM_EnvironmentType { | |
| 349 | ZigLLVM_UnknownEnvironment, | |
| 350 | ||
| 351 | ZigLLVM_GNU, | |
| 352 | ZigLLVM_GNUABIN32, | |
| 353 | ZigLLVM_GNUABI64, | |
| 354 | ZigLLVM_GNUEABI, | |
| 355 | ZigLLVM_GNUEABIHF, | |
| 356 | ZigLLVM_GNUX32, | |
| 357 | ZigLLVM_CODE16, | |
| 358 | ZigLLVM_EABI, | |
| 359 | ZigLLVM_EABIHF, | |
| 360 | ZigLLVM_Android, | |
| 361 | ZigLLVM_Musl, | |
| 362 | ZigLLVM_MuslEABI, | |
| 363 | ZigLLVM_MuslEABIHF, | |
| 364 | ||
| 365 | ZigLLVM_MSVC, | |
| 366 | ZigLLVM_Itanium, | |
| 367 | ZigLLVM_Cygnus, | |
| 368 | ZigLLVM_AMDOpenCL, | |
| 369 | ZigLLVM_CoreCLR, | |
| 370 | ZigLLVM_OpenCL, | |
| 371 | ZigLLVM_Simulator, | |
| 372 | ||
| 373 | ZigLLVM_LastEnvironmentType = ZigLLVM_Simulator | |
| 374 | }; | |
| 375 | ||
| 376 | enum ZigLLVM_ObjectFormatType { | |
| 377 | ZigLLVM_UnknownObjectFormat, | |
| 378 | ||
| 379 | ZigLLVM_COFF, | |
| 380 | ZigLLVM_ELF, | |
| 381 | ZigLLVM_MachO, | |
| 382 | ZigLLVM_Wasm, | |
| 383 | }; | |
| 384 | ||
| 385 | ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch); | |
| 386 | ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch); | |
| 387 | ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor); | |
| 388 | ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os); | |
| 389 | ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType env_type); | |
| 390 | ||
| 391 | ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, | |
| 392 | void (*append_diagnostic)(void *, const char *, size_t), void *context); | |
| 393 | ||
| 394 | ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type, | |
| 395 | enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type, | |
| 396 | enum ZigLLVM_ObjectFormatType *oformat); | |
| 397 | ||
| 398 | #endif |
src/zig_llvm.hpp deleted-387| ... | ... | @@ -1,387 +0,0 @@ |
| 1 | /* | |
| 2 | * Copyright (c) 2015 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_LLVM_HPP | |
| 9 | #define ZIG_ZIG_LLVM_HPP | |
| 10 | ||
| 11 | #include <llvm-c/Core.h> | |
| 12 | #include <llvm-c/Analysis.h> | |
| 13 | #include <llvm-c/Target.h> | |
| 14 | #include <llvm-c/Initialization.h> | |
| 15 | #include <llvm-c/TargetMachine.h> | |
| 16 | ||
| 17 | struct ZigLLVMDIType; | |
| 18 | struct ZigLLVMDIBuilder; | |
| 19 | struct ZigLLVMDICompileUnit; | |
| 20 | struct ZigLLVMDIScope; | |
| 21 | struct ZigLLVMDIFile; | |
| 22 | struct ZigLLVMDILexicalBlock; | |
| 23 | struct ZigLLVMDISubprogram; | |
| 24 | struct ZigLLVMDISubroutineType; | |
| 25 | struct ZigLLVMDILocalVariable; | |
| 26 | struct ZigLLVMDIGlobalVariable; | |
| 27 | struct ZigLLVMDILocation; | |
| 28 | struct ZigLLVMDIEnumerator; | |
| 29 | struct ZigLLVMInsertionPoint; | |
| 30 | ||
| 31 | void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); | |
| 32 | void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); | |
| 33 | ||
| 34 | char *ZigLLVMGetHostCPUName(void); | |
| 35 | char *ZigLLVMGetNativeFeatures(void); | |
| 36 | ||
| 37 | // We use a custom enum here since LLVM does not expose LLVMIr as an emit | |
| 38 | // output through the same mechanism as assembly/binary. | |
| 39 | enum ZigLLVM_EmitOutputType { | |
| 40 | ZigLLVM_EmitAssembly, | |
| 41 | ZigLLVM_EmitBinary, | |
| 42 | ZigLLVM_EmitLLVMIr, | |
| 43 | }; | |
| 44 | ||
| 45 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | |
| 46 | const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug); | |
| 47 | ||
| 48 | enum ZigLLVM_FnInline { | |
| 49 | ZigLLVM_FnInlineAuto, | |
| 50 | ZigLLVM_FnInlineAlways, | |
| 51 | ZigLLVM_FnInlineNever, | |
| 52 | }; | |
| 53 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | |
| 54 | unsigned NumArgs, unsigned CC, ZigLLVM_FnInline fn_inline, const char *Name); | |
| 55 | ||
| 56 | LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, | |
| 57 | LLVMValueRef new_val, LLVMAtomicOrdering success_ordering, | |
| 58 | LLVMAtomicOrdering failure_ordering); | |
| 59 | ||
| 60 | LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 61 | const char *name); | |
| 62 | LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 63 | const char *name); | |
| 64 | LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 65 | const char *name); | |
| 66 | LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, | |
| 67 | const char *name); | |
| 68 | ||
| 69 | ZigLLVMDIType *ZigLLVMCreateDebugPointerType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *pointee_type, | |
| 70 | uint64_t size_in_bits, uint64_t align_in_bits, const char *name); | |
| 71 | ||
| 72 | ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const char *name, | |
| 73 | uint64_t size_in_bits, unsigned encoding); | |
| 74 | ||
| 75 | ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, | |
| 76 | uint64_t size_in_bits, uint64_t align_in_bits, ZigLLVMDIType *elem_type, | |
| 77 | int elem_count); | |
| 78 | ||
| 79 | ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(ZigLLVMDIBuilder *dibuilder, const char *name, int64_t val); | |
| 80 | ||
| 81 | ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope, | |
| 82 | const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits, | |
| 83 | uint64_t align_in_bits, ZigLLVMDIEnumerator **enumerator_array, int enumerator_array_len, | |
| 84 | ZigLLVMDIType *underlying_type, const char *unique_id); | |
| 85 | ||
| 86 | ZigLLVMDIType *ZigLLVMCreateDebugStructType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope, | |
| 87 | const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits, | |
| 88 | uint64_t align_in_bits, unsigned flags, ZigLLVMDIType *derived_from, | |
| 89 | ZigLLVMDIType **types_array, int types_array_len, unsigned run_time_lang, ZigLLVMDIType *vtable_holder, | |
| 90 | const char *unique_id); | |
| 91 | ||
| 92 | ZigLLVMDIType *ZigLLVMCreateDebugUnionType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope, | |
| 93 | const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits, | |
| 94 | uint64_t align_in_bits, unsigned flags, ZigLLVMDIType **types_array, int types_array_len, | |
| 95 | unsigned run_time_lang, const char *unique_id); | |
| 96 | ||
| 97 | ZigLLVMDIType *ZigLLVMCreateDebugMemberType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope, | |
| 98 | const char *name, ZigLLVMDIFile *file, unsigned line, uint64_t size_in_bits, | |
| 99 | uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, ZigLLVMDIType *type); | |
| 100 | ||
| 101 | ZigLLVMDIType *ZigLLVMCreateReplaceableCompositeType(ZigLLVMDIBuilder *dibuilder, unsigned tag, | |
| 102 | const char *name, ZigLLVMDIScope *scope, ZigLLVMDIFile *file, unsigned line); | |
| 103 | ||
| 104 | ZigLLVMDIType *ZigLLVMCreateDebugForwardDeclType(ZigLLVMDIBuilder *dibuilder, unsigned tag, | |
| 105 | const char *name, ZigLLVMDIScope *scope, ZigLLVMDIFile *file, unsigned line); | |
| 106 | ||
| 107 | void ZigLLVMReplaceTemporary(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *type, | |
| 108 | ZigLLVMDIType *replacement); | |
| 109 | ||
| 110 | void ZigLLVMReplaceDebugArrays(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *type, | |
| 111 | ZigLLVMDIType **types_array, int types_array_len); | |
| 112 | ||
| 113 | ZigLLVMDIType *ZigLLVMCreateSubroutineType(ZigLLVMDIBuilder *dibuilder_wrapped, | |
| 114 | ZigLLVMDIType **types_array, int types_array_len, unsigned flags); | |
| 115 | ||
| 116 | unsigned ZigLLVMEncoding_DW_ATE_unsigned(void); | |
| 117 | unsigned ZigLLVMEncoding_DW_ATE_signed(void); | |
| 118 | unsigned ZigLLVMEncoding_DW_ATE_float(void); | |
| 119 | unsigned ZigLLVMEncoding_DW_ATE_boolean(void); | |
| 120 | unsigned ZigLLVMEncoding_DW_ATE_unsigned_char(void); | |
| 121 | unsigned ZigLLVMEncoding_DW_ATE_signed_char(void); | |
| 122 | unsigned ZigLLVMLang_DW_LANG_C99(void); | |
| 123 | unsigned ZigLLVMTag_DW_variable(void); | |
| 124 | unsigned ZigLLVMTag_DW_structure_type(void); | |
| 125 | unsigned ZigLLVMTag_DW_union_type(void); | |
| 126 | ||
| 127 | ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); | |
| 128 | void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module); | |
| 129 | void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module); | |
| 130 | ||
| 131 | void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, ZigLLVMDIScope *scope); | |
| 132 | void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder); | |
| 133 | ||
| 134 | ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(ZigLLVMDILexicalBlock *lexical_block); | |
| 135 | ZigLLVMDIScope *ZigLLVMCompileUnitToScope(ZigLLVMDICompileUnit *compile_unit); | |
| 136 | ZigLLVMDIScope *ZigLLVMFileToScope(ZigLLVMDIFile *difile); | |
| 137 | ZigLLVMDIScope *ZigLLVMSubprogramToScope(ZigLLVMDISubprogram *subprogram); | |
| 138 | ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type); | |
| 139 | ||
| 140 | ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(ZigLLVMDIBuilder *dbuilder, | |
| 141 | ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no, | |
| 142 | ZigLLVMDIType *type, bool always_preserve, unsigned flags); | |
| 143 | ||
| 144 | ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder, | |
| 145 | ZigLLVMDIScope *scope, const char *name, const char *linkage_name, ZigLLVMDIFile *file, | |
| 146 | unsigned line_no, ZigLLVMDIType *di_type, bool is_local_to_unit); | |
| 147 | ||
| 148 | ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder, | |
| 149 | ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no, | |
| 150 | ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no); | |
| 151 | ||
| 152 | ZigLLVMDILexicalBlock *ZigLLVMCreateLexicalBlock(ZigLLVMDIBuilder *dbuilder, ZigLLVMDIScope *scope, | |
| 153 | ZigLLVMDIFile *file, unsigned line, unsigned col); | |
| 154 | ||
| 155 | ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder, | |
| 156 | unsigned lang, ZigLLVMDIFile *difile, const char *producer, | |
| 157 | bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name, | |
| 158 | uint64_t dwo_id, bool emit_debug_info); | |
| 159 | ||
| 160 | ZigLLVMDIFile *ZigLLVMCreateFile(ZigLLVMDIBuilder *dibuilder, const char *filename, const char *directory); | |
| 161 | ||
| 162 | ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope, | |
| 163 | const char *name, const char *linkage_name, ZigLLVMDIFile *file, unsigned lineno, | |
| 164 | ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, unsigned scope_line, | |
| 165 | unsigned flags, bool is_optimized, ZigLLVMDISubprogram *decl_subprogram); | |
| 166 | ||
| 167 | void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram); | |
| 168 | ||
| 169 | void ZigLLVMDIBuilderFinalize(ZigLLVMDIBuilder *dibuilder); | |
| 170 | ||
| 171 | LLVMValueRef ZigLLVMInsertDeclareAtEnd(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage, | |
| 172 | ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref); | |
| 173 | LLVMValueRef ZigLLVMInsertDeclare(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage, | |
| 174 | ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr); | |
| 175 | ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, ZigLLVMDIScope *scope); | |
| 176 | ||
| 177 | void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); | |
| 178 | ||
| 179 | void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); | |
| 180 | void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); | |
| 181 | ||
| 182 | void ZigLLVMParseCommandLineOptions(int argc, const char *const *argv); | |
| 183 | ||
| 184 | ||
| 185 | // copied from include/llvm/ADT/Triple.h | |
| 186 | ||
| 187 | enum ZigLLVM_ArchType { | |
| 188 | ZigLLVM_UnknownArch, | |
| 189 | ||
| 190 | ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale | |
| 191 | ZigLLVM_armeb, // ARM (big endian): armeb | |
| 192 | ZigLLVM_aarch64, // AArch64 (little endian): aarch64 | |
| 193 | ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be | |
| 194 | ZigLLVM_arc, // ARC: Synopsys ARC | |
| 195 | ZigLLVM_avr, // AVR: Atmel AVR microcontroller | |
| 196 | ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) | |
| 197 | ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) | |
| 198 | ZigLLVM_hexagon, // Hexagon: hexagon | |
| 199 | ZigLLVM_mips, // MIPS: mips, mipsallegrex | |
| 200 | ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexel | |
| 201 | ZigLLVM_mips64, // MIPS64: mips64 | |
| 202 | ZigLLVM_mips64el, // MIPS64EL: mips64el | |
| 203 | ZigLLVM_msp430, // MSP430: msp430 | |
| 204 | ZigLLVM_nios2, // NIOSII: nios2 | |
| 205 | ZigLLVM_ppc, // PPC: powerpc | |
| 206 | ZigLLVM_ppc64, // PPC64: powerpc64, ppu | |
| 207 | ZigLLVM_ppc64le, // PPC64LE: powerpc64le | |
| 208 | ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX | |
| 209 | ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs | |
| 210 | ZigLLVM_riscv32, // RISC-V (32-bit): riscv32 | |
| 211 | ZigLLVM_riscv64, // RISC-V (64-bit): riscv64 | |
| 212 | ZigLLVM_sparc, // Sparc: sparc | |
| 213 | ZigLLVM_sparcv9, // Sparcv9: Sparcv9 | |
| 214 | ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant | |
| 215 | ZigLLVM_systemz, // SystemZ: s390x | |
| 216 | ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce | |
| 217 | ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele | |
| 218 | ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.* | |
| 219 | ZigLLVM_thumbeb, // Thumb (big endian): thumbeb | |
| 220 | ZigLLVM_x86, // X86: i[3-9]86 | |
| 221 | ZigLLVM_x86_64, // X86-64: amd64, x86_64 | |
| 222 | ZigLLVM_xcore, // XCore: xcore | |
| 223 | ZigLLVM_nvptx, // NVPTX: 32-bit | |
| 224 | ZigLLVM_nvptx64, // NVPTX: 64-bit | |
| 225 | ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl) | |
| 226 | ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl) | |
| 227 | ZigLLVM_amdil, // AMDIL | |
| 228 | ZigLLVM_amdil64, // AMDIL with 64-bit pointers | |
| 229 | ZigLLVM_hsail, // AMD HSAIL | |
| 230 | ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers | |
| 231 | ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version | |
| 232 | ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version | |
| 233 | ZigLLVM_kalimba, // Kalimba: generic kalimba | |
| 234 | ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors | |
| 235 | ZigLLVM_lanai, // Lanai: Lanai 32-bit | |
| 236 | ZigLLVM_wasm32, // WebAssembly with 32-bit pointers | |
| 237 | ZigLLVM_wasm64, // WebAssembly with 64-bit pointers | |
| 238 | ZigLLVM_renderscript32, // 32-bit RenderScript | |
| 239 | ZigLLVM_renderscript64, // 64-bit RenderScript | |
| 240 | ||
| 241 | ZigLLVM_LastArchType = ZigLLVM_renderscript64 | |
| 242 | }; | |
| 243 | ||
| 244 | enum ZigLLVM_SubArchType { | |
| 245 | ZigLLVM_NoSubArch, | |
| 246 | ||
| 247 | ZigLLVM_ARMSubArch_v8_3a, | |
| 248 | ZigLLVM_ARMSubArch_v8_2a, | |
| 249 | ZigLLVM_ARMSubArch_v8_1a, | |
| 250 | ZigLLVM_ARMSubArch_v8, | |
| 251 | ZigLLVM_ARMSubArch_v8r, | |
| 252 | ZigLLVM_ARMSubArch_v8m_baseline, | |
| 253 | ZigLLVM_ARMSubArch_v8m_mainline, | |
| 254 | ZigLLVM_ARMSubArch_v7, | |
| 255 | ZigLLVM_ARMSubArch_v7em, | |
| 256 | ZigLLVM_ARMSubArch_v7m, | |
| 257 | ZigLLVM_ARMSubArch_v7s, | |
| 258 | ZigLLVM_ARMSubArch_v7k, | |
| 259 | ZigLLVM_ARMSubArch_v7ve, | |
| 260 | ZigLLVM_ARMSubArch_v6, | |
| 261 | ZigLLVM_ARMSubArch_v6m, | |
| 262 | ZigLLVM_ARMSubArch_v6k, | |
| 263 | ZigLLVM_ARMSubArch_v6t2, | |
| 264 | ZigLLVM_ARMSubArch_v5, | |
| 265 | ZigLLVM_ARMSubArch_v5te, | |
| 266 | ZigLLVM_ARMSubArch_v4t, | |
| 267 | ||
| 268 | ZigLLVM_KalimbaSubArch_v3, | |
| 269 | ZigLLVM_KalimbaSubArch_v4, | |
| 270 | ZigLLVM_KalimbaSubArch_v5, | |
| 271 | }; | |
| 272 | ||
| 273 | enum ZigLLVM_VendorType { | |
| 274 | ZigLLVM_UnknownVendor, | |
| 275 | ||
| 276 | ZigLLVM_Apple, | |
| 277 | ZigLLVM_PC, | |
| 278 | ZigLLVM_SCEI, | |
| 279 | ZigLLVM_BGP, | |
| 280 | ZigLLVM_BGQ, | |
| 281 | ZigLLVM_Freescale, | |
| 282 | ZigLLVM_IBM, | |
| 283 | ZigLLVM_ImaginationTechnologies, | |
| 284 | ZigLLVM_MipsTechnologies, | |
| 285 | ZigLLVM_NVIDIA, | |
| 286 | ZigLLVM_CSR, | |
| 287 | ZigLLVM_Myriad, | |
| 288 | ZigLLVM_AMD, | |
| 289 | ZigLLVM_Mesa, | |
| 290 | ZigLLVM_SUSE, | |
| 291 | ||
| 292 | ZigLLVM_LastVendorType = ZigLLVM_SUSE | |
| 293 | }; | |
| 294 | ||
| 295 | enum ZigLLVM_OSType { | |
| 296 | ZigLLVM_UnknownOS, | |
| 297 | ||
| 298 | ZigLLVM_Ananas, | |
| 299 | ZigLLVM_CloudABI, | |
| 300 | ZigLLVM_Darwin, | |
| 301 | ZigLLVM_DragonFly, | |
| 302 | ZigLLVM_FreeBSD, | |
| 303 | ZigLLVM_Fuchsia, | |
| 304 | ZigLLVM_IOS, | |
| 305 | ZigLLVM_KFreeBSD, | |
| 306 | ZigLLVM_Linux, | |
| 307 | ZigLLVM_Lv2, // PS3 | |
| 308 | ZigLLVM_MacOSX, | |
| 309 | ZigLLVM_NetBSD, | |
| 310 | ZigLLVM_OpenBSD, | |
| 311 | ZigLLVM_Solaris, | |
| 312 | ZigLLVM_Win32, | |
| 313 | ZigLLVM_Haiku, | |
| 314 | ZigLLVM_Minix, | |
| 315 | ZigLLVM_RTEMS, | |
| 316 | ZigLLVM_NaCl, // Native Client | |
| 317 | ZigLLVM_CNK, // BG/P Compute-Node Kernel | |
| 318 | ZigLLVM_Bitrig, | |
| 319 | ZigLLVM_AIX, | |
| 320 | ZigLLVM_CUDA, // NVIDIA CUDA | |
| 321 | ZigLLVM_NVCL, // NVIDIA OpenCL | |
| 322 | ZigLLVM_AMDHSA, // AMD HSA Runtime | |
| 323 | ZigLLVM_PS4, | |
| 324 | ZigLLVM_ELFIAMCU, | |
| 325 | ZigLLVM_TvOS, // Apple tvOS | |
| 326 | ZigLLVM_WatchOS, // Apple watchOS | |
| 327 | ZigLLVM_Mesa3D, | |
| 328 | ZigLLVM_Contiki, | |
| 329 | ||
| 330 | ZigLLVM_LastOSType = ZigLLVM_Contiki | |
| 331 | }; | |
| 332 | ||
| 333 | enum ZigLLVM_EnvironmentType { | |
| 334 | ZigLLVM_UnknownEnvironment, | |
| 335 | ||
| 336 | ZigLLVM_GNU, | |
| 337 | ZigLLVM_GNUABIN32, | |
| 338 | ZigLLVM_GNUABI64, | |
| 339 | ZigLLVM_GNUEABI, | |
| 340 | ZigLLVM_GNUEABIHF, | |
| 341 | ZigLLVM_GNUX32, | |
| 342 | ZigLLVM_CODE16, | |
| 343 | ZigLLVM_EABI, | |
| 344 | ZigLLVM_EABIHF, | |
| 345 | ZigLLVM_Android, | |
| 346 | ZigLLVM_Musl, | |
| 347 | ZigLLVM_MuslEABI, | |
| 348 | ZigLLVM_MuslEABIHF, | |
| 349 | ||
| 350 | ZigLLVM_MSVC, | |
| 351 | ZigLLVM_Itanium, | |
| 352 | ZigLLVM_Cygnus, | |
| 353 | ZigLLVM_AMDOpenCL, | |
| 354 | ZigLLVM_CoreCLR, | |
| 355 | ZigLLVM_OpenCL, | |
| 356 | ZigLLVM_Simulator, // Simulator variants of other systems, e.g., Apple's iOS | |
| 357 | ||
| 358 | ZigLLVM_LastEnvironmentType = ZigLLVM_Simulator | |
| 359 | }; | |
| 360 | ||
| 361 | enum ZigLLVM_ObjectFormatType { | |
| 362 | ZigLLVM_UnknownObjectFormat, | |
| 363 | ||
| 364 | ZigLLVM_COFF, | |
| 365 | ZigLLVM_ELF, | |
| 366 | ZigLLVM_MachO, | |
| 367 | ZigLLVM_Wasm, | |
| 368 | }; | |
| 369 | ||
| 370 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch); | |
| 371 | const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch); | |
| 372 | const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor); | |
| 373 | const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os); | |
| 374 | const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type); | |
| 375 | ||
| 376 | /* | |
| 377 | * This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here. | |
| 378 | */ | |
| 379 | struct Buf; | |
| 380 | ||
| 381 | bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, Buf *diag); | |
| 382 | ||
| 383 | void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, | |
| 384 | ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, | |
| 385 | ZigLLVM_ObjectFormatType *oformat); | |
| 386 | ||
| 387 | #endif |
std/array_list.zig+3-2| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 2 | 3 | const assert = debug.assert; |
| 3 | const mem = @import("mem.zig"); | |
| 4 | const mem = std.mem; | |
| 4 | 5 | const Allocator = mem.Allocator; |
| 5 | 6 | |
| 6 | 7 | pub fn ArrayList(comptime T: type) -> type { |
std/base64.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const assert = @import("debug.zig").assert; | |
| 2 | const mem = @import("mem.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 3 | 4 | |
| 4 | 5 | pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 5 | 6 | pub const standard_pad_char = '='; |
std/buffer.zig+5-4| ... | ... | @@ -1,10 +1,11 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 2 | const mem = @import("mem.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 3 | const mem = std.mem; | |
| 3 | 4 | const Allocator = mem.Allocator; |
| 4 | 5 | const assert = debug.assert; |
| 5 | const ArrayList = @import("array_list.zig").ArrayList; | |
| 6 | const ArrayList = std.ArrayList; | |
| 6 | 7 | |
| 7 | const fmt = @import("fmt/index.zig"); | |
| 8 | const fmt = std.fmt; | |
| 8 | 9 | |
| 9 | 10 | /// A buffer that allocates memory and maintains a null byte at the end. |
| 10 | 11 | pub const Buffer = struct { |
std/build.zig+7| ... | ... | @@ -784,6 +784,13 @@ const Target = union(enum) { |
| 784 | 784 | }; |
| 785 | 785 | } |
| 786 | 786 | |
| 787 | pub fn libFileExt(self: &const Target) -> []const u8 { | |
| 788 | return switch (self.getOs()) { | |
| 789 | builtin.Os.windows => ".lib", | |
| 790 | else => ".a", | |
| 791 | }; | |
| 792 | } | |
| 793 | ||
| 787 | 794 | pub fn getOs(self: &const Target) -> builtin.Os { |
| 788 | 795 | return switch (*self) { |
| 789 | 796 | Target.Native => builtin.os, |
std/cstr.zig+57-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 2 | const mem = @import("mem.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 3 | const mem = std.mem; | |
| 3 | 4 | const assert = debug.assert; |
| 4 | 5 | |
| 5 | 6 | pub fn len(ptr: &const u8) -> usize { |
| ... | ... | @@ -47,3 +48,57 @@ pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) -> %[]u8 { |
| 47 | 48 | result[slice.len] = 0; |
| 48 | 49 | return result; |
| 49 | 50 | } |
| 51 | ||
| 52 | pub const NullTerminated2DArray = struct { | |
| 53 | allocator: &mem.Allocator, | |
| 54 | byte_count: usize, | |
| 55 | ptr: ?&?&u8, | |
| 56 | ||
| 57 | /// Takes N lists of strings, concatenates the lists together, and adds a null terminator | |
| 58 | /// Caller must deinit result | |
| 59 | pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) -> %NullTerminated2DArray { | |
| 60 | var new_len: usize = 1; // 1 for the list null | |
| 61 | var byte_count: usize = 0; | |
| 62 | for (slices) |slice| { | |
| 63 | new_len += slice.len; | |
| 64 | for (slice) |inner| { | |
| 65 | byte_count += inner.len; | |
| 66 | } | |
| 67 | byte_count += slice.len; // for the null terminators of inner | |
| 68 | } | |
| 69 | ||
| 70 | const index_size = @sizeOf(usize) * new_len; // size of the ptrs | |
| 71 | byte_count += index_size; | |
| 72 | ||
| 73 | const buf = %return allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count); | |
| 74 | %defer allocator.free(buf); | |
| 75 | ||
| 76 | var write_index = index_size; | |
| 77 | const index_buf = ([]?&u8)(buf); | |
| 78 | ||
| 79 | var i: usize = 0; | |
| 80 | for (slices) |slice| { | |
| 81 | for (slice) |inner| { | |
| 82 | index_buf[i] = &buf[write_index]; | |
| 83 | i += 1; | |
| 84 | mem.copy(u8, buf[write_index..], inner); | |
| 85 | write_index += inner.len; | |
| 86 | buf[write_index] = 0; | |
| 87 | write_index += 1; | |
| 88 | } | |
| 89 | } | |
| 90 | index_buf[i] = null; | |
| 91 | ||
| 92 | return NullTerminated2DArray { | |
| 93 | .allocator = allocator, | |
| 94 | .byte_count = byte_count, | |
| 95 | .ptr = @ptrCast(?&?&u8, buf.ptr), | |
| 96 | }; | |
| 97 | } | |
| 98 | ||
| 99 | pub fn deinit(self: &NullTerminated2DArray) { | |
| 100 | const buf = @ptrCast(&u8, self.ptr); | |
| 101 | self.allocator.free(buf[0..self.byte_count]); | |
| 102 | } | |
| 103 | }; | |
| 104 |
std/debug.zig deleted-1050| ... | ... | @@ -1,1050 +0,0 @@ |
| 1 | const std = @import("index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const mem = std.mem; | |
| 4 | const io = std.io; | |
| 5 | const os = std.os; | |
| 6 | const elf = @import("elf.zig"); | |
| 7 | const DW = @import("dwarf.zig"); | |
| 8 | const ArrayList = std.ArrayList; | |
| 9 | const builtin = @import("builtin"); | |
| 10 | ||
| 11 | error MissingDebugInfo; | |
| 12 | error InvalidDebugInfo; | |
| 13 | error UnsupportedDebugInfo; | |
| 14 | ||
| 15 | ||
| 16 | /// Tries to write to stderr, unbuffered, and ignores any error returned. | |
| 17 | /// Does not append a newline. | |
| 18 | /// TODO atomic/multithread support | |
| 19 | var stderr_file: io.File = undefined; | |
| 20 | var stderr_file_out_stream: io.FileOutStream = undefined; | |
| 21 | var stderr_stream: ?&io.OutStream = null; | |
| 22 | pub fn warn(comptime fmt: []const u8, args: ...) { | |
| 23 | const stderr = getStderrStream() %% return; | |
| 24 | stderr.print(fmt, args) %% return; | |
| 25 | } | |
| 26 | fn getStderrStream() -> %&io.OutStream { | |
| 27 | if (stderr_stream) |st| { | |
| 28 | return st; | |
| 29 | } else { | |
| 30 | stderr_file = %return io.getStdErr(); | |
| 31 | stderr_file_out_stream = io.FileOutStream.init(&stderr_file); | |
| 32 | const st = &stderr_file_out_stream.stream; | |
| 33 | stderr_stream = st; | |
| 34 | return st; | |
| 35 | } | |
| 36 | } | |
| 37 | ||
| 38 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. | |
| 39 | pub fn dumpStackTrace() { | |
| 40 | const stderr = getStderrStream() %% return; | |
| 41 | writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% return; | |
| 42 | } | |
| 43 | ||
| 44 | /// This function invokes undefined behavior when `ok` is `false`. | |
| 45 | /// In Debug and ReleaseSafe modes, calls to this function are always | |
| 46 | /// generated, and the `unreachable` statement triggers a panic. | |
| 47 | /// In ReleaseFast and ReleaseSmall modes, calls to this function can be | |
| 48 | /// optimized away. | |
| 49 | pub fn assert(ok: bool) { | |
| 50 | if (!ok) { | |
| 51 | // In ReleaseFast test mode, we still want assert(false) to crash, so | |
| 52 | // we insert an explicit call to @panic instead of unreachable. | |
| 53 | // TODO we should use `assertOrPanic` in tests and remove this logic. | |
| 54 | if (builtin.is_test) { | |
| 55 | @panic("assertion failure"); | |
| 56 | } else { | |
| 57 | unreachable; // assertion failure | |
| 58 | } | |
| 59 | } | |
| 60 | } | |
| 61 | ||
| 62 | /// Call this function when you want to panic if the condition is not true. | |
| 63 | /// If `ok` is `false`, this function will panic in every release mode. | |
| 64 | pub fn assertOrPanic(ok: bool) { | |
| 65 | if (!ok) { | |
| 66 | @panic("assertion failure"); | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | var panicking = false; | |
| 71 | /// This is the default panic implementation. | |
| 72 | pub fn panic(comptime format: []const u8, args: ...) -> noreturn { | |
| 73 | // TODO an intrinsic that labels this as unlikely to be reached | |
| 74 | ||
| 75 | // TODO | |
| 76 | // if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { } | |
| 77 | if (panicking) { | |
| 78 | // Panicked during a panic. | |
| 79 | // TODO detect if a different thread caused the panic, because in that case | |
| 80 | // we would want to return here instead of calling abort, so that the thread | |
| 81 | // which first called panic can finish printing a stack trace. | |
| 82 | os.abort(); | |
| 83 | } else { | |
| 84 | panicking = true; | |
| 85 | } | |
| 86 | ||
| 87 | const stderr = getStderrStream() %% os.abort(); | |
| 88 | stderr.print(format ++ "\n", args) %% os.abort(); | |
| 89 | writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% os.abort(); | |
| 90 | ||
| 91 | os.abort(); | |
| 92 | } | |
| 93 | ||
| 94 | const GREEN = "\x1b[32;1m"; | |
| 95 | const WHITE = "\x1b[37;1m"; | |
| 96 | const DIM = "\x1b[2m"; | |
| 97 | const RESET = "\x1b[0m"; | |
| 98 | ||
| 99 | error PathNotFound; | |
| 100 | error InvalidDebugInfo; | |
| 101 | ||
| 102 | pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty_color: bool, | |
| 103 | ignore_frame_count: usize) -> %void | |
| 104 | { | |
| 105 | switch (builtin.object_format) { | |
| 106 | builtin.ObjectFormat.elf => { | |
| 107 | var stack_trace = ElfStackTrace { | |
| 108 | .self_exe_file = undefined, | |
| 109 | .elf = undefined, | |
| 110 | .debug_info = undefined, | |
| 111 | .debug_abbrev = undefined, | |
| 112 | .debug_str = undefined, | |
| 113 | .debug_line = undefined, | |
| 114 | .debug_ranges = null, | |
| 115 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | |
| 116 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | |
| 117 | }; | |
| 118 | const st = &stack_trace; | |
| 119 | st.self_exe_file = %return os.openSelfExe(); | |
| 120 | defer st.self_exe_file.close(); | |
| 121 | ||
| 122 | %return st.elf.openFile(allocator, &st.self_exe_file); | |
| 123 | defer st.elf.close(); | |
| 124 | ||
| 125 | st.debug_info = (%return st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; | |
| 126 | st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; | |
| 127 | st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo; | |
| 128 | st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; | |
| 129 | st.debug_ranges = (%return st.elf.findSection(".debug_ranges")); | |
| 130 | %return scanAllCompileUnits(st); | |
| 131 | ||
| 132 | var ignored_count: usize = 0; | |
| 133 | ||
| 134 | var fp = @ptrToInt(@frameAddress()); | |
| 135 | while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { | |
| 136 | if (ignored_count < ignore_frame_count) { | |
| 137 | ignored_count += 1; | |
| 138 | continue; | |
| 139 | } | |
| 140 | ||
| 141 | const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); | |
| 142 | ||
| 143 | // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal | |
| 144 | // at compile time. I'll call it issue #313 | |
| 145 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; | |
| 146 | ||
| 147 | const compile_unit = findCompileUnit(st, return_address) %% { | |
| 148 | %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", | |
| 149 | return_address); | |
| 150 | continue; | |
| 151 | }; | |
| 152 | const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name); | |
| 153 | if (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| { | |
| 154 | defer line_info.deinit(); | |
| 155 | %return out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ | |
| 156 | DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", | |
| 157 | line_info.file_name, line_info.line, line_info.column, | |
| 158 | return_address, compile_unit_name); | |
| 159 | if (printLineFromFile(st.allocator(), out_stream, line_info)) { | |
| 160 | if (line_info.column == 0) { | |
| 161 | %return out_stream.write("\n"); | |
| 162 | } else { | |
| 163 | {var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) { | |
| 164 | %return out_stream.writeByte(' '); | |
| 165 | }} | |
| 166 | %return out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); | |
| 167 | } | |
| 168 | } else |err| switch (err) { | |
| 169 | error.EndOfFile, error.PathNotFound => {}, | |
| 170 | else => return err, | |
| 171 | } | |
| 172 | } else |err| switch (err) { | |
| 173 | error.MissingDebugInfo, error.InvalidDebugInfo => { | |
| 174 | %return out_stream.print(ptr_hex ++ " in ??? ({})\n", | |
| 175 | return_address, compile_unit_name); | |
| 176 | }, | |
| 177 | else => return err, | |
| 178 | } | |
| 179 | } | |
| 180 | }, | |
| 181 | builtin.ObjectFormat.coff => { | |
| 182 | %return out_stream.write("(stack trace unavailable for COFF object format)\n"); | |
| 183 | }, | |
| 184 | builtin.ObjectFormat.macho => { | |
| 185 | %return out_stream.write("(stack trace unavailable for Mach-O object format)\n"); | |
| 186 | }, | |
| 187 | builtin.ObjectFormat.wasm => { | |
| 188 | %return out_stream.write("(stack trace unavailable for WASM object format)\n"); | |
| 189 | }, | |
| 190 | builtin.ObjectFormat.unknown => { | |
| 191 | %return out_stream.write("(stack trace unavailable for unknown object format)\n"); | |
| 192 | }, | |
| 193 | } | |
| 194 | } | |
| 195 | ||
| 196 | fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) -> %void { | |
| 197 | var f = %return io.File.openRead(line_info.file_name, allocator); | |
| 198 | defer f.close(); | |
| 199 | // TODO fstat and make sure that the file has the correct size | |
| 200 | ||
| 201 | var buf: [os.page_size]u8 = undefined; | |
| 202 | var line: usize = 1; | |
| 203 | var column: usize = 1; | |
| 204 | var abs_index: usize = 0; | |
| 205 | while (true) { | |
| 206 | const amt_read = %return f.read(buf[0..]); | |
| 207 | const slice = buf[0..amt_read]; | |
| 208 | ||
| 209 | for (slice) |byte| { | |
| 210 | if (line == line_info.line) { | |
| 211 | %return out_stream.writeByte(byte); | |
| 212 | if (byte == '\n') { | |
| 213 | return; | |
| 214 | } | |
| 215 | } | |
| 216 | if (byte == '\n') { | |
| 217 | line += 1; | |
| 218 | column = 1; | |
| 219 | } else { | |
| 220 | column += 1; | |
| 221 | } | |
| 222 | } | |
| 223 | ||
| 224 | if (amt_read < buf.len) | |
| 225 | return error.EndOfFile; | |
| 226 | } | |
| 227 | } | |
| 228 | ||
| 229 | const ElfStackTrace = struct { | |
| 230 | self_exe_file: io.File, | |
| 231 | elf: elf.Elf, | |
| 232 | debug_info: &elf.SectionHeader, | |
| 233 | debug_abbrev: &elf.SectionHeader, | |
| 234 | debug_str: &elf.SectionHeader, | |
| 235 | debug_line: &elf.SectionHeader, | |
| 236 | debug_ranges: ?&elf.SectionHeader, | |
| 237 | abbrev_table_list: ArrayList(AbbrevTableHeader), | |
| 238 | compile_unit_list: ArrayList(CompileUnit), | |
| 239 | ||
| 240 | pub fn allocator(self: &const ElfStackTrace) -> &mem.Allocator { | |
| 241 | return self.abbrev_table_list.allocator; | |
| 242 | } | |
| 243 | ||
| 244 | pub fn readString(self: &ElfStackTrace) -> %[]u8 { | |
| 245 | var in_file_stream = io.FileInStream.init(&self.self_exe_file); | |
| 246 | const in_stream = &in_file_stream.stream; | |
| 247 | return readStringRaw(self.allocator(), in_stream); | |
| 248 | } | |
| 249 | }; | |
| 250 | ||
| 251 | const PcRange = struct { | |
| 252 | start: u64, | |
| 253 | end: u64, | |
| 254 | }; | |
| 255 | ||
| 256 | const CompileUnit = struct { | |
| 257 | version: u16, | |
| 258 | is_64: bool, | |
| 259 | die: &Die, | |
| 260 | index: usize, | |
| 261 | pc_range: ?PcRange, | |
| 262 | }; | |
| 263 | ||
| 264 | const AbbrevTable = ArrayList(AbbrevTableEntry); | |
| 265 | ||
| 266 | const AbbrevTableHeader = struct { | |
| 267 | // offset from .debug_abbrev | |
| 268 | offset: u64, | |
| 269 | table: AbbrevTable, | |
| 270 | }; | |
| 271 | ||
| 272 | const AbbrevTableEntry = struct { | |
| 273 | has_children: bool, | |
| 274 | abbrev_code: u64, | |
| 275 | tag_id: u64, | |
| 276 | attrs: ArrayList(AbbrevAttr), | |
| 277 | }; | |
| 278 | ||
| 279 | const AbbrevAttr = struct { | |
| 280 | attr_id: u64, | |
| 281 | form_id: u64, | |
| 282 | }; | |
| 283 | ||
| 284 | const FormValue = union(enum) { | |
| 285 | Address: u64, | |
| 286 | Block: []u8, | |
| 287 | Const: Constant, | |
| 288 | ExprLoc: []u8, | |
| 289 | Flag: bool, | |
| 290 | SecOffset: u64, | |
| 291 | Ref: []u8, | |
| 292 | RefAddr: u64, | |
| 293 | RefSig8: u64, | |
| 294 | String: []u8, | |
| 295 | StrPtr: u64, | |
| 296 | }; | |
| 297 | ||
| 298 | const Constant = struct { | |
| 299 | payload: []u8, | |
| 300 | signed: bool, | |
| 301 | ||
| 302 | fn asUnsignedLe(self: &const Constant) -> %u64 { | |
| 303 | if (self.payload.len > @sizeOf(u64)) | |
| 304 | return error.InvalidDebugInfo; | |
| 305 | if (self.signed) | |
| 306 | return error.InvalidDebugInfo; | |
| 307 | return mem.readInt(self.payload, u64, builtin.Endian.Little); | |
| 308 | } | |
| 309 | }; | |
| 310 | ||
| 311 | const Die = struct { | |
| 312 | tag_id: u64, | |
| 313 | has_children: bool, | |
| 314 | attrs: ArrayList(Attr), | |
| 315 | ||
| 316 | const Attr = struct { | |
| 317 | id: u64, | |
| 318 | value: FormValue, | |
| 319 | }; | |
| 320 | ||
| 321 | fn getAttr(self: &const Die, id: u64) -> ?&const FormValue { | |
| 322 | for (self.attrs.toSliceConst()) |*attr| { | |
| 323 | if (attr.id == id) | |
| 324 | return &attr.value; | |
| 325 | } | |
| 326 | return null; | |
| 327 | } | |
| 328 | ||
| 329 | fn getAttrAddr(self: &const Die, id: u64) -> %u64 { | |
| 330 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 331 | return switch (*form_value) { | |
| 332 | FormValue.Address => |value| value, | |
| 333 | else => error.InvalidDebugInfo, | |
| 334 | }; | |
| 335 | } | |
| 336 | ||
| 337 | fn getAttrSecOffset(self: &const Die, id: u64) -> %u64 { | |
| 338 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 339 | return switch (*form_value) { | |
| 340 | FormValue.Const => |value| value.asUnsignedLe(), | |
| 341 | FormValue.SecOffset => |value| value, | |
| 342 | else => error.InvalidDebugInfo, | |
| 343 | }; | |
| 344 | } | |
| 345 | ||
| 346 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { | |
| 347 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 348 | return switch (*form_value) { | |
| 349 | FormValue.Const => |value| value.asUnsignedLe(), | |
| 350 | else => error.InvalidDebugInfo, | |
| 351 | }; | |
| 352 | } | |
| 353 | ||
| 354 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) -> %[]u8 { | |
| 355 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 356 | return switch (*form_value) { | |
| 357 | FormValue.String => |value| value, | |
| 358 | FormValue.StrPtr => |offset| getString(st, offset), | |
| 359 | else => error.InvalidDebugInfo, | |
| 360 | }; | |
| 361 | } | |
| 362 | }; | |
| 363 | ||
| 364 | const FileEntry = struct { | |
| 365 | file_name: []const u8, | |
| 366 | dir_index: usize, | |
| 367 | mtime: usize, | |
| 368 | len_bytes: usize, | |
| 369 | }; | |
| 370 | ||
| 371 | const LineInfo = struct { | |
| 372 | line: usize, | |
| 373 | column: usize, | |
| 374 | file_name: []u8, | |
| 375 | allocator: &mem.Allocator, | |
| 376 | ||
| 377 | fn deinit(self: &const LineInfo) { | |
| 378 | self.allocator.free(self.file_name); | |
| 379 | } | |
| 380 | }; | |
| 381 | ||
| 382 | const LineNumberProgram = struct { | |
| 383 | address: usize, | |
| 384 | file: usize, | |
| 385 | line: isize, | |
| 386 | column: usize, | |
| 387 | is_stmt: bool, | |
| 388 | basic_block: bool, | |
| 389 | end_sequence: bool, | |
| 390 | ||
| 391 | target_address: usize, | |
| 392 | include_dirs: []const []const u8, | |
| 393 | file_entries: &ArrayList(FileEntry), | |
| 394 | ||
| 395 | prev_address: usize, | |
| 396 | prev_file: usize, | |
| 397 | prev_line: isize, | |
| 398 | prev_column: usize, | |
| 399 | prev_is_stmt: bool, | |
| 400 | prev_basic_block: bool, | |
| 401 | prev_end_sequence: bool, | |
| 402 | ||
| 403 | pub fn init(is_stmt: bool, include_dirs: []const []const u8, | |
| 404 | file_entries: &ArrayList(FileEntry), target_address: usize) -> LineNumberProgram | |
| 405 | { | |
| 406 | return LineNumberProgram { | |
| 407 | .address = 0, | |
| 408 | .file = 1, | |
| 409 | .line = 1, | |
| 410 | .column = 0, | |
| 411 | .is_stmt = is_stmt, | |
| 412 | .basic_block = false, | |
| 413 | .end_sequence = false, | |
| 414 | .include_dirs = include_dirs, | |
| 415 | .file_entries = file_entries, | |
| 416 | .target_address = target_address, | |
| 417 | .prev_address = 0, | |
| 418 | .prev_file = undefined, | |
| 419 | .prev_line = undefined, | |
| 420 | .prev_column = undefined, | |
| 421 | .prev_is_stmt = undefined, | |
| 422 | .prev_basic_block = undefined, | |
| 423 | .prev_end_sequence = undefined, | |
| 424 | }; | |
| 425 | } | |
| 426 | ||
| 427 | pub fn checkLineMatch(self: &LineNumberProgram) -> %?LineInfo { | |
| 428 | if (self.target_address >= self.prev_address and self.target_address < self.address) { | |
| 429 | const file_entry = if (self.prev_file == 0) { | |
| 430 | return error.MissingDebugInfo; | |
| 431 | } else if (self.prev_file - 1 >= self.file_entries.len) { | |
| 432 | return error.InvalidDebugInfo; | |
| 433 | } else &self.file_entries.items[self.prev_file - 1]; | |
| 434 | ||
| 435 | const dir_name = if (file_entry.dir_index >= self.include_dirs.len) { | |
| 436 | return error.InvalidDebugInfo; | |
| 437 | } else self.include_dirs[file_entry.dir_index]; | |
| 438 | const file_name = %return os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); | |
| 439 | %defer self.file_entries.allocator.free(file_name); | |
| 440 | return LineInfo { | |
| 441 | .line = if (self.prev_line >= 0) usize(self.prev_line) else 0, | |
| 442 | .column = self.prev_column, | |
| 443 | .file_name = file_name, | |
| 444 | .allocator = self.file_entries.allocator, | |
| 445 | }; | |
| 446 | } | |
| 447 | ||
| 448 | self.prev_address = self.address; | |
| 449 | self.prev_file = self.file; | |
| 450 | self.prev_line = self.line; | |
| 451 | self.prev_column = self.column; | |
| 452 | self.prev_is_stmt = self.is_stmt; | |
| 453 | self.prev_basic_block = self.basic_block; | |
| 454 | self.prev_end_sequence = self.end_sequence; | |
| 455 | return null; | |
| 456 | } | |
| 457 | }; | |
| 458 | ||
| 459 | fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) -> %[]u8 { | |
| 460 | var buf = ArrayList(u8).init(allocator); | |
| 461 | while (true) { | |
| 462 | const byte = %return in_stream.readByte(); | |
| 463 | if (byte == 0) | |
| 464 | break; | |
| 465 | %return buf.append(byte); | |
| 466 | } | |
| 467 | return buf.toSlice(); | |
| 468 | } | |
| 469 | ||
| 470 | fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 { | |
| 471 | const pos = st.debug_str.offset + offset; | |
| 472 | %return st.self_exe_file.seekTo(pos); | |
| 473 | return st.readString(); | |
| 474 | } | |
| 475 | ||
| 476 | fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 { | |
| 477 | const buf = %return global_allocator.alloc(u8, size); | |
| 478 | %defer global_allocator.free(buf); | |
| 479 | if ((%return in_stream.read(buf)) < size) return error.EndOfFile; | |
| 480 | return buf; | |
| 481 | } | |
| 482 | ||
| 483 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 484 | const buf = %return readAllocBytes(allocator, in_stream, size); | |
| 485 | return FormValue { .Block = buf }; | |
| 486 | } | |
| 487 | ||
| 488 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 489 | const block_len = %return in_stream.readVarInt(builtin.Endian.Little, usize, size); | |
| 490 | return parseFormValueBlockLen(allocator, in_stream, block_len); | |
| 491 | } | |
| 492 | ||
| 493 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { | |
| 494 | return FormValue { .Const = Constant { | |
| 495 | .signed = signed, | |
| 496 | .payload = %return readAllocBytes(allocator, in_stream, size), | |
| 497 | }}; | |
| 498 | } | |
| 499 | ||
| 500 | fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) -> %u64 { | |
| 501 | return if (is_64) %return in_stream.readIntLe(u64) | |
| 502 | else u64(%return in_stream.readIntLe(u32)) ; | |
| 503 | } | |
| 504 | ||
| 505 | fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { | |
| 506 | return if (@sizeOf(usize) == 4) u64(%return in_stream.readIntLe(u32)) | |
| 507 | else if (@sizeOf(usize) == 8) %return in_stream.readIntLe(u64) | |
| 508 | else unreachable; | |
| 509 | } | |
| 510 | ||
| 511 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 512 | const buf = %return readAllocBytes(allocator, in_stream, size); | |
| 513 | return FormValue { .Ref = buf }; | |
| 514 | } | |
| 515 | ||
| 516 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue { | |
| 517 | const block_len = %return in_stream.readIntLe(T); | |
| 518 | return parseFormValueRefLen(allocator, in_stream, block_len); | |
| 519 | } | |
| 520 | ||
| 521 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue { | |
| 522 | return switch (form_id) { | |
| 523 | DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) }, | |
| 524 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), | |
| 525 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), | |
| 526 | DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), | |
| 527 | DW.FORM_block => x: { | |
| 528 | const block_len = %return readULeb128(in_stream); | |
| 529 | return parseFormValueBlockLen(allocator, in_stream, block_len); | |
| 530 | }, | |
| 531 | DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1), | |
| 532 | DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), | |
| 533 | DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), | |
| 534 | DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), | |
| 535 | DW.FORM_udata, DW.FORM_sdata => { | |
| 536 | const block_len = %return readULeb128(in_stream); | |
| 537 | const signed = form_id == DW.FORM_sdata; | |
| 538 | return parseFormValueConstant(allocator, in_stream, signed, block_len); | |
| 539 | }, | |
| 540 | DW.FORM_exprloc => { | |
| 541 | const size = %return readULeb128(in_stream); | |
| 542 | const buf = %return readAllocBytes(allocator, in_stream, size); | |
| 543 | return FormValue { .ExprLoc = buf }; | |
| 544 | }, | |
| 545 | DW.FORM_flag => FormValue { .Flag = (%return in_stream.readByte()) != 0 }, | |
| 546 | DW.FORM_flag_present => FormValue { .Flag = true }, | |
| 547 | DW.FORM_sec_offset => FormValue { .SecOffset = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 548 | ||
| 549 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), | |
| 550 | DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), | |
| 551 | DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, u32), | |
| 552 | DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64), | |
| 553 | DW.FORM_ref_udata => { | |
| 554 | const ref_len = %return readULeb128(in_stream); | |
| 555 | return parseFormValueRefLen(allocator, in_stream, ref_len); | |
| 556 | }, | |
| 557 | ||
| 558 | DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 559 | DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) }, | |
| 560 | ||
| 561 | DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) }, | |
| 562 | DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 563 | DW.FORM_indirect => { | |
| 564 | const child_form_id = %return readULeb128(in_stream); | |
| 565 | return parseFormValue(allocator, in_stream, child_form_id, is_64); | |
| 566 | }, | |
| 567 | else => error.InvalidDebugInfo, | |
| 568 | }; | |
| 569 | } | |
| 570 | ||
| 571 | fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable { | |
| 572 | const in_file = &st.self_exe_file; | |
| 573 | var in_file_stream = io.FileInStream.init(in_file); | |
| 574 | const in_stream = &in_file_stream.stream; | |
| 575 | var result = AbbrevTable.init(st.allocator()); | |
| 576 | while (true) { | |
| 577 | const abbrev_code = %return readULeb128(in_stream); | |
| 578 | if (abbrev_code == 0) | |
| 579 | return result; | |
| 580 | %return result.append(AbbrevTableEntry { | |
| 581 | .abbrev_code = abbrev_code, | |
| 582 | .tag_id = %return readULeb128(in_stream), | |
| 583 | .has_children = (%return in_stream.readByte()) == DW.CHILDREN_yes, | |
| 584 | .attrs = ArrayList(AbbrevAttr).init(st.allocator()), | |
| 585 | }); | |
| 586 | const attrs = &result.items[result.len - 1].attrs; | |
| 587 | ||
| 588 | while (true) { | |
| 589 | const attr_id = %return readULeb128(in_stream); | |
| 590 | const form_id = %return readULeb128(in_stream); | |
| 591 | if (attr_id == 0 and form_id == 0) | |
| 592 | break; | |
| 593 | %return attrs.append(AbbrevAttr { | |
| 594 | .attr_id = attr_id, | |
| 595 | .form_id = form_id, | |
| 596 | }); | |
| 597 | } | |
| 598 | } | |
| 599 | } | |
| 600 | ||
| 601 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, | |
| 602 | /// seeks in the stream and parses it. | |
| 603 | fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) -> %&const AbbrevTable { | |
| 604 | for (st.abbrev_table_list.toSlice()) |*header| { | |
| 605 | if (header.offset == abbrev_offset) { | |
| 606 | return &header.table; | |
| 607 | } | |
| 608 | } | |
| 609 | %return st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); | |
| 610 | %return st.abbrev_table_list.append(AbbrevTableHeader { | |
| 611 | .offset = abbrev_offset, | |
| 612 | .table = %return parseAbbrevTable(st), | |
| 613 | }); | |
| 614 | return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table; | |
| 615 | } | |
| 616 | ||
| 617 | fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?&const AbbrevTableEntry { | |
| 618 | for (abbrev_table.toSliceConst()) |*table_entry| { | |
| 619 | if (table_entry.abbrev_code == abbrev_code) | |
| 620 | return table_entry; | |
| 621 | } | |
| 622 | return null; | |
| 623 | } | |
| 624 | ||
| 625 | fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -> %Die { | |
| 626 | const in_file = &st.self_exe_file; | |
| 627 | var in_file_stream = io.FileInStream.init(in_file); | |
| 628 | const in_stream = &in_file_stream.stream; | |
| 629 | const abbrev_code = %return readULeb128(in_stream); | |
| 630 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo; | |
| 631 | ||
| 632 | var result = Die { | |
| 633 | .tag_id = table_entry.tag_id, | |
| 634 | .has_children = table_entry.has_children, | |
| 635 | .attrs = ArrayList(Die.Attr).init(st.allocator()), | |
| 636 | }; | |
| 637 | %return result.attrs.resize(table_entry.attrs.len); | |
| 638 | for (table_entry.attrs.toSliceConst()) |attr, i| { | |
| 639 | result.attrs.items[i] = Die.Attr { | |
| 640 | .id = attr.attr_id, | |
| 641 | .value = %return parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), | |
| 642 | }; | |
| 643 | } | |
| 644 | return result; | |
| 645 | } | |
| 646 | ||
| 647 | fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) -> %LineInfo { | |
| 648 | const compile_unit_cwd = %return compile_unit.die.getAttrString(st, DW.AT_comp_dir); | |
| 649 | ||
| 650 | const in_file = &st.self_exe_file; | |
| 651 | const debug_line_end = st.debug_line.offset + st.debug_line.size; | |
| 652 | var this_offset = st.debug_line.offset; | |
| 653 | var this_index: usize = 0; | |
| 654 | ||
| 655 | var in_file_stream = io.FileInStream.init(in_file); | |
| 656 | const in_stream = &in_file_stream.stream; | |
| 657 | ||
| 658 | while (this_offset < debug_line_end) : (this_index += 1) { | |
| 659 | %return in_file.seekTo(this_offset); | |
| 660 | ||
| 661 | var is_64: bool = undefined; | |
| 662 | const unit_length = %return readInitialLength(in_stream, &is_64); | |
| 663 | if (unit_length == 0) | |
| 664 | return error.MissingDebugInfo; | |
| 665 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 666 | ||
| 667 | if (compile_unit.index != this_index) { | |
| 668 | this_offset += next_offset; | |
| 669 | continue; | |
| 670 | } | |
| 671 | ||
| 672 | const version = %return in_stream.readInt(st.elf.endian, u16); | |
| 673 | if (version != 2) return error.InvalidDebugInfo; | |
| 674 | ||
| 675 | const prologue_length = %return in_stream.readInt(st.elf.endian, u32); | |
| 676 | const prog_start_offset = (%return in_file.getPos()) + prologue_length; | |
| 677 | ||
| 678 | const minimum_instruction_length = %return in_stream.readByte(); | |
| 679 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; | |
| 680 | ||
| 681 | const default_is_stmt = (%return in_stream.readByte()) != 0; | |
| 682 | const line_base = %return in_stream.readByteSigned(); | |
| 683 | ||
| 684 | const line_range = %return in_stream.readByte(); | |
| 685 | if (line_range == 0) | |
| 686 | return error.InvalidDebugInfo; | |
| 687 | ||
| 688 | const opcode_base = %return in_stream.readByte(); | |
| 689 | ||
| 690 | const standard_opcode_lengths = %return st.allocator().alloc(u8, opcode_base - 1); | |
| 691 | ||
| 692 | {var i: usize = 0; while (i < opcode_base - 1) : (i += 1) { | |
| 693 | standard_opcode_lengths[i] = %return in_stream.readByte(); | |
| 694 | }} | |
| 695 | ||
| 696 | var include_directories = ArrayList([]u8).init(st.allocator()); | |
| 697 | %return include_directories.append(compile_unit_cwd); | |
| 698 | while (true) { | |
| 699 | const dir = %return st.readString(); | |
| 700 | if (dir.len == 0) | |
| 701 | break; | |
| 702 | %return include_directories.append(dir); | |
| 703 | } | |
| 704 | ||
| 705 | var file_entries = ArrayList(FileEntry).init(st.allocator()); | |
| 706 | var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), | |
| 707 | &file_entries, target_address); | |
| 708 | ||
| 709 | while (true) { | |
| 710 | const file_name = %return st.readString(); | |
| 711 | if (file_name.len == 0) | |
| 712 | break; | |
| 713 | const dir_index = %return readULeb128(in_stream); | |
| 714 | const mtime = %return readULeb128(in_stream); | |
| 715 | const len_bytes = %return readULeb128(in_stream); | |
| 716 | %return file_entries.append(FileEntry { | |
| 717 | .file_name = file_name, | |
| 718 | .dir_index = dir_index, | |
| 719 | .mtime = mtime, | |
| 720 | .len_bytes = len_bytes, | |
| 721 | }); | |
| 722 | } | |
| 723 | ||
| 724 | %return in_file.seekTo(prog_start_offset); | |
| 725 | ||
| 726 | while (true) { | |
| 727 | const opcode = %return in_stream.readByte(); | |
| 728 | ||
| 729 | var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash | |
| 730 | if (opcode == DW.LNS_extended_op) { | |
| 731 | const op_size = %return readULeb128(in_stream); | |
| 732 | if (op_size < 1) | |
| 733 | return error.InvalidDebugInfo; | |
| 734 | sub_op = %return in_stream.readByte(); | |
| 735 | switch (sub_op) { | |
| 736 | DW.LNE_end_sequence => { | |
| 737 | prog.end_sequence = true; | |
| 738 | if (%return prog.checkLineMatch()) |info| return info; | |
| 739 | return error.MissingDebugInfo; | |
| 740 | }, | |
| 741 | DW.LNE_set_address => { | |
| 742 | const addr = %return in_stream.readInt(st.elf.endian, usize); | |
| 743 | prog.address = addr; | |
| 744 | }, | |
| 745 | DW.LNE_define_file => { | |
| 746 | const file_name = %return st.readString(); | |
| 747 | const dir_index = %return readULeb128(in_stream); | |
| 748 | const mtime = %return readULeb128(in_stream); | |
| 749 | const len_bytes = %return readULeb128(in_stream); | |
| 750 | %return file_entries.append(FileEntry { | |
| 751 | .file_name = file_name, | |
| 752 | .dir_index = dir_index, | |
| 753 | .mtime = mtime, | |
| 754 | .len_bytes = len_bytes, | |
| 755 | }); | |
| 756 | }, | |
| 757 | else => { | |
| 758 | const fwd_amt = math.cast(isize, op_size - 1) %% return error.InvalidDebugInfo; | |
| 759 | %return in_file.seekForward(fwd_amt); | |
| 760 | }, | |
| 761 | } | |
| 762 | } else if (opcode >= opcode_base) { | |
| 763 | // special opcodes | |
| 764 | const adjusted_opcode = opcode - opcode_base; | |
| 765 | const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); | |
| 766 | const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); | |
| 767 | prog.line += inc_line; | |
| 768 | prog.address += inc_addr; | |
| 769 | if (%return prog.checkLineMatch()) |info| return info; | |
| 770 | prog.basic_block = false; | |
| 771 | } else { | |
| 772 | switch (opcode) { | |
| 773 | DW.LNS_copy => { | |
| 774 | if (%return prog.checkLineMatch()) |info| return info; | |
| 775 | prog.basic_block = false; | |
| 776 | }, | |
| 777 | DW.LNS_advance_pc => { | |
| 778 | const arg = %return readULeb128(in_stream); | |
| 779 | prog.address += arg * minimum_instruction_length; | |
| 780 | }, | |
| 781 | DW.LNS_advance_line => { | |
| 782 | const arg = %return readILeb128(in_stream); | |
| 783 | prog.line += arg; | |
| 784 | }, | |
| 785 | DW.LNS_set_file => { | |
| 786 | const arg = %return readULeb128(in_stream); | |
| 787 | prog.file = arg; | |
| 788 | }, | |
| 789 | DW.LNS_set_column => { | |
| 790 | const arg = %return readULeb128(in_stream); | |
| 791 | prog.column = arg; | |
| 792 | }, | |
| 793 | DW.LNS_negate_stmt => { | |
| 794 | prog.is_stmt = !prog.is_stmt; | |
| 795 | }, | |
| 796 | DW.LNS_set_basic_block => { | |
| 797 | prog.basic_block = true; | |
| 798 | }, | |
| 799 | DW.LNS_const_add_pc => { | |
| 800 | const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); | |
| 801 | prog.address += inc_addr; | |
| 802 | }, | |
| 803 | DW.LNS_fixed_advance_pc => { | |
| 804 | const arg = %return in_stream.readInt(st.elf.endian, u16); | |
| 805 | prog.address += arg; | |
| 806 | }, | |
| 807 | DW.LNS_set_prologue_end => { | |
| 808 | }, | |
| 809 | else => { | |
| 810 | if (opcode - 1 >= standard_opcode_lengths.len) | |
| 811 | return error.InvalidDebugInfo; | |
| 812 | const len_bytes = standard_opcode_lengths[opcode - 1]; | |
| 813 | %return in_file.seekForward(len_bytes); | |
| 814 | }, | |
| 815 | } | |
| 816 | } | |
| 817 | } | |
| 818 | ||
| 819 | this_offset += next_offset; | |
| 820 | } | |
| 821 | ||
| 822 | return error.MissingDebugInfo; | |
| 823 | } | |
| 824 | ||
| 825 | fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { | |
| 826 | const debug_info_end = st.debug_info.offset + st.debug_info.size; | |
| 827 | var this_unit_offset = st.debug_info.offset; | |
| 828 | var cu_index: usize = 0; | |
| 829 | ||
| 830 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); | |
| 831 | const in_stream = &in_file_stream.stream; | |
| 832 | ||
| 833 | while (this_unit_offset < debug_info_end) { | |
| 834 | %return st.self_exe_file.seekTo(this_unit_offset); | |
| 835 | ||
| 836 | var is_64: bool = undefined; | |
| 837 | const unit_length = %return readInitialLength(in_stream, &is_64); | |
| 838 | if (unit_length == 0) | |
| 839 | return; | |
| 840 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 841 | ||
| 842 | const version = %return in_stream.readInt(st.elf.endian, u16); | |
| 843 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | |
| 844 | ||
| 845 | const debug_abbrev_offset = | |
| 846 | if (is_64) %return in_stream.readInt(st.elf.endian, u64) | |
| 847 | else %return in_stream.readInt(st.elf.endian, u32); | |
| 848 | ||
| 849 | const address_size = %return in_stream.readByte(); | |
| 850 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; | |
| 851 | ||
| 852 | const compile_unit_pos = %return st.self_exe_file.getPos(); | |
| 853 | const abbrev_table = %return getAbbrevTable(st, debug_abbrev_offset); | |
| 854 | ||
| 855 | %return st.self_exe_file.seekTo(compile_unit_pos); | |
| 856 | ||
| 857 | const compile_unit_die = %return st.allocator().create(Die); | |
| 858 | *compile_unit_die = %return parseDie(st, abbrev_table, is_64); | |
| 859 | ||
| 860 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) | |
| 861 | return error.InvalidDebugInfo; | |
| 862 | ||
| 863 | const pc_range = x: { | |
| 864 | if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| { | |
| 865 | if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| { | |
| 866 | const pc_end = switch (*high_pc_value) { | |
| 867 | FormValue.Address => |value| value, | |
| 868 | FormValue.Const => |value| b: { | |
| 869 | const offset = %return value.asUnsignedLe(); | |
| 870 | break :b (low_pc + offset); | |
| 871 | }, | |
| 872 | else => return error.InvalidDebugInfo, | |
| 873 | }; | |
| 874 | break :x PcRange { | |
| 875 | .start = low_pc, | |
| 876 | .end = pc_end, | |
| 877 | }; | |
| 878 | } else { | |
| 879 | break :x null; | |
| 880 | } | |
| 881 | } else |err| { | |
| 882 | if (err != error.MissingDebugInfo) | |
| 883 | return err; | |
| 884 | break :x null; | |
| 885 | } | |
| 886 | }; | |
| 887 | ||
| 888 | %return st.compile_unit_list.append(CompileUnit { | |
| 889 | .version = version, | |
| 890 | .is_64 = is_64, | |
| 891 | .pc_range = pc_range, | |
| 892 | .die = compile_unit_die, | |
| 893 | .index = cu_index, | |
| 894 | }); | |
| 895 | ||
| 896 | this_unit_offset += next_offset; | |
| 897 | cu_index += 1; | |
| 898 | } | |
| 899 | } | |
| 900 | ||
| 901 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUnit { | |
| 902 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); | |
| 903 | const in_stream = &in_file_stream.stream; | |
| 904 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | |
| 905 | if (compile_unit.pc_range) |range| { | |
| 906 | if (target_address >= range.start and target_address < range.end) | |
| 907 | return compile_unit; | |
| 908 | } | |
| 909 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { | |
| 910 | var base_address: usize = 0; | |
| 911 | if (st.debug_ranges) |debug_ranges| { | |
| 912 | %return st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); | |
| 913 | while (true) { | |
| 914 | const begin_addr = %return in_stream.readIntLe(usize); | |
| 915 | const end_addr = %return in_stream.readIntLe(usize); | |
| 916 | if (begin_addr == 0 and end_addr == 0) { | |
| 917 | break; | |
| 918 | } | |
| 919 | if (begin_addr == @maxValue(usize)) { | |
| 920 | base_address = begin_addr; | |
| 921 | continue; | |
| 922 | } | |
| 923 | if (target_address >= begin_addr and target_address < end_addr) { | |
| 924 | return compile_unit; | |
| 925 | } | |
| 926 | } | |
| 927 | } | |
| 928 | } else |err| { | |
| 929 | if (err != error.MissingDebugInfo) | |
| 930 | return err; | |
| 931 | continue; | |
| 932 | } | |
| 933 | } | |
| 934 | return error.MissingDebugInfo; | |
| 935 | } | |
| 936 | ||
| 937 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { | |
| 938 | const first_32_bits = %return in_stream.readIntLe(u32); | |
| 939 | *is_64 = (first_32_bits == 0xffffffff); | |
| 940 | if (*is_64) { | |
| 941 | return in_stream.readIntLe(u64); | |
| 942 | } else { | |
| 943 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; | |
| 944 | return u64(first_32_bits); | |
| 945 | } | |
| 946 | } | |
| 947 | ||
| 948 | fn readULeb128(in_stream: &io.InStream) -> %u64 { | |
| 949 | var result: u64 = 0; | |
| 950 | var shift: usize = 0; | |
| 951 | ||
| 952 | while (true) { | |
| 953 | const byte = %return in_stream.readByte(); | |
| 954 | ||
| 955 | var operand: u64 = undefined; | |
| 956 | ||
| 957 | if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) | |
| 958 | return error.InvalidDebugInfo; | |
| 959 | ||
| 960 | result |= operand; | |
| 961 | ||
| 962 | if ((byte & 0b10000000) == 0) | |
| 963 | return result; | |
| 964 | ||
| 965 | shift += 7; | |
| 966 | } | |
| 967 | } | |
| 968 | ||
| 969 | fn readILeb128(in_stream: &io.InStream) -> %i64 { | |
| 970 | var result: i64 = 0; | |
| 971 | var shift: usize = 0; | |
| 972 | ||
| 973 | while (true) { | |
| 974 | const byte = %return in_stream.readByte(); | |
| 975 | ||
| 976 | var operand: i64 = undefined; | |
| 977 | ||
| 978 | if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) | |
| 979 | return error.InvalidDebugInfo; | |
| 980 | ||
| 981 | result |= operand; | |
| 982 | shift += 7; | |
| 983 | ||
| 984 | if ((byte & 0b10000000) == 0) { | |
| 985 | if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) | |
| 986 | result |= -(i64(1) << u6(shift)); | |
| 987 | return result; | |
| 988 | } | |
| 989 | } | |
| 990 | } | |
| 991 | ||
| 992 | pub const global_allocator = &global_fixed_allocator.allocator; | |
| 993 | var global_fixed_allocator = mem.FixedBufferAllocator.init(global_allocator_mem[0..]); | |
| 994 | var global_allocator_mem: [100 * 1024]u8 = undefined; | |
| 995 | ||
| 996 | /// Allocator that fails after N allocations, useful for making sure out of | |
| 997 | /// memory conditions are handled correctly. | |
| 998 | pub const FailingAllocator = struct { | |
| 999 | allocator: mem.Allocator, | |
| 1000 | index: usize, | |
| 1001 | fail_index: usize, | |
| 1002 | internal_allocator: &mem.Allocator, | |
| 1003 | allocated_bytes: usize, | |
| 1004 | ||
| 1005 | pub fn init(allocator: &mem.Allocator, fail_index: usize) -> FailingAllocator { | |
| 1006 | return FailingAllocator { | |
| 1007 | .internal_allocator = allocator, | |
| 1008 | .fail_index = fail_index, | |
| 1009 | .index = 0, | |
| 1010 | .allocated_bytes = 0, | |
| 1011 | .allocator = mem.Allocator { | |
| 1012 | .allocFn = alloc, | |
| 1013 | .reallocFn = realloc, | |
| 1014 | .freeFn = free, | |
| 1015 | }, | |
| 1016 | }; | |
| 1017 | } | |
| 1018 | ||
| 1019 | fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) -> %[]u8 { | |
| 1020 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); | |
| 1021 | if (self.index == self.fail_index) { | |
| 1022 | return error.OutOfMemory; | |
| 1023 | } | |
| 1024 | self.index += 1; | |
| 1025 | const result = %return self.internal_allocator.allocFn(self.internal_allocator, n, alignment); | |
| 1026 | self.allocated_bytes += result.len; | |
| 1027 | return result; | |
| 1028 | } | |
| 1029 | ||
| 1030 | fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | |
| 1031 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); | |
| 1032 | if (new_size <= old_mem.len) { | |
| 1033 | self.allocated_bytes -= old_mem.len - new_size; | |
| 1034 | return self.internal_allocator.reallocFn(self.internal_allocator, old_mem, new_size, alignment); | |
| 1035 | } | |
| 1036 | if (self.index == self.fail_index) { | |
| 1037 | return error.OutOfMemory; | |
| 1038 | } | |
| 1039 | self.index += 1; | |
| 1040 | const result = %return self.internal_allocator.reallocFn(self.internal_allocator, old_mem, new_size, alignment); | |
| 1041 | self.allocated_bytes += new_size - old_mem.len; | |
| 1042 | return result; | |
| 1043 | } | |
| 1044 | ||
| 1045 | fn free(allocator: &mem.Allocator, bytes: []u8) { | |
| 1046 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); | |
| 1047 | self.allocated_bytes -= bytes.len; | |
| 1048 | return self.internal_allocator.freeFn(self.internal_allocator, bytes); | |
| 1049 | } | |
| 1050 | }; |
std/debug/failing_allocator.zig created+64| ... | ... | @@ -0,0 +1,64 @@ |
| 1 | const std = @import("../index.zig"); | |
| 2 | const mem = std.mem; | |
| 3 | ||
| 4 | /// Allocator that fails after N allocations, useful for making sure out of | |
| 5 | /// memory conditions are handled correctly. | |
| 6 | pub const FailingAllocator = struct { | |
| 7 | allocator: mem.Allocator, | |
| 8 | index: usize, | |
| 9 | fail_index: usize, | |
| 10 | internal_allocator: &mem.Allocator, | |
| 11 | allocated_bytes: usize, | |
| 12 | freed_bytes: usize, | |
| 13 | deallocations: usize, | |
| 14 | ||
| 15 | pub fn init(allocator: &mem.Allocator, fail_index: usize) -> FailingAllocator { | |
| 16 | return FailingAllocator { | |
| 17 | .internal_allocator = allocator, | |
| 18 | .fail_index = fail_index, | |
| 19 | .index = 0, | |
| 20 | .allocated_bytes = 0, | |
| 21 | .freed_bytes = 0, | |
| 22 | .deallocations = 0, | |
| 23 | .allocator = mem.Allocator { | |
| 24 | .allocFn = alloc, | |
| 25 | .reallocFn = realloc, | |
| 26 | .freeFn = free, | |
| 27 | }, | |
| 28 | }; | |
| 29 | } | |
| 30 | ||
| 31 | fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) -> %[]u8 { | |
| 32 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); | |
| 33 | if (self.index == self.fail_index) { | |
| 34 | return error.OutOfMemory; | |
| 35 | } | |
| 36 | const result = %return self.internal_allocator.allocFn(self.internal_allocator, n, alignment); | |
| 37 | self.allocated_bytes += result.len; | |
| 38 | self.index += 1; | |
| 39 | return result; | |
| 40 | } | |
| 41 | ||
| 42 | fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | |
| 43 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); | |
| 44 | if (new_size <= old_mem.len) { | |
| 45 | self.freed_bytes += old_mem.len - new_size; | |
| 46 | return self.internal_allocator.reallocFn(self.internal_allocator, old_mem, new_size, alignment); | |
| 47 | } | |
| 48 | if (self.index == self.fail_index) { | |
| 49 | return error.OutOfMemory; | |
| 50 | } | |
| 51 | const result = %return self.internal_allocator.reallocFn(self.internal_allocator, old_mem, new_size, alignment); | |
| 52 | self.allocated_bytes += new_size - old_mem.len; | |
| 53 | self.deallocations += 1; | |
| 54 | self.index += 1; | |
| 55 | return result; | |
| 56 | } | |
| 57 | ||
| 58 | fn free(allocator: &mem.Allocator, bytes: []u8) { | |
| 59 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); | |
| 60 | self.freed_bytes += bytes.len; | |
| 61 | self.deallocations += 1; | |
| 62 | return self.internal_allocator.freeFn(self.internal_allocator, bytes); | |
| 63 | } | |
| 64 | }; |
std/debug/index.zig created+996| ... | ... | @@ -0,0 +1,996 @@ |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const mem = std.mem; | |
| 4 | const io = std.io; | |
| 5 | const os = std.os; | |
| 6 | const elf = std.elf; | |
| 7 | const DW = std.dwarf; | |
| 8 | const ArrayList = std.ArrayList; | |
| 9 | const builtin = @import("builtin"); | |
| 10 | ||
| 11 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; | |
| 12 | ||
| 13 | error MissingDebugInfo; | |
| 14 | error InvalidDebugInfo; | |
| 15 | error UnsupportedDebugInfo; | |
| 16 | ||
| 17 | ||
| 18 | /// Tries to write to stderr, unbuffered, and ignores any error returned. | |
| 19 | /// Does not append a newline. | |
| 20 | /// TODO atomic/multithread support | |
| 21 | var stderr_file: io.File = undefined; | |
| 22 | var stderr_file_out_stream: io.FileOutStream = undefined; | |
| 23 | var stderr_stream: ?&io.OutStream = null; | |
| 24 | pub fn warn(comptime fmt: []const u8, args: ...) { | |
| 25 | const stderr = getStderrStream() %% return; | |
| 26 | stderr.print(fmt, args) %% return; | |
| 27 | } | |
| 28 | fn getStderrStream() -> %&io.OutStream { | |
| 29 | if (stderr_stream) |st| { | |
| 30 | return st; | |
| 31 | } else { | |
| 32 | stderr_file = %return io.getStdErr(); | |
| 33 | stderr_file_out_stream = io.FileOutStream.init(&stderr_file); | |
| 34 | const st = &stderr_file_out_stream.stream; | |
| 35 | stderr_stream = st; | |
| 36 | return st; | |
| 37 | } | |
| 38 | } | |
| 39 | ||
| 40 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. | |
| 41 | pub fn dumpStackTrace() { | |
| 42 | const stderr = getStderrStream() %% return; | |
| 43 | writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% return; | |
| 44 | } | |
| 45 | ||
| 46 | /// This function invokes undefined behavior when `ok` is `false`. | |
| 47 | /// In Debug and ReleaseSafe modes, calls to this function are always | |
| 48 | /// generated, and the `unreachable` statement triggers a panic. | |
| 49 | /// In ReleaseFast and ReleaseSmall modes, calls to this function can be | |
| 50 | /// optimized away. | |
| 51 | pub fn assert(ok: bool) { | |
| 52 | if (!ok) { | |
| 53 | // In ReleaseFast test mode, we still want assert(false) to crash, so | |
| 54 | // we insert an explicit call to @panic instead of unreachable. | |
| 55 | // TODO we should use `assertOrPanic` in tests and remove this logic. | |
| 56 | if (builtin.is_test) { | |
| 57 | @panic("assertion failure"); | |
| 58 | } else { | |
| 59 | unreachable; // assertion failure | |
| 60 | } | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | /// Call this function when you want to panic if the condition is not true. | |
| 65 | /// If `ok` is `false`, this function will panic in every release mode. | |
| 66 | pub fn assertOrPanic(ok: bool) { | |
| 67 | if (!ok) { | |
| 68 | @panic("assertion failure"); | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | var panicking = false; | |
| 73 | /// This is the default panic implementation. | |
| 74 | pub fn panic(comptime format: []const u8, args: ...) -> noreturn { | |
| 75 | // TODO an intrinsic that labels this as unlikely to be reached | |
| 76 | ||
| 77 | // TODO | |
| 78 | // if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { } | |
| 79 | if (panicking) { | |
| 80 | // Panicked during a panic. | |
| 81 | // TODO detect if a different thread caused the panic, because in that case | |
| 82 | // we would want to return here instead of calling abort, so that the thread | |
| 83 | // which first called panic can finish printing a stack trace. | |
| 84 | os.abort(); | |
| 85 | } else { | |
| 86 | panicking = true; | |
| 87 | } | |
| 88 | ||
| 89 | const stderr = getStderrStream() %% os.abort(); | |
| 90 | stderr.print(format ++ "\n", args) %% os.abort(); | |
| 91 | writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% os.abort(); | |
| 92 | ||
| 93 | os.abort(); | |
| 94 | } | |
| 95 | ||
| 96 | const GREEN = "\x1b[32;1m"; | |
| 97 | const WHITE = "\x1b[37;1m"; | |
| 98 | const DIM = "\x1b[2m"; | |
| 99 | const RESET = "\x1b[0m"; | |
| 100 | ||
| 101 | error PathNotFound; | |
| 102 | error InvalidDebugInfo; | |
| 103 | ||
| 104 | pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty_color: bool, | |
| 105 | ignore_frame_count: usize) -> %void | |
| 106 | { | |
| 107 | switch (builtin.object_format) { | |
| 108 | builtin.ObjectFormat.elf => { | |
| 109 | var stack_trace = ElfStackTrace { | |
| 110 | .self_exe_file = undefined, | |
| 111 | .elf = undefined, | |
| 112 | .debug_info = undefined, | |
| 113 | .debug_abbrev = undefined, | |
| 114 | .debug_str = undefined, | |
| 115 | .debug_line = undefined, | |
| 116 | .debug_ranges = null, | |
| 117 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | |
| 118 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | |
| 119 | }; | |
| 120 | const st = &stack_trace; | |
| 121 | st.self_exe_file = %return os.openSelfExe(); | |
| 122 | defer st.self_exe_file.close(); | |
| 123 | ||
| 124 | %return st.elf.openFile(allocator, &st.self_exe_file); | |
| 125 | defer st.elf.close(); | |
| 126 | ||
| 127 | st.debug_info = (%return st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; | |
| 128 | st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; | |
| 129 | st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo; | |
| 130 | st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; | |
| 131 | st.debug_ranges = (%return st.elf.findSection(".debug_ranges")); | |
| 132 | %return scanAllCompileUnits(st); | |
| 133 | ||
| 134 | var ignored_count: usize = 0; | |
| 135 | ||
| 136 | var fp = @ptrToInt(@frameAddress()); | |
| 137 | while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { | |
| 138 | if (ignored_count < ignore_frame_count) { | |
| 139 | ignored_count += 1; | |
| 140 | continue; | |
| 141 | } | |
| 142 | ||
| 143 | const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); | |
| 144 | ||
| 145 | // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal | |
| 146 | // at compile time. I'll call it issue #313 | |
| 147 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; | |
| 148 | ||
| 149 | const compile_unit = findCompileUnit(st, return_address) %% { | |
| 150 | %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", | |
| 151 | return_address); | |
| 152 | continue; | |
| 153 | }; | |
| 154 | const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name); | |
| 155 | if (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| { | |
| 156 | defer line_info.deinit(); | |
| 157 | %return out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ | |
| 158 | DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", | |
| 159 | line_info.file_name, line_info.line, line_info.column, | |
| 160 | return_address, compile_unit_name); | |
| 161 | if (printLineFromFile(st.allocator(), out_stream, line_info)) { | |
| 162 | if (line_info.column == 0) { | |
| 163 | %return out_stream.write("\n"); | |
| 164 | } else { | |
| 165 | {var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) { | |
| 166 | %return out_stream.writeByte(' '); | |
| 167 | }} | |
| 168 | %return out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); | |
| 169 | } | |
| 170 | } else |err| switch (err) { | |
| 171 | error.EndOfFile, error.PathNotFound => {}, | |
| 172 | else => return err, | |
| 173 | } | |
| 174 | } else |err| switch (err) { | |
| 175 | error.MissingDebugInfo, error.InvalidDebugInfo => { | |
| 176 | %return out_stream.print(ptr_hex ++ " in ??? ({})\n", | |
| 177 | return_address, compile_unit_name); | |
| 178 | }, | |
| 179 | else => return err, | |
| 180 | } | |
| 181 | } | |
| 182 | }, | |
| 183 | builtin.ObjectFormat.coff => { | |
| 184 | %return out_stream.write("(stack trace unavailable for COFF object format)\n"); | |
| 185 | }, | |
| 186 | builtin.ObjectFormat.macho => { | |
| 187 | %return out_stream.write("(stack trace unavailable for Mach-O object format)\n"); | |
| 188 | }, | |
| 189 | builtin.ObjectFormat.wasm => { | |
| 190 | %return out_stream.write("(stack trace unavailable for WASM object format)\n"); | |
| 191 | }, | |
| 192 | builtin.ObjectFormat.unknown => { | |
| 193 | %return out_stream.write("(stack trace unavailable for unknown object format)\n"); | |
| 194 | }, | |
| 195 | } | |
| 196 | } | |
| 197 | ||
| 198 | fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) -> %void { | |
| 199 | var f = %return io.File.openRead(line_info.file_name, allocator); | |
| 200 | defer f.close(); | |
| 201 | // TODO fstat and make sure that the file has the correct size | |
| 202 | ||
| 203 | var buf: [os.page_size]u8 = undefined; | |
| 204 | var line: usize = 1; | |
| 205 | var column: usize = 1; | |
| 206 | var abs_index: usize = 0; | |
| 207 | while (true) { | |
| 208 | const amt_read = %return f.read(buf[0..]); | |
| 209 | const slice = buf[0..amt_read]; | |
| 210 | ||
| 211 | for (slice) |byte| { | |
| 212 | if (line == line_info.line) { | |
| 213 | %return out_stream.writeByte(byte); | |
| 214 | if (byte == '\n') { | |
| 215 | return; | |
| 216 | } | |
| 217 | } | |
| 218 | if (byte == '\n') { | |
| 219 | line += 1; | |
| 220 | column = 1; | |
| 221 | } else { | |
| 222 | column += 1; | |
| 223 | } | |
| 224 | } | |
| 225 | ||
| 226 | if (amt_read < buf.len) | |
| 227 | return error.EndOfFile; | |
| 228 | } | |
| 229 | } | |
| 230 | ||
| 231 | const ElfStackTrace = struct { | |
| 232 | self_exe_file: io.File, | |
| 233 | elf: elf.Elf, | |
| 234 | debug_info: &elf.SectionHeader, | |
| 235 | debug_abbrev: &elf.SectionHeader, | |
| 236 | debug_str: &elf.SectionHeader, | |
| 237 | debug_line: &elf.SectionHeader, | |
| 238 | debug_ranges: ?&elf.SectionHeader, | |
| 239 | abbrev_table_list: ArrayList(AbbrevTableHeader), | |
| 240 | compile_unit_list: ArrayList(CompileUnit), | |
| 241 | ||
| 242 | pub fn allocator(self: &const ElfStackTrace) -> &mem.Allocator { | |
| 243 | return self.abbrev_table_list.allocator; | |
| 244 | } | |
| 245 | ||
| 246 | pub fn readString(self: &ElfStackTrace) -> %[]u8 { | |
| 247 | var in_file_stream = io.FileInStream.init(&self.self_exe_file); | |
| 248 | const in_stream = &in_file_stream.stream; | |
| 249 | return readStringRaw(self.allocator(), in_stream); | |
| 250 | } | |
| 251 | }; | |
| 252 | ||
| 253 | const PcRange = struct { | |
| 254 | start: u64, | |
| 255 | end: u64, | |
| 256 | }; | |
| 257 | ||
| 258 | const CompileUnit = struct { | |
| 259 | version: u16, | |
| 260 | is_64: bool, | |
| 261 | die: &Die, | |
| 262 | index: usize, | |
| 263 | pc_range: ?PcRange, | |
| 264 | }; | |
| 265 | ||
| 266 | const AbbrevTable = ArrayList(AbbrevTableEntry); | |
| 267 | ||
| 268 | const AbbrevTableHeader = struct { | |
| 269 | // offset from .debug_abbrev | |
| 270 | offset: u64, | |
| 271 | table: AbbrevTable, | |
| 272 | }; | |
| 273 | ||
| 274 | const AbbrevTableEntry = struct { | |
| 275 | has_children: bool, | |
| 276 | abbrev_code: u64, | |
| 277 | tag_id: u64, | |
| 278 | attrs: ArrayList(AbbrevAttr), | |
| 279 | }; | |
| 280 | ||
| 281 | const AbbrevAttr = struct { | |
| 282 | attr_id: u64, | |
| 283 | form_id: u64, | |
| 284 | }; | |
| 285 | ||
| 286 | const FormValue = union(enum) { | |
| 287 | Address: u64, | |
| 288 | Block: []u8, | |
| 289 | Const: Constant, | |
| 290 | ExprLoc: []u8, | |
| 291 | Flag: bool, | |
| 292 | SecOffset: u64, | |
| 293 | Ref: []u8, | |
| 294 | RefAddr: u64, | |
| 295 | RefSig8: u64, | |
| 296 | String: []u8, | |
| 297 | StrPtr: u64, | |
| 298 | }; | |
| 299 | ||
| 300 | const Constant = struct { | |
| 301 | payload: []u8, | |
| 302 | signed: bool, | |
| 303 | ||
| 304 | fn asUnsignedLe(self: &const Constant) -> %u64 { | |
| 305 | if (self.payload.len > @sizeOf(u64)) | |
| 306 | return error.InvalidDebugInfo; | |
| 307 | if (self.signed) | |
| 308 | return error.InvalidDebugInfo; | |
| 309 | return mem.readInt(self.payload, u64, builtin.Endian.Little); | |
| 310 | } | |
| 311 | }; | |
| 312 | ||
| 313 | const Die = struct { | |
| 314 | tag_id: u64, | |
| 315 | has_children: bool, | |
| 316 | attrs: ArrayList(Attr), | |
| 317 | ||
| 318 | const Attr = struct { | |
| 319 | id: u64, | |
| 320 | value: FormValue, | |
| 321 | }; | |
| 322 | ||
| 323 | fn getAttr(self: &const Die, id: u64) -> ?&const FormValue { | |
| 324 | for (self.attrs.toSliceConst()) |*attr| { | |
| 325 | if (attr.id == id) | |
| 326 | return &attr.value; | |
| 327 | } | |
| 328 | return null; | |
| 329 | } | |
| 330 | ||
| 331 | fn getAttrAddr(self: &const Die, id: u64) -> %u64 { | |
| 332 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 333 | return switch (*form_value) { | |
| 334 | FormValue.Address => |value| value, | |
| 335 | else => error.InvalidDebugInfo, | |
| 336 | }; | |
| 337 | } | |
| 338 | ||
| 339 | fn getAttrSecOffset(self: &const Die, id: u64) -> %u64 { | |
| 340 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 341 | return switch (*form_value) { | |
| 342 | FormValue.Const => |value| value.asUnsignedLe(), | |
| 343 | FormValue.SecOffset => |value| value, | |
| 344 | else => error.InvalidDebugInfo, | |
| 345 | }; | |
| 346 | } | |
| 347 | ||
| 348 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { | |
| 349 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 350 | return switch (*form_value) { | |
| 351 | FormValue.Const => |value| value.asUnsignedLe(), | |
| 352 | else => error.InvalidDebugInfo, | |
| 353 | }; | |
| 354 | } | |
| 355 | ||
| 356 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) -> %[]u8 { | |
| 357 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | |
| 358 | return switch (*form_value) { | |
| 359 | FormValue.String => |value| value, | |
| 360 | FormValue.StrPtr => |offset| getString(st, offset), | |
| 361 | else => error.InvalidDebugInfo, | |
| 362 | }; | |
| 363 | } | |
| 364 | }; | |
| 365 | ||
| 366 | const FileEntry = struct { | |
| 367 | file_name: []const u8, | |
| 368 | dir_index: usize, | |
| 369 | mtime: usize, | |
| 370 | len_bytes: usize, | |
| 371 | }; | |
| 372 | ||
| 373 | const LineInfo = struct { | |
| 374 | line: usize, | |
| 375 | column: usize, | |
| 376 | file_name: []u8, | |
| 377 | allocator: &mem.Allocator, | |
| 378 | ||
| 379 | fn deinit(self: &const LineInfo) { | |
| 380 | self.allocator.free(self.file_name); | |
| 381 | } | |
| 382 | }; | |
| 383 | ||
| 384 | const LineNumberProgram = struct { | |
| 385 | address: usize, | |
| 386 | file: usize, | |
| 387 | line: isize, | |
| 388 | column: usize, | |
| 389 | is_stmt: bool, | |
| 390 | basic_block: bool, | |
| 391 | end_sequence: bool, | |
| 392 | ||
| 393 | target_address: usize, | |
| 394 | include_dirs: []const []const u8, | |
| 395 | file_entries: &ArrayList(FileEntry), | |
| 396 | ||
| 397 | prev_address: usize, | |
| 398 | prev_file: usize, | |
| 399 | prev_line: isize, | |
| 400 | prev_column: usize, | |
| 401 | prev_is_stmt: bool, | |
| 402 | prev_basic_block: bool, | |
| 403 | prev_end_sequence: bool, | |
| 404 | ||
| 405 | pub fn init(is_stmt: bool, include_dirs: []const []const u8, | |
| 406 | file_entries: &ArrayList(FileEntry), target_address: usize) -> LineNumberProgram | |
| 407 | { | |
| 408 | return LineNumberProgram { | |
| 409 | .address = 0, | |
| 410 | .file = 1, | |
| 411 | .line = 1, | |
| 412 | .column = 0, | |
| 413 | .is_stmt = is_stmt, | |
| 414 | .basic_block = false, | |
| 415 | .end_sequence = false, | |
| 416 | .include_dirs = include_dirs, | |
| 417 | .file_entries = file_entries, | |
| 418 | .target_address = target_address, | |
| 419 | .prev_address = 0, | |
| 420 | .prev_file = undefined, | |
| 421 | .prev_line = undefined, | |
| 422 | .prev_column = undefined, | |
| 423 | .prev_is_stmt = undefined, | |
| 424 | .prev_basic_block = undefined, | |
| 425 | .prev_end_sequence = undefined, | |
| 426 | }; | |
| 427 | } | |
| 428 | ||
| 429 | pub fn checkLineMatch(self: &LineNumberProgram) -> %?LineInfo { | |
| 430 | if (self.target_address >= self.prev_address and self.target_address < self.address) { | |
| 431 | const file_entry = if (self.prev_file == 0) { | |
| 432 | return error.MissingDebugInfo; | |
| 433 | } else if (self.prev_file - 1 >= self.file_entries.len) { | |
| 434 | return error.InvalidDebugInfo; | |
| 435 | } else &self.file_entries.items[self.prev_file - 1]; | |
| 436 | ||
| 437 | const dir_name = if (file_entry.dir_index >= self.include_dirs.len) { | |
| 438 | return error.InvalidDebugInfo; | |
| 439 | } else self.include_dirs[file_entry.dir_index]; | |
| 440 | const file_name = %return os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); | |
| 441 | %defer self.file_entries.allocator.free(file_name); | |
| 442 | return LineInfo { | |
| 443 | .line = if (self.prev_line >= 0) usize(self.prev_line) else 0, | |
| 444 | .column = self.prev_column, | |
| 445 | .file_name = file_name, | |
| 446 | .allocator = self.file_entries.allocator, | |
| 447 | }; | |
| 448 | } | |
| 449 | ||
| 450 | self.prev_address = self.address; | |
| 451 | self.prev_file = self.file; | |
| 452 | self.prev_line = self.line; | |
| 453 | self.prev_column = self.column; | |
| 454 | self.prev_is_stmt = self.is_stmt; | |
| 455 | self.prev_basic_block = self.basic_block; | |
| 456 | self.prev_end_sequence = self.end_sequence; | |
| 457 | return null; | |
| 458 | } | |
| 459 | }; | |
| 460 | ||
| 461 | fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) -> %[]u8 { | |
| 462 | var buf = ArrayList(u8).init(allocator); | |
| 463 | while (true) { | |
| 464 | const byte = %return in_stream.readByte(); | |
| 465 | if (byte == 0) | |
| 466 | break; | |
| 467 | %return buf.append(byte); | |
| 468 | } | |
| 469 | return buf.toSlice(); | |
| 470 | } | |
| 471 | ||
| 472 | fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 { | |
| 473 | const pos = st.debug_str.offset + offset; | |
| 474 | %return st.self_exe_file.seekTo(pos); | |
| 475 | return st.readString(); | |
| 476 | } | |
| 477 | ||
| 478 | fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 { | |
| 479 | const buf = %return global_allocator.alloc(u8, size); | |
| 480 | %defer global_allocator.free(buf); | |
| 481 | if ((%return in_stream.read(buf)) < size) return error.EndOfFile; | |
| 482 | return buf; | |
| 483 | } | |
| 484 | ||
| 485 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 486 | const buf = %return readAllocBytes(allocator, in_stream, size); | |
| 487 | return FormValue { .Block = buf }; | |
| 488 | } | |
| 489 | ||
| 490 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 491 | const block_len = %return in_stream.readVarInt(builtin.Endian.Little, usize, size); | |
| 492 | return parseFormValueBlockLen(allocator, in_stream, block_len); | |
| 493 | } | |
| 494 | ||
| 495 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { | |
| 496 | return FormValue { .Const = Constant { | |
| 497 | .signed = signed, | |
| 498 | .payload = %return readAllocBytes(allocator, in_stream, size), | |
| 499 | }}; | |
| 500 | } | |
| 501 | ||
| 502 | fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) -> %u64 { | |
| 503 | return if (is_64) %return in_stream.readIntLe(u64) | |
| 504 | else u64(%return in_stream.readIntLe(u32)) ; | |
| 505 | } | |
| 506 | ||
| 507 | fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { | |
| 508 | return if (@sizeOf(usize) == 4) u64(%return in_stream.readIntLe(u32)) | |
| 509 | else if (@sizeOf(usize) == 8) %return in_stream.readIntLe(u64) | |
| 510 | else unreachable; | |
| 511 | } | |
| 512 | ||
| 513 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 514 | const buf = %return readAllocBytes(allocator, in_stream, size); | |
| 515 | return FormValue { .Ref = buf }; | |
| 516 | } | |
| 517 | ||
| 518 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue { | |
| 519 | const block_len = %return in_stream.readIntLe(T); | |
| 520 | return parseFormValueRefLen(allocator, in_stream, block_len); | |
| 521 | } | |
| 522 | ||
| 523 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue { | |
| 524 | return switch (form_id) { | |
| 525 | DW.FORM_addr => FormValue { .Address = %return parseFormValueTargetAddrSize(in_stream) }, | |
| 526 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), | |
| 527 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), | |
| 528 | DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), | |
| 529 | DW.FORM_block => x: { | |
| 530 | const block_len = %return readULeb128(in_stream); | |
| 531 | return parseFormValueBlockLen(allocator, in_stream, block_len); | |
| 532 | }, | |
| 533 | DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1), | |
| 534 | DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), | |
| 535 | DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), | |
| 536 | DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), | |
| 537 | DW.FORM_udata, DW.FORM_sdata => { | |
| 538 | const block_len = %return readULeb128(in_stream); | |
| 539 | const signed = form_id == DW.FORM_sdata; | |
| 540 | return parseFormValueConstant(allocator, in_stream, signed, block_len); | |
| 541 | }, | |
| 542 | DW.FORM_exprloc => { | |
| 543 | const size = %return readULeb128(in_stream); | |
| 544 | const buf = %return readAllocBytes(allocator, in_stream, size); | |
| 545 | return FormValue { .ExprLoc = buf }; | |
| 546 | }, | |
| 547 | DW.FORM_flag => FormValue { .Flag = (%return in_stream.readByte()) != 0 }, | |
| 548 | DW.FORM_flag_present => FormValue { .Flag = true }, | |
| 549 | DW.FORM_sec_offset => FormValue { .SecOffset = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 550 | ||
| 551 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), | |
| 552 | DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), | |
| 553 | DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, u32), | |
| 554 | DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64), | |
| 555 | DW.FORM_ref_udata => { | |
| 556 | const ref_len = %return readULeb128(in_stream); | |
| 557 | return parseFormValueRefLen(allocator, in_stream, ref_len); | |
| 558 | }, | |
| 559 | ||
| 560 | DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 561 | DW.FORM_ref_sig8 => FormValue { .RefSig8 = %return in_stream.readIntLe(u64) }, | |
| 562 | ||
| 563 | DW.FORM_string => FormValue { .String = %return readStringRaw(allocator, in_stream) }, | |
| 564 | DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, | |
| 565 | DW.FORM_indirect => { | |
| 566 | const child_form_id = %return readULeb128(in_stream); | |
| 567 | return parseFormValue(allocator, in_stream, child_form_id, is_64); | |
| 568 | }, | |
| 569 | else => error.InvalidDebugInfo, | |
| 570 | }; | |
| 571 | } | |
| 572 | ||
| 573 | fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable { | |
| 574 | const in_file = &st.self_exe_file; | |
| 575 | var in_file_stream = io.FileInStream.init(in_file); | |
| 576 | const in_stream = &in_file_stream.stream; | |
| 577 | var result = AbbrevTable.init(st.allocator()); | |
| 578 | while (true) { | |
| 579 | const abbrev_code = %return readULeb128(in_stream); | |
| 580 | if (abbrev_code == 0) | |
| 581 | return result; | |
| 582 | %return result.append(AbbrevTableEntry { | |
| 583 | .abbrev_code = abbrev_code, | |
| 584 | .tag_id = %return readULeb128(in_stream), | |
| 585 | .has_children = (%return in_stream.readByte()) == DW.CHILDREN_yes, | |
| 586 | .attrs = ArrayList(AbbrevAttr).init(st.allocator()), | |
| 587 | }); | |
| 588 | const attrs = &result.items[result.len - 1].attrs; | |
| 589 | ||
| 590 | while (true) { | |
| 591 | const attr_id = %return readULeb128(in_stream); | |
| 592 | const form_id = %return readULeb128(in_stream); | |
| 593 | if (attr_id == 0 and form_id == 0) | |
| 594 | break; | |
| 595 | %return attrs.append(AbbrevAttr { | |
| 596 | .attr_id = attr_id, | |
| 597 | .form_id = form_id, | |
| 598 | }); | |
| 599 | } | |
| 600 | } | |
| 601 | } | |
| 602 | ||
| 603 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, | |
| 604 | /// seeks in the stream and parses it. | |
| 605 | fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) -> %&const AbbrevTable { | |
| 606 | for (st.abbrev_table_list.toSlice()) |*header| { | |
| 607 | if (header.offset == abbrev_offset) { | |
| 608 | return &header.table; | |
| 609 | } | |
| 610 | } | |
| 611 | %return st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); | |
| 612 | %return st.abbrev_table_list.append(AbbrevTableHeader { | |
| 613 | .offset = abbrev_offset, | |
| 614 | .table = %return parseAbbrevTable(st), | |
| 615 | }); | |
| 616 | return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table; | |
| 617 | } | |
| 618 | ||
| 619 | fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?&const AbbrevTableEntry { | |
| 620 | for (abbrev_table.toSliceConst()) |*table_entry| { | |
| 621 | if (table_entry.abbrev_code == abbrev_code) | |
| 622 | return table_entry; | |
| 623 | } | |
| 624 | return null; | |
| 625 | } | |
| 626 | ||
| 627 | fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -> %Die { | |
| 628 | const in_file = &st.self_exe_file; | |
| 629 | var in_file_stream = io.FileInStream.init(in_file); | |
| 630 | const in_stream = &in_file_stream.stream; | |
| 631 | const abbrev_code = %return readULeb128(in_stream); | |
| 632 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo; | |
| 633 | ||
| 634 | var result = Die { | |
| 635 | .tag_id = table_entry.tag_id, | |
| 636 | .has_children = table_entry.has_children, | |
| 637 | .attrs = ArrayList(Die.Attr).init(st.allocator()), | |
| 638 | }; | |
| 639 | %return result.attrs.resize(table_entry.attrs.len); | |
| 640 | for (table_entry.attrs.toSliceConst()) |attr, i| { | |
| 641 | result.attrs.items[i] = Die.Attr { | |
| 642 | .id = attr.attr_id, | |
| 643 | .value = %return parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), | |
| 644 | }; | |
| 645 | } | |
| 646 | return result; | |
| 647 | } | |
| 648 | ||
| 649 | fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) -> %LineInfo { | |
| 650 | const compile_unit_cwd = %return compile_unit.die.getAttrString(st, DW.AT_comp_dir); | |
| 651 | ||
| 652 | const in_file = &st.self_exe_file; | |
| 653 | const debug_line_end = st.debug_line.offset + st.debug_line.size; | |
| 654 | var this_offset = st.debug_line.offset; | |
| 655 | var this_index: usize = 0; | |
| 656 | ||
| 657 | var in_file_stream = io.FileInStream.init(in_file); | |
| 658 | const in_stream = &in_file_stream.stream; | |
| 659 | ||
| 660 | while (this_offset < debug_line_end) : (this_index += 1) { | |
| 661 | %return in_file.seekTo(this_offset); | |
| 662 | ||
| 663 | var is_64: bool = undefined; | |
| 664 | const unit_length = %return readInitialLength(in_stream, &is_64); | |
| 665 | if (unit_length == 0) | |
| 666 | return error.MissingDebugInfo; | |
| 667 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 668 | ||
| 669 | if (compile_unit.index != this_index) { | |
| 670 | this_offset += next_offset; | |
| 671 | continue; | |
| 672 | } | |
| 673 | ||
| 674 | const version = %return in_stream.readInt(st.elf.endian, u16); | |
| 675 | if (version != 2) return error.InvalidDebugInfo; | |
| 676 | ||
| 677 | const prologue_length = %return in_stream.readInt(st.elf.endian, u32); | |
| 678 | const prog_start_offset = (%return in_file.getPos()) + prologue_length; | |
| 679 | ||
| 680 | const minimum_instruction_length = %return in_stream.readByte(); | |
| 681 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; | |
| 682 | ||
| 683 | const default_is_stmt = (%return in_stream.readByte()) != 0; | |
| 684 | const line_base = %return in_stream.readByteSigned(); | |
| 685 | ||
| 686 | const line_range = %return in_stream.readByte(); | |
| 687 | if (line_range == 0) | |
| 688 | return error.InvalidDebugInfo; | |
| 689 | ||
| 690 | const opcode_base = %return in_stream.readByte(); | |
| 691 | ||
| 692 | const standard_opcode_lengths = %return st.allocator().alloc(u8, opcode_base - 1); | |
| 693 | ||
| 694 | {var i: usize = 0; while (i < opcode_base - 1) : (i += 1) { | |
| 695 | standard_opcode_lengths[i] = %return in_stream.readByte(); | |
| 696 | }} | |
| 697 | ||
| 698 | var include_directories = ArrayList([]u8).init(st.allocator()); | |
| 699 | %return include_directories.append(compile_unit_cwd); | |
| 700 | while (true) { | |
| 701 | const dir = %return st.readString(); | |
| 702 | if (dir.len == 0) | |
| 703 | break; | |
| 704 | %return include_directories.append(dir); | |
| 705 | } | |
| 706 | ||
| 707 | var file_entries = ArrayList(FileEntry).init(st.allocator()); | |
| 708 | var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), | |
| 709 | &file_entries, target_address); | |
| 710 | ||
| 711 | while (true) { | |
| 712 | const file_name = %return st.readString(); | |
| 713 | if (file_name.len == 0) | |
| 714 | break; | |
| 715 | const dir_index = %return readULeb128(in_stream); | |
| 716 | const mtime = %return readULeb128(in_stream); | |
| 717 | const len_bytes = %return readULeb128(in_stream); | |
| 718 | %return file_entries.append(FileEntry { | |
| 719 | .file_name = file_name, | |
| 720 | .dir_index = dir_index, | |
| 721 | .mtime = mtime, | |
| 722 | .len_bytes = len_bytes, | |
| 723 | }); | |
| 724 | } | |
| 725 | ||
| 726 | %return in_file.seekTo(prog_start_offset); | |
| 727 | ||
| 728 | while (true) { | |
| 729 | const opcode = %return in_stream.readByte(); | |
| 730 | ||
| 731 | var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash | |
| 732 | if (opcode == DW.LNS_extended_op) { | |
| 733 | const op_size = %return readULeb128(in_stream); | |
| 734 | if (op_size < 1) | |
| 735 | return error.InvalidDebugInfo; | |
| 736 | sub_op = %return in_stream.readByte(); | |
| 737 | switch (sub_op) { | |
| 738 | DW.LNE_end_sequence => { | |
| 739 | prog.end_sequence = true; | |
| 740 | if (%return prog.checkLineMatch()) |info| return info; | |
| 741 | return error.MissingDebugInfo; | |
| 742 | }, | |
| 743 | DW.LNE_set_address => { | |
| 744 | const addr = %return in_stream.readInt(st.elf.endian, usize); | |
| 745 | prog.address = addr; | |
| 746 | }, | |
| 747 | DW.LNE_define_file => { | |
| 748 | const file_name = %return st.readString(); | |
| 749 | const dir_index = %return readULeb128(in_stream); | |
| 750 | const mtime = %return readULeb128(in_stream); | |
| 751 | const len_bytes = %return readULeb128(in_stream); | |
| 752 | %return file_entries.append(FileEntry { | |
| 753 | .file_name = file_name, | |
| 754 | .dir_index = dir_index, | |
| 755 | .mtime = mtime, | |
| 756 | .len_bytes = len_bytes, | |
| 757 | }); | |
| 758 | }, | |
| 759 | else => { | |
| 760 | const fwd_amt = math.cast(isize, op_size - 1) %% return error.InvalidDebugInfo; | |
| 761 | %return in_file.seekForward(fwd_amt); | |
| 762 | }, | |
| 763 | } | |
| 764 | } else if (opcode >= opcode_base) { | |
| 765 | // special opcodes | |
| 766 | const adjusted_opcode = opcode - opcode_base; | |
| 767 | const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); | |
| 768 | const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); | |
| 769 | prog.line += inc_line; | |
| 770 | prog.address += inc_addr; | |
| 771 | if (%return prog.checkLineMatch()) |info| return info; | |
| 772 | prog.basic_block = false; | |
| 773 | } else { | |
| 774 | switch (opcode) { | |
| 775 | DW.LNS_copy => { | |
| 776 | if (%return prog.checkLineMatch()) |info| return info; | |
| 777 | prog.basic_block = false; | |
| 778 | }, | |
| 779 | DW.LNS_advance_pc => { | |
| 780 | const arg = %return readULeb128(in_stream); | |
| 781 | prog.address += arg * minimum_instruction_length; | |
| 782 | }, | |
| 783 | DW.LNS_advance_line => { | |
| 784 | const arg = %return readILeb128(in_stream); | |
| 785 | prog.line += arg; | |
| 786 | }, | |
| 787 | DW.LNS_set_file => { | |
| 788 | const arg = %return readULeb128(in_stream); | |
| 789 | prog.file = arg; | |
| 790 | }, | |
| 791 | DW.LNS_set_column => { | |
| 792 | const arg = %return readULeb128(in_stream); | |
| 793 | prog.column = arg; | |
| 794 | }, | |
| 795 | DW.LNS_negate_stmt => { | |
| 796 | prog.is_stmt = !prog.is_stmt; | |
| 797 | }, | |
| 798 | DW.LNS_set_basic_block => { | |
| 799 | prog.basic_block = true; | |
| 800 | }, | |
| 801 | DW.LNS_const_add_pc => { | |
| 802 | const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); | |
| 803 | prog.address += inc_addr; | |
| 804 | }, | |
| 805 | DW.LNS_fixed_advance_pc => { | |
| 806 | const arg = %return in_stream.readInt(st.elf.endian, u16); | |
| 807 | prog.address += arg; | |
| 808 | }, | |
| 809 | DW.LNS_set_prologue_end => { | |
| 810 | }, | |
| 811 | else => { | |
| 812 | if (opcode - 1 >= standard_opcode_lengths.len) | |
| 813 | return error.InvalidDebugInfo; | |
| 814 | const len_bytes = standard_opcode_lengths[opcode - 1]; | |
| 815 | %return in_file.seekForward(len_bytes); | |
| 816 | }, | |
| 817 | } | |
| 818 | } | |
| 819 | } | |
| 820 | ||
| 821 | this_offset += next_offset; | |
| 822 | } | |
| 823 | ||
| 824 | return error.MissingDebugInfo; | |
| 825 | } | |
| 826 | ||
| 827 | fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { | |
| 828 | const debug_info_end = st.debug_info.offset + st.debug_info.size; | |
| 829 | var this_unit_offset = st.debug_info.offset; | |
| 830 | var cu_index: usize = 0; | |
| 831 | ||
| 832 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); | |
| 833 | const in_stream = &in_file_stream.stream; | |
| 834 | ||
| 835 | while (this_unit_offset < debug_info_end) { | |
| 836 | %return st.self_exe_file.seekTo(this_unit_offset); | |
| 837 | ||
| 838 | var is_64: bool = undefined; | |
| 839 | const unit_length = %return readInitialLength(in_stream, &is_64); | |
| 840 | if (unit_length == 0) | |
| 841 | return; | |
| 842 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | |
| 843 | ||
| 844 | const version = %return in_stream.readInt(st.elf.endian, u16); | |
| 845 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | |
| 846 | ||
| 847 | const debug_abbrev_offset = | |
| 848 | if (is_64) %return in_stream.readInt(st.elf.endian, u64) | |
| 849 | else %return in_stream.readInt(st.elf.endian, u32); | |
| 850 | ||
| 851 | const address_size = %return in_stream.readByte(); | |
| 852 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; | |
| 853 | ||
| 854 | const compile_unit_pos = %return st.self_exe_file.getPos(); | |
| 855 | const abbrev_table = %return getAbbrevTable(st, debug_abbrev_offset); | |
| 856 | ||
| 857 | %return st.self_exe_file.seekTo(compile_unit_pos); | |
| 858 | ||
| 859 | const compile_unit_die = %return st.allocator().create(Die); | |
| 860 | *compile_unit_die = %return parseDie(st, abbrev_table, is_64); | |
| 861 | ||
| 862 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) | |
| 863 | return error.InvalidDebugInfo; | |
| 864 | ||
| 865 | const pc_range = x: { | |
| 866 | if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| { | |
| 867 | if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| { | |
| 868 | const pc_end = switch (*high_pc_value) { | |
| 869 | FormValue.Address => |value| value, | |
| 870 | FormValue.Const => |value| b: { | |
| 871 | const offset = %return value.asUnsignedLe(); | |
| 872 | break :b (low_pc + offset); | |
| 873 | }, | |
| 874 | else => return error.InvalidDebugInfo, | |
| 875 | }; | |
| 876 | break :x PcRange { | |
| 877 | .start = low_pc, | |
| 878 | .end = pc_end, | |
| 879 | }; | |
| 880 | } else { | |
| 881 | break :x null; | |
| 882 | } | |
| 883 | } else |err| { | |
| 884 | if (err != error.MissingDebugInfo) | |
| 885 | return err; | |
| 886 | break :x null; | |
| 887 | } | |
| 888 | }; | |
| 889 | ||
| 890 | %return st.compile_unit_list.append(CompileUnit { | |
| 891 | .version = version, | |
| 892 | .is_64 = is_64, | |
| 893 | .pc_range = pc_range, | |
| 894 | .die = compile_unit_die, | |
| 895 | .index = cu_index, | |
| 896 | }); | |
| 897 | ||
| 898 | this_unit_offset += next_offset; | |
| 899 | cu_index += 1; | |
| 900 | } | |
| 901 | } | |
| 902 | ||
| 903 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUnit { | |
| 904 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); | |
| 905 | const in_stream = &in_file_stream.stream; | |
| 906 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | |
| 907 | if (compile_unit.pc_range) |range| { | |
| 908 | if (target_address >= range.start and target_address < range.end) | |
| 909 | return compile_unit; | |
| 910 | } | |
| 911 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { | |
| 912 | var base_address: usize = 0; | |
| 913 | if (st.debug_ranges) |debug_ranges| { | |
| 914 | %return st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); | |
| 915 | while (true) { | |
| 916 | const begin_addr = %return in_stream.readIntLe(usize); | |
| 917 | const end_addr = %return in_stream.readIntLe(usize); | |
| 918 | if (begin_addr == 0 and end_addr == 0) { | |
| 919 | break; | |
| 920 | } | |
| 921 | if (begin_addr == @maxValue(usize)) { | |
| 922 | base_address = begin_addr; | |
| 923 | continue; | |
| 924 | } | |
| 925 | if (target_address >= begin_addr and target_address < end_addr) { | |
| 926 | return compile_unit; | |
| 927 | } | |
| 928 | } | |
| 929 | } | |
| 930 | } else |err| { | |
| 931 | if (err != error.MissingDebugInfo) | |
| 932 | return err; | |
| 933 | continue; | |
| 934 | } | |
| 935 | } | |
| 936 | return error.MissingDebugInfo; | |
| 937 | } | |
| 938 | ||
| 939 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { | |
| 940 | const first_32_bits = %return in_stream.readIntLe(u32); | |
| 941 | *is_64 = (first_32_bits == 0xffffffff); | |
| 942 | if (*is_64) { | |
| 943 | return in_stream.readIntLe(u64); | |
| 944 | } else { | |
| 945 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; | |
| 946 | return u64(first_32_bits); | |
| 947 | } | |
| 948 | } | |
| 949 | ||
| 950 | fn readULeb128(in_stream: &io.InStream) -> %u64 { | |
| 951 | var result: u64 = 0; | |
| 952 | var shift: usize = 0; | |
| 953 | ||
| 954 | while (true) { | |
| 955 | const byte = %return in_stream.readByte(); | |
| 956 | ||
| 957 | var operand: u64 = undefined; | |
| 958 | ||
| 959 | if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) | |
| 960 | return error.InvalidDebugInfo; | |
| 961 | ||
| 962 | result |= operand; | |
| 963 | ||
| 964 | if ((byte & 0b10000000) == 0) | |
| 965 | return result; | |
| 966 | ||
| 967 | shift += 7; | |
| 968 | } | |
| 969 | } | |
| 970 | ||
| 971 | fn readILeb128(in_stream: &io.InStream) -> %i64 { | |
| 972 | var result: i64 = 0; | |
| 973 | var shift: usize = 0; | |
| 974 | ||
| 975 | while (true) { | |
| 976 | const byte = %return in_stream.readByte(); | |
| 977 | ||
| 978 | var operand: i64 = undefined; | |
| 979 | ||
| 980 | if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) | |
| 981 | return error.InvalidDebugInfo; | |
| 982 | ||
| 983 | result |= operand; | |
| 984 | shift += 7; | |
| 985 | ||
| 986 | if ((byte & 0b10000000) == 0) { | |
| 987 | if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) | |
| 988 | result |= -(i64(1) << u6(shift)); | |
| 989 | return result; | |
| 990 | } | |
| 991 | } | |
| 992 | } | |
| 993 | ||
| 994 | pub const global_allocator = &global_fixed_allocator.allocator; | |
| 995 | var global_fixed_allocator = mem.FixedBufferAllocator.init(global_allocator_mem[0..]); | |
| 996 | var global_allocator_mem: [100 * 1024]u8 = undefined; |
std/fmt/errol/index.zig+4-3| ... | ... | @@ -1,10 +1,11 @@ |
| 1 | const std = @import("../../index.zig"); | |
| 1 | 2 | const enum3 = @import("enum3.zig").enum3; |
| 2 | 3 | const enum3_data = @import("enum3.zig").enum3_data; |
| 3 | 4 | const lookup_table = @import("lookup.zig").lookup_table; |
| 4 | 5 | const HP = @import("lookup.zig").HP; |
| 5 | const math = @import("../../math/index.zig"); | |
| 6 | const mem = @import("../../mem.zig"); | |
| 7 | const assert = @import("../../debug.zig").assert; | |
| 6 | const math = std.math; | |
| 7 | const mem = std.mem; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | pub const FloatDecimal = struct { |
| 10 | 11 | digits: []u8, |
std/fmt/index.zig+4-3| ... | ... | @@ -1,7 +1,8 @@ |
| 1 | const math = @import("../math/index.zig"); | |
| 2 | const debug = @import("../debug.zig"); | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const debug = std.debug; | |
| 3 | 4 | const assert = debug.assert; |
| 4 | const mem = @import("../mem.zig"); | |
| 5 | const mem = std.mem; | |
| 5 | 6 | const builtin = @import("builtin"); |
| 6 | 7 | const errol3 = @import("errol/index.zig").errol3; |
| 7 | 8 |
std/hash_map.zig+4-3| ... | ... | @@ -1,7 +1,8 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 2 | 3 | const assert = debug.assert; |
| 3 | const math = @import("math/index.zig"); | |
| 4 | const mem = @import("mem.zig"); | |
| 4 | const math = std.math; | |
| 5 | const mem = std.mem; | |
| 5 | 6 | const Allocator = mem.Allocator; |
| 6 | 7 | const builtin = @import("builtin"); |
| 7 | 8 |
std/heap.zig+5-4| ... | ... | @@ -1,10 +1,11 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 2 | 3 | const assert = debug.assert; |
| 3 | const mem = @import("mem.zig"); | |
| 4 | const os = @import("os/index.zig"); | |
| 4 | const mem = std.mem; | |
| 5 | const os = std.os; | |
| 5 | 6 | const builtin = @import("builtin"); |
| 6 | 7 | const Os = builtin.Os; |
| 7 | const c = @import("c/index.zig"); | |
| 8 | const c = std.c; | |
| 8 | 9 | |
| 9 | 10 | const Allocator = mem.Allocator; |
| 10 | 11 |
std/index.zig+2-2| ... | ... | @@ -11,7 +11,7 @@ pub const base64 = @import("base64.zig"); |
| 11 | 11 | pub const build = @import("build.zig"); |
| 12 | 12 | pub const c = @import("c/index.zig"); |
| 13 | 13 | pub const cstr = @import("cstr.zig"); |
| 14 | pub const debug = @import("debug.zig"); | |
| 14 | pub const debug = @import("debug/index.zig"); | |
| 15 | 15 | pub const dwarf = @import("dwarf.zig"); |
| 16 | 16 | pub const elf = @import("elf.zig"); |
| 17 | 17 | pub const empty_import = @import("empty.zig"); |
| ... | ... | @@ -39,7 +39,7 @@ test "std" { |
| 39 | 39 | _ = @import("build.zig"); |
| 40 | 40 | _ = @import("c/index.zig"); |
| 41 | 41 | _ = @import("cstr.zig"); |
| 42 | _ = @import("debug.zig"); | |
| 42 | _ = @import("debug/index.zig"); | |
| 43 | 43 | _ = @import("dwarf.zig"); |
| 44 | 44 | _ = @import("elf.zig"); |
| 45 | 45 | _ = @import("empty.zig"); |
std/linked_list.zig+3-2| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 2 | 3 | const assert = debug.assert; |
| 3 | const mem = @import("mem.zig"); | |
| 4 | const mem = std.mem; | |
| 4 | 5 | const Allocator = mem.Allocator; |
| 5 | 6 | |
| 6 | 7 | /// Generic doubly linked list. |
std/math/acos.zig+3-2| ... | ... | @@ -2,8 +2,9 @@ |
| 2 | 2 | // |
| 3 | 3 | // - acos(x) = nan if x < -1 or x > 1 |
| 4 | 4 | |
| 5 | const math = @import("index.zig"); | |
| 6 | const assert = @import("../debug.zig").assert; | |
| 5 | const std = @import("../index.zig"); | |
| 6 | const math = std.math; | |
| 7 | const assert = std.debug.assert; | |
| 7 | 8 | |
| 8 | 9 | pub fn acos(x: var) -> @typeOf(x) { |
| 9 | 10 | const T = @typeOf(x); |
std/math/acosh.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - acosh(nan) = nan |
| 5 | 5 | |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn acosh(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/math/asin.zig+3-2| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | // - asin(+-0) = +-0 |
| 4 | 4 | // - asin(x) = nan if x < -1 or x > 1 |
| 5 | 5 | |
| 6 | const math = @import("index.zig"); | |
| 7 | const assert = @import("../debug.zig").assert; | |
| 6 | const std = @import("../index.zig"); | |
| 7 | const math = std.math; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | pub fn asin(x: var) -> @typeOf(x) { |
| 10 | 11 | const T = @typeOf(x); |
std/math/asinh.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - asinh(+-inf) = +-inf |
| 5 | 5 | // - asinh(nan) = nan |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn asinh(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/math/atan.zig+3-2| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | // - atan(+-0) = +-0 |
| 4 | 4 | // - atan(+-inf) = +-pi/2 |
| 5 | 5 | |
| 6 | const math = @import("index.zig"); | |
| 7 | const assert = @import("../debug.zig").assert; | |
| 6 | const std = @import("../index.zig"); | |
| 7 | const math = std.math; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | pub fn atan(x: var) -> @typeOf(x) { |
| 10 | 11 | const T = @typeOf(x); |
std/math/atan2.zig+3-2| ... | ... | @@ -18,8 +18,9 @@ |
| 18 | 18 | // atan2(+inf, x) = +pi/2 |
| 19 | 19 | // atan2(-inf, x) = -pi/2 |
| 20 | 20 | |
| 21 | const math = @import("index.zig"); | |
| 22 | const assert = @import("../debug.zig").assert; | |
| 21 | const std = @import("../index.zig"); | |
| 22 | const math = std.math; | |
| 23 | const assert = std.debug.assert; | |
| 23 | 24 | |
| 24 | 25 | fn atan2(comptime T: type, x: T, y: T) -> T { |
| 25 | 26 | return switch (T) { |
std/math/atanh.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - atanh(x) = nan if |x| > 1 with signal |
| 5 | 5 | // - atanh(nan) = nan |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn atanh(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/math/cbrt.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - cbrt(+-inf) = +-inf |
| 5 | 5 | // - cbrt(nan) = nan |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn cbrt(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/math/ceil.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - ceil(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | |
| 11 | 12 | pub fn ceil(x: var) -> @typeOf(x) { |
| 12 | 13 | const T = @typeOf(x); |
std/math/copysign.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn copysign(comptime T: type, x: T, y: T) -> T { |
| 5 | 6 | return switch (T) { |
std/math/cos.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - cos(nan) = nan |
| 5 | 5 | |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn cos(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/math/cosh.zig+3-2| ... | ... | @@ -5,9 +5,10 @@ |
| 5 | 5 | // - cosh(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const math = @import("index.zig"); | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 9 | 10 | const expo2 = @import("expo2.zig").expo2; |
| 10 | const assert = @import("../debug.zig").assert; | |
| 11 | const assert = std.debug.assert; | |
| 11 | 12 | |
| 12 | 13 | pub fn cosh(x: var) -> @typeOf(x) { |
| 13 | 14 | const T = @typeOf(x); |
std/math/exp.zig+3-2| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | // - exp(+inf) = +inf |
| 4 | 4 | // - exp(nan) = nan |
| 5 | 5 | |
| 6 | const math = @import("index.zig"); | |
| 7 | const assert = @import("../debug.zig").assert; | |
| 6 | const std = @import("../index.zig"); | |
| 7 | const math = std.math; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | pub fn exp(x: var) -> @typeOf(x) { |
| 10 | 11 | const T = @typeOf(x); |
std/math/exp2.zig+3-2| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | // - exp2(+inf) = +inf |
| 4 | 4 | // - exp2(nan) = nan |
| 5 | 5 | |
| 6 | const math = @import("index.zig"); | |
| 7 | const assert = @import("../debug.zig").assert; | |
| 6 | const std = @import("../index.zig"); | |
| 7 | const math = std.math; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | pub fn exp2(x: var) -> @typeOf(x) { |
| 10 | 11 | const T = @typeOf(x); |
std/math/expm1.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - expm1(-inf) = -1 |
| 5 | 5 | // - expm1(nan) = nan |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn expm1(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/math/fabs.zig+3-2| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | // - fabs(+-inf) = +inf |
| 4 | 4 | // - fabs(nan) = nan |
| 5 | 5 | |
| 6 | const math = @import("index.zig"); | |
| 7 | const assert = @import("../debug.zig").assert; | |
| 6 | const std = @import("../index.zig"); | |
| 7 | const math = std.math; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | pub fn fabs(x: var) -> @typeOf(x) { |
| 10 | 11 | const T = @typeOf(x); |
std/math/floor.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - floor(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const assert = @import("../debug.zig").assert; | |
| 9 | const math = @import("index.zig"); | |
| 8 | const assert = std.debug.assert; | |
| 9 | const std = @import("../index.zig"); | |
| 10 | const math = std.math; | |
| 10 | 11 | |
| 11 | 12 | pub fn floor(x: var) -> @typeOf(x) { |
| 12 | 13 | const T = @typeOf(x); |
std/math/fma.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) -> T { |
| 5 | 6 | return switch (T) { |
std/math/frexp.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - frexp(+-inf) = +-inf, 0 |
| 5 | 5 | // - frexp(nan) = nan, undefined |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | fn frexp_result(comptime T: type) -> type { |
| 11 | 12 | return struct { |
std/math/hypot.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - hypot(nan, y) = nan |
| 6 | 6 | // - hypot(x, nan) = nan |
| 7 | 7 | |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | |
| 11 | 12 | pub fn hypot(comptime T: type, x: T, y: T) -> T { |
| 12 | 13 | return switch (T) { |
std/math/ilogb.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - ilogb(0) = @maxValue(i32) |
| 5 | 5 | // - ilogb(nan) = @maxValue(i32) |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn ilogb(x: var) -> i32 { |
| 11 | 12 | const T = @typeOf(x); |
std/math/index.zig+2-1| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("../index.zig"); | |
| 2 | 3 | const TypeId = builtin.TypeId; |
| 3 | const assert = @import("../debug.zig").assert; | |
| 4 | const assert = std.debug.assert; | |
| 4 | 5 | |
| 5 | 6 | pub const e = 2.71828182845904523536028747135266249775724709369995; |
| 6 | 7 | pub const pi = 3.14159265358979323846264338327950288419716939937510; |
std/math/inf.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn inf(comptime T: type) -> T { |
| 5 | 6 | return switch (T) { |
std/math/isfinite.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn isFinite(x: var) -> bool { |
| 5 | 6 | const T = @typeOf(x); |
std/math/isinf.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn isInf(x: var) -> bool { |
| 5 | 6 | const T = @typeOf(x); |
std/math/isnan.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn isNan(x: var) -> bool { |
| 5 | 6 | const T = @typeOf(x); |
std/math/isnormal.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn isNormal(x: var) -> bool { |
| 5 | 6 | const T = @typeOf(x); |
std/math/ln.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - ln(x) = nan if x < 0 |
| 6 | 6 | // - ln(nan) = nan |
| 7 | 7 | |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | const builtin = @import("builtin"); |
| 11 | 12 | const TypeId = builtin.TypeId; |
| 12 | 13 |
std/math/log.zig+3-2| ... | ... | @@ -1,7 +1,8 @@ |
| 1 | const math = @import("index.zig"); | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 2 | 3 | const builtin = @import("builtin"); |
| 3 | 4 | const TypeId = builtin.TypeId; |
| 4 | const assert = @import("../debug.zig").assert; | |
| 5 | const assert = std.debug.assert; | |
| 5 | 6 | |
| 6 | 7 | pub fn log(comptime T: type, base: T, x: T) -> T { |
| 7 | 8 | if (base == 2) { |
std/math/log10.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - log10(x) = nan if x < 0 |
| 6 | 6 | // - log10(nan) = nan |
| 7 | 7 | |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | const builtin = @import("builtin"); |
| 11 | 12 | const TypeId = builtin.TypeId; |
| 12 | 13 |
std/math/log1p.zig+3-2| ... | ... | @@ -6,8 +6,9 @@ |
| 6 | 6 | // - log1p(x) = nan if x < -1 |
| 7 | 7 | // - log1p(nan) = nan |
| 8 | 8 | |
| 9 | const math = @import("index.zig"); | |
| 10 | const assert = @import("../debug.zig").assert; | |
| 9 | const std = @import("../index.zig"); | |
| 10 | const math = std.math; | |
| 11 | const assert = std.debug.assert; | |
| 11 | 12 | |
| 12 | 13 | pub fn log1p(x: var) -> @typeOf(x) { |
| 13 | 14 | const T = @typeOf(x); |
std/math/log2.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - log2(x) = nan if x < 0 |
| 6 | 6 | // - log2(nan) = nan |
| 7 | 7 | |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | const builtin = @import("builtin"); |
| 11 | 12 | const TypeId = builtin.TypeId; |
| 12 | 13 |
std/math/modf.zig+3-2| ... | ... | @@ -3,8 +3,9 @@ |
| 3 | 3 | // - modf(+-inf) = +-inf, nan |
| 4 | 4 | // - modf(nan) = nan, nan |
| 5 | 5 | |
| 6 | const math = @import("index.zig"); | |
| 7 | const assert = @import("../debug.zig").assert; | |
| 6 | const std = @import("../index.zig"); | |
| 7 | const math = std.math; | |
| 8 | const assert = std.debug.assert; | |
| 8 | 9 | |
| 9 | 10 | fn modf_result(comptime T: type) -> type { |
| 10 | 11 | return struct { |
std/math/pow.zig+3-2| ... | ... | @@ -22,8 +22,9 @@ |
| 22 | 22 | // pow(x, y) = nan for finite x < 0 and finite non-integer y |
| 23 | 23 | |
| 24 | 24 | const builtin = @import("builtin"); |
| 25 | const math = @import("index.zig"); | |
| 26 | const assert = @import("../debug.zig").assert; | |
| 25 | const std = @import("../index.zig"); | |
| 26 | const math = std.math; | |
| 27 | const assert = std.debug.assert; | |
| 27 | 28 | |
| 28 | 29 | // This implementation is taken from the go stlib, musl is a bit more complex. |
| 29 | 30 | pub fn pow(comptime T: type, x: T, y: T) -> T { |
std/math/round.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - round(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const assert = @import("../debug.zig").assert; | |
| 9 | const math = @import("index.zig"); | |
| 8 | const assert = std.debug.assert; | |
| 9 | const std = @import("../index.zig"); | |
| 10 | const math = std.math; | |
| 10 | 11 | |
| 11 | 12 | pub fn round(x: var) -> @typeOf(x) { |
| 12 | 13 | const T = @typeOf(x); |
std/math/scalbn.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn scalbn(x: var, n: i32) -> @typeOf(x) { |
| 5 | 6 | const T = @typeOf(x); |
std/math/signbit.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const math = @import("index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const math = std.math; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub fn signbit(x: var) -> bool { |
| 5 | 6 | const T = @typeOf(x); |
std/math/sin.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - sin(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | |
| 11 | 12 | pub fn sin(x: var) -> @typeOf(x) { |
| 12 | 13 | const T = @typeOf(x); |
std/math/sinh.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - sinh(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | const expo2 = @import("expo2.zig").expo2; |
| 11 | 12 | |
| 12 | 13 | pub fn sinh(x: var) -> @typeOf(x) { |
std/math/sqrt.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - sqrt(x) = nan if x < 0 |
| 6 | 6 | // - sqrt(nan) = nan |
| 7 | 7 | |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | const builtin = @import("builtin"); |
| 11 | 12 | const TypeId = builtin.TypeId; |
| 12 | 13 |
std/math/tan.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - tan(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | |
| 11 | 12 | pub fn tan(x: var) -> @typeOf(x) { |
| 12 | 13 | const T = @typeOf(x); |
std/math/tanh.zig+3-2| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | // - sinh(nan) = nan |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const math = @import("index.zig"); | |
| 9 | const assert = @import("../debug.zig").assert; | |
| 8 | const std = @import("../index.zig"); | |
| 9 | const math = std.math; | |
| 10 | const assert = std.debug.assert; | |
| 10 | 11 | const expo2 = @import("expo2.zig").expo2; |
| 11 | 12 | |
| 12 | 13 | pub fn tanh(x: var) -> @typeOf(x) { |
std/math/trunc.zig+3-2| ... | ... | @@ -4,8 +4,9 @@ |
| 4 | 4 | // - trunc(+-inf) = +-inf |
| 5 | 5 | // - trunc(nan) = nan |
| 6 | 6 | |
| 7 | const math = @import("index.zig"); | |
| 8 | const assert = @import("../debug.zig").assert; | |
| 7 | const std = @import("../index.zig"); | |
| 8 | const math = std.math; | |
| 9 | const assert = std.debug.assert; | |
| 9 | 10 | |
| 10 | 11 | pub fn trunc(x: var) -> @typeOf(x) { |
| 11 | 12 | const T = @typeOf(x); |
std/mem.zig+3-2| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | const debug = @import("debug.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const debug = std.debug; | |
| 2 | 3 | const assert = debug.assert; |
| 3 | const math = @import("math/index.zig"); | |
| 4 | const math = std.math; | |
| 4 | 5 | const builtin = @import("builtin"); |
| 5 | 6 | |
| 6 | 7 | error OutOfMemory; |
std/net.zig+4-3| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | const linux = @import("os/linux.zig"); | |
| 2 | const assert = @import("debug.zig").assert; | |
| 3 | const endian = @import("endian.zig"); | |
| 1 | const std = @import("index.zig"); | |
| 2 | const linux = std.os.linux; | |
| 3 | const assert = std.debug.assert; | |
| 4 | const endian = std.endian; | |
| 4 | 5 | |
| 5 | 6 | error SigInterrupt; |
| 6 | 7 | error Io; |
std/os/darwin.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const c = @import("../c/index.zig"); | |
| 2 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const c = std.c; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | |
| 4 | 5 | pub use @import("darwin_errno.zig"); |
| 5 | 6 |
std/os/index.zig+11-10| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | const std = @import("../index.zig"); | |
| 1 | 2 | const builtin = @import("builtin"); |
| 2 | 3 | const Os = builtin.Os; |
| 3 | 4 | const is_windows = builtin.os == Os.windows; |
| ... | ... | @@ -37,22 +38,22 @@ pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock; |
| 37 | 38 | |
| 38 | 39 | pub const FileHandle = if (is_windows) windows.HANDLE else i32; |
| 39 | 40 | |
| 40 | const debug = @import("../debug.zig"); | |
| 41 | const debug = std.debug; | |
| 41 | 42 | const assert = debug.assert; |
| 42 | 43 | |
| 43 | const c = @import("../c/index.zig"); | |
| 44 | const c = std.c; | |
| 44 | 45 | |
| 45 | const mem = @import("../mem.zig"); | |
| 46 | const mem = std.mem; | |
| 46 | 47 | const Allocator = mem.Allocator; |
| 47 | 48 | |
| 48 | const BufMap = @import("../buf_map.zig").BufMap; | |
| 49 | const cstr = @import("../cstr.zig"); | |
| 49 | const BufMap = std.BufMap; | |
| 50 | const cstr = std.cstr; | |
| 50 | 51 | |
| 51 | const io = @import("../io.zig"); | |
| 52 | const base64 = @import("../base64.zig"); | |
| 53 | const ArrayList = @import("../array_list.zig").ArrayList; | |
| 54 | const Buffer = @import("../buffer.zig").Buffer; | |
| 55 | const math = @import("../index.zig").math; | |
| 52 | const io = std.io; | |
| 53 | const base64 = std.base64; | |
| 54 | const ArrayList = std.ArrayList; | |
| 55 | const Buffer = std.Buffer; | |
| 56 | const math = std.math; | |
| 56 | 57 | |
| 57 | 58 | error SystemResources; |
| 58 | 59 | error AccessDenied; |
std/os/linux.zig+2-1| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | const assert = @import("../debug.zig").assert; | |
| 1 | const std = @import("../index.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 2 | 3 | const builtin = @import("builtin"); |
| 3 | 4 | const arch = switch (builtin.arch) { |
| 4 | 5 | builtin.Arch.x86_64 => @import("linux_x86_64.zig"), |
std/os/path.zig+7-7| ... | ... | @@ -1,16 +1,16 @@ |
| 1 | const std = @import("../index.zig"); | |
| 1 | 2 | const builtin = @import("builtin"); |
| 2 | 3 | const Os = builtin.Os; |
| 3 | const debug = @import("../debug.zig"); | |
| 4 | const debug = std.debug; | |
| 4 | 5 | const assert = debug.assert; |
| 5 | const mem = @import("../mem.zig"); | |
| 6 | const fmt = @import("../fmt/index.zig"); | |
| 6 | const mem = std.mem; | |
| 7 | const fmt = std.fmt; | |
| 7 | 8 | const Allocator = mem.Allocator; |
| 8 | const os = @import("index.zig"); | |
| 9 | const math = @import("../math/index.zig"); | |
| 9 | const os = std.os; | |
| 10 | const math = std.math; | |
| 10 | 11 | const posix = os.posix; |
| 11 | 12 | const windows = os.windows; |
| 12 | const c = @import("../c/index.zig"); | |
| 13 | const cstr = @import("../cstr.zig"); | |
| 13 | const cstr = std.cstr; | |
| 14 | 14 | |
| 15 | 15 | pub const sep_windows = '\\'; |
| 16 | 16 | pub const sep_posix = '/'; |
std/rand.zig+4-3| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | const std = @import("index.zig"); | |
| 1 | 2 | const builtin = @import("builtin"); |
| 2 | const assert = @import("debug.zig").assert; | |
| 3 | const assert = std.debug.assert; | |
| 3 | 4 | const rand_test = @import("rand_test.zig"); |
| 4 | const mem = @import("mem.zig"); | |
| 5 | const math = @import("math/index.zig"); | |
| 5 | const mem = std.mem; | |
| 6 | const math = std.math; | |
| 6 | 7 | |
| 7 | 8 | pub const MT19937_32 = MersenneTwister( |
| 8 | 9 | u32, 624, 397, 31, |
std/special/compiler_rt/fixunsdfdi_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunsdfdi(a: f64, expected: u64) { |
| 5 | 5 | const x = __fixunsdfdi(a); |
std/special/compiler_rt/fixunsdfsi_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunsdfsi(a: f64, expected: u32) { |
| 5 | 5 | const x = __fixunsdfsi(a); |
std/special/compiler_rt/fixunsdfti_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunsdfti(a: f64, expected: u128) { |
| 5 | 5 | const x = __fixunsdfti(a); |
std/special/compiler_rt/fixunssfdi_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunssfdi(a: f32, expected: u64) { |
| 5 | 5 | const x = __fixunssfdi(a); |
std/special/compiler_rt/fixunssfsi_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunssfsi(a: f32, expected: u32) { |
| 5 | 5 | const x = __fixunssfsi(a); |
std/special/compiler_rt/fixunssfti_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunssfti(a: f32, expected: u128) { |
| 5 | 5 | const x = __fixunssfti(a); |
std/special/compiler_rt/fixunstfdi_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunstfdi(a: f128, expected: u64) { |
| 5 | 5 | const x = __fixunstfdi(a); |
std/special/compiler_rt/fixunstfsi_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunstfsi(a: f128, expected: u32) { |
| 5 | 5 | const x = __fixunstfsi(a); |
std/special/compiler_rt/fixunstfti_test.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; |
| 2 | const assert = @import("../../debug.zig").assert; | |
| 2 | const assert = @import("../../index.zig").debug.assert; | |
| 3 | 3 | |
| 4 | 4 | fn test__fixunstfti(a: f128, expected: u128) { |
| 5 | 5 | const x = __fixunstfti(a); |
std/special/compiler_rt/index.zig+1-1| ... | ... | @@ -68,7 +68,7 @@ comptime { |
| 68 | 68 | } |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | const assert = @import("../../debug.zig").assert; | |
| 71 | const assert = @import("../../index.zig").debug.assert; | |
| 72 | 72 | |
| 73 | 73 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 74 | 74 |
test/cases/union.zig+15| ... | ... | @@ -220,3 +220,18 @@ fn assertIsTheUnion2Item1(value: &const TheUnion2) { |
| 220 | 220 | assert(*value == TheUnion2.Item1); |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | ||
| 224 | pub const PackThis = union(enum) { | |
| 225 | Invalid: bool, | |
| 226 | StringLiteral: u2, | |
| 227 | }; | |
| 228 | ||
| 229 | test "constant packed union" { | |
| 230 | testConstPackedUnion([]PackThis { | |
| 231 | PackThis { .StringLiteral = 1 }, | |
| 232 | }); | |
| 233 | } | |
| 234 | ||
| 235 | fn testConstPackedUnion(expected_tokens: []const PackThis) { | |
| 236 | assert(expected_tokens[0].StringLiteral == 1); | |
| 237 | } |