├── .gitignore
├── src
├── main.zig
├── debug.zig
├── config.zig
├── bkg_runtime.zig
├── optimizer.zig
├── cli.zig
├── compiler.zig
├── analyzer.zig
├── version_manager.zig
├── lto.zig
├── runtime.zig
├── translated
│ ├── boptimizer.zig
│ └── liblz4.zig
└── thread_pool.zig
├── install.sh
├── .gitmodules
├── .github
└── workflows
│ └── CI.yml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | zig-out
2 | zig-cache
3 | .vscode
4 | .zigmod
5 | deps.zig
6 | example
7 | tmp
8 | bkg
9 | .gyro
10 | gyro.lock
11 | */zig-cache
12 | bkg_runtime
13 | build
14 | dev.sh
--------------------------------------------------------------------------------
/src/main.zig:
--------------------------------------------------------------------------------
1 | const std = @import("std");
2 | const cli = @import("cli.zig");
3 |
4 | // Allocator
5 | var gpa = std.heap.GeneralPurposeAllocator(.{}){};
6 | var arena = std.heap.ArenaAllocator.init(gpa.allocator());
7 | var allocator = arena.allocator();
8 |
9 | pub fn main() anyerror!void {
10 |
11 | // Free all memory when main exits
12 | defer arena.deinit();
13 |
14 | // Initialize CLI
15 | try cli.init(allocator);
16 |
17 | }
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | ARCH=`uname -m`
6 | OS=`uname`
7 | TARGET="bkg-${ARCH}-"
8 |
9 | if [ "${OS}" = "Linux" ]
10 | then
11 | TARGET="${TARGET}linux"
12 | elif [ "$OS" = "Darwin" ]
13 | then
14 | if [ "${ARCH}" = "arm64" ]
15 | then
16 | TARGET="bkg-aarch64-macos"
17 | else
18 | TARGET="${TARGET}macos"
19 | fi
20 | else
21 | echo "Unsupported OS/CPU"
22 | exit 1
23 | fi
24 |
25 | URL="https://github.com/theseyan/bkg/releases/latest/download/"
26 | URL="${URL}${TARGET}"
27 |
28 | echo "Downloading bkg... $URL"
29 | curl --fail --location --progress-bar --output /usr/local/bin/bkg $URL
30 | chmod +x /usr/local/bin/bkg
31 | echo "bkg was successfully installed to /usr/local/bin/bkg"
32 | echo "Run \`bkg --help\` to get started!"
33 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "deps/lz4"]
2 | path = deps/lz4
3 | url = https://github.com/lz4/lz4
4 | [submodule "deps/known-folders"]
5 | path = deps/known-folders
6 | url = https://github.com/ziglibs/known-folders
7 | [submodule "deps/zip"]
8 | path = deps/zip
9 | url = https://github.com/kuba--/zip
10 | [submodule "deps/zig-clap"]
11 | path = deps/zig-clap
12 | url = https://github.com/Hejsil/zig-clap
13 | [submodule "deps/bOptimizer"]
14 | path = deps/bOptimizer
15 | url = https://github.com/theseyan/bOptimizer
16 | [submodule "deps/zelda"]
17 | path = deps/zelda
18 | url = https://github.com/haze/zelda
19 | [submodule "deps/zfetch"]
20 | path = deps/zfetch
21 | url = https://github.com/theseyan/zfetch
22 | [submodule "deps/microtar"]
23 | path = deps/microtar
24 | url = https://github.com/Inndy/microtar
25 |
--------------------------------------------------------------------------------
/src/debug.zig:
--------------------------------------------------------------------------------
1 | const std = @import("std");
2 |
3 | // Whether debug mode is enabled
4 | pub var debug = false;
5 |
6 | // Starting timestamp for measuring app lifetime
7 | pub var startTime: i64 = undefined;
8 |
9 | // Allocator
10 | var allocator: std.mem.Allocator = undefined;
11 |
12 | // Prints a debug message
13 | pub fn print(comptime msg: []const u8, args: anytype) void {
14 |
15 | std.debug.print("[bkg] " ++ msg ++ "\n", args);
16 |
17 | }
18 |
19 | // Prints a error message
20 | pub fn err(comptime msg: []const u8, args: anytype) void {
21 | std.debug.print("\n❌ " ++ msg ++ "\n", args);
22 | }
23 |
24 | // Prints a warning message
25 | pub fn warn(comptime msg: []const u8, args: anytype) void {
26 | std.debug.print("\n⚠️ " ++ msg ++ "\n", args);
27 | }
28 |
29 | pub fn init(alloc: std.mem.Allocator) void {
30 | allocator = alloc;
31 | }
--------------------------------------------------------------------------------
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI
4 |
5 | # Controls when the workflow will run
6 | on:
7 | # Triggers the workflow on push or pull request events but only for the "main" branch
8 | push:
9 | branches: [ "main" ]
10 | pull_request:
11 | branches: [ "main" ]
12 |
13 | # Allows you to run this workflow manually from the Actions tab
14 | workflow_dispatch:
15 |
16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
17 | jobs:
18 | # This workflow contains a single job called "build"
19 | build:
20 | # The type of runner that the job will run on
21 | runs-on: ubuntu-latest
22 |
23 | # Steps represent a sequence of tasks that will be executed as part of the job
24 | steps:
25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
26 | - uses: actions/checkout@v3
27 |
28 | # Runs a single command using the runners shell
29 | - name: Run a one-line script
30 | run: echo Hello, world!
31 |
32 | # Runs a set of commands using the runners shell
33 | - name: Run a multi-line script
34 | run: |
35 | echo Add other actions to build,
36 | echo test, and deploy your project.
37 |
--------------------------------------------------------------------------------
/src/config.zig:
--------------------------------------------------------------------------------
1 | // Configuration manager
2 | const std = @import("std");
3 | const json = std.json;
4 |
5 | // Configuration struct
6 | pub const Config = struct {
7 | entry: []const u8 = "index.js", // Entrypoint of the application
8 | debug: bool = false, // Toggles debug logs at runtime
9 | lto: ?struct { // Link-Time Optimization
10 | format: []const u8 = "cjs", // "cjs" or "esm"
11 | includes: [][]const u8 = &.{}, // Globs of file paths to package as assets into the binary
12 | } = null
13 | };
14 |
15 | // Default configuration JSON
16 | // Injected automatically if no bkg.config.json was provided
17 | pub const defaultConfig: Config = .{
18 | .entry = "index.js",
19 | .debug = false,
20 | .lto = null
21 | };
22 |
23 | // Stores the configuration
24 | var config: Config = undefined;
25 |
26 | // Loads and parses config JSON file
27 | pub fn load(allocator: std.mem.Allocator, path: ?[]const u8, buffer: ?[]u8) !void {
28 |
29 | var buf: []u8 = undefined;
30 |
31 | if(path != null) {
32 | // Open config.json
33 | var file = try std.fs.openFileAbsolute(path.?, .{});
34 | defer file.close();
35 |
36 | // Read into buffer
37 | // Config file should not exceed 4 KiB
38 | buf = try file.readToEndAlloc(allocator, 4 * 1024);
39 | }else if(buffer != null) {
40 | buf = buffer.?;
41 | }
42 |
43 | // Parse the JSON payload and store the struct
44 | config = x: {
45 | var stream = json.TokenStream.init(buf);
46 | const res = json.parse(Config, &stream, .{.allocator = allocator, .ignore_unknown_fields = true});
47 | break :x res catch |e| {
48 | return e;
49 | };
50 | };
51 |
52 | }
53 |
54 | // Attempt to load configuration from disk
55 | // If not, load defaults
56 | pub fn tryLoadConfig(allocator: std.mem.Allocator, path: []const u8) !void {
57 |
58 | load(allocator, path, null) catch |e| switch(e) {
59 | error.FileNotFound => {
60 | var configObj = try allocator.create(Config);
61 | configObj.* = defaultConfig;
62 | config = configObj.*;
63 | return;
64 | },
65 | else => return e
66 | };
67 |
68 | }
69 |
70 | // Returns a pointer to the loaded configuration
71 | pub fn get() *Config {
72 | return &config;
73 | }
--------------------------------------------------------------------------------
/src/bkg_runtime.zig:
--------------------------------------------------------------------------------
1 | // This program is compiled separately as the runtime for packaging
2 | // It should only deal with running the packaged app
3 |
4 | // To build the runtime & strip debug symbols:
5 | // zig build-exe -Drelease-fast src/bkg_runtime.zig --strip -lc deps/lz4/lib/lz4.c deps/microtar/src/microtar.c --pkg-begin known-folders deps/known-folders/known-folders.zig --pkg-end
6 |
7 | const std = @import("std");
8 | const runtime = @import("runtime.zig");
9 | const knownFolders = @import("known-folders");
10 | const config = @import("config.zig");
11 | const debug = @import("debug.zig");
12 |
13 | // Using evented IO causes a bug in the Zig compiler
14 | // https://github.com/ziglang/zig/issues/11985
15 | // pub const io_mode = .evented;
16 |
17 | var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator);
18 | var allocator = arena.allocator();
19 |
20 | pub fn main() !void {
21 |
22 | // De-initialize allocator when main exits
23 | defer arena.deinit();
24 |
25 | // Get path to this binary
26 | var selfPath = try std.fs.selfExePathAlloc(allocator);
27 | var basename = std.fs.path.basename(selfPath);
28 |
29 | // Parse executable headers
30 | const headers = try runtime.parseBinary(allocator, selfPath);
31 |
32 | // We run the app in /tmp directory
33 | var runtimeDir = "/tmp";
34 |
35 | // App directory is formatted as: .{basename}_runtime_{hash}
36 | // where hash is the CRC32 hash of LZ4 compressed sources buffer
37 | var appDirPath = try std.mem.concat(allocator, u8, &.{runtimeDir, "/.", basename, "_runtime_", headers.hash});
38 |
39 | var appDir: ?void = std.fs.makeDirAbsolute(appDirPath) catch |e| switch(e) {
40 | error.PathAlreadyExists => null,
41 | else => return error.FailedToCreateAppDir,
42 | };
43 |
44 | if(appDir != null) {
45 | // Directory was created
46 | try runtime.extractArchive(allocator, selfPath, appDirPath, headers);
47 | }else {
48 | // Directory already exists, load configuration
49 | try config.load(allocator, try std.mem.concat(allocator, u8, &.{appDirPath, "/bkg.config.json"}), null);
50 | if(config.get().debug) debug.debug = true;
51 |
52 | if(debug.debug) {
53 | debug.print("Debug logs are enabled", .{});
54 | debug.print("Configuration file loaded from disk!", .{});
55 | debug.print("App directory already exists, skipping extraction..", .{});
56 | }
57 | }
58 |
59 | if(debug.debug) {
60 | debug.print("CRC32 Hash:\t{s}", .{headers.hash});
61 | debug.print("Compressed Size:\t{any} bytes", .{headers.compressed});
62 | debug.print("Starting Bun runtime..", .{});
63 | }
64 |
65 | // Execute process
66 | try runtime.execProcess(allocator, appDirPath, config.get());
67 |
68 | }
--------------------------------------------------------------------------------
/src/optimizer.zig:
--------------------------------------------------------------------------------
1 | // Performs bundling, minification and optimization on Javascript sources
2 |
3 | const std = @import("std");
4 | const boptimizer = @import("translated/boptimizer.zig");
5 | const json = std.json;
6 | const lto = @import("lto.zig");
7 | const analyzer = @import("analyzer.zig");
8 | const debug = @import("debug.zig");
9 |
10 | // Glob patterns to exclude when copying a module
11 | pub const ModuleCopyExcludes = [_][]const u8{
12 | ".gitignore", ".git", "*.md", ".prettierrc", "tsconfig.base.json", ".github", "LICENSE"
13 | };
14 |
15 | pub const BuildResultFileLocation = struct {
16 | File: []const u8,
17 | Namespace: []const u8,
18 | Line: u16,
19 | Column: u16,
20 | Length: u16,
21 | LineText: []const u8,
22 | Suggestion: []const u8
23 | };
24 |
25 | pub const OptimizerMessage = struct {
26 | ID: ?[]const u8,
27 | PluginName: []const u8,
28 | Text: []const u8,
29 | Location: ?BuildResultFileLocation,
30 | Notes: ?[]struct {
31 | Text: []const u8,
32 | Location: ?BuildResultFileLocation
33 | },
34 | Detail: ?u8 = null
35 | };
36 |
37 | pub const BuildResult = struct {
38 | Status: i8,
39 | Data: ?[]OptimizerMessage,
40 | Metadata: ?[]const u8
41 | };
42 |
43 | pub const OptimizeResult = struct {
44 | status: enum { Success, Failure, Warning },
45 | errors: []OptimizerMessage = &.{},
46 | warnings: []OptimizerMessage = &.{},
47 | inputs: [][]const u8 = &.{},
48 | meta: struct {
49 | bundleSize: i64 = 0
50 | },
51 | buildResult: BuildResult
52 | };
53 |
54 | // Optimizes a module in-place, and places it on disk to a temporary location
55 | // Module must be pure
56 | pub fn optimizePureModuleToDisk(allocator: std.mem.Allocator, module: []const u8, entry: []const u8, outDir: []const u8) !void {
57 | const modulePath = try std.mem.concat(allocator, u8, &.{outDir, "/node_modules/", module});
58 |
59 | // Make module path
60 | try std.fs.cwd().makePath(modulePath);
61 |
62 | // Optimize module
63 | var result: *OptimizeResult = try optimize(allocator, entry, try std.mem.concat(allocator, u8, &.{modulePath, "/index.js"}), "cjs", "");
64 |
65 | if(result.status != .Success and lto.checkAllowedDynamicModule(module) == false) {
66 | return error.FailedOptimizePureModule;
67 | }
68 | }
69 |
70 | // Copies a module to another location on disk
71 | pub fn copyModuleToDisk(allocator: std.mem.Allocator, root: []const u8, module: []const u8, outDir: []const u8) !void {
72 | const modulePath = try std.mem.concat(allocator, u8, &.{outDir, "/node_modules/", module});
73 | const origPath = try std.mem.concat(allocator, u8, &.{root, "/node_modules/", module});
74 |
75 | // Make module path
76 | try std.fs.cwd().makePath(modulePath);
77 |
78 | var dir = try std.fs.openIterableDirAbsolute(origPath, .{});
79 | defer dir.close();
80 | var walker = try dir.walk(allocator);
81 |
82 | walkerLoop: while (try walker.next()) |entry| {
83 | // Ignore files/folder that are excluded
84 | inline for(ModuleCopyExcludes[0..ModuleCopyExcludes.len]) |glob| {
85 | if(analyzer.globMatchComptime(glob, entry.path)) continue :walkerLoop;
86 | }
87 |
88 | if(entry.kind == .Directory) {
89 | try std.fs.makeDirAbsolute(try std.mem.concat(allocator, u8, &.{modulePath, "/", entry.path}));
90 | }else {
91 | try std.fs.copyFileAbsolute(try std.mem.concat(allocator, u8, &.{origPath, "/", entry.path}), try std.mem.concat(allocator, u8, &.{modulePath, "/", entry.path}), .{});
92 | }
93 | }
94 | }
95 |
96 | // Performs optimization on an entry point recursively
97 | pub fn optimize(allocator: std.mem.Allocator, entry: []const u8, out: []const u8, format: []const u8, externals: []u8) !*OptimizeResult {
98 |
99 | const entrySentinel = try std.mem.concatWithSentinel(allocator, u8, &.{entry}, 0);
100 | const outSentinel = try std.mem.concatWithSentinel(allocator, u8, &.{out}, 0);
101 | const formatSentinel = try std.mem.concatWithSentinel(allocator, u8, &.{format}, 0);
102 |
103 | const resultPtr = boptimizer.build(entrySentinel.ptr, outSentinel.ptr, formatSentinel.ptr, externals.ptr);
104 | const result: []u8 = resultPtr[0..std.mem.indexOfSentinel(u8, 0, resultPtr)];
105 |
106 | // Get wrapper build result
107 | const buildResult: BuildResult = x: {
108 | var stream = json.TokenStream.init(result);
109 | const res = json.parse(BuildResult, &stream, .{.allocator = allocator, .ignore_unknown_fields = true});
110 | break :x res catch |e| {
111 | return e;
112 | };
113 | };
114 |
115 | // Create optimization result
116 | var optimizeResult: *OptimizeResult = try allocator.create(OptimizeResult);
117 | optimizeResult.status = switch (buildResult.Status) {
118 | -1 => .Failure,
119 | 0 => .Warning,
120 | 1 => .Success,
121 | else => return error.UnknownOptimizeStatus
122 | };
123 |
124 | if(optimizeResult.status == .Warning) { optimizeResult.warnings = buildResult.Data.?; }
125 | else if(optimizeResult.status == .Failure) {
126 | optimizeResult.errors = buildResult.Data.?;
127 | return optimizeResult;
128 | }
129 |
130 | // Parse meta JSON
131 | var parser = json.Parser.init(allocator, false);
132 | var tree = try parser.parse(buildResult.Metadata.?);
133 |
134 | var outputs = tree.root.Object.get("outputs");
135 | var outputsIterator = outputs.?.Object.iterator();
136 | var outputBasename = std.fs.path.basename(out);
137 |
138 | // Get output bundle size in bytes
139 | while(outputsIterator.next()) |output| {
140 | if(std.mem.eql(u8, std.fs.path.basename(output.key_ptr.*), outputBasename)) {
141 | optimizeResult.meta.bundleSize = outputs.?.Object.get(output.key_ptr.*).?.Object.get("bytes").?.Integer;
142 | break;
143 | }
144 | }
145 |
146 | // Parse list of input sources
147 | var inputsObj = tree.root.Object.get("inputs");
148 | var iterator = inputsObj.?.Object.iterator();
149 |
150 | if(inputsObj == null or inputsObj.?.Object.count() == 0) {
151 | optimizeResult.inputs = &.{};
152 | }else {
153 | var inputsArrayList = std.ArrayList([]const u8).init(allocator);
154 | while(iterator.next()) |item| {
155 | try inputsArrayList.append(item.key_ptr.*);
156 | }
157 |
158 | optimizeResult.inputs = try inputsArrayList.toOwnedSlice();
159 | }
160 |
161 | // Save struct so we can free it later
162 | optimizeResult.buildResult = buildResult;
163 |
164 | return optimizeResult;
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
bkg
4 |
5 | Package Bun apps into a single executable
6 |
7 |
8 |

9 |
10 |
11 |
12 |
13 | bkg is a CLI tool that can generate self-sufficient binaries from your Bun code for multiple platforms.
14 |
15 | ## Usage
16 |
17 | Fastest way to install:
18 | ```
19 | curl -fsSL https://github.com/theseyan/bkg/raw/main/install.sh | sudo sh
20 | ```
21 |
22 | OR, get the [latest release](https://github.com/theseyan/bkg/releases) for your platform (`bkg_runtime-` binaries are not required, they will be automatically downloaded).
23 |
24 | Run `bkg --help` to get a list of options on usage:
25 |
26 | ```console
27 | Usage: bkg [options]
28 | Example: bkg myProject -o myapp
29 |
30 | Options:
31 | -h, --help Display this help message.
32 | -o, --output Output file name
33 | -t, --target Target architecture to build for (default is Host)
34 | --targets Display list of supported targets
35 | --runtime Path to custom Bun binary (not recommended)
36 | -v, --version Display bkg version.
37 | ...
38 | ```
39 | ### `bkg.config.json`
40 | bkg assumes `index.js` to be the entry point of your application. This can be changed by creating `bkg.config.json` at the root directory of your project:
41 | ```json
42 | {
43 | "entry": "app.ts"
44 | }
45 | ```
46 |
47 | ## Why?
48 | - Distribute a single binary that can run without Bun or any external dependencies installed
49 | - Build executables for any platform supported by Bun
50 | - Around 1/2 the size of Bun runtime
51 | - Package any asset into the binary, not just scripts and modules
52 | - No performance regression except for the first startup
53 | - Although not yet possible, the goal is generating bytecode and the ability to distribute binaries stripped of sources
54 |
55 | ## Link-Time Optimizations (LTO)
56 | Since `v0.0.4`, bkg has support for an experimental LTO mode.
57 |
58 | When LTO is enabled, bkg will attempt to statically analyze your code, bundle sources and perform tree shaking/minification at compile time.
59 | For large projects, this drastically reduces application size and boosts cold startup times.
60 |
61 | To enable LTO, compile with `--lto` or add the following field to `bkg.config.json`:
62 | ```json
63 | {
64 | "lto": {
65 | "format": "cjs"
66 | }
67 | }
68 | ```
69 |
70 | Only reachable code is packaged into the executable; To include additional assets, use `--include "path/to/files/*"` flag or set the `lto.includes` field in configuration with a comma-separated list of glob file paths.
71 |
72 | ## Differences from `pkg`
73 |
74 | bkg and pkg (Node) have a number of differences arising either from a design decision or a Bun limitation:
75 | - **Sources are not compiled to bytecode:** Bun does not expose a JavascriptCore equivalent of `v8::ScriptCompiler` yet, hence sources are kept intact in the compiled executable.
76 | - **File system:** bkg does not embed a virtual filesystem but instead archives sources using the very fast [LZ4 compression](https://github.com/lz4/lz4) which are decompressed to a temporary location at runtime. This makes the resulting binary about 1/2 the size of Bun itself, while not having to keep the entire runtime in memory.
77 | - **Import resolution:** Unlike pkg, we do not recursively traverse through each import in the sources and package those files (yet). bkg will simply archive the entire source folder - this will change in version 1.0.
78 |
79 | ## Key takeaways
80 |
81 | - bkg is **not** meant for very dynamic environments (for eg. serverless), as it adds considerable overhead to startup time. However, this overhead is only valid for the first start as the decompressed sources are cached in the filesystem onwards.
82 | - It is not recommended to perform `fs` operations with relative paths, as there is no guarantee where the sources may be placed at runtime. This will be fixed when I complete overriding some of `fs` default paths.
83 | - Generated executables are already stripped and must not be stripped again.
84 |
85 | # Building from source
86 | bkg is written in Zig and compilation is fairly straightforward. The prerequisites are:
87 | - Zig version [0.11.0-dev.944+a193ec432](https://ziglang.org/builds/zig-0.11.0-dev.944+a193ec432.tar.xz)
88 |
89 | ```bash
90 | # Clone the repository and update submodules
91 | git clone https://github.com/theseyan/bkg && cd bkg
92 | git submodule update --init --recursive
93 |
94 | # Build for x86_64-linux
95 | zig build -Drelease-fast -Dtarget=x86_64-linux
96 |
97 | # [Optional] Build runtime for x86_64-linux & strip it
98 | zig build-exe -target x86_64-linux src/bkg_runtime.zig -fstrip -lc deps/lz4/lib/lz4.c deps/microtar/src/microtar.c --pkg-begin known-folders deps/known-folders/known-folders.zig --pkg-end
99 |
100 | # Run bkg
101 | ./zig-out/bin/bkg --help
102 |
103 | # OR, build runtime and CLI for all platforms
104 | # Generated executables are placed in /build
105 | chmod +x build.sh && ./build.sh
106 | ```
107 |
108 | # Todo
109 |
110 | **Release v0.1.0:**
111 | - :white_check_mark: ~~Switch to LZ4 high compression variant that compresses more but doesn't affect decompression speed (and shaves off 7MB!)~~
112 | - :white_check_mark: ~~Runtime: Stream decompressed buffer directly to microtar instead of through the filesystem. This will greatly improve startup time.~~
113 | - :white_check_mark: ~~Compiler: Stream archive directly to `LZ4_compress_HC` instead of through the filesystem~~
114 | - :white_check_mark: ~~Use [zfetch](https://github.com/truemedian/zfetch) instead of cURL~~
115 | - :white_check_mark: ~~JSON configuration file~~
116 | - :white_check_mark: ~~Pass CLI args to javascript~~
117 | - :white_check_mark: ~~Named app directory containing the CRC32 hash of project sources. This will fix outdated cached code being executed.~~
118 | - Override Bun default variables with an injected JS entry point
119 |
120 | **Roadmap: v1.0**
121 | - Optimizer/Bundler based on [esbuild](https://esbuild.github.io/) to bundle entire source tree into a handful of JS files. This is important because currently our biggest bottleneck is decompression speed with lots of files (>1000 files) which is common in projects with `node_modules`. Ideally, this will be replaced by Bun's own bundler.
122 | - Runtime hash checking against inflated sources to prevent execution of modified scripts
123 | - Prettier CLI output with colors & loaders
124 | - Prebuild, postbuild options and CLI argument counterparts of `bkg.config.json`
125 | - Pass Bun CLI flags
126 | - Fork a custom build of Bun with only the JS runtime to further reduce binary size
127 | - :white_check_mark: ~~Multithreaded decompression for even faster cold starts~~
128 |
129 | **Optimizer Progress:**
130 | See [bOptimizer](https://github.com/theseyan/boptimizer).
--------------------------------------------------------------------------------
/src/cli.zig:
--------------------------------------------------------------------------------
1 | // bkg CLI
2 | const std = @import("std");
3 | const clap = @import("clap");
4 | const knownFolders = @import("known-folders");
5 | const compiler = @import("compiler.zig");
6 | const versionManager = @import("version_manager.zig");
7 | const debug = std.debug;
8 | const io = std.io;
9 | const lto = @import("lto.zig");
10 | const config = @import("config.zig");
11 |
12 | // Initializes CLI environment
13 | pub fn init(allocator: std.mem.Allocator) anyerror!void {
14 |
15 | // Parameters & head strings
16 | const head =
17 | \\Usage: bkg [options]
18 | \\
19 | \\Options:
20 | ;
21 | const paramsStr =
22 | \\ -o, --output Output file name
23 | \\ -i, --includes Comma-separated list of files to include into the binary
24 | \\ -t, --target Target architecture to build for (default is Host)
25 | \\ -b, --baseline Use non-AVX2 (baseline) build of Bun for compatibility
26 | \\ --lto Enable Link-Time Optimizations (experimental)
27 | \\ --targets Display list of supported targets
28 | \\ -h, --help Display this help message.
29 | \\ -v, --version Display bkg version.
30 | \\ -d, --debug Enable debug logs at runtime
31 | \\ --runtime Path to custom Bun binary (not recommended)
32 | \\ ...
33 | \\
34 | ;
35 | const params = comptime clap.parseParamsComptime(paramsStr);
36 |
37 | // We use optional diagnostics
38 | var diag = clap.Diagnostic{};
39 | var res = clap.parse(clap.Help, ¶ms, clap.parsers.default, .{
40 | .diagnostic = &diag,
41 | }) catch |err| {
42 | diag.report(io.getStdErr().writer(), err) catch {};
43 | return err;
44 | };
45 | defer res.deinit();
46 |
47 | // is provided
48 | if(res.positionals.len > 0) {
49 |
50 | // Absolute path to input directory
51 | var project: []const u8 = try std.fs.realpathAlloc(allocator, res.positionals[0]);
52 | defer allocator.free(project);
53 |
54 | // Target string to build for
55 | // example: x86_64-linux
56 | var target: []const u8 = undefined;
57 |
58 | // Absolute output path of the resulting executable
59 | var output: []const u8 = undefined;
60 |
61 | // Whether to use a baseline build of Bun
62 | var baseline: ?[]const u8 = if (res.args.baseline) "baseline" else null;
63 |
64 | // Whether to enable debug mode
65 | var debugMode: bool = false;
66 |
67 | // TODO: Ability to use custom Bun binary
68 | if(res.args.runtime != null) {
69 | debug.print("Custom bun binary is not supported in this version, prebuilt will be used.\n", .{});
70 | }
71 |
72 | // Get build target
73 | if(res.args.target != null) {
74 | target = res.args.target.?;
75 | debug.print("Building for target {s}\n", .{res.args.target.?});
76 | }else {
77 | target = try comptime compiler.getHostTargetString();
78 | debug.print("No target was specified, building for {s}\n", .{target});
79 | }
80 |
81 | if (res.args.baseline) debug.print("Using non-AVX2 (baseline) build of Bun...\n", .{});
82 | if (res.args.debug) {
83 | debugMode = true;
84 | debug.print("Building with Debug mode enabled...\n", .{});
85 | }
86 |
87 | // Get output path
88 | if(res.args.output != null) {
89 | var basename = std.fs.path.basename(res.args.output.?);
90 | var dirname = std.fs.path.dirname(res.args.output.?) orelse ".";
91 | output = try std.mem.concat(allocator, u8, &.{try std.fs.realpathAlloc(allocator, dirname), "/", basename});
92 | }else {
93 | var cwdPath = try std.fs.realpathAlloc(allocator, ".");
94 | defer allocator.free(cwdPath);
95 | output = try std.mem.concat(allocator, u8, &.{cwdPath, "/app"});
96 | }
97 |
98 | // Get configuration
99 | try config.tryLoadConfig(allocator, try std.mem.concat(allocator, u8, &.{project, "/bkg.config.json"}));
100 |
101 | // Whether LTO is enabled
102 | const isLTO = if(res.args.lto) true else if(config.get().lto != null) true else false;
103 |
104 | // List of globs to package as assets into the binary
105 | var includes: [][]const u8 = undefined;
106 |
107 | if(res.args.includes != null and isLTO) {
108 | var iterator = std.mem.split(u8, res.args.includes.?, ",");
109 | var list = std.ArrayList([]const u8).init(allocator);
110 | while(iterator.next()) |glob| {
111 | try list.append(glob);
112 | }
113 | includes = try list.toOwnedSlice();
114 | }else if(isLTO) {
115 | includes = config.get().lto.?.includes;
116 | }
117 |
118 | // Initialize version manager
119 | try versionManager.init(allocator);
120 | defer versionManager.deinit();
121 |
122 | // Make sure we have the latest Bun and bkg runtime for the target
123 | var runtimePath = try versionManager.downloadBun(try versionManager.getLatestBunVersion(), target, baseline);
124 | var bkgRuntimePath = try versionManager.downloadRuntime(try versionManager.getLatestBkgVersion(), target);
125 |
126 | // Initialize LTO
127 | if(isLTO) {
128 | try lto.init(allocator, project, includes);
129 |
130 | std.debug.print("Performing Link-Time Optimizations...\n", .{});
131 | project = try lto.LTO(config.get().entry, config.get().lto.?.format);
132 | }else {
133 | //std.debug.print("Skipping Link-Time Optimizations because it was disabled. It is highly recommended to enable LTO in production builds.\n", .{});
134 | }
135 |
136 | // Build the executable
137 | var out = try compiler.build(allocator, runtimePath, bkgRuntimePath, target, project, output, debugMode);
138 |
139 | // Clean up
140 | if(isLTO) {
141 | std.debug.print("Cleaning up...\n", .{});
142 | try lto.cleanup();
143 | }
144 |
145 | // Finish up
146 | std.debug.print("⚡ Built {s} for target {s}.\n", .{std.fs.path.basename(out), target});
147 |
148 | }
149 | // Parse other CLI flags
150 | else {
151 | // Parse params
152 | if (res.args.help) {
153 | debug.print("{s}\n{s}\n", .{head, paramsStr});
154 | }
155 | else if (res.args.version) {
156 | debug.print("0.0.4\n", .{});
157 | }
158 | else if (res.args.targets) {
159 | debug.print("x86_64-linux\naarch64-linux\nx86_64-macos\naarch64-macos\n", .{});
160 | }
161 | // No param provided, display help
162 | else {
163 | debug.print("{s}\n{s}\n", .{head, paramsStr});
164 | }
165 | }
166 |
167 | }
--------------------------------------------------------------------------------
/src/compiler.zig:
--------------------------------------------------------------------------------
1 | // Archives source files into TAR and compresses with LZ4
2 | const std = @import("std");
3 | const lz4 = @import("translated/lz4hc.zig");
4 | const mtar = @import("translated/libmicrotar.zig");
5 | const builtin = @import("builtin");
6 | const defaultConfig = @import("config.zig").defaultConfig;
7 | const debug = @import("debug.zig");
8 |
9 | // Performs the build process for a given Bun binary, target, project path and output path
10 | pub fn build(allocator: std.mem.Allocator, bunPath: []const u8, bkgPath: []const u8, target: []const u8, project: []const u8, out: []const u8, isDebug: bool) anyerror![]const u8 {
11 |
12 | // Make sure outfile path is not an existing directory
13 | var isDir = std.fs.openDirAbsolute(out, .{}) catch |e| switch(e) {
14 | else => null
15 | };
16 | if(isDir != null) {
17 | std.debug.print("Output path `{s}` is an existing directory. Please use a different name for the binary.\n", .{out});
18 | isDir.?.close();
19 | return error.PathIsDirectory;
20 | }
21 |
22 | // Copy bkg runtime to temporary directory
23 | try std.fs.copyFileAbsolute(bkgPath, out, .{});
24 |
25 | // Build archive and apply compression
26 | try compressArchive(allocator, try buildArchive(allocator, bunPath, project, isDebug), out);
27 |
28 | // Give executable permissions
29 | var file: ?std.fs.File = std.fs.openFileAbsolute(out, .{}) catch |e| switch(e) {
30 | else => null
31 | };
32 | if(file != null) {
33 | try file.?.chmod(0o777);
34 | file.?.close();
35 | }else {
36 | std.debug.print("Could not mark binary as executable. Run `chmod +x {s}` to do it manually.\n", .{std.fs.path.basename(out)});
37 | }
38 |
39 | _ = target;
40 | return out;
41 |
42 | }
43 |
44 | // Builds a TAR archive given a root directory
45 | pub fn buildArchive(allocator: std.mem.Allocator, bun_path: []const u8, root: []const u8, isDebug: bool) ![]u8 {
46 |
47 | std.debug.print("Building archive...\n", .{});
48 |
49 | // Allocate 512 MiB for storing compressed buffer
50 | var buffer = try allocator.alloc(u8, 512 * 1024 * 1024);
51 |
52 | // TAR archive
53 | var tar = try allocator.create(mtar.mtar_t);
54 | var memStream = try allocator.create(mtar.mtar_mem_stream_t);
55 | defer allocator.destroy(tar);
56 | defer allocator.destroy(memStream);
57 |
58 | tar.* = std.mem.zeroes(mtar.mtar_t);
59 | memStream.* = std.mem.zeroes(mtar.mtar_mem_stream_t);
60 | _ = mtar.mtar_init_mem_stream(memStream, buffer.ptr, buffer.len);
61 | _ = mtar.mtar_open_mem(tar, memStream);
62 |
63 | // Recursively search for files
64 | var dir = try std.fs.openIterableDirAbsolute(root, .{});
65 | defer dir.close();
66 | var walker = try dir.walk(allocator);
67 | defer walker.deinit();
68 |
69 | // Whether bkg.config.json was found while walking
70 | var customConfig = false;
71 |
72 | // Add sources to archive
73 | while (try walker.next()) |entry| {
74 | // Handle directories
75 | if(entry.kind == .Directory) {
76 | std.debug.print("Writing directory {s}\n", .{entry.path});
77 | _ = mtar.mtar_write_dir_header(tar, (try allocator.dupeZ(u8, entry.path)).ptr);
78 | continue;
79 | }
80 |
81 | // Check if custom config file is present
82 | if(std.mem.eql(u8, entry.path, "bkg.config.json")) customConfig = true;
83 |
84 | // Read source into buffer
85 | var file = std.fs.openFileAbsolute(try std.mem.concat(allocator, u8, &.{root, "/", entry.path}), .{}) catch |e| {
86 | std.debug.print("Could not open {s}: {any}. Skipping...\n", .{entry.path, e});
87 | continue;
88 | };
89 | const buf: [:0]u8 = try file.readToEndAllocOptions(allocator, 1024 * 1024 * 1024, null, @alignOf(u8), 0);
90 | const mode = try file.mode();
91 |
92 | if(mode & 0o100 == 0o100) {
93 | std.debug.print("{s} is executable\n", .{entry.path});
94 | }
95 |
96 | std.debug.print("Writing file {s} with {any} bytes\n", .{entry.path, @intCast(c_uint, buf.len)});
97 |
98 | // Write buffer to archive
99 | _ = mtar.mtar_write_file_header(tar, (try allocator.dupeZ(u8, entry.path)).ptr, @intCast(c_uint, buf.len));
100 | _ = mtar.mtar_write_data(tar, buf.ptr, @intCast(c_uint, buf.len));
101 |
102 | // Close & free memory for this file
103 | allocator.free(buf);
104 | file.close();
105 | }
106 |
107 | // If no custom config is present, add default config to archive
108 | if(customConfig == false) {
109 | std.debug.print("Configuration file not found, using default\n", .{});
110 |
111 | var newConfig = defaultConfig;
112 | if(isDebug) newConfig.debug = true;
113 |
114 | var configString = try std.json.stringifyAlloc(allocator, newConfig, .{});
115 | defer allocator.free(configString);
116 |
117 | _ = mtar.mtar_write_file_header(tar, "bkg.config.json", @intCast(c_uint, configString.len));
118 | _ = mtar.mtar_write_data(tar, configString.ptr, @intCast(c_uint, configString.len));
119 | }
120 |
121 | // Add Bun binary to archive
122 | {
123 | std.debug.print("Adding Bun binary...\n", .{});
124 | var bun = try std.fs.openFileAbsolute(bun_path, .{});
125 | const bunBuf: []u8 = try bun.readToEndAlloc(allocator, 256 * 1024 * 1024);
126 |
127 | _ = mtar.mtar_write_file_header(tar, "bkg_bun", @intCast(c_uint, bunBuf.len));
128 | _ = mtar.mtar_write_data(tar, bunBuf.ptr, @intCast(c_uint, bunBuf.len));
129 |
130 | allocator.free(bunBuf);
131 | bun.close();
132 | }
133 |
134 | // Finalize the archive
135 | _ = mtar.mtar_finalize(tar);
136 | _ = mtar.mtar_close(tar);
137 |
138 | std.debug.print("Finalized archive\n", .{});
139 |
140 | return buffer[0..memStream.pos];
141 |
142 | }
143 |
144 | // Applies LZ4 compression on given TAR archive
145 | pub fn compressArchive(allocator: std.mem.Allocator, buf: []u8, target: []const u8) !void {
146 |
147 | std.debug.print("Compressing archive...\n", .{});
148 |
149 | // Allocate 512 MiB buffer for storing compressed archive
150 | var compressed: []u8 = try allocator.alloc(u8, 512 * 1024 * 1024);
151 | defer allocator.free(compressed);
152 |
153 | // Perform LZ4 HC compression with compression level 12 (max)
154 | var compSize = lz4.LZ4_compress_HC(buf.ptr, compressed.ptr, @intCast(c_int, buf.len), 512 * 1024 * 1024, @intCast(c_int, 12));
155 |
156 | std.debug.print("Compressed to {} bytes\n", .{compSize});
157 |
158 | // Calculate CRC32 Hash from the LZ4 compressed buffer
159 | // This is added to the binary and prevents outdated cached code from
160 | // stopping an updated executable extracting new code.
161 | var hashFunc = std.hash.Crc32.init();
162 | hashFunc.update(compressed[0..@intCast(usize, compSize)]);
163 | var hash = hashFunc.final();
164 |
165 | std.debug.print("Calculated CRC32 hash: {any}\n", .{hash});
166 |
167 | var file = try std.fs.openFileAbsolute(target, .{.mode = .read_write});
168 | defer file.close();
169 |
170 | // Seek to end of binary
171 | var stat = try file.stat();
172 | try file.seekTo(stat.size);
173 |
174 | std.debug.print("Writing archive to binary...\n", .{});
175 |
176 | // Write compressed archive to binary
177 | _ = try file.writeAll(compressed[0..@intCast(usize, compSize)]);
178 | std.debug.print("Written {} bytes to binary\n", .{compSize});
179 |
180 | // Write CRC32 hash + compressed size (10 + 10) bytes at the end
181 | {
182 | std.debug.print("Finalizing binary...\n", .{});
183 | var compSizeBuffer: []u8 = try std.fmt.allocPrint(allocator, "{d}", .{compSize});
184 | var hashBuffer: []u8 = try std.fmt.allocPrint(allocator, "{d}", .{hash});
185 | var compSizeBuf10 = try allocator.alloc(u8, 10);
186 | var hashBuf10 = try allocator.alloc(u8, 10);
187 | defer allocator.free(compSizeBuffer);
188 | defer allocator.free(hashBuffer);
189 |
190 | // Fill empty bytes with 0s
191 | for(compSizeBuf10[0..10]) |_, i| {
192 | if(i >= compSizeBuffer.len) { compSizeBuf10[i] = 0; }
193 | else { compSizeBuf10[i] = compSizeBuffer[i]; }
194 | }
195 | for(hashBuf10[0..10]) |_, i| {
196 | if(i >= hashBuffer.len) { hashBuf10[i] = 0; }
197 | else { hashBuf10[i] = hashBuffer[i]; }
198 | }
199 |
200 | _ = try file.writeAll(hashBuf10);
201 | _ = try file.writeAll(compSizeBuf10);
202 | }
203 |
204 | std.debug.print("Done\n", .{});
205 |
206 | // Free compressed buffer
207 | allocator.free(buf);
208 |
209 | }
210 |
211 | // Creates and returns a standard target string for Host OS
212 | pub fn getHostTargetString() ![]const u8 {
213 | const tag = builtin.target.os.tag;
214 | const arch = builtin.target.cpu.arch;
215 |
216 | var tagStr = switch(tag) {
217 | .windows => "windows",
218 | .linux => "linux",
219 | .macos => "macos",
220 | else => return error.UnknownOs
221 | };
222 |
223 | var archStr = switch(arch) {
224 | .aarch64 => "aarch64",
225 | .x86_64 => "x86_64",
226 | else => return error.UnknownCpu
227 | };
228 |
229 | const target = archStr ++ "-" ++ tagStr;
230 | return target;
231 | }
--------------------------------------------------------------------------------
/src/analyzer.zig:
--------------------------------------------------------------------------------
1 | // Analyzes sources and node_modules to find and collect native/pure modules
2 | // Used in conjunction with the optimizer to enable link-time optimizations
3 | const std = @import("std");
4 | const debug = @import("debug.zig");
5 |
6 | // TODO: This may be incomplete
7 | pub const NativeExtensions = [_][]const u8{"*.node", "*.so", "*.so.*", "*.dll", "*.exe", "*.dylib"};
8 |
9 | const Module = struct {
10 | type: []const u8, // "native" or "pure"
11 | path: []const u8, // import-able path of the module
12 | name: []const u8, // name of the module
13 | main: []const u8, // Main entrypoint of package
14 | deps: []*const Module // list of dependencies
15 | };
16 |
17 | const PackageJSON = struct {
18 | main: []const u8 = "index.js",
19 | deps: [][]const u8,
20 | name: []const u8
21 | };
22 |
23 | // Central repository of all modules
24 | var modules: std.ArrayList(Module) = undefined;
25 |
26 | pub fn init(allocator: std.mem.Allocator) !void {
27 | modules = std.ArrayList(Module).init(allocator);
28 | }
29 |
30 | // Analyzer
31 | pub fn analyze(allocator: std.mem.Allocator, root: []const u8) !*const std.ArrayList(Module) {
32 | var dir = std.fs.openIterableDirAbsolute(root, .{}) catch |e| switch (e) {
33 | error.FileNotFound => {
34 | // node_modules is absent, this project has no dependencies
35 | return &modules;
36 | },
37 | else => return e
38 | };
39 | defer dir.close();
40 | var walker = try dir.walk(allocator);
41 |
42 | // Register all packages without dependencies
43 | while (try walker.next()) |entry| {
44 | const basename = std.fs.path.basename(entry.path);
45 |
46 | if(entry.kind != .Directory and std.mem.eql(u8, basename, "package.json")) {
47 | const path = entry.path[0..(entry.path.len - basename.len - 1)];
48 | const parsed = try parsePackage(allocator, root, entry.path);
49 | const name = if (parsed.name.len == 0) std.fs.path.basename(path) else parsed.name;
50 | const modtype = try analyzeModule(allocator, try std.mem.concat(allocator, u8, &.{root, "/", path}));
51 |
52 | var deps = std.ArrayList(*const Module).init(allocator);
53 |
54 | // Register the module to store
55 | try modules.append(Module{
56 | .type = modtype,
57 | .path = try allocator.dupe(u8, path),
58 | .name = try allocator.dupe(u8, name),
59 | .main = try allocator.dupe(u8, parsed.main),
60 | .deps = try deps.toOwnedSlice()
61 | });
62 | }
63 | }
64 | walker.deinit();
65 |
66 | // Parse every registered module and populate its dependencies
67 | for(modules.items[0..modules.items.len]) |module, i| {
68 | const parsed = try parsePackage(allocator, root, try std.mem.concat(allocator, u8, &.{module.path, "/package.json"}));
69 | var depsArrayList = std.ArrayList(*const Module).init(allocator);
70 |
71 | for(parsed.deps[0..parsed.deps.len]) |dep| {
72 | var depPtr = getModulePtr(dep) catch |e| switch(e) {
73 | error.ModuleNotFound => {
74 | // We don't want a missing module to break LTO completely
75 | // Some packages (eg: resolve) have tests to intentionally have missing modules
76 | std.debug.print("Module `{s}` has missing dependency: `{s}`. Skipping..\n", .{module.name, dep});
77 | continue;
78 | },
79 | else => return e
80 | };
81 | try depsArrayList.append(depPtr);
82 | }
83 |
84 | const replaceModule = Module{
85 | .type = module.type,
86 | .path = module.path,
87 | .name = module.name,
88 | .main = module.main,
89 | .deps = try depsArrayList.toOwnedSlice()
90 | };
91 |
92 | try modules.replaceRange(i, 1, &.{replaceModule});
93 | }
94 |
95 | return &modules;
96 | }
97 |
98 | // Gets a pointer to a module stored in repository
99 | pub fn getModulePtr(path: []const u8) !*const Module {
100 | for(modules.items[0..modules.items.len]) |module, i| {
101 | if(std.mem.eql(u8, module.path, path)) return &modules.items[i];
102 | }
103 | return error.ModuleNotFound;
104 | }
105 |
106 | // Analyzes a modules directory to find whether it is "native" or "pure"
107 | pub fn analyzeModule(allocator: std.mem.Allocator, path: []const u8) ![]const u8 {
108 | var dir = try std.fs.openIterableDirAbsolute(path, .{});
109 | defer dir.close();
110 | var walker = try dir.walk(allocator);
111 | defer walker.deinit();
112 |
113 | while (try walker.next()) |entry| {
114 | if(entry.kind == .Directory) continue;
115 | //const fullPath = try std.mem.concat(allocator, u8, &.{path, "/", entry.path});
116 | const basename = std.fs.path.basename(entry.path);
117 | //const stat = try std.fs.cwd().statFile(fullPath);
118 | //defer allocator.free(fullPath);
119 |
120 | // TODO: Modules having executable files are native
121 | //if(stat.mode & 0o100 == 0o100) return "native";
122 |
123 | inline for(NativeExtensions[0..NativeExtensions.len]) |ext| {
124 | if(globMatchComptime(ext, basename)) return "native";
125 | }
126 | }
127 |
128 | return "pure";
129 | }
130 |
131 | // Parses a modules package.json
132 | pub fn parsePackage(allocator: std.mem.Allocator, root: []const u8, path: []const u8) !PackageJSON {
133 | // Open package.json
134 | var file = std.fs.openFileAbsolute(std.mem.concat(allocator, u8, &.{root, "/", path}) catch |e| @panic(@errorName(e)), .{}) catch |e| @panic(@errorName(e));
135 | defer file.close();
136 |
137 | // Read into buffer
138 | // package.json should not exceed 32 KiB
139 | const buf = file.readToEndAlloc(allocator, 32 * 1024) catch |e| @panic(@errorName(e));
140 |
141 | // Parse the JSON payload
142 | var parser = std.json.Parser.init(allocator, false);
143 | var tree: ?std.json.ValueTree = parser.parse(buf) catch |e| switch (e) {
144 | error.UnexpectedEndOfJson => null,
145 | else => return e
146 | };
147 |
148 | // We don't want a malformed package.json to stop the LTO process
149 | // Moreover, some packages (eg: resolve) intentionally have malformed JSON for testing
150 | if(tree == null) {
151 | std.debug.print("{s} has malformed JSON. Skipping..\n", .{path});
152 | return PackageJSON{
153 | .name = "",
154 | .main = "index.js",
155 | .deps = &.{}
156 | };
157 | }
158 |
159 | var deps = tree.?.root.Object.get("dependencies");
160 | var main = tree.?.root.Object.get("main");
161 | var pkgName = tree.?.root.Object.get("name");
162 | var depsArray: [][]const u8 = undefined;
163 |
164 | // Strings guaranteed to be valid
165 | var mainStr: []const u8 = undefined;
166 | var pkgNameStr: []const u8 = undefined;
167 |
168 | // Validate fields
169 | if(main != null and (switch(main.?) {.String => true, else => false })) { mainStr = main.?.String; }
170 | else { mainStr = "index.js"; }
171 | if(pkgName != null and (switch(pkgName.?) {.String => true, else => false })) { pkgNameStr = pkgName.?.String; }
172 | else { pkgNameStr = ""; }
173 |
174 |
175 | if(deps == null or deps.?.Object.count() == 0) {
176 | depsArray = &.{};
177 | }else {
178 | var iterator = deps.?.Object.iterator();
179 | var depsArrayList = std.ArrayList([]const u8).init(allocator);
180 |
181 | while(iterator.next()) |entry| {
182 | try depsArrayList.append(entry.key_ptr.*);
183 | }
184 |
185 | depsArray = try depsArrayList.toOwnedSlice();
186 | }
187 |
188 | return PackageJSON{
189 | .name = pkgNameStr,
190 | .main = mainStr,
191 | .deps = depsArray
192 | };
193 | }
194 |
195 | // Checks if a path is a module
196 | pub fn isModule(allocator: std.mem.Allocator, path: []const u8) !bool {
197 | var file: ?std.fs.File = std.fs.openFileAbsolute(try std.mem.concat(allocator, u8, &.{path, "/package.json"}), .{}) catch |e| switch (e) {
198 | error.FileNotFound => null,
199 | error.NotDir => null,
200 | else => return e
201 | };
202 |
203 | if(file == null) {
204 | return false;
205 | }else {
206 | file.?.close();
207 | return true;
208 | }
209 | }
210 |
211 | // Tests a path string against a glob pattern
212 | pub fn globMatch(pattern: []const u8, str: []const u8) bool {
213 | if (std.mem.eql(u8, pattern, "*")) return true;
214 |
215 | var i: usize = 0;
216 | var it = std.mem.tokenize(u8, pattern, "*");
217 | var exact_begin = pattern.len > 0 and pattern[0] != '*';
218 |
219 | while (it.next()) |substr| {
220 | if (std.mem.indexOf(u8, str[i..], substr)) |j| {
221 | if (exact_begin) {
222 | if (j != 0) return false;
223 | exact_begin = false;
224 | }
225 |
226 | i += j + substr.len;
227 | } else return false;
228 | }
229 |
230 | return if (pattern[pattern.len - 1] == '*') true else i == str.len;
231 | }
232 |
233 | // Comptime variant of globMatch
234 | pub fn globMatchComptime(comptime pattern: []const u8, str: []const u8) bool {
235 | comptime if (std.mem.eql(u8, pattern, "*")) return true;
236 |
237 | var i: usize = 0;
238 | comptime var it = std.mem.tokenize(u8, pattern, "*");
239 | var exact_begin = comptime pattern.len > 0 and pattern[0] != '*';
240 |
241 | inline while (comptime it.next()) |substr| {
242 | if (std.mem.indexOf(u8, str[i..], substr)) |j| {
243 | if (exact_begin) {
244 | if (j != 0) return false;
245 | exact_begin = false;
246 | }
247 |
248 | i += j + substr.len;
249 | } else return false;
250 | }
251 |
252 | return comptime if (pattern[pattern.len - 1] == '*') true else i == str.len;
253 | }
--------------------------------------------------------------------------------
/src/version_manager.zig:
--------------------------------------------------------------------------------
1 | // Manager for bun binaries
2 | // Handles binaries for multiple architectures and their versions
3 | const std = @import("std");
4 | const json = std.json;
5 | const knownFolders = @import("known-folders");
6 | const zip = @import("translated/libzip.zig");
7 | const zfetch = @import("zfetch");
8 | const debug = @import("debug.zig");
9 |
10 | // GitHub API URL for fetching latest Bun & bkg releases
11 | const bunLatestAPI = "https://api.github.com/repos/oven-sh/bun/releases/latest";
12 | const bkgLatestAPI = "https://api.github.com/repos/theseyan/bkg/releases/latest";
13 |
14 | // Holds the allocator
15 | var vmAllocator: std.mem.Allocator = undefined;
16 |
17 | // We only need tag_name from API JSON response
18 | pub const APIReleaseTag = struct{
19 | tag_name: []const u8
20 | };
21 |
22 | // Initialize Version Manager
23 | // Inits zfetch, makes sure .bkg directory exists
24 | pub fn init(allocator: std.mem.Allocator) anyerror!void {
25 |
26 | // Save pointer to allocator
27 | vmAllocator = allocator;
28 |
29 | // .bkg directory present in home directory
30 | const homeDir = (try knownFolders.getPath(vmAllocator, knownFolders.KnownFolder.home)) orelse @panic("Failed to get path to home directory.");
31 | const bkgDir = try std.mem.concat(vmAllocator, u8, &.{homeDir, "/.bkg"});
32 |
33 | // Check if bkg root exists
34 | _ = std.fs.openDirAbsolute(bkgDir, .{}) catch |e| {
35 | if(e == error.FileNotFound) {
36 | // Create bkg root
37 | try std.fs.makeDirAbsolute(bkgDir);
38 | }
39 | };
40 |
41 | // Initialize zfetch
42 | try zfetch.init();
43 |
44 | }
45 |
46 | // De-initializes Version Manager
47 | pub fn deinit() void {
48 |
49 | zfetch.deinit();
50 |
51 | }
52 |
53 | // Custom downloader that respects HTTP 3xx redirects
54 | pub fn download(url: []const u8, path: []const u8) !usize {
55 |
56 | // Init headers and request
57 | var headers = zfetch.Headers.init(vmAllocator);
58 | defer headers.deinit();
59 | var req = try zfetch.Request.init(vmAllocator, url, null);
60 | defer req.deinit();
61 |
62 | // Perform request
63 | try headers.appendValue("Accept", "application/octet-stream");
64 | try headers.appendValue("User-Agent", "theseyan/bkg");
65 | try req.do(.GET, headers, null);
66 |
67 | // Follow 3xx redirects
68 | if (req.status.code > 300 and req.status.code < 400) {
69 | var locationHeader = req.headers.search("Location");
70 | return download(locationHeader.?.value, path);
71 | }
72 | // If status is neither 200 or 3xx
73 | else if(req.status.code != 200) {
74 | return error.DownloadFailed;
75 | }
76 |
77 | // Create file on disk
78 | const file = try std.fs.createFileAbsolute(path, .{});
79 | const writer = file.writer();
80 | const reader = req.reader();
81 |
82 | // Write download buffer to file
83 | var size: usize = 0;
84 | var buf: [65535]u8 = undefined;
85 | while (true) {
86 | const read = try reader.read(&buf);
87 | if (read == 0) break;
88 | size += read;
89 | try writer.writeAll(buf[0..read]);
90 | }
91 |
92 | return size;
93 |
94 | }
95 |
96 | // Custom fetch that respects 3xx redirects
97 | // Returns a buffer that must be freed manually
98 | pub fn fetch(url: []const u8) ![]const u8 {
99 |
100 | // Init headers and request
101 | var headers = zfetch.Headers.init(vmAllocator);
102 | defer headers.deinit();
103 | var req = try zfetch.Request.init(vmAllocator, url, null);
104 | defer req.deinit();
105 |
106 | // Perform request
107 | try headers.appendValue("Accept", "*/*");
108 | try headers.appendValue("User-Agent", "theseyan/bkg");
109 | try req.do(.GET, headers, null);
110 |
111 | // Follow 3xx redirects
112 | if (req.status.code > 300 and req.status.code < 400) {
113 | var locationHeader = req.headers.search("Location");
114 | return fetch(locationHeader.?.value);
115 | }
116 | // If status is neither 200 or 3xx
117 | else if(req.status.code != 200) {
118 | return error.FetchFailed;
119 | }
120 |
121 | // Read response buffer
122 | const reader = req.reader();
123 | const buffer = try reader.readAllAlloc(vmAllocator, 8 * 1024 * 1024); // Response body should not exceed 8 MiB
124 |
125 | return buffer;
126 |
127 | }
128 |
129 | // Fetches the latest release tag from Bun's official GitHub repo
130 | // example: bun-v0.1.7
131 | pub fn getLatestBunVersion() anyerror![]const u8 {
132 |
133 | var response_buffer = try fetch(bunLatestAPI);
134 | defer vmAllocator.free(response_buffer);
135 |
136 | // Parse JSON
137 | var config: APIReleaseTag = x: {
138 | var stream = json.TokenStream.init(response_buffer);
139 | const res = json.parse(APIReleaseTag, &stream, .{.allocator = vmAllocator, .ignore_unknown_fields = true});
140 | break :x res catch |e| {
141 | std.debug.print("Error while parsing JSON: {}\n", .{e});
142 | return error.ErrorParsingJSON;
143 | };
144 | };
145 |
146 | return config.tag_name;
147 |
148 | }
149 |
150 | // Downloads Bun binary for a given version and platform
151 | // Returns immediately if the binary already exists
152 | // example: bun-v0.1.8, aarch64-linux
153 | pub fn downloadBun(version: []const u8, arch: []const u8, specifier: ?[]const u8) anyerror![]const u8 {
154 |
155 | std.debug.print("Downloading {s} for target {s}...\n", .{version, arch});
156 |
157 | // Construct URL to bun release
158 | const postfix = if(specifier == null) try getBunTargetString(arch) else try std.mem.concat(vmAllocator, u8, &.{try getBunTargetString(arch), "-", specifier.?});
159 | var releaseUrl = try std.mem.concat(vmAllocator, u8, &.{"https://github.com/oven-sh/bun/releases/download/", version, "/bun-", postfix, ".zip"});
160 |
161 | const homeDir = (try knownFolders.getPath(vmAllocator, knownFolders.KnownFolder.home)) orelse @panic("Failed to get path to home directory.");
162 | const runtimeDir = try std.mem.concat(vmAllocator, u8, &.{homeDir, "/.bkg/runtime"});
163 |
164 | // Formatted as {tag}-{target}/bun-{target}/bun
165 | // example: bun-v0.1.8-linux-x64/bun-x64-linux/bun
166 | const bunPath = try std.mem.concat(vmAllocator, u8, &.{homeDir, "/.bkg/runtime/", version, "-", postfix, "/bun-", postfix, "/bun"});
167 | const bunZipPath = try std.mem.concatWithSentinel(vmAllocator, u8, &.{homeDir, "/.bkg/runtime/", version, "-", postfix, ".zip"}, 0);
168 | const extractDir = try std.mem.concatWithSentinel(vmAllocator, u8, &.{runtimeDir, "/", version, "-", postfix}, 0);
169 |
170 | // Create /runtime directory if it doesn't already exist
171 | _ = std.fs.openDirAbsolute(runtimeDir, .{}) catch |e| {
172 | if(e == error.FileNotFound) try std.fs.makeDirAbsolute(runtimeDir);
173 | };
174 |
175 | // Check if the binary already exists
176 | const bin: ?std.fs.File = std.fs.openFileAbsolute(bunPath, .{}) catch |err| switch (err) {
177 | error.FileNotFound => null,
178 | else => return err,
179 | };
180 |
181 | // Return if it already exists
182 | if (bin) |f| {
183 | f.close();
184 | std.debug.print("Runtime already exists, skipping\n", .{});
185 | return bunPath;
186 | }
187 |
188 | // Write to file
189 | var written = try download(releaseUrl, bunZipPath);
190 | std.debug.print("Downloaded {any} bytes to disk\n", .{written});
191 | std.debug.print("Extracting to {s}...\n", .{extractDir});
192 |
193 | // Extract the zip archive
194 | var arg: c_int = 2;
195 | _ = zip.zip_extract(bunZipPath.ptr, extractDir.ptr, zip_extract_entry, &arg);
196 |
197 | // Delete the archive since it's no longer needed
198 | try std.fs.deleteFileAbsolute(bunZipPath);
199 |
200 | return bunPath;
201 |
202 | }
203 |
204 | // Fetches the latest release tag from bkg's GitHub repo
205 | // example: v0.0.1
206 | pub fn getLatestBkgVersion() anyerror![]const u8 {
207 |
208 | var response_buffer = try fetch(bkgLatestAPI);
209 | defer vmAllocator.free(response_buffer);
210 |
211 | // Parse JSON
212 | var config: APIReleaseTag = x: {
213 | var stream = json.TokenStream.init(response_buffer);
214 | const res = json.parse(APIReleaseTag, &stream, .{.allocator = vmAllocator, .ignore_unknown_fields = true});
215 | break :x res catch |e| {
216 | std.debug.print("Error while parsing JSON: {}\n", .{e});
217 | return error.ErrorParsingJSON;
218 | };
219 | };
220 |
221 | return config.tag_name;
222 |
223 | }
224 |
225 | // Downloads bkg runtime binary for a given version and platform
226 | // Returns immediately if the binary already exists
227 | // example: v0.0.1, aarch64-linux
228 | pub fn downloadRuntime(version: []const u8, arch: []const u8) anyerror![]const u8 {
229 |
230 | const homePath = (try knownFolders.getPath(vmAllocator, knownFolders.KnownFolder.home)) orelse return error.CannotGetHomePath;
231 | const runtimePath = try std.mem.concat(vmAllocator, u8, &.{homePath, "/.bkg/bkg_runtime/", arch, "/bkg_runtime-", version});
232 | const runtimeDir = try std.mem.concat(vmAllocator, u8, &.{homePath, "/.bkg/bkg_runtime"});
233 |
234 | std.debug.print("Downloading bkg runtime {s} for target {s}...\n", .{version, arch});
235 |
236 | // Construct URL to download release
237 | var releaseUrl = try std.mem.concat(vmAllocator, u8, &.{"https://github.com/theseyan/bkg/releases/download/", version, "/bkg_runtime-", version, "-", arch});
238 |
239 | // Create /bkg_runtime and {arch} directory if it doesn't already exist
240 | _ = std.fs.openDirAbsolute(runtimeDir, .{}) catch |e| {
241 | if(e == error.FileNotFound) try std.fs.makeDirAbsolute(runtimeDir);
242 | };
243 | _ = std.fs.openDirAbsolute(try std.mem.concat(vmAllocator, u8, &.{runtimeDir, "/", arch}), .{}) catch |e| {
244 | if(e == error.FileNotFound) try std.fs.makeDirAbsolute(try std.mem.concat(vmAllocator, u8, &.{runtimeDir, "/", arch}));
245 | };
246 |
247 | // Check if the binary already exists
248 | const bin: ?std.fs.File = std.fs.openFileAbsolute(runtimePath, .{}) catch |err| switch (err) {
249 | error.FileNotFound => null,
250 | else => return err,
251 | };
252 |
253 | // Return if it already exists
254 | if (bin) |f| {
255 | f.close();
256 | std.debug.print("bkg runtime already exists, skipping\n", .{});
257 | return runtimePath;
258 | }
259 |
260 | // Download the file
261 | const written = try download(releaseUrl, runtimePath);
262 | std.debug.print("Downloaded {any} bytes to disk\n", .{written});
263 |
264 | return runtimePath;
265 |
266 | }
267 |
268 | // Placeholder callback for zip_extract
269 | fn zip_extract_entry(_: [*c]const u8, _: ?*anyopaque) callconv(.C) c_int {
270 | return 0;
271 | }
272 |
273 | // Returns a Bun target string from a standard one
274 | pub fn getBunTargetString(target: []const u8) ![]const u8 {
275 |
276 | if(std.mem.eql(u8, target, "x86_64-linux")) {
277 | return "linux-x64";
278 | }else if(std.mem.eql(u8, target, "aarch64-linux")) {
279 | return "linux-aarch64";
280 | }else if(std.mem.eql(u8, target, "x86_64-macos")) {
281 | return "darwin-x64";
282 | }else if(std.mem.eql(u8, target, "aarch64-macos")) {
283 | return "darwin-aarch64";
284 | }else {
285 | return error.UnknownTarget;
286 | }
287 |
288 | }
--------------------------------------------------------------------------------
/src/lto.zig:
--------------------------------------------------------------------------------
1 | // Combines the analyzer and optimizer to perform Link Time Optimizations (LTO)
2 |
3 | const std = @import("std");
4 | const optimizer = @import("optimizer.zig");
5 | const analyzer = @import("analyzer.zig");
6 | const debug = @import("debug.zig");
7 |
8 | var allocator: std.mem.Allocator = undefined;
9 | var root: []const u8 = undefined;
10 | var tempDir: []const u8 = undefined;
11 | var includes: [][]const u8 = &.{};
12 |
13 | // Modules marked as external
14 | // They will not be optimized
15 | var externals: std.ArrayList([]const u8) = undefined;
16 |
17 | // External modules with all pure dependencies
18 | // They can be optimized in place
19 | var leafModules: std.ArrayList([]const u8) = undefined;
20 |
21 | // Some modules, although being dynamic, can mostly function even when bundled
22 | // This is an inexhaustible list of such exceptions
23 | pub const AllowedDynamicModules = [_][]const u8{"express"};
24 |
25 | // Force modules to be marked external, even if they are pure
26 | pub const ForcedExternalModules = [_][]const u8{};
27 |
28 | pub fn init(alloc: std.mem.Allocator, rootDir: []const u8, includesArray: [][]const u8) !void {
29 | try analyzer.init(alloc);
30 | allocator = alloc;
31 | root = rootDir;
32 | includes = includesArray;
33 |
34 | // Create temporary build directory
35 | tempDir = try createTempBuildDir();
36 | }
37 |
38 | // Performs LTO on an entrypoint
39 | pub fn LTO(entry: []const u8, format: []const u8) ![]const u8 {
40 |
41 | // Mark externals and leaf modules
42 | try markExternals(entry, format);
43 |
44 | // Optimize every leaf module in-place
45 | for(leafModules.items[0..leafModules.items.len]) |leaf| {
46 | std.debug.print("Optimizing leaf `{s}` in-place...\n", .{leaf});
47 | const entrypoint = try analyzer.getModulePtr(leaf);
48 | try optimizer.optimizePureModuleToDisk(allocator, leaf, try std.mem.concat(allocator, u8, &.{root, "/node_modules/", leaf, "/", entrypoint.main}), tempDir);
49 | }
50 |
51 | // Copy every external module
52 | for(externals.items[0..externals.items.len]) |external| {
53 | std.debug.print("Copying external `{s}`...\n", .{external});
54 | try optimizer.copyModuleToDisk(allocator, root, external, tempDir);
55 | }
56 |
57 | // Copy included assets
58 | std.debug.print("Copying assets...\n", .{});
59 | var dir = try std.fs.openIterableDirAbsolute(root, .{});
60 | defer dir.close();
61 | var walker = try dir.walk(allocator);
62 |
63 | while (try walker.next()) |file| {
64 | if(file.kind == .Directory) continue;
65 | for(includes[0..includes.len]) |glob| {
66 | if(analyzer.globMatch(glob, file.path)) {
67 | const basename = std.fs.path.basename(file.path);
68 |
69 | // Make sure directory exists
70 | try std.fs.cwd().makePath(try std.mem.concat(allocator, u8, &.{tempDir, "/", file.path[0..(file.path.len - basename.len - 1)]}));
71 |
72 | std.debug.print("Copying `{s}`...\n", .{file.path});
73 |
74 | // Copy the file
75 | try std.fs.copyFileAbsolute(try std.mem.concat(allocator, u8, &.{root, "/", file.path}), try std.mem.concat(allocator, u8, &.{tempDir, "/", file.path}), .{});
76 | }
77 | }
78 | }
79 |
80 | // Optimize application entrypoint
81 | std.debug.print("Optimizing entrypoint...\n", .{});
82 | const externalsString = try std.mem.concat(allocator, u8, &.{try std.mem.join(allocator, ",", externals.items), ","});
83 | var result = try optimizer.optimize(allocator, try std.mem.concat(allocator, u8, &.{root, "/", entry}), try std.mem.concat(allocator, u8, &.{tempDir, "/index.js"}), format, externalsString);
84 |
85 | if(result.status == .Failure) {
86 | return error.LTOFailedOptimizeEntrypoint;
87 | }else if(result.status == .Warning) {
88 | for(result.warnings[0..result.warnings.len]) |warning| {
89 | debug.warn("Warning: `{?s}` [{?s}:{?d}:{?d}]\n{s}", .{warning.Location.?.LineText, warning.Location.?.File, warning.Location.?.Line, warning.Location.?.Column, warning.Text});
90 | }
91 | }
92 |
93 | std.debug.print("Bundled and optimized application code ({any} KiB)!\n", .{@divTrunc(result.meta.bundleSize, 1024)});
94 | return tempDir;
95 |
96 | }
97 |
98 | // Cleans up build artifacts generated during LTO
99 | pub fn cleanup() !void {
100 | try std.fs.cwd().deleteTree(tempDir);
101 | }
102 |
103 | // Creates a temporary directory for storing build assets
104 | // Should be deleted after compilation
105 | fn createTempBuildDir() ![]const u8 {
106 | var timeBuffer: []u8 = try allocator.alloc(u8, 13);
107 | var timeBufferStream = std.io.fixedBufferStream(timeBuffer);
108 | defer allocator.free(timeBuffer);
109 |
110 | try std.fmt.format(timeBufferStream.writer(), "{}", .{std.time.milliTimestamp()});
111 | var path = try std.mem.concat(allocator, u8, &.{"/tmp/.__bkg-build-", timeBuffer});
112 | try std.fs.makeDirAbsolute(path);
113 |
114 | return path;
115 | }
116 |
117 | // Statically analyzes node_modules to find native modules
118 | // Gets dynamic modules and marks external modules
119 | pub fn markExternals(entry: []const u8, format: []const u8) !void {
120 |
121 | const nodeModules = try std.mem.concat(allocator, u8, &.{root, "/node_modules"});
122 | const entryAbsolute = try std.mem.concat(allocator, u8, &.{root, "/", entry});
123 |
124 | // Run static analyzer
125 | var modules = try analyzer.analyze(allocator, nodeModules);
126 |
127 | // Mark all dynamic and native modules as external
128 | externals = std.ArrayList([]const u8).init(allocator);
129 | leafModules = std.ArrayList([]const u8).init(allocator);
130 |
131 | // Mark forced external modules
132 | inline for(ForcedExternalModules[0..ForcedExternalModules.len]) |module| {
133 | recursiveMark(module);
134 | }
135 |
136 | // Mark native modules
137 | for(modules.items[0..modules.items.len]) |module| {
138 | if(std.mem.eql(u8, module.type, "native")) {
139 | recursiveMark(module.name);
140 | }
141 | }
142 |
143 | // Mark dynamic modules
144 | var dynamicModules = getDynamicModules(entryAbsolute, format) catch |e| switch(e) {
145 | error.SourceIsDynamic => {
146 | debug.err("Error: Dynamic require/import found in source code! bkg is unable optimize this with LTO, please rewrite it to a static import or disable LTO with `--nolto` flag.", .{});
147 | return e;
148 | },
149 | else => return e
150 | };
151 |
152 | for(dynamicModules[0..dynamicModules.len]) |module| {
153 | recursiveMark(module);
154 | }
155 | }
156 |
157 | // Marks given module and it's native/dynamic dependencies recursively as external
158 | pub fn recursiveMark(module: []const u8) void {
159 |
160 | // Make sure this module isn't already marked
161 | for(externals.items[0..externals.items.len]) |item| if(std.mem.eql(u8, item, module)) return;
162 | for(leafModules.items[0..leafModules.items.len]) |item| if(std.mem.eql(u8, item, module)) return;
163 |
164 | // Get dynamic dependencies of this module
165 | var modulePtr = analyzer.getModulePtr(module) catch |e| @panic(@errorName(e));
166 | var dynamicModules = getDynamicModules(std.mem.concatWithSentinel(allocator, u8, &.{root, "/node_modules/", modulePtr.path, "/", modulePtr.main}, 0) catch |e| @panic(@errorName(e)), "cjs") catch |e| @panic(@errorName(e));
167 |
168 | std.debug.print("`{s}` is external module with {any} impure dependencies\n", .{module, dynamicModules.len});
169 |
170 | // This module is external, but it has dynamic dependencies which must also be marked
171 | externals.append(module) catch |e| @panic(@errorName(e));
172 |
173 | // Any pure dependencies are leaf modules
174 | leafLoop: for(modulePtr.deps[0..modulePtr.deps.len]) |leaf| {
175 | for(dynamicModules[0..dynamicModules.len]) |mod| { if(std.mem.eql(u8, leaf.path, mod)) continue :leafLoop; }
176 |
177 | leafModules.append(leaf.name) catch |e| @panic(@errorName(e));
178 | std.debug.print("Marked `{s}` as external leaf module\n", .{leaf.name});
179 | }
180 |
181 | // Mark dynamic dependencies
182 | for(dynamicModules[0..dynamicModules.len]) |mod| {
183 | return recursiveMark(mod);
184 | }
185 |
186 | }
187 |
188 | // Checks if given module is in allowed list of exceptions
189 | pub fn checkAllowedDynamicModule(module: []const u8) bool {
190 | inline for(AllowedDynamicModules[0..AllowedDynamicModules.len]) |mod| {
191 | if(std.mem.eql(u8, mod, module)) return true;
192 | }
193 | return false;
194 | }
195 |
196 | // Runs an optimizer pass to find modules with dynamic imports/requires
197 | pub fn getDynamicModules(entry: []const u8, format: []const u8) ![][]const u8 {
198 | var tempFile = try std.mem.concat(allocator, u8, &.{tempDir, "/tempOptimizerPass.js"});
199 | var result = try optimizer.optimize(allocator, entry, tempFile, format, "");
200 | const nodeModules = try std.mem.concat(allocator, u8, &.{root, "/node_modules"});
201 |
202 | // Delete temp bundled file
203 | if(result.status != .Failure) { try std.fs.deleteFileAbsolute(tempFile); }
204 | else {
205 | for(result.errors[0..result.errors.len]) |err| {
206 | std.debug.print("LTO Error: {s}\n", .{err.Text});
207 | std.debug.print("at `{s}` [{s}:{any}:{any}]\n", .{err.Location.?.LineText, err.Location.?.File, err.Location.?.Line, err.Location.?.Column});
208 | }
209 | std.debug.print("To build without LTO, you can run with `--nolto`.\n", .{});
210 |
211 | return error.OptimizeFailed;
212 | }
213 |
214 | var modules = std.ArrayList([]const u8).init(allocator);
215 |
216 | // If there are warnings, there might be dynamic modules
217 | if(result.status != .Success) {
218 | for(result.warnings[0..result.warnings.len]) |message| {
219 | if(std.mem.eql(u8, message.ID.?, "unsupported-require-call") or std.mem.eql(u8, message.ID.?, "unsupported-dynamic-import")) {
220 | const absPath = try std.fs.cwd().realpathAlloc(allocator, message.Location.?.File);
221 |
222 | // Make sure this is in node_modules
223 | if(std.mem.startsWith(u8, absPath, nodeModules)) {
224 |
225 | var iterator = std.mem.split(u8, try std.mem.replaceOwned(u8, allocator, absPath, nodeModules, ""), "/");
226 | _ = iterator.next(); // Skip leading slash
227 | var currentSearchPath: []u8 = "";
228 |
229 | // From the file path, get the path/name of module
230 | while(iterator.next()) |dir| {
231 | currentSearchPath = try std.mem.concat(allocator, u8, &.{currentSearchPath, "/", dir});
232 | const fullPath = try std.mem.concat(allocator, u8, &.{nodeModules, currentSearchPath});
233 | defer allocator.free(fullPath);
234 |
235 | if((try analyzer.isModule(allocator, fullPath)) and checkAllowedDynamicModule(currentSearchPath[1..currentSearchPath.len]) == false) {
236 | try modules.append(currentSearchPath[1..currentSearchPath.len]);
237 | }
238 | }
239 |
240 | }else {
241 | // We don't support sources that use dynamic imports / requires
242 | return error.SourceIsDynamic;
243 | }
244 | }
245 | }
246 | }
247 |
248 | // Free JSON resources
249 | defer std.json.parseFree(optimizer.BuildResult, result.buildResult, .{.allocator = allocator, .ignore_unknown_fields = true});
250 | defer allocator.destroy(result);
251 |
252 | return modules.toOwnedSlice();
253 | }
--------------------------------------------------------------------------------
/src/runtime.zig:
--------------------------------------------------------------------------------
1 | // Inflates & extracts Bun & source files at runtime
2 | const process = std.process;
3 | const fs = std.fs;
4 | const ChildProcess = std.ChildProcess;
5 | const std = @import("std");
6 | const lz4 = @import("translated/liblz4.zig");
7 | const mtar = @import("translated/libmicrotar.zig");
8 | const config = @import("config.zig");
9 | const threadpool = @import("thread_pool.zig");
10 | const debug = @import("debug.zig");
11 |
12 | const ParseResult = struct {
13 | compressed: usize,
14 | hash: []const u8
15 | };
16 |
17 | // Used during multithreaded extraction
18 | var pool: threadpool = undefined;
19 | var alloc: std.mem.Allocator = undefined;
20 | var extractRoot: []const u8 = undefined;
21 | var m1 = std.Thread.Mutex{};
22 | var m2 = std.Thread.Mutex{};
23 | var numTasks: usize = undefined;
24 |
25 | // Parses a bkg binary to get the compressed size header and CRC32 hash
26 | pub fn parseBinary(allocator: std.mem.Allocator, path: []const u8) anyerror!ParseResult {
27 |
28 | var file = try std.fs.openFileAbsolute(path, .{});
29 | defer file.close();
30 |
31 | // Seek to 20 bytes before the end
32 | var stat = try file.stat();
33 | try file.seekTo(stat.size - 20);
34 |
35 | // Read 20 bytes
36 | const buf: []const u8 = try file.readToEndAlloc(allocator, 1024);
37 | defer allocator.free(buf);
38 |
39 | var crcBuf: []const u8 = buf[0..10];
40 | var compSizeBuf: []const u8 = buf[10..20];
41 |
42 | // Parse into usize
43 | var nullIndex = std.mem.indexOfScalar(u8, compSizeBuf, 0) orelse 10;
44 | var crcNullIndex = std.mem.indexOfScalar(u8, crcBuf, 0) orelse 10;
45 |
46 | var compSize = std.fmt.parseInt(usize, compSizeBuf[0..nullIndex], 0) catch {
47 | return error.FailedParseCompressedSize;
48 | };
49 |
50 | return ParseResult{
51 | .compressed = compSize,
52 | .hash = try allocator.dupe(u8, crcBuf[0..crcNullIndex])
53 | };
54 |
55 | }
56 |
57 | // Worker function that extracts a single file and writes it to disk
58 | // This function may be called from multiple threads, simultaneously
59 | fn extractCallback(op: *threadpool.Task) void {
60 |
61 | var name = op.data.name orelse return;
62 |
63 | var header = op.data.header;
64 | var tar = op.data.tar;
65 |
66 | // Allocate memory for this file
67 | var fileBuf: []u8 = alloc.alloc(u8, header.size) catch @panic("Failed to allocate memory for extracted file!");
68 |
69 | m1.lock();
70 | {
71 | // Read contents of the file
72 | _ = mtar.mtar_read_data(tar, fileBuf.ptr, header.size);
73 |
74 | // Write file to disk
75 | var exfile = std.fs.createFileAbsolute(std.mem.concat(alloc, u8, &.{extractRoot, "/", name}) catch @panic("Failed to concat during extraction!"), .{.read = false}) catch |e| {
76 | std.debug.print("Failed to create {s} during extraction: {s}\n", .{name, @errorName(e)});
77 | @panic("exiting due to FS error");
78 | };
79 | _ = exfile.writeAll(fileBuf) catch @panic("Failed to write file contents");
80 |
81 | // Close and free resources
82 | exfile.close();
83 | alloc.free(fileBuf);
84 | _ = mtar.mtar_close(tar);
85 | alloc.destroy(op.data.tar);
86 | alloc.destroy(op.data.header);
87 | alloc.destroy(op.data);
88 | }
89 | m1.unlock();
90 |
91 | // We must lock to prevent race conditions and other weird errors
92 | // due to massive concurrency
93 | {
94 | m2.lock();
95 | op.data.index.* += 1;
96 | if(op.data.index.* == numTasks) pool.shutdown();
97 | m2.unlock();
98 | }
99 |
100 | }
101 |
102 | // Extracts compressed archive from a binary, decompresses it
103 | // and then de-archives it to a temporary location in the filesystem
104 | // We prefer OS temp directory because it's always world writeable.
105 | // However, this may change.
106 | pub fn extractArchive(allocator: std.mem.Allocator, target: []const u8, root: []const u8, parsed: ParseResult) !void {
107 |
108 | alloc = allocator;
109 | extractRoot = root;
110 |
111 | // Open binary
112 | var file = try std.fs.openFileAbsolute(target, .{});
113 | defer file.close();
114 |
115 | // Seek to start of compressed archive
116 | var stat = try file.stat();
117 | try file.seekTo(stat.size - parsed.compressed - 20); // 20 bytes for header
118 |
119 | // Compressed archive can be upto 512MB
120 | const buf: []u8 = try file.readToEndAlloc(allocator, 512 * 1024 * 1024);
121 | defer allocator.free(buf);
122 |
123 | // Decompressed archive can be upto 1024MB
124 | var decompressed: []u8 = try allocator.alloc(u8, 1024 * 1024 * 1024);
125 |
126 | // Store timestamp used for profiling
127 | debug.startTime = std.time.milliTimestamp();
128 |
129 | // Perform LZ4 decompression
130 | var result = lz4.LZ4_decompress_safe(buf[0..parsed.compressed].ptr, decompressed.ptr, @intCast(c_int, parsed.compressed), 1024 * 1024 * 1024);
131 |
132 | // Validate decompression
133 | if(result < 0) {
134 | debug.err("Failed to decompress payload!", .{});
135 | return error.FailedDecompressPayload;
136 | }
137 |
138 | // Open decompressed archive
139 | var tar: mtar.mtar_t = std.mem.zeroes(mtar.mtar_t);
140 | var header: *mtar.mtar_header_t = try allocator.create(mtar.mtar_header_t);
141 | _ = mtar_open_mem(&tar, decompressed[0..@intCast(usize, result)].ptr);
142 |
143 | // Load configuration file before everything else
144 | _ = mtar.mtar_find(&tar, "bkg.config.json", header);
145 | var configBuf: []u8 = alloc.alloc(u8, header.size) catch @panic("Failed to allocate memory for configuration file!");
146 | _ = mtar.mtar_read_data(&tar, configBuf.ptr, header.size);
147 | _ = mtar.mtar_rewind(&tar);
148 | config.load(allocator, null, configBuf) catch @panic("Failed to parse configuration file!");
149 | debug.debug = config.get().debug;
150 |
151 | if(debug.debug) {
152 | debug.init(allocator);
153 | debug.print("Debug logs are enabled", .{});
154 | debug.print("Configuration file loaded from archive!", .{});
155 | }
156 |
157 | // Initialize threadpool with number of threads available in OS
158 | const threads = try std.Thread.getCpuCount();
159 | pool = threadpool.init(.{
160 | .max_threads = @intCast(u32, threads)
161 | });
162 |
163 | if(debug.debug) debug.print("Initialized thread pool using {any} threads", .{threads});
164 |
165 | // Initial no-op task
166 | var initData = threadpool.ExtractData{
167 | .name = null,
168 | .buffer = undefined,
169 | .bufSize = undefined,
170 | .index = undefined,
171 | .header = undefined,
172 | .tar = undefined
173 | };
174 | var initTaskStruct = threadpool.Task{
175 | .callback = extractCallback,
176 | .data = &initData
177 | };
178 | var initTask = &initTaskStruct;
179 |
180 | //var batch = try allocator.create(threadpool.Batch);
181 | var batch = threadpool.Batch.from(initTask);
182 |
183 | // Used to track progress across tasks
184 | var index = try allocator.create(usize);
185 | index.* = 0;
186 |
187 | // Iterate through the archive
188 | while (mtar.mtar_read_header(&tar, header) != mtar.MTAR_ENULLRECORD) {
189 | var nullIndex = std.mem.indexOfScalar(u8, &header.name, 0) orelse header.name.len;
190 | var name = header.name[0..nullIndex];
191 |
192 | // Create directory
193 | if(header.type == mtar.MTAR_TDIR) {
194 | _ = try std.fs.makeDirAbsolute(try std.mem.concat(allocator, u8, &.{root, "/", name}));
195 | }
196 | else if(header.type == mtar.MTAR_TREG) {
197 | var task = try allocator.create(threadpool.Task);
198 | var data = try allocator.create(threadpool.ExtractData);
199 |
200 | // Allocate TAR and header objects for this task
201 | var dupeTar: *mtar.mtar_t = alloc.create(mtar.mtar_t) catch @panic("Failed to allocate TAR struct");
202 |
203 | dupeTar.* = tar;
204 | var dupeHeader = try allocator.create(mtar.mtar_header_t);
205 | dupeHeader.* = header.*;
206 |
207 | data.* = .{
208 | .name = dupeHeader.name[0..(std.mem.indexOfScalar(u8, &dupeHeader.name, 0) orelse dupeHeader.name.len)],
209 | .header = dupeHeader,
210 | .buffer = &decompressed,
211 | .bufSize = &result,
212 | .index = index,
213 | .tar = dupeTar
214 | };
215 |
216 | task.* = threadpool.Task{
217 | .callback = extractCallback,
218 | .data = data
219 | };
220 |
221 | // Push task to batch
222 | var newbatch = threadpool.Batch.from(task);
223 | batch.push(newbatch);
224 | }
225 |
226 | _ = mtar.mtar_next(&tar);
227 | }
228 |
229 | numTasks = batch.len - 1;
230 | if(debug.debug) debug.print("Scheduling write batch with {any} tasks ({any}ms)", .{numTasks, std.time.milliTimestamp() - debug.startTime});
231 |
232 | // Schedule tasks to thread pool
233 | pool.schedule(batch);
234 |
235 | // Wait for completion
236 | pool.deinit();
237 |
238 | if(debug.debug) debug.print("Extracted to disk! ({any}ms)", .{std.time.milliTimestamp() - debug.startTime});
239 |
240 | // Close the archive
241 | _ = mtar.mtar_close(&tar);
242 |
243 | // Free decompressed buffer
244 | allocator.free(decompressed);
245 |
246 | }
247 |
248 | // (Old) Single threaded implementation of the extractor
249 | // This is ~30x slower than the newer multithreaded implementation on a 12-threads CPU
250 | pub fn extractArchiveSingleThreaded(allocator: std.mem.Allocator, target: []const u8, root: []const u8, parsed: ParseResult) anyerror!void {
251 |
252 | // Open binary
253 | var file = try std.fs.openFileAbsolute(target, .{});
254 | defer file.close();
255 |
256 | // Seek to start of compressed archive
257 | var stat = try file.stat();
258 | try file.seekTo(stat.size - parsed.compressed - 20); // 20 bytes for header
259 |
260 | // Compressed archive can be upto 512MB
261 | const buf: []u8 = try file.readToEndAlloc(allocator, 512 * 1024 * 1024);
262 | defer allocator.free(buf);
263 |
264 | // Decompressed archive can be upto 1024MB
265 | var decompressed: []u8 = try allocator.alloc(u8, 1024 * 1024 * 1024);
266 |
267 | debug.startTime = std.time.milliTimestamp();
268 |
269 | // Perform LZ4 decompression
270 | var result = lz4.LZ4_decompress_safe(buf[0..parsed.compressed].ptr, decompressed.ptr, @intCast(c_int, parsed.compressed), 1024 * 1024 * 1024);
271 |
272 | //std.debug.print("[{any}] Decompressed to memory\n", .{std.time.milliTimestamp() - startTime});
273 |
274 | // Open decompressed archive
275 | var tar: mtar.mtar_t = std.mem.zeroes(mtar.mtar_t);
276 | var memStream: mtar.mtar_mem_stream_t = std.mem.zeroes(mtar.mtar_mem_stream_t);
277 | var header: *mtar.mtar_header_t = try allocator.create(mtar.mtar_header_t);
278 |
279 | _ = mtar.mtar_init_mem_stream(&memStream, decompressed[0..@intCast(usize, result)].ptr, @intCast(usize, result));
280 | _ = mtar.mtar_open_mem(&tar, &memStream);
281 |
282 | // Iterate through the archive
283 | while (mtar.mtar_read_header(&tar, header) != mtar.MTAR_ENULLRECORD) {
284 | var nullIndex = std.mem.indexOfScalar(u8, &header.name, 0) orelse header.name.len;
285 | var name = header.name[0..nullIndex];
286 |
287 | // Create directory
288 | if(header.type == mtar.MTAR_TDIR) {
289 | _ = try std.fs.makeDirAbsolute(try std.mem.concat(allocator, u8, &.{root, "/", name}));
290 | }
291 | else if(header.type == mtar.MTAR_TREG) {
292 | _ = mtar.mtar_find(&tar, name.ptr, header);
293 | var fileBuf: []u8 = try allocator.alloc(u8, @intCast(usize, header.size));
294 | _ = mtar.mtar_read_data(&tar, fileBuf.ptr, header.size);
295 |
296 | var exfile = try std.fs.createFileAbsolute(try std.mem.concat(allocator, u8, &.{root, "/", name}), .{});
297 | _ = try exfile.write(fileBuf);
298 | exfile.close();
299 |
300 | allocator.free(fileBuf);
301 | }
302 |
303 | _ = mtar.mtar_next(&tar);
304 | }
305 |
306 | //std.debug.print("[{any} ms] Extracted everything\n", .{std.time.milliTimestamp() - startTime});
307 |
308 | // Close the archive
309 | _ = mtar.mtar_close(&tar);
310 |
311 | // Free decompressed buffer
312 | allocator.free(decompressed);
313 |
314 | }
315 |
316 | // Initiates Bun runtime after extraction
317 | pub fn execProcess(allocator: std.mem.Allocator, root: []const u8, configuration: *config.Config) anyerror!void {
318 |
319 | // Give executable permissions to bun
320 | var file: ?std.fs.File = std.fs.openFileAbsolute(try std.mem.concat(allocator, u8, &.{root, "/", "bkg_bun"}), .{}) catch |e| switch(e) {
321 | error.AccessDenied => null,
322 | else => return e
323 | };
324 |
325 | // We get an error.AccessDenied if the file is already executable
326 | // Only chmod if it isn't executable already
327 | if(file != null) {
328 | try file.?.chmod(0o755);
329 | file.?.close();
330 | }
331 |
332 | var cmd_args = std.ArrayList([]const u8).init(allocator);
333 | defer cmd_args.deinit();
334 | try cmd_args.appendSlice(&[_][]const u8{
335 | try std.mem.concat(allocator, u8, &.{root, "/", "bkg_bun"}),
336 | try std.mem.concat(allocator, u8, &.{root, "/", configuration.entry})
337 | });
338 |
339 | // Add passed commandline arguments
340 | var iterator = try std.process.argsWithAllocator(allocator);
341 | defer iterator.deinit();
342 | _ = iterator.skip();
343 | while(iterator.next()) |arg| {
344 | try cmd_args.appendSlice(&[_][]const u8{arg});
345 | }
346 |
347 | // Initiate child process
348 | try exec(allocator, "", cmd_args.items);
349 |
350 | }
351 |
352 | // Starts Bun as a child process, with the entry script
353 | // stdin, stdout & stderr are piped to parent process
354 | pub fn exec(a: std.mem.Allocator, cwd: []const u8, argv: []const []const u8) !void {
355 |
356 | _ = cwd;
357 | var child_process = ChildProcess.init(argv, a);
358 |
359 | child_process.stdout_behavior = .Inherit;
360 | child_process.spawn() catch |err| {
361 | std.debug.print("The following command failed:\n", .{});
362 | return err;
363 | };
364 |
365 | const term = try child_process.wait();
366 | switch (term) {
367 | .Exited => |code| {
368 | if (code != 0) {
369 | std.debug.print("The following command exited with error code {any}:\n", .{code});
370 | return error.CommandFailed;
371 | }
372 | },
373 | else => {
374 | std.debug.print("The following command terminated unexpectedly:\n", .{});
375 | return error.CommandFailed;
376 | },
377 | }
378 |
379 | }
380 |
381 | // Callback functions required by microtar
382 | // Streams decompressed LZ4 buffer directly to mtar in memory
383 |
384 | fn mtar_mem_write(tar: [*c]mtar.mtar_t, data: ?*const anyopaque, size: c_uint) callconv(.C) c_int {
385 | _ = tar;
386 | _ = data;
387 | _ = size;
388 | return mtar.MTAR_EWRITEFAIL;
389 | }
390 |
391 | // mem_read should supply data to microtar
392 | fn mtar_mem_read(tar: ?*mtar.mtar_t, data: ?*anyopaque, size: c_uint) callconv(.C) c_int {
393 |
394 | // TODO: Return error on null pointer?
395 | const dataPtr = data orelse return mtar.MTAR_ENULLRECORD;
396 | const thisTar = tar orelse return mtar.MTAR_EFAILURE;
397 |
398 | const buffer = @ptrCast([*]u8, @alignCast(@alignOf(u8), dataPtr));
399 | const streamPtr = thisTar.stream orelse return mtar.MTAR_ENULLRECORD;
400 | const streamBuffer: [*]u8 = @ptrCast([*]u8, @alignCast(@alignOf([*]u8), streamPtr));
401 |
402 | //const end = if (streamBuffer.*.len < (thisTar.pos + size)) streamBuffer.*.len else (thisTar.pos + size);
403 | for (streamBuffer[thisTar.pos..(thisTar.pos + size)]) |b, i| buffer[i] = b;
404 |
405 | return mtar.MTAR_ESUCCESS;
406 |
407 | }
408 |
409 | fn mtar_mem_seek(tar: ?*mtar.mtar_t, offset: c_uint) callconv(.C) c_int {
410 | _ = tar;
411 | _ = offset;
412 | return mtar.MTAR_ESUCCESS;
413 | }
414 |
415 | fn mtar_mem_close(tar: ?*mtar.mtar_t) callconv(.C) c_int {
416 | _ = tar;
417 | return mtar.MTAR_ESUCCESS;
418 | }
419 |
420 | fn mtar_open_mem(tar: *mtar.mtar_t, data: [*]u8) c_int {
421 |
422 | tar.write = mtar_mem_write;
423 | tar.read = mtar_mem_read;
424 | tar.seek = mtar_mem_seek;
425 | tar.close = mtar_mem_close;
426 | tar.stream = data;
427 |
428 | // Return ok
429 | return mtar.MTAR_ESUCCESS;
430 |
431 | }
--------------------------------------------------------------------------------
/src/translated/boptimizer.zig:
--------------------------------------------------------------------------------
1 | pub const __builtin_bswap16 = @import("std").zig.c_builtins.__builtin_bswap16;
2 | pub const __builtin_bswap32 = @import("std").zig.c_builtins.__builtin_bswap32;
3 | pub const __builtin_bswap64 = @import("std").zig.c_builtins.__builtin_bswap64;
4 | pub const __builtin_signbit = @import("std").zig.c_builtins.__builtin_signbit;
5 | pub const __builtin_signbitf = @import("std").zig.c_builtins.__builtin_signbitf;
6 | pub const __builtin_popcount = @import("std").zig.c_builtins.__builtin_popcount;
7 | pub const __builtin_ctz = @import("std").zig.c_builtins.__builtin_ctz;
8 | pub const __builtin_clz = @import("std").zig.c_builtins.__builtin_clz;
9 | pub const __builtin_sqrt = @import("std").zig.c_builtins.__builtin_sqrt;
10 | pub const __builtin_sqrtf = @import("std").zig.c_builtins.__builtin_sqrtf;
11 | pub const __builtin_sin = @import("std").zig.c_builtins.__builtin_sin;
12 | pub const __builtin_sinf = @import("std").zig.c_builtins.__builtin_sinf;
13 | pub const __builtin_cos = @import("std").zig.c_builtins.__builtin_cos;
14 | pub const __builtin_cosf = @import("std").zig.c_builtins.__builtin_cosf;
15 | pub const __builtin_exp = @import("std").zig.c_builtins.__builtin_exp;
16 | pub const __builtin_expf = @import("std").zig.c_builtins.__builtin_expf;
17 | pub const __builtin_exp2 = @import("std").zig.c_builtins.__builtin_exp2;
18 | pub const __builtin_exp2f = @import("std").zig.c_builtins.__builtin_exp2f;
19 | pub const __builtin_log = @import("std").zig.c_builtins.__builtin_log;
20 | pub const __builtin_logf = @import("std").zig.c_builtins.__builtin_logf;
21 | pub const __builtin_log2 = @import("std").zig.c_builtins.__builtin_log2;
22 | pub const __builtin_log2f = @import("std").zig.c_builtins.__builtin_log2f;
23 | pub const __builtin_log10 = @import("std").zig.c_builtins.__builtin_log10;
24 | pub const __builtin_log10f = @import("std").zig.c_builtins.__builtin_log10f;
25 | pub const __builtin_abs = @import("std").zig.c_builtins.__builtin_abs;
26 | pub const __builtin_fabs = @import("std").zig.c_builtins.__builtin_fabs;
27 | pub const __builtin_fabsf = @import("std").zig.c_builtins.__builtin_fabsf;
28 | pub const __builtin_floor = @import("std").zig.c_builtins.__builtin_floor;
29 | pub const __builtin_floorf = @import("std").zig.c_builtins.__builtin_floorf;
30 | pub const __builtin_ceil = @import("std").zig.c_builtins.__builtin_ceil;
31 | pub const __builtin_ceilf = @import("std").zig.c_builtins.__builtin_ceilf;
32 | pub const __builtin_trunc = @import("std").zig.c_builtins.__builtin_trunc;
33 | pub const __builtin_truncf = @import("std").zig.c_builtins.__builtin_truncf;
34 | pub const __builtin_round = @import("std").zig.c_builtins.__builtin_round;
35 | pub const __builtin_roundf = @import("std").zig.c_builtins.__builtin_roundf;
36 | pub const __builtin_strlen = @import("std").zig.c_builtins.__builtin_strlen;
37 | pub const __builtin_strcmp = @import("std").zig.c_builtins.__builtin_strcmp;
38 | pub const __builtin_object_size = @import("std").zig.c_builtins.__builtin_object_size;
39 | pub const __builtin___memset_chk = @import("std").zig.c_builtins.__builtin___memset_chk;
40 | pub const __builtin_memset = @import("std").zig.c_builtins.__builtin_memset;
41 | pub const __builtin___memcpy_chk = @import("std").zig.c_builtins.__builtin___memcpy_chk;
42 | pub const __builtin_memcpy = @import("std").zig.c_builtins.__builtin_memcpy;
43 | pub const __builtin_expect = @import("std").zig.c_builtins.__builtin_expect;
44 | pub const __builtin_nanf = @import("std").zig.c_builtins.__builtin_nanf;
45 | pub const __builtin_huge_valf = @import("std").zig.c_builtins.__builtin_huge_valf;
46 | pub const __builtin_inff = @import("std").zig.c_builtins.__builtin_inff;
47 | pub const __builtin_isnan = @import("std").zig.c_builtins.__builtin_isnan;
48 | pub const __builtin_isinf = @import("std").zig.c_builtins.__builtin_isinf;
49 | pub const __builtin_isinf_sign = @import("std").zig.c_builtins.__builtin_isinf_sign;
50 | pub const __has_builtin = @import("std").zig.c_builtins.__has_builtin;
51 | pub const __builtin_assume = @import("std").zig.c_builtins.__builtin_assume;
52 | pub const __builtin_unreachable = @import("std").zig.c_builtins.__builtin_unreachable;
53 | pub const __builtin_constant_p = @import("std").zig.c_builtins.__builtin_constant_p;
54 | pub const __builtin_mul_overflow = @import("std").zig.c_builtins.__builtin_mul_overflow;
55 | pub const ptrdiff_t = c_long;
56 | pub const wchar_t = c_int;
57 | pub const max_align_t = extern struct {
58 | __clang_max_align_nonce1: c_longlong align(8),
59 | __clang_max_align_nonce2: c_longdouble align(16),
60 | };
61 | pub const _GoString_ = extern struct {
62 | p: [*c]const u8,
63 | n: ptrdiff_t,
64 | };
65 | pub const GoInt8 = i8;
66 | pub const GoUint8 = u8;
67 | pub const GoInt16 = c_short;
68 | pub const GoUint16 = c_ushort;
69 | pub const GoInt32 = c_int;
70 | pub const GoUint32 = c_uint;
71 | pub const GoInt64 = c_longlong;
72 | pub const GoUint64 = c_ulonglong;
73 | pub const GoInt = GoInt64;
74 | pub const GoUint = GoUint64;
75 | pub const GoUintptr = usize;
76 | pub const GoFloat32 = f32;
77 | pub const GoFloat64 = f64; // deps/bOptimizer/build/out/libboptimizer-x86_64-linux.h:51:24: warning: unsupported type: 'Complex'
78 | pub const GoComplex64 = @compileError("unable to resolve typedef child type"); // deps/bOptimizer/build/out/libboptimizer-x86_64-linux.h:51:24
79 | // deps/bOptimizer/build/out/libboptimizer-x86_64-linux.h:52:25: warning: unsupported type: 'Complex'
80 | pub const GoComplex128 = @compileError("unable to resolve typedef child type"); // deps/bOptimizer/build/out/libboptimizer-x86_64-linux.h:52:25
81 | pub const _check_for_64_bit_pointer_matching_GoInt = [1]u8;
82 | pub const GoString = _GoString_;
83 | pub const GoMap = ?*anyopaque;
84 | pub const GoChan = ?*anyopaque;
85 | pub const GoInterface = extern struct {
86 | t: ?*anyopaque,
87 | v: ?*anyopaque,
88 | };
89 | pub const GoSlice = extern struct {
90 | data: ?*anyopaque,
91 | len: GoInt,
92 | cap: GoInt,
93 | };
94 | pub extern fn build(entry: [*c]u8, out: [*c]u8, format: [*c]u8, externals: [*c]u8) [*c]u8;
95 | pub const __INTMAX_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `L`"); // (no file):80:9
96 | pub const __UINTMAX_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `UL`"); // (no file):86:9
97 | pub const __FLT16_DENORM_MIN__ = @compileError("unable to translate C expr: unexpected token 'IntegerLiteral'"); // (no file):109:9
98 | pub const __FLT16_EPSILON__ = @compileError("unable to translate C expr: unexpected token 'IntegerLiteral'"); // (no file):113:9
99 | pub const __FLT16_MAX__ = @compileError("unable to translate C expr: unexpected token 'IntegerLiteral'"); // (no file):119:9
100 | pub const __FLT16_MIN__ = @compileError("unable to translate C expr: unexpected token 'IntegerLiteral'"); // (no file):122:9
101 | pub const __INT64_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `L`"); // (no file):183:9
102 | pub const __UINT32_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `U`"); // (no file):205:9
103 | pub const __UINT64_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `UL`"); // (no file):213:9
104 | pub const __seg_gs = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // (no file):342:9
105 | pub const __seg_fs = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // (no file):343:9
106 | pub const offsetof = @compileError("unable to translate macro: undefined identifier `__builtin_offsetof`"); // /home/theseyan/zig/lib/include/stddef.h:104:9
107 | pub const __llvm__ = @as(c_int, 1);
108 | pub const __clang__ = @as(c_int, 1);
109 | pub const __clang_major__ = @as(c_int, 15);
110 | pub const __clang_minor__ = @as(c_int, 0);
111 | pub const __clang_patchlevel__ = @as(c_int, 6);
112 | pub const __clang_version__ = "15.0.6 (https://github.com/ziglang/zig-bootstrap b9a466fd23d7777e1b3b87d49074ce66370fb7b3)";
113 | pub const __GNUC__ = @as(c_int, 4);
114 | pub const __GNUC_MINOR__ = @as(c_int, 2);
115 | pub const __GNUC_PATCHLEVEL__ = @as(c_int, 1);
116 | pub const __GXX_ABI_VERSION = @as(c_int, 1002);
117 | pub const __ATOMIC_RELAXED = @as(c_int, 0);
118 | pub const __ATOMIC_CONSUME = @as(c_int, 1);
119 | pub const __ATOMIC_ACQUIRE = @as(c_int, 2);
120 | pub const __ATOMIC_RELEASE = @as(c_int, 3);
121 | pub const __ATOMIC_ACQ_REL = @as(c_int, 4);
122 | pub const __ATOMIC_SEQ_CST = @as(c_int, 5);
123 | pub const __OPENCL_MEMORY_SCOPE_WORK_ITEM = @as(c_int, 0);
124 | pub const __OPENCL_MEMORY_SCOPE_WORK_GROUP = @as(c_int, 1);
125 | pub const __OPENCL_MEMORY_SCOPE_DEVICE = @as(c_int, 2);
126 | pub const __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES = @as(c_int, 3);
127 | pub const __OPENCL_MEMORY_SCOPE_SUB_GROUP = @as(c_int, 4);
128 | pub const __PRAGMA_REDEFINE_EXTNAME = @as(c_int, 1);
129 | pub const __VERSION__ = "Clang 15.0.6 (https://github.com/ziglang/zig-bootstrap b9a466fd23d7777e1b3b87d49074ce66370fb7b3)";
130 | pub const __OBJC_BOOL_IS_BOOL = @as(c_int, 0);
131 | pub const __CONSTANT_CFSTRINGS__ = @as(c_int, 1);
132 | pub const __clang_literal_encoding__ = "UTF-8";
133 | pub const __clang_wide_literal_encoding__ = "UTF-32";
134 | pub const __ORDER_LITTLE_ENDIAN__ = @as(c_int, 1234);
135 | pub const __ORDER_BIG_ENDIAN__ = @as(c_int, 4321);
136 | pub const __ORDER_PDP_ENDIAN__ = @as(c_int, 3412);
137 | pub const __BYTE_ORDER__ = __ORDER_LITTLE_ENDIAN__;
138 | pub const __LITTLE_ENDIAN__ = @as(c_int, 1);
139 | pub const _LP64 = @as(c_int, 1);
140 | pub const __LP64__ = @as(c_int, 1);
141 | pub const __CHAR_BIT__ = @as(c_int, 8);
142 | pub const __BOOL_WIDTH__ = @as(c_int, 8);
143 | pub const __SHRT_WIDTH__ = @as(c_int, 16);
144 | pub const __INT_WIDTH__ = @as(c_int, 32);
145 | pub const __LONG_WIDTH__ = @as(c_int, 64);
146 | pub const __LLONG_WIDTH__ = @as(c_int, 64);
147 | pub const __BITINT_MAXWIDTH__ = @as(c_int, 128);
148 | pub const __SCHAR_MAX__ = @as(c_int, 127);
149 | pub const __SHRT_MAX__ = @as(c_int, 32767);
150 | pub const __INT_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
151 | pub const __LONG_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
152 | pub const __LONG_LONG_MAX__ = @as(c_longlong, 9223372036854775807);
153 | pub const __WCHAR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
154 | pub const __WCHAR_WIDTH__ = @as(c_int, 32);
155 | pub const __WINT_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
156 | pub const __WINT_WIDTH__ = @as(c_int, 32);
157 | pub const __INTMAX_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
158 | pub const __INTMAX_WIDTH__ = @as(c_int, 64);
159 | pub const __SIZE_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
160 | pub const __SIZE_WIDTH__ = @as(c_int, 64);
161 | pub const __UINTMAX_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
162 | pub const __UINTMAX_WIDTH__ = @as(c_int, 64);
163 | pub const __PTRDIFF_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
164 | pub const __PTRDIFF_WIDTH__ = @as(c_int, 64);
165 | pub const __INTPTR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
166 | pub const __INTPTR_WIDTH__ = @as(c_int, 64);
167 | pub const __UINTPTR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
168 | pub const __UINTPTR_WIDTH__ = @as(c_int, 64);
169 | pub const __SIZEOF_DOUBLE__ = @as(c_int, 8);
170 | pub const __SIZEOF_FLOAT__ = @as(c_int, 4);
171 | pub const __SIZEOF_INT__ = @as(c_int, 4);
172 | pub const __SIZEOF_LONG__ = @as(c_int, 8);
173 | pub const __SIZEOF_LONG_DOUBLE__ = @as(c_int, 16);
174 | pub const __SIZEOF_LONG_LONG__ = @as(c_int, 8);
175 | pub const __SIZEOF_POINTER__ = @as(c_int, 8);
176 | pub const __SIZEOF_SHORT__ = @as(c_int, 2);
177 | pub const __SIZEOF_PTRDIFF_T__ = @as(c_int, 8);
178 | pub const __SIZEOF_SIZE_T__ = @as(c_int, 8);
179 | pub const __SIZEOF_WCHAR_T__ = @as(c_int, 4);
180 | pub const __SIZEOF_WINT_T__ = @as(c_int, 4);
181 | pub const __SIZEOF_INT128__ = @as(c_int, 16);
182 | pub const __INTMAX_TYPE__ = c_long;
183 | pub const __INTMAX_FMTd__ = "ld";
184 | pub const __INTMAX_FMTi__ = "li";
185 | pub const __UINTMAX_TYPE__ = c_ulong;
186 | pub const __UINTMAX_FMTo__ = "lo";
187 | pub const __UINTMAX_FMTu__ = "lu";
188 | pub const __UINTMAX_FMTx__ = "lx";
189 | pub const __UINTMAX_FMTX__ = "lX";
190 | pub const __PTRDIFF_TYPE__ = c_long;
191 | pub const __PTRDIFF_FMTd__ = "ld";
192 | pub const __PTRDIFF_FMTi__ = "li";
193 | pub const __INTPTR_TYPE__ = c_long;
194 | pub const __INTPTR_FMTd__ = "ld";
195 | pub const __INTPTR_FMTi__ = "li";
196 | pub const __SIZE_TYPE__ = c_ulong;
197 | pub const __SIZE_FMTo__ = "lo";
198 | pub const __SIZE_FMTu__ = "lu";
199 | pub const __SIZE_FMTx__ = "lx";
200 | pub const __SIZE_FMTX__ = "lX";
201 | pub const __WCHAR_TYPE__ = c_int;
202 | pub const __WINT_TYPE__ = c_uint;
203 | pub const __SIG_ATOMIC_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
204 | pub const __SIG_ATOMIC_WIDTH__ = @as(c_int, 32);
205 | pub const __CHAR16_TYPE__ = c_ushort;
206 | pub const __CHAR32_TYPE__ = c_uint;
207 | pub const __UINTPTR_TYPE__ = c_ulong;
208 | pub const __UINTPTR_FMTo__ = "lo";
209 | pub const __UINTPTR_FMTu__ = "lu";
210 | pub const __UINTPTR_FMTx__ = "lx";
211 | pub const __UINTPTR_FMTX__ = "lX";
212 | pub const __FLT16_HAS_DENORM__ = @as(c_int, 1);
213 | pub const __FLT16_DIG__ = @as(c_int, 3);
214 | pub const __FLT16_DECIMAL_DIG__ = @as(c_int, 5);
215 | pub const __FLT16_HAS_INFINITY__ = @as(c_int, 1);
216 | pub const __FLT16_HAS_QUIET_NAN__ = @as(c_int, 1);
217 | pub const __FLT16_MANT_DIG__ = @as(c_int, 11);
218 | pub const __FLT16_MAX_10_EXP__ = @as(c_int, 4);
219 | pub const __FLT16_MAX_EXP__ = @as(c_int, 16);
220 | pub const __FLT16_MIN_10_EXP__ = -@as(c_int, 4);
221 | pub const __FLT16_MIN_EXP__ = -@as(c_int, 13);
222 | pub const __FLT_DENORM_MIN__ = @as(f32, 1.40129846e-45);
223 | pub const __FLT_HAS_DENORM__ = @as(c_int, 1);
224 | pub const __FLT_DIG__ = @as(c_int, 6);
225 | pub const __FLT_DECIMAL_DIG__ = @as(c_int, 9);
226 | pub const __FLT_EPSILON__ = @as(f32, 1.19209290e-7);
227 | pub const __FLT_HAS_INFINITY__ = @as(c_int, 1);
228 | pub const __FLT_HAS_QUIET_NAN__ = @as(c_int, 1);
229 | pub const __FLT_MANT_DIG__ = @as(c_int, 24);
230 | pub const __FLT_MAX_10_EXP__ = @as(c_int, 38);
231 | pub const __FLT_MAX_EXP__ = @as(c_int, 128);
232 | pub const __FLT_MAX__ = @as(f32, 3.40282347e+38);
233 | pub const __FLT_MIN_10_EXP__ = -@as(c_int, 37);
234 | pub const __FLT_MIN_EXP__ = -@as(c_int, 125);
235 | pub const __FLT_MIN__ = @as(f32, 1.17549435e-38);
236 | pub const __DBL_DENORM_MIN__ = @as(f64, 4.9406564584124654e-324);
237 | pub const __DBL_HAS_DENORM__ = @as(c_int, 1);
238 | pub const __DBL_DIG__ = @as(c_int, 15);
239 | pub const __DBL_DECIMAL_DIG__ = @as(c_int, 17);
240 | pub const __DBL_EPSILON__ = @as(f64, 2.2204460492503131e-16);
241 | pub const __DBL_HAS_INFINITY__ = @as(c_int, 1);
242 | pub const __DBL_HAS_QUIET_NAN__ = @as(c_int, 1);
243 | pub const __DBL_MANT_DIG__ = @as(c_int, 53);
244 | pub const __DBL_MAX_10_EXP__ = @as(c_int, 308);
245 | pub const __DBL_MAX_EXP__ = @as(c_int, 1024);
246 | pub const __DBL_MAX__ = @as(f64, 1.7976931348623157e+308);
247 | pub const __DBL_MIN_10_EXP__ = -@as(c_int, 307);
248 | pub const __DBL_MIN_EXP__ = -@as(c_int, 1021);
249 | pub const __DBL_MIN__ = @as(f64, 2.2250738585072014e-308);
250 | pub const __LDBL_DENORM_MIN__ = @as(c_longdouble, 3.64519953188247460253e-4951);
251 | pub const __LDBL_HAS_DENORM__ = @as(c_int, 1);
252 | pub const __LDBL_DIG__ = @as(c_int, 18);
253 | pub const __LDBL_DECIMAL_DIG__ = @as(c_int, 21);
254 | pub const __LDBL_EPSILON__ = @as(c_longdouble, 1.08420217248550443401e-19);
255 | pub const __LDBL_HAS_INFINITY__ = @as(c_int, 1);
256 | pub const __LDBL_HAS_QUIET_NAN__ = @as(c_int, 1);
257 | pub const __LDBL_MANT_DIG__ = @as(c_int, 64);
258 | pub const __LDBL_MAX_10_EXP__ = @as(c_int, 4932);
259 | pub const __LDBL_MAX_EXP__ = @as(c_int, 16384);
260 | pub const __LDBL_MAX__ = @as(c_longdouble, 1.18973149535723176502e+4932);
261 | pub const __LDBL_MIN_10_EXP__ = -@as(c_int, 4931);
262 | pub const __LDBL_MIN_EXP__ = -@as(c_int, 16381);
263 | pub const __LDBL_MIN__ = @as(c_longdouble, 3.36210314311209350626e-4932);
264 | pub const __POINTER_WIDTH__ = @as(c_int, 64);
265 | pub const __BIGGEST_ALIGNMENT__ = @as(c_int, 16);
266 | pub const __WINT_UNSIGNED__ = @as(c_int, 1);
267 | pub const __INT8_TYPE__ = i8;
268 | pub const __INT8_FMTd__ = "hhd";
269 | pub const __INT8_FMTi__ = "hhi";
270 | pub const __INT8_C_SUFFIX__ = "";
271 | pub const __INT16_TYPE__ = c_short;
272 | pub const __INT16_FMTd__ = "hd";
273 | pub const __INT16_FMTi__ = "hi";
274 | pub const __INT16_C_SUFFIX__ = "";
275 | pub const __INT32_TYPE__ = c_int;
276 | pub const __INT32_FMTd__ = "d";
277 | pub const __INT32_FMTi__ = "i";
278 | pub const __INT32_C_SUFFIX__ = "";
279 | pub const __INT64_TYPE__ = c_long;
280 | pub const __INT64_FMTd__ = "ld";
281 | pub const __INT64_FMTi__ = "li";
282 | pub const __UINT8_TYPE__ = u8;
283 | pub const __UINT8_FMTo__ = "hho";
284 | pub const __UINT8_FMTu__ = "hhu";
285 | pub const __UINT8_FMTx__ = "hhx";
286 | pub const __UINT8_FMTX__ = "hhX";
287 | pub const __UINT8_C_SUFFIX__ = "";
288 | pub const __UINT8_MAX__ = @as(c_int, 255);
289 | pub const __INT8_MAX__ = @as(c_int, 127);
290 | pub const __UINT16_TYPE__ = c_ushort;
291 | pub const __UINT16_FMTo__ = "ho";
292 | pub const __UINT16_FMTu__ = "hu";
293 | pub const __UINT16_FMTx__ = "hx";
294 | pub const __UINT16_FMTX__ = "hX";
295 | pub const __UINT16_C_SUFFIX__ = "";
296 | pub const __UINT16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
297 | pub const __INT16_MAX__ = @as(c_int, 32767);
298 | pub const __UINT32_TYPE__ = c_uint;
299 | pub const __UINT32_FMTo__ = "o";
300 | pub const __UINT32_FMTu__ = "u";
301 | pub const __UINT32_FMTx__ = "x";
302 | pub const __UINT32_FMTX__ = "X";
303 | pub const __UINT32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
304 | pub const __INT32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
305 | pub const __UINT64_TYPE__ = c_ulong;
306 | pub const __UINT64_FMTo__ = "lo";
307 | pub const __UINT64_FMTu__ = "lu";
308 | pub const __UINT64_FMTx__ = "lx";
309 | pub const __UINT64_FMTX__ = "lX";
310 | pub const __UINT64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
311 | pub const __INT64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
312 | pub const __INT_LEAST8_TYPE__ = i8;
313 | pub const __INT_LEAST8_MAX__ = @as(c_int, 127);
314 | pub const __INT_LEAST8_WIDTH__ = @as(c_int, 8);
315 | pub const __INT_LEAST8_FMTd__ = "hhd";
316 | pub const __INT_LEAST8_FMTi__ = "hhi";
317 | pub const __UINT_LEAST8_TYPE__ = u8;
318 | pub const __UINT_LEAST8_MAX__ = @as(c_int, 255);
319 | pub const __UINT_LEAST8_FMTo__ = "hho";
320 | pub const __UINT_LEAST8_FMTu__ = "hhu";
321 | pub const __UINT_LEAST8_FMTx__ = "hhx";
322 | pub const __UINT_LEAST8_FMTX__ = "hhX";
323 | pub const __INT_LEAST16_TYPE__ = c_short;
324 | pub const __INT_LEAST16_MAX__ = @as(c_int, 32767);
325 | pub const __INT_LEAST16_WIDTH__ = @as(c_int, 16);
326 | pub const __INT_LEAST16_FMTd__ = "hd";
327 | pub const __INT_LEAST16_FMTi__ = "hi";
328 | pub const __UINT_LEAST16_TYPE__ = c_ushort;
329 | pub const __UINT_LEAST16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
330 | pub const __UINT_LEAST16_FMTo__ = "ho";
331 | pub const __UINT_LEAST16_FMTu__ = "hu";
332 | pub const __UINT_LEAST16_FMTx__ = "hx";
333 | pub const __UINT_LEAST16_FMTX__ = "hX";
334 | pub const __INT_LEAST32_TYPE__ = c_int;
335 | pub const __INT_LEAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
336 | pub const __INT_LEAST32_WIDTH__ = @as(c_int, 32);
337 | pub const __INT_LEAST32_FMTd__ = "d";
338 | pub const __INT_LEAST32_FMTi__ = "i";
339 | pub const __UINT_LEAST32_TYPE__ = c_uint;
340 | pub const __UINT_LEAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
341 | pub const __UINT_LEAST32_FMTo__ = "o";
342 | pub const __UINT_LEAST32_FMTu__ = "u";
343 | pub const __UINT_LEAST32_FMTx__ = "x";
344 | pub const __UINT_LEAST32_FMTX__ = "X";
345 | pub const __INT_LEAST64_TYPE__ = c_long;
346 | pub const __INT_LEAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
347 | pub const __INT_LEAST64_WIDTH__ = @as(c_int, 64);
348 | pub const __INT_LEAST64_FMTd__ = "ld";
349 | pub const __INT_LEAST64_FMTi__ = "li";
350 | pub const __UINT_LEAST64_TYPE__ = c_ulong;
351 | pub const __UINT_LEAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
352 | pub const __UINT_LEAST64_FMTo__ = "lo";
353 | pub const __UINT_LEAST64_FMTu__ = "lu";
354 | pub const __UINT_LEAST64_FMTx__ = "lx";
355 | pub const __UINT_LEAST64_FMTX__ = "lX";
356 | pub const __INT_FAST8_TYPE__ = i8;
357 | pub const __INT_FAST8_MAX__ = @as(c_int, 127);
358 | pub const __INT_FAST8_WIDTH__ = @as(c_int, 8);
359 | pub const __INT_FAST8_FMTd__ = "hhd";
360 | pub const __INT_FAST8_FMTi__ = "hhi";
361 | pub const __UINT_FAST8_TYPE__ = u8;
362 | pub const __UINT_FAST8_MAX__ = @as(c_int, 255);
363 | pub const __UINT_FAST8_FMTo__ = "hho";
364 | pub const __UINT_FAST8_FMTu__ = "hhu";
365 | pub const __UINT_FAST8_FMTx__ = "hhx";
366 | pub const __UINT_FAST8_FMTX__ = "hhX";
367 | pub const __INT_FAST16_TYPE__ = c_short;
368 | pub const __INT_FAST16_MAX__ = @as(c_int, 32767);
369 | pub const __INT_FAST16_WIDTH__ = @as(c_int, 16);
370 | pub const __INT_FAST16_FMTd__ = "hd";
371 | pub const __INT_FAST16_FMTi__ = "hi";
372 | pub const __UINT_FAST16_TYPE__ = c_ushort;
373 | pub const __UINT_FAST16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
374 | pub const __UINT_FAST16_FMTo__ = "ho";
375 | pub const __UINT_FAST16_FMTu__ = "hu";
376 | pub const __UINT_FAST16_FMTx__ = "hx";
377 | pub const __UINT_FAST16_FMTX__ = "hX";
378 | pub const __INT_FAST32_TYPE__ = c_int;
379 | pub const __INT_FAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
380 | pub const __INT_FAST32_WIDTH__ = @as(c_int, 32);
381 | pub const __INT_FAST32_FMTd__ = "d";
382 | pub const __INT_FAST32_FMTi__ = "i";
383 | pub const __UINT_FAST32_TYPE__ = c_uint;
384 | pub const __UINT_FAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
385 | pub const __UINT_FAST32_FMTo__ = "o";
386 | pub const __UINT_FAST32_FMTu__ = "u";
387 | pub const __UINT_FAST32_FMTx__ = "x";
388 | pub const __UINT_FAST32_FMTX__ = "X";
389 | pub const __INT_FAST64_TYPE__ = c_long;
390 | pub const __INT_FAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
391 | pub const __INT_FAST64_WIDTH__ = @as(c_int, 64);
392 | pub const __INT_FAST64_FMTd__ = "ld";
393 | pub const __INT_FAST64_FMTi__ = "li";
394 | pub const __UINT_FAST64_TYPE__ = c_ulong;
395 | pub const __UINT_FAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
396 | pub const __UINT_FAST64_FMTo__ = "lo";
397 | pub const __UINT_FAST64_FMTu__ = "lu";
398 | pub const __UINT_FAST64_FMTx__ = "lx";
399 | pub const __UINT_FAST64_FMTX__ = "lX";
400 | pub const __USER_LABEL_PREFIX__ = "";
401 | pub const __FINITE_MATH_ONLY__ = @as(c_int, 0);
402 | pub const __GNUC_STDC_INLINE__ = @as(c_int, 1);
403 | pub const __GCC_ATOMIC_TEST_AND_SET_TRUEVAL = @as(c_int, 1);
404 | pub const __CLANG_ATOMIC_BOOL_LOCK_FREE = @as(c_int, 2);
405 | pub const __CLANG_ATOMIC_CHAR_LOCK_FREE = @as(c_int, 2);
406 | pub const __CLANG_ATOMIC_CHAR16_T_LOCK_FREE = @as(c_int, 2);
407 | pub const __CLANG_ATOMIC_CHAR32_T_LOCK_FREE = @as(c_int, 2);
408 | pub const __CLANG_ATOMIC_WCHAR_T_LOCK_FREE = @as(c_int, 2);
409 | pub const __CLANG_ATOMIC_SHORT_LOCK_FREE = @as(c_int, 2);
410 | pub const __CLANG_ATOMIC_INT_LOCK_FREE = @as(c_int, 2);
411 | pub const __CLANG_ATOMIC_LONG_LOCK_FREE = @as(c_int, 2);
412 | pub const __CLANG_ATOMIC_LLONG_LOCK_FREE = @as(c_int, 2);
413 | pub const __CLANG_ATOMIC_POINTER_LOCK_FREE = @as(c_int, 2);
414 | pub const __GCC_ATOMIC_BOOL_LOCK_FREE = @as(c_int, 2);
415 | pub const __GCC_ATOMIC_CHAR_LOCK_FREE = @as(c_int, 2);
416 | pub const __GCC_ATOMIC_CHAR16_T_LOCK_FREE = @as(c_int, 2);
417 | pub const __GCC_ATOMIC_CHAR32_T_LOCK_FREE = @as(c_int, 2);
418 | pub const __GCC_ATOMIC_WCHAR_T_LOCK_FREE = @as(c_int, 2);
419 | pub const __GCC_ATOMIC_SHORT_LOCK_FREE = @as(c_int, 2);
420 | pub const __GCC_ATOMIC_INT_LOCK_FREE = @as(c_int, 2);
421 | pub const __GCC_ATOMIC_LONG_LOCK_FREE = @as(c_int, 2);
422 | pub const __GCC_ATOMIC_LLONG_LOCK_FREE = @as(c_int, 2);
423 | pub const __GCC_ATOMIC_POINTER_LOCK_FREE = @as(c_int, 2);
424 | pub const __NO_INLINE__ = @as(c_int, 1);
425 | pub const __PIC__ = @as(c_int, 2);
426 | pub const __pic__ = @as(c_int, 2);
427 | pub const __FLT_RADIX__ = @as(c_int, 2);
428 | pub const __DECIMAL_DIG__ = __LDBL_DECIMAL_DIG__;
429 | pub const __SSP_STRONG__ = @as(c_int, 2);
430 | pub const __GCC_ASM_FLAG_OUTPUTS__ = @as(c_int, 1);
431 | pub const __code_model_small__ = @as(c_int, 1);
432 | pub const __amd64__ = @as(c_int, 1);
433 | pub const __amd64 = @as(c_int, 1);
434 | pub const __x86_64 = @as(c_int, 1);
435 | pub const __x86_64__ = @as(c_int, 1);
436 | pub const __SEG_GS = @as(c_int, 1);
437 | pub const __SEG_FS = @as(c_int, 1);
438 | pub const __k8 = @as(c_int, 1);
439 | pub const __k8__ = @as(c_int, 1);
440 | pub const __tune_k8__ = @as(c_int, 1);
441 | pub const __REGISTER_PREFIX__ = "";
442 | pub const __NO_MATH_INLINES = @as(c_int, 1);
443 | pub const __AES__ = @as(c_int, 1);
444 | pub const __VAES__ = @as(c_int, 1);
445 | pub const __PCLMUL__ = @as(c_int, 1);
446 | pub const __VPCLMULQDQ__ = @as(c_int, 1);
447 | pub const __LAHF_SAHF__ = @as(c_int, 1);
448 | pub const __LZCNT__ = @as(c_int, 1);
449 | pub const __RDRND__ = @as(c_int, 1);
450 | pub const __FSGSBASE__ = @as(c_int, 1);
451 | pub const __BMI__ = @as(c_int, 1);
452 | pub const __BMI2__ = @as(c_int, 1);
453 | pub const __POPCNT__ = @as(c_int, 1);
454 | pub const __PRFCHW__ = @as(c_int, 1);
455 | pub const __RDSEED__ = @as(c_int, 1);
456 | pub const __ADX__ = @as(c_int, 1);
457 | pub const __MOVBE__ = @as(c_int, 1);
458 | pub const __FMA__ = @as(c_int, 1);
459 | pub const __F16C__ = @as(c_int, 1);
460 | pub const __GFNI__ = @as(c_int, 1);
461 | pub const __AVX512CD__ = @as(c_int, 1);
462 | pub const __AVX512VPOPCNTDQ__ = @as(c_int, 1);
463 | pub const __AVX512VNNI__ = @as(c_int, 1);
464 | pub const __AVX512DQ__ = @as(c_int, 1);
465 | pub const __AVX512BITALG__ = @as(c_int, 1);
466 | pub const __AVX512BW__ = @as(c_int, 1);
467 | pub const __AVX512VL__ = @as(c_int, 1);
468 | pub const __AVX512VBMI__ = @as(c_int, 1);
469 | pub const __AVX512VBMI2__ = @as(c_int, 1);
470 | pub const __AVX512IFMA__ = @as(c_int, 1);
471 | pub const __AVX512VP2INTERSECT__ = @as(c_int, 1);
472 | pub const __SHA__ = @as(c_int, 1);
473 | pub const __FXSR__ = @as(c_int, 1);
474 | pub const __XSAVE__ = @as(c_int, 1);
475 | pub const __XSAVEOPT__ = @as(c_int, 1);
476 | pub const __XSAVEC__ = @as(c_int, 1);
477 | pub const __XSAVES__ = @as(c_int, 1);
478 | pub const __CLFLUSHOPT__ = @as(c_int, 1);
479 | pub const __CLWB__ = @as(c_int, 1);
480 | pub const __SHSTK__ = @as(c_int, 1);
481 | pub const __RDPID__ = @as(c_int, 1);
482 | pub const __MOVDIRI__ = @as(c_int, 1);
483 | pub const __MOVDIR64B__ = @as(c_int, 1);
484 | pub const __INVPCID__ = @as(c_int, 1);
485 | pub const __AVX512F__ = @as(c_int, 1);
486 | pub const __AVX2__ = @as(c_int, 1);
487 | pub const __AVX__ = @as(c_int, 1);
488 | pub const __SSE4_2__ = @as(c_int, 1);
489 | pub const __SSE4_1__ = @as(c_int, 1);
490 | pub const __SSSE3__ = @as(c_int, 1);
491 | pub const __SSE3__ = @as(c_int, 1);
492 | pub const __SSE2__ = @as(c_int, 1);
493 | pub const __SSE2_MATH__ = @as(c_int, 1);
494 | pub const __SSE__ = @as(c_int, 1);
495 | pub const __SSE_MATH__ = @as(c_int, 1);
496 | pub const __MMX__ = @as(c_int, 1);
497 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 = @as(c_int, 1);
498 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 = @as(c_int, 1);
499 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 = @as(c_int, 1);
500 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 = @as(c_int, 1);
501 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 = @as(c_int, 1);
502 | pub const __SIZEOF_FLOAT128__ = @as(c_int, 16);
503 | pub const unix = @as(c_int, 1);
504 | pub const __unix = @as(c_int, 1);
505 | pub const __unix__ = @as(c_int, 1);
506 | pub const linux = @as(c_int, 1);
507 | pub const __linux = @as(c_int, 1);
508 | pub const __linux__ = @as(c_int, 1);
509 | pub const __ELF__ = @as(c_int, 1);
510 | pub const __gnu_linux__ = @as(c_int, 1);
511 | pub const __FLOAT128__ = @as(c_int, 1);
512 | pub const __STDC__ = @as(c_int, 1);
513 | pub const __STDC_HOSTED__ = @as(c_int, 1);
514 | pub const __STDC_VERSION__ = @as(c_long, 201710);
515 | pub const __STDC_UTF_16__ = @as(c_int, 1);
516 | pub const __STDC_UTF_32__ = @as(c_int, 1);
517 | pub const __GLIBC_MINOR__ = @as(c_int, 31);
518 | pub const _DEBUG = @as(c_int, 1);
519 | pub const __GCC_HAVE_DWARF2_CFI_ASM = @as(c_int, 1);
520 | pub const __STDDEF_H = "";
521 | pub const __need_ptrdiff_t = "";
522 | pub const __need_size_t = "";
523 | pub const __need_wchar_t = "";
524 | pub const __need_NULL = "";
525 | pub const __need_STDDEF_H_misc = "";
526 | pub const _PTRDIFF_T = "";
527 | pub const _SIZE_T = "";
528 | pub const _WCHAR_T = "";
529 | pub const NULL = @import("std").zig.c_translation.cast(?*anyopaque, @as(c_int, 0));
530 | pub const __CLANG_MAX_ALIGN_T_DEFINED = "";
531 | pub const GO_CGO_EXPORT_PROLOGUE_H = "";
532 | pub const GO_CGO_PROLOGUE_H = "";
533 |
--------------------------------------------------------------------------------
/src/thread_pool.zig:
--------------------------------------------------------------------------------
1 | const std = @import("std");
2 | const ThreadPool = @This();
3 |
4 | const assert = std.debug.assert;
5 | const Atomic = std.atomic.Atomic;
6 | const mtar = @import("translated/libmicrotar.zig");
7 |
8 | stack_size: u32,
9 | max_threads: u32,
10 | sync: Atomic(u32) = Atomic(u32).init(@bitCast(u32, Sync{})),
11 | idle_event: Event = .{},
12 | join_event: Event = .{},
13 | run_queue: Node.Queue = .{},
14 | threads: Atomic(?*Thread) = Atomic(?*Thread).init(null),
15 |
16 | const Sync = packed struct {
17 | /// Tracks the number of threads not searching for Tasks
18 | idle: u14 = 0,
19 | /// Tracks the number of threads spawned
20 | spawned: u14 = 0,
21 | /// What you see is what you get
22 | unused: bool = false,
23 | /// Used to not miss notifications while state = waking
24 | notified: bool = false,
25 | /// The current state of the thread pool
26 | state: enum(u2) {
27 | /// A notification can be issued to wake up a sleeping as the "waking thread".
28 | pending = 0,
29 | /// The state was notifiied with a signal. A thread is woken up.
30 | /// The first thread to transition to `waking` becomes the "waking thread".
31 | signaled,
32 | /// There is a "waking thread" among us.
33 | /// No other thread should be woken up until the waking thread transitions the state.
34 | waking,
35 | /// The thread pool was terminated. Start decremented `spawned` so that it can be joined.
36 | shutdown,
37 | } = .pending,
38 | };
39 |
40 | /// Configuration options for the thread pool.
41 | /// TODO: add CPU core affinity?
42 | pub const Config = struct {
43 | stack_size: u32 = (std.Thread.SpawnConfig{}).stack_size,
44 | max_threads: u32,
45 | };
46 |
47 | /// Statically initialize the thread pool using the configuration.
48 | pub fn init(config: Config) ThreadPool {
49 | return .{
50 | .stack_size = std.math.max(1, config.stack_size),
51 | .max_threads = std.math.max(1, config.max_threads),
52 | };
53 | }
54 |
55 | /// Wait for a thread to call shutdown() on the thread pool and kill the worker threads.
56 | pub fn deinit(self: *ThreadPool) void {
57 | self.join();
58 | self.* = undefined;
59 | }
60 |
61 | pub const ExtractData = struct {
62 | name: ?[]u8,
63 | buffer: *[]u8,
64 | bufSize: *c_int,
65 | index: *usize,
66 | header: *mtar.mtar_header_t,
67 | tar: *mtar.mtar_t
68 | };
69 |
70 | /// A Task represents the unit of Work / Job / Execution that the ThreadPool schedules.
71 | /// The user provides a `callback` which is invoked when the *Task can run on a thread.
72 | pub const Task = struct {
73 | node: Node = .{},
74 | callback: *const fn (*Task) void,
75 | data: *ExtractData
76 | };
77 |
78 | /// An unordered collection of Tasks which can be submitted for scheduling as a group.
79 | pub const Batch = struct {
80 | len: usize = 0,
81 | head: ?*Task = null,
82 | tail: ?*Task = null,
83 |
84 | /// Create a batch from a single task.
85 | pub fn from(task: *Task) Batch {
86 | return Batch{
87 | .len = 1,
88 | .head = task,
89 | .tail = task,
90 | };
91 | }
92 |
93 | /// Another batch into this one, taking ownership of its tasks.
94 | pub fn push(self: *Batch, batch: Batch) void {
95 | if (batch.len == 0) return;
96 | if (self.len == 0) {
97 | self.* = batch;
98 | } else {
99 | self.tail.?.node.next = if (batch.head) |h| &h.node else null;
100 | self.tail = batch.tail;
101 | self.len += batch.len;
102 | }
103 | }
104 | };
105 |
106 | /// Schedule a batch of tasks to be executed by some thread on the thread pool.
107 | pub fn schedule(self: *ThreadPool, batch: Batch) void {
108 | // Sanity check
109 | if (batch.len == 0) {
110 | return;
111 | }
112 |
113 | // Extract out the Node's from the Tasks
114 | var list = Node.List{
115 | .head = &batch.head.?.node,
116 | .tail = &batch.tail.?.node,
117 | };
118 |
119 | // Push the task Nodes to the most approriate queue
120 | if (Thread.current) |thread| {
121 | thread.run_buffer.push(&list) catch thread.run_queue.push(list);
122 | } else {
123 | self.run_queue.push(list);
124 | }
125 |
126 | // Try to notify a thread
127 | const is_waking = false;
128 | return self.notify(is_waking);
129 | }
130 |
131 | inline fn notify(self: *ThreadPool, is_waking: bool) void {
132 | // Fast path to check the Sync state to avoid calling into notifySlow().
133 | // If we're waking, then we need to update the state regardless
134 | if (!is_waking) {
135 | const sync = @bitCast(Sync, self.sync.load(.Monotonic));
136 | if (sync.notified) {
137 | return;
138 | }
139 | }
140 |
141 | return self.notifySlow(is_waking);
142 | }
143 |
144 | noinline fn notifySlow(self: *ThreadPool, is_waking: bool) void {
145 | var sync = @bitCast(Sync, self.sync.load(.Monotonic));
146 | while (sync.state != .shutdown) {
147 |
148 | const can_wake = is_waking or (sync.state == .pending);
149 | if (is_waking) {
150 | assert(sync.state == .waking);
151 | }
152 |
153 | var new_sync = sync;
154 | new_sync.notified = true;
155 | if (can_wake and sync.idle > 0) { // wake up an idle thread
156 | new_sync.state = .signaled;
157 | } else if (can_wake and sync.spawned < self.max_threads) { // spawn a new thread
158 | new_sync.state = .signaled;
159 | new_sync.spawned += 1;
160 | } else if (is_waking) { // no other thread to pass on "waking" status
161 | new_sync.state = .pending;
162 | } else if (sync.notified) { // nothing to update
163 | return;
164 | }
165 |
166 | // Release barrier synchronizes with Acquire in wait()
167 | // to ensure pushes to run queues happen before observing a posted notification.
168 | sync = @bitCast(Sync, self.sync.tryCompareAndSwap(
169 | @bitCast(u32, sync),
170 | @bitCast(u32, new_sync),
171 | .Release,
172 | .Monotonic,
173 | ) orelse {
174 | // We signaled to notify an idle thread
175 | if (can_wake and sync.idle > 0) {
176 | return self.idle_event.notify();
177 | }
178 |
179 | // We signaled to spawn a new thread
180 | if (can_wake and sync.spawned < self.max_threads) {
181 | const spawn_config = std.Thread.SpawnConfig{ .stack_size = self.stack_size };
182 | const thread = std.Thread.spawn(spawn_config, Thread.run, .{self}) catch return self.unregister(null);
183 | return thread.detach();
184 | }
185 |
186 | return;
187 | });
188 | }
189 | }
190 |
191 | noinline fn wait(self: *ThreadPool, _is_waking: bool) error{Shutdown}!bool {
192 | var is_idle = false;
193 | var is_waking = _is_waking;
194 | var sync = @bitCast(Sync, self.sync.load(.Monotonic));
195 |
196 | while (true) {
197 | if (sync.state == .shutdown) return error.Shutdown;
198 | if (is_waking) assert(sync.state == .waking);
199 |
200 | // Consume a notification made by notify().
201 | if (sync.notified) {
202 | var new_sync = sync;
203 | new_sync.notified = false;
204 | if (is_idle)
205 | new_sync.idle -= 1;
206 | if (sync.state == .signaled)
207 | new_sync.state = .waking;
208 |
209 | // Acquire barrier synchronizes with notify()
210 | // to ensure that pushes to run queue are observed after wait() returns.
211 | sync = @bitCast(Sync, self.sync.tryCompareAndSwap(
212 | @bitCast(u32, sync),
213 | @bitCast(u32, new_sync),
214 | .Acquire,
215 | .Monotonic,
216 | ) orelse {
217 | return is_waking or (sync.state == .signaled);
218 | });
219 |
220 | // No notification to consume.
221 | // Mark this thread as idle before sleeping on the idle_event.
222 | } else if (!is_idle) {
223 | var new_sync = sync;
224 | new_sync.idle += 1;
225 | if (is_waking)
226 | new_sync.state = .pending;
227 |
228 | sync = @bitCast(Sync, self.sync.tryCompareAndSwap(
229 | @bitCast(u32, sync),
230 | @bitCast(u32, new_sync),
231 | .Monotonic,
232 | .Monotonic,
233 | ) orelse {
234 | is_waking = false;
235 | is_idle = true;
236 | continue;
237 | });
238 |
239 | // Wait for a signal by either notify() or shutdown() without wasting cpu cycles.
240 | // TODO: Add I/O polling here.
241 | } else {
242 | self.idle_event.wait();
243 | sync = @bitCast(Sync, self.sync.load(.Monotonic));
244 | }
245 | }
246 | }
247 |
248 | /// Marks the thread pool as shutdown
249 | pub noinline fn shutdown(self: *ThreadPool) void {
250 | var sync = @bitCast(Sync, self.sync.load(.Monotonic));
251 | while (sync.state != .shutdown) {
252 | var new_sync = sync;
253 | new_sync.notified = true;
254 | new_sync.state = .shutdown;
255 | new_sync.idle = 0;
256 |
257 | // Full barrier to synchronize with both wait() and notify()
258 | sync = @bitCast(Sync, self.sync.tryCompareAndSwap(
259 | @bitCast(u32, sync),
260 | @bitCast(u32, new_sync),
261 | .AcqRel,
262 | .Monotonic,
263 | ) orelse {
264 | // Wake up any threads sleeping on the idle_event.
265 | // TODO: I/O polling notification here.
266 | if (sync.idle > 0) self.idle_event.shutdown();
267 | return;
268 | });
269 | }
270 | }
271 |
272 | fn register(noalias self: *ThreadPool, noalias thread: *Thread) void {
273 | // Push the thread onto the threads stack in a lock-free manner.
274 | var threads = self.threads.load(.Monotonic);
275 | while (true) {
276 | thread.next = threads;
277 | threads = self.threads.tryCompareAndSwap(
278 | threads,
279 | thread,
280 | .Release,
281 | .Monotonic,
282 | ) orelse break;
283 | }
284 | }
285 |
286 | fn unregister(noalias self: *ThreadPool, noalias maybe_thread: ?*Thread) void {
287 | // Un-spawn one thread, either due to a failed OS thread spawning or the thread is exitting.
288 | const one_spawned = @bitCast(u32, Sync{ .spawned = 1 });
289 | const sync = @bitCast(Sync, self.sync.fetchSub(one_spawned, .Release));
290 | assert(sync.spawned > 0);
291 |
292 | // The last thread to exit must wake up the thread pool join()er
293 | // who will start the chain to shutdown all the threads.
294 | if (sync.state == .shutdown and sync.spawned == 1) {
295 | self.join_event.notify();
296 | }
297 |
298 | // If this is a thread pool thread, wait for a shutdown signal by the thread pool join()er.
299 | const thread = maybe_thread orelse return;
300 | thread.join_event.wait();
301 |
302 | // After receiving the shutdown signal, shutdown the next thread in the pool.
303 | // We have to do that without touching the thread pool itself since it's memory is invalidated by now.
304 | // So just follow our .next link.
305 | const next_thread = thread.next orelse return;
306 | next_thread.join_event.notify();
307 | }
308 |
309 | fn join(self: *ThreadPool) void {
310 | // Wait for the thread pool to be shutdown() then for all threads to enter a joinable state
311 | var sync = @bitCast(Sync, self.sync.load(.Monotonic));
312 | if (!(sync.state == .shutdown and sync.spawned == 0)) {
313 | self.join_event.wait();
314 | sync = @bitCast(Sync, self.sync.load(.Monotonic));
315 | }
316 |
317 | assert(sync.state == .shutdown);
318 | assert(sync.spawned == 0);
319 |
320 | // If there are threads, start off the chain sending it the shutdown signal.
321 | // The thread receives the shutdown signal and sends it to the next thread, and the next..
322 | const thread = self.threads.load(.Acquire) orelse return;
323 | thread.join_event.notify();
324 | }
325 |
326 | const Thread = struct {
327 | next: ?*Thread = null,
328 | target: ?*Thread = null,
329 | join_event: Event = .{},
330 | run_queue: Node.Queue = .{},
331 | run_buffer: Node.Buffer = .{},
332 |
333 | threadlocal var current: ?*Thread = null;
334 |
335 | /// Thread entry point which runs a worker for the ThreadPool
336 | fn run(thread_pool: *ThreadPool) void {
337 | var self = Thread{};
338 | current = &self;
339 |
340 | thread_pool.register(&self);
341 | defer thread_pool.unregister(&self);
342 |
343 | var is_waking = false;
344 | while (true) {
345 | is_waking = thread_pool.wait(is_waking) catch return;
346 |
347 | while (self.pop(thread_pool)) |result| {
348 | if (result.pushed or is_waking)
349 | thread_pool.notify(is_waking);
350 | is_waking = false;
351 |
352 | const task = @fieldParentPtr(Task, "node", result.node);
353 | (task.callback)(task);
354 | }
355 | }
356 | }
357 |
358 | /// Try to dequeue a Node/Task from the ThreadPool.
359 | /// Spurious reports of dequeue() returning empty are allowed.
360 | fn pop(noalias self: *Thread, noalias thread_pool: *ThreadPool) ?Node.Buffer.Stole {
361 | // Check our local buffer first
362 | if (self.run_buffer.pop()) |node| {
363 | return Node.Buffer.Stole{
364 | .node = node,
365 | .pushed = false,
366 | };
367 | }
368 |
369 | // Then check our local queue
370 | if (self.run_buffer.consume(&self.run_queue)) |stole| {
371 | return stole;
372 | }
373 |
374 | // Then the global queue
375 | if (self.run_buffer.consume(&thread_pool.run_queue)) |stole| {
376 | return stole;
377 | }
378 |
379 | // TODO: add optimistic I/O polling here
380 |
381 | // Then try work stealing from other threads
382 | var num_threads: u32 = @bitCast(Sync, thread_pool.sync.load(.Monotonic)).spawned;
383 | while (num_threads > 0) : (num_threads -= 1) {
384 | // Traverse the stack of registered threads on the thread pool
385 | const target = self.target orelse thread_pool.threads.load(.Acquire) orelse unreachable;
386 | self.target = target.next;
387 |
388 | // Try to steal from their queue first to avoid contention (the target steal's from queue last).
389 | if (self.run_buffer.consume(&target.run_queue)) |stole| {
390 | return stole;
391 | }
392 |
393 | // Skip stealing from the buffer if we're the target.
394 | // We still steal from our own queue above given it may have just been locked the first time we tried.
395 | if (target == self) {
396 | continue;
397 | }
398 |
399 | // Steal from the buffer of a remote thread as a last resort
400 | if (self.run_buffer.steal(&target.run_buffer)) |stole| {
401 | return stole;
402 | }
403 | }
404 |
405 | return null;
406 | }
407 | };
408 |
409 | /// An event which stores 1 semaphore token and is multi-threaded safe.
410 | /// The event can be shutdown(), waking up all wait()ing threads and
411 | /// making subsequent wait()'s return immediately.
412 | const Event = struct {
413 | state: Atomic(u32) = Atomic(u32).init(EMPTY),
414 |
415 | const EMPTY = 0;
416 | const WAITING = 1;
417 | const NOTIFIED = 2;
418 | const SHUTDOWN = 3;
419 |
420 | /// Wait for and consume a notification
421 | /// or wait for the event to be shutdown entirely
422 | noinline fn wait(self: *Event) void {
423 | var acquire_with: u32 = EMPTY;
424 | var state = self.state.load(.Monotonic);
425 |
426 | while (true) {
427 | // If we're shutdown then exit early.
428 | // Acquire barrier to ensure operations before the shutdown() are seen after the wait().
429 | // Shutdown is rare so it's better to have an Acquire barrier here instead of on CAS failure + load which are common.
430 | if (state == SHUTDOWN) {
431 | std.atomic.fence(.Acquire);
432 | return;
433 | }
434 |
435 | // Consume a notification when it pops up.
436 | // Acquire barrier to ensure operations before the notify() appear after the wait().
437 | if (state == NOTIFIED) {
438 | state = self.state.tryCompareAndSwap(
439 | state,
440 | acquire_with,
441 | .Acquire,
442 | .Monotonic,
443 | ) orelse return;
444 | continue;
445 | }
446 |
447 | // There is no notification to consume, we should wait on the event by ensuring its WAITING.
448 | if (state != WAITING) blk: {
449 | state = self.state.tryCompareAndSwap(
450 | state,
451 | WAITING,
452 | .Monotonic,
453 | .Monotonic,
454 | ) orelse break :blk;
455 | continue;
456 | }
457 |
458 | // Wait on the event until a notify() or shutdown().
459 | // If we wake up to a notification, we must acquire it with WAITING instead of EMPTY
460 | // since there may be other threads sleeping on the Futex who haven't been woken up yet.
461 | //
462 | // Acquiring to WAITING will make the next notify() or shutdown() wake a sleeping futex thread
463 | // who will either exit on SHUTDOWN or acquire with WAITING again, ensuring all threads are awoken.
464 | // This unfortunately results in the last notify() or shutdown() doing an extra futex wake but that's fine.
465 | std.Thread.Futex.wait(&self.state, WAITING);
466 | state = self.state.load(.Monotonic);
467 | acquire_with = WAITING;
468 | }
469 | }
470 |
471 | /// Post a notification to the event if it doesn't have one already
472 | /// then wake up a waiting thread if there is one as well.
473 | fn notify(self: *Event) void {
474 | return self.wake(NOTIFIED, 1);
475 | }
476 |
477 | /// Marks the event as shutdown, making all future wait()'s return immediately.
478 | /// Then wakes up any threads currently waiting on the Event.
479 | fn shutdown(self: *Event) void {
480 | return self.wake(SHUTDOWN, std.math.maxInt(u32));
481 | }
482 |
483 | fn wake(self: *Event, release_with: u32, wake_threads: u32) void {
484 | // Update the Event to notifty it with the new `release_with` state (either NOTIFIED or SHUTDOWN).
485 | // Release barrier to ensure any operations before this are this to happen before the wait() in the other threads.
486 | const state = self.state.swap(release_with, .Release);
487 |
488 | // Only wake threads sleeping in futex if the state is WAITING.
489 | // Avoids unnecessary wake ups.
490 | if (state == WAITING) {
491 | std.Thread.Futex.wake(&self.state, wake_threads);
492 | }
493 | }
494 | };
495 |
496 | /// Linked list intrusive memory node and lock-free data structures to operate with it
497 | const Node = struct {
498 | next: ?*Node = null,
499 |
500 | /// A linked list of Nodes
501 | const List = struct {
502 | head: *Node,
503 | tail: *Node,
504 | };
505 |
506 | /// An unbounded multi-producer-(non blocking)-multi-consumer queue of Node pointers.
507 | const Queue = struct {
508 | stack: Atomic(usize) = Atomic(usize).init(0),
509 | cache: ?*Node = null,
510 |
511 | const HAS_CACHE: usize = 0b01;
512 | const IS_CONSUMING: usize = 0b10;
513 | const PTR_MASK: usize = ~(HAS_CACHE | IS_CONSUMING);
514 |
515 | comptime {
516 | assert(@alignOf(Node) >= ((IS_CONSUMING | HAS_CACHE) + 1));
517 | }
518 |
519 | fn push(noalias self: *Queue, list: List) void {
520 | var stack = self.stack.load(.Monotonic);
521 | while (true) {
522 | // Attach the list to the stack (pt. 1)
523 | list.tail.next = @intToPtr(?*Node, stack & PTR_MASK);
524 |
525 | // Update the stack with the list (pt. 2).
526 | // Don't change the HAS_CACHE and IS_CONSUMING bits of the consumer.
527 | var new_stack = @ptrToInt(list.head);
528 | assert(new_stack & ~PTR_MASK == 0);
529 | new_stack |= (stack & ~PTR_MASK);
530 |
531 | // Push to the stack with a release barrier for the consumer to see the proper list links.
532 | stack = self.stack.tryCompareAndSwap(
533 | stack,
534 | new_stack,
535 | .Release,
536 | .Monotonic,
537 | ) orelse break;
538 | }
539 | }
540 |
541 | fn tryAcquireConsumer(self: *Queue) error{Empty, Contended}!?*Node {
542 | var stack = self.stack.load(.Monotonic);
543 | while (true) {
544 | if (stack & IS_CONSUMING != 0)
545 | return error.Contended; // The queue already has a consumer.
546 | if (stack & (HAS_CACHE | PTR_MASK) == 0)
547 | return error.Empty; // The queue is empty when there's nothing cached and nothing in the stack.
548 |
549 | // When we acquire the consumer, also consume the pushed stack if the cache is empty.
550 | var new_stack = stack | HAS_CACHE | IS_CONSUMING;
551 | if (stack & HAS_CACHE == 0) {
552 | assert(stack & PTR_MASK != 0);
553 | new_stack &= ~PTR_MASK;
554 | }
555 |
556 | // Acquire barrier on getting the consumer to see cache/Node updates done by previous consumers
557 | // and to ensure our cache/Node updates in pop() happen after that of previous consumers.
558 | stack = self.stack.tryCompareAndSwap(
559 | stack,
560 | new_stack,
561 | .Acquire,
562 | .Monotonic,
563 | ) orelse return self.cache orelse @intToPtr(*Node, stack & PTR_MASK);
564 | }
565 | }
566 |
567 | fn releaseConsumer(noalias self: *Queue, noalias consumer: ?*Node) void {
568 | // Stop consuming and remove the HAS_CACHE bit as well if the consumer's cache is empty.
569 | // When HAS_CACHE bit is zeroed, the next consumer will acquire the pushed stack nodes.
570 | var remove = IS_CONSUMING;
571 | if (consumer == null)
572 | remove |= HAS_CACHE;
573 |
574 | // Release the consumer with a release barrier to ensure cache/node accesses
575 | // happen before the consumer was released and before the next consumer starts using the cache.
576 | self.cache = consumer;
577 | const stack = self.stack.fetchSub(remove, .Release);
578 | assert(stack & remove != 0);
579 | }
580 |
581 | fn pop(noalias self: *Queue, noalias consumer_ref: *?*Node) ?*Node {
582 | // Check the consumer cache (fast path)
583 | if (consumer_ref.*) |node| {
584 | consumer_ref.* = node.next;
585 | return node;
586 | }
587 |
588 | // Load the stack to see if there was anything pushed that we could grab.
589 | var stack = self.stack.load(.Monotonic);
590 | assert(stack & IS_CONSUMING != 0);
591 | if (stack & PTR_MASK == 0) {
592 | return null;
593 | }
594 |
595 | // Nodes have been pushed to the stack, grab then with an Acquire barrier to see the Node links.
596 | stack = self.stack.swap(HAS_CACHE | IS_CONSUMING, .Acquire);
597 | assert(stack & IS_CONSUMING != 0);
598 | assert(stack & PTR_MASK != 0);
599 |
600 | const node = @intToPtr(*Node, stack & PTR_MASK);
601 | consumer_ref.* = node.next;
602 | return node;
603 | }
604 | };
605 |
606 | /// A bounded single-producer, multi-consumer ring buffer for node pointers.
607 | const Buffer = struct {
608 | head: Atomic(Index) = Atomic(Index).init(0),
609 | tail: Atomic(Index) = Atomic(Index).init(0),
610 | array: [capacity]Atomic(*Node) = undefined,
611 |
612 | const Index = u32;
613 | const capacity = 256; // Appears to be a pretty good trade-off in space vs contended throughput
614 | comptime {
615 | assert(std.math.maxInt(Index) >= capacity);
616 | assert(std.math.isPowerOfTwo(capacity));
617 | }
618 |
619 | fn push(noalias self: *Buffer, noalias list: *List) error{Overflow}!void {
620 | var head = self.head.load(.Monotonic);
621 | var tail = self.tail.loadUnchecked(); // we're the only thread that can change this
622 |
623 | while (true) {
624 | var size = tail -% head;
625 | assert(size <= capacity);
626 |
627 | // Push nodes from the list to the buffer if it's not empty..
628 | if (size < capacity) {
629 | var nodes: ?*Node = list.head;
630 | while (size < capacity) : (size += 1) {
631 | const node = nodes orelse break;
632 | nodes = node.next;
633 |
634 | // Array written atomically with weakest ordering since it could be getting atomically read by steal().
635 | self.array[tail % capacity].store(node, .Unordered);
636 | tail +%= 1;
637 | }
638 |
639 | // Release barrier synchronizes with Acquire loads for steal()ers to see the array writes.
640 | self.tail.store(tail, .Release);
641 |
642 | // Update the list with the nodes we pushed to the buffer and try again if there's more.
643 | list.head = nodes orelse return;
644 | std.atomic.spinLoopHint();
645 | head = self.head.load(.Monotonic);
646 | continue;
647 | }
648 |
649 | // Try to steal/overflow half of the tasks in the buffer to make room for future push()es.
650 | // Migrating half amortizes the cost of stealing while requiring future pops to still use the buffer.
651 | // Acquire barrier to ensure the linked list creation after the steal only happens after we succesfully steal.
652 | var migrate = size / 2;
653 | head = self.head.tryCompareAndSwap(
654 | head,
655 | head +% migrate,
656 | .Acquire,
657 | .Monotonic,
658 | ) orelse {
659 | // Link the migrated Nodes together
660 | const first = self.array[head % capacity].loadUnchecked();
661 | while (migrate > 0) : (migrate -= 1) {
662 | const prev = self.array[head % capacity].loadUnchecked();
663 | head +%= 1;
664 | prev.next = self.array[head % capacity].loadUnchecked();
665 | }
666 |
667 | // Append the list that was supposed to be pushed to the end of the migrated Nodes
668 | const last = self.array[(head -% 1) % capacity].loadUnchecked();
669 | last.next = list.head;
670 | list.tail.next = null;
671 |
672 | // Return the migrated nodes + the original list as overflowed
673 | list.head = first;
674 | return error.Overflow;
675 | };
676 | }
677 | }
678 |
679 | fn pop(self: *Buffer) ?*Node {
680 | var head = self.head.load(.Monotonic);
681 | var tail = self.tail.loadUnchecked(); // we're the only thread that can change this
682 |
683 | while (true) {
684 | // Quick sanity check and return null when not empty
685 | var size = tail -% head;
686 | assert(size <= capacity);
687 | if (size == 0) {
688 | return null;
689 | }
690 |
691 | // Dequeue with an acquire barrier to ensure any writes done to the Node
692 | // only happen after we succesfully claim it from the array.
693 | head = self.head.tryCompareAndSwap(
694 | head,
695 | head +% 1,
696 | .Acquire,
697 | .Monotonic,
698 | ) orelse return self.array[head % capacity].loadUnchecked();
699 | }
700 | }
701 |
702 | const Stole = struct {
703 | node: *Node,
704 | pushed: bool,
705 | };
706 |
707 | fn consume(noalias self: *Buffer, noalias queue: *Queue) ?Stole {
708 | var consumer = queue.tryAcquireConsumer() catch return null;
709 | defer queue.releaseConsumer(consumer);
710 |
711 | const head = self.head.load(.Monotonic);
712 | const tail = self.tail.loadUnchecked(); // we're the only thread that can change this
713 |
714 | const size = tail -% head;
715 | assert(size <= capacity);
716 | assert(size == 0); // we should only be consuming if our array is empty
717 |
718 | // Pop nodes from the queue and push them to our array.
719 | // Atomic stores to the array as steal() threads may be atomically reading from it.
720 | var pushed: Index = 0;
721 | while (pushed < capacity) : (pushed += 1) {
722 | const node = queue.pop(&consumer) orelse break;
723 | self.array[(tail +% pushed) % capacity].store(node, .Unordered);
724 | }
725 |
726 | // We will be returning one node that we stole from the queue.
727 | // Get an extra, and if that's not possible, take one from our array.
728 | const node = queue.pop(&consumer) orelse blk: {
729 | if (pushed == 0) return null;
730 | pushed -= 1;
731 | break :blk self.array[(tail +% pushed) % capacity].loadUnchecked();
732 | };
733 |
734 | // Update the array tail with the nodes we pushed to it.
735 | // Release barrier to synchronize with Acquire barrier in steal()'s to see the written array Nodes.
736 | if (pushed > 0) self.tail.store(tail +% pushed, .Release);
737 | return Stole{
738 | .node = node,
739 | .pushed = pushed > 0,
740 | };
741 | }
742 |
743 | fn steal(noalias self: *Buffer, noalias buffer: *Buffer) ?Stole {
744 | const head = self.head.load(.Monotonic);
745 | const tail = self.tail.loadUnchecked(); // we're the only thread that can change this
746 |
747 | const size = tail -% head;
748 | assert(size <= capacity);
749 | assert(size == 0); // we should only be stealing if our array is empty
750 |
751 | while (true) : (std.atomic.spinLoopHint()) {
752 | const buffer_head = buffer.head.load(.Acquire);
753 | const buffer_tail = buffer.tail.load(.Acquire);
754 |
755 | // Overly large size indicates the the tail was updated a lot after the head was loaded.
756 | // Reload both and try again.
757 | const buffer_size = buffer_tail -% buffer_head;
758 | if (buffer_size > capacity) {
759 | continue;
760 | }
761 |
762 | // Try to steal half (divCeil) to amortize the cost of stealing from other threads.
763 | const steal_size = buffer_size - (buffer_size / 2);
764 | if (steal_size == 0) {
765 | return null;
766 | }
767 |
768 | // Copy the nodes we will steal from the target's array to our own.
769 | // Atomically load from the target buffer array as it may be pushing and atomically storing to it.
770 | // Atomic store to our array as other steal() threads may be atomically loading from it as above.
771 | var i: Index = 0;
772 | while (i < steal_size) : (i += 1) {
773 | const node = buffer.array[(buffer_head +% i) % capacity].load(.Unordered);
774 | self.array[(tail +% i) % capacity].store(node, .Unordered);
775 | }
776 |
777 | // Try to commit the steal from the target buffer using:
778 | // - an Acquire barrier to ensure that we only interact with the stolen Nodes after the steal was committed.
779 | // - a Release barrier to ensure that the Nodes are copied above prior to the committing of the steal
780 | // because if they're copied after the steal, the could be getting rewritten by the target's push().
781 | _ = buffer.head.compareAndSwap(
782 | buffer_head,
783 | buffer_head +% steal_size,
784 | .AcqRel,
785 | .Monotonic,
786 | ) orelse {
787 | // Pop one from the nodes we stole as we'll be returning it
788 | const pushed = steal_size - 1;
789 | const node = self.array[(tail +% pushed) % capacity].loadUnchecked();
790 |
791 | // Update the array tail with the nodes we pushed to it.
792 | // Release barrier to synchronize with Acquire barrier in steal()'s to see the written array Nodes.
793 | if (pushed > 0) self.tail.store(tail +% pushed, .Release);
794 | return Stole{
795 | .node = node,
796 | .pushed = pushed > 0,
797 | };
798 | };
799 | }
800 | }
801 | };
802 | };
--------------------------------------------------------------------------------
/src/translated/liblz4.zig:
--------------------------------------------------------------------------------
1 | pub const __builtin_bswap16 = @import("std").zig.c_builtins.__builtin_bswap16;
2 | pub const __builtin_bswap32 = @import("std").zig.c_builtins.__builtin_bswap32;
3 | pub const __builtin_bswap64 = @import("std").zig.c_builtins.__builtin_bswap64;
4 | pub const __builtin_signbit = @import("std").zig.c_builtins.__builtin_signbit;
5 | pub const __builtin_signbitf = @import("std").zig.c_builtins.__builtin_signbitf;
6 | pub const __builtin_popcount = @import("std").zig.c_builtins.__builtin_popcount;
7 | pub const __builtin_ctz = @import("std").zig.c_builtins.__builtin_ctz;
8 | pub const __builtin_clz = @import("std").zig.c_builtins.__builtin_clz;
9 | pub const __builtin_sqrt = @import("std").zig.c_builtins.__builtin_sqrt;
10 | pub const __builtin_sqrtf = @import("std").zig.c_builtins.__builtin_sqrtf;
11 | pub const __builtin_sin = @import("std").zig.c_builtins.__builtin_sin;
12 | pub const __builtin_sinf = @import("std").zig.c_builtins.__builtin_sinf;
13 | pub const __builtin_cos = @import("std").zig.c_builtins.__builtin_cos;
14 | pub const __builtin_cosf = @import("std").zig.c_builtins.__builtin_cosf;
15 | pub const __builtin_exp = @import("std").zig.c_builtins.__builtin_exp;
16 | pub const __builtin_expf = @import("std").zig.c_builtins.__builtin_expf;
17 | pub const __builtin_exp2 = @import("std").zig.c_builtins.__builtin_exp2;
18 | pub const __builtin_exp2f = @import("std").zig.c_builtins.__builtin_exp2f;
19 | pub const __builtin_log = @import("std").zig.c_builtins.__builtin_log;
20 | pub const __builtin_logf = @import("std").zig.c_builtins.__builtin_logf;
21 | pub const __builtin_log2 = @import("std").zig.c_builtins.__builtin_log2;
22 | pub const __builtin_log2f = @import("std").zig.c_builtins.__builtin_log2f;
23 | pub const __builtin_log10 = @import("std").zig.c_builtins.__builtin_log10;
24 | pub const __builtin_log10f = @import("std").zig.c_builtins.__builtin_log10f;
25 | pub const __builtin_abs = @import("std").zig.c_builtins.__builtin_abs;
26 | pub const __builtin_fabs = @import("std").zig.c_builtins.__builtin_fabs;
27 | pub const __builtin_fabsf = @import("std").zig.c_builtins.__builtin_fabsf;
28 | pub const __builtin_floor = @import("std").zig.c_builtins.__builtin_floor;
29 | pub const __builtin_floorf = @import("std").zig.c_builtins.__builtin_floorf;
30 | pub const __builtin_ceil = @import("std").zig.c_builtins.__builtin_ceil;
31 | pub const __builtin_ceilf = @import("std").zig.c_builtins.__builtin_ceilf;
32 | pub const __builtin_trunc = @import("std").zig.c_builtins.__builtin_trunc;
33 | pub const __builtin_truncf = @import("std").zig.c_builtins.__builtin_truncf;
34 | pub const __builtin_round = @import("std").zig.c_builtins.__builtin_round;
35 | pub const __builtin_roundf = @import("std").zig.c_builtins.__builtin_roundf;
36 | pub const __builtin_strlen = @import("std").zig.c_builtins.__builtin_strlen;
37 | pub const __builtin_strcmp = @import("std").zig.c_builtins.__builtin_strcmp;
38 | pub const __builtin_object_size = @import("std").zig.c_builtins.__builtin_object_size;
39 | pub const __builtin___memset_chk = @import("std").zig.c_builtins.__builtin___memset_chk;
40 | pub const __builtin_memset = @import("std").zig.c_builtins.__builtin_memset;
41 | pub const __builtin___memcpy_chk = @import("std").zig.c_builtins.__builtin___memcpy_chk;
42 | pub const __builtin_memcpy = @import("std").zig.c_builtins.__builtin_memcpy;
43 | pub const __builtin_expect = @import("std").zig.c_builtins.__builtin_expect;
44 | pub const __builtin_nanf = @import("std").zig.c_builtins.__builtin_nanf;
45 | pub const __builtin_huge_valf = @import("std").zig.c_builtins.__builtin_huge_valf;
46 | pub const __builtin_inff = @import("std").zig.c_builtins.__builtin_inff;
47 | pub const __builtin_isnan = @import("std").zig.c_builtins.__builtin_isnan;
48 | pub const __builtin_isinf = @import("std").zig.c_builtins.__builtin_isinf;
49 | pub const __builtin_isinf_sign = @import("std").zig.c_builtins.__builtin_isinf_sign;
50 | pub const __has_builtin = @import("std").zig.c_builtins.__has_builtin;
51 | pub const __builtin_assume = @import("std").zig.c_builtins.__builtin_assume;
52 | pub const __builtin_unreachable = @import("std").zig.c_builtins.__builtin_unreachable;
53 | pub const __builtin_constant_p = @import("std").zig.c_builtins.__builtin_constant_p;
54 | pub const __builtin_mul_overflow = @import("std").zig.c_builtins.__builtin_mul_overflow;
55 | pub const ptrdiff_t = c_long;
56 | pub const wchar_t = c_int;
57 | pub const max_align_t = extern struct {
58 | __clang_max_align_nonce1: c_longlong align(8),
59 | __clang_max_align_nonce2: c_longdouble align(16),
60 | };
61 | pub extern fn LZ4_versionNumber() c_int;
62 | pub extern fn LZ4_versionString() [*c]const u8;
63 | pub extern fn LZ4_compress_default(src: [*c]const u8, dst: [*c]u8, srcSize: c_int, dstCapacity: c_int) c_int;
64 | pub extern fn LZ4_decompress_safe(src: [*c]const u8, dst: [*c]u8, compressedSize: c_int, dstCapacity: c_int) c_int;
65 | pub extern fn LZ4_compressBound(inputSize: c_int) c_int;
66 | pub extern fn LZ4_compress_fast(src: [*c]const u8, dst: [*c]u8, srcSize: c_int, dstCapacity: c_int, acceleration: c_int) c_int;
67 | pub extern fn LZ4_sizeofState() c_int;
68 | pub extern fn LZ4_compress_fast_extState(state: ?*anyopaque, src: [*c]const u8, dst: [*c]u8, srcSize: c_int, dstCapacity: c_int, acceleration: c_int) c_int;
69 | pub extern fn LZ4_compress_destSize(src: [*c]const u8, dst: [*c]u8, srcSizePtr: [*c]c_int, targetDstSize: c_int) c_int;
70 | pub extern fn LZ4_decompress_safe_partial(src: [*c]const u8, dst: [*c]u8, srcSize: c_int, targetOutputSize: c_int, dstCapacity: c_int) c_int;
71 | pub const LZ4_u32 = u32;
72 | pub const LZ4_byte = u8;
73 | pub const struct_LZ4_stream_t_internal = extern struct {
74 | hashTable: [4096]LZ4_u32,
75 | dictionary: [*c]const LZ4_byte,
76 | dictCtx: [*c]const LZ4_stream_t_internal,
77 | currentOffset: LZ4_u32,
78 | tableType: LZ4_u32,
79 | dictSize: LZ4_u32,
80 | };
81 | pub const LZ4_stream_t_internal = struct_LZ4_stream_t_internal;
82 | pub const union_LZ4_stream_u = extern union {
83 | minStateSize: [16416]u8,
84 | internal_donotuse: LZ4_stream_t_internal,
85 | };
86 | pub const LZ4_stream_t = union_LZ4_stream_u;
87 | pub extern fn LZ4_createStream() [*c]LZ4_stream_t;
88 | pub extern fn LZ4_freeStream(streamPtr: [*c]LZ4_stream_t) c_int;
89 | pub extern fn LZ4_resetStream_fast(streamPtr: [*c]LZ4_stream_t) void;
90 | pub extern fn LZ4_loadDict(streamPtr: [*c]LZ4_stream_t, dictionary: [*c]const u8, dictSize: c_int) c_int;
91 | pub extern fn LZ4_compress_fast_continue(streamPtr: [*c]LZ4_stream_t, src: [*c]const u8, dst: [*c]u8, srcSize: c_int, dstCapacity: c_int, acceleration: c_int) c_int;
92 | pub extern fn LZ4_saveDict(streamPtr: [*c]LZ4_stream_t, safeBuffer: [*c]u8, maxDictSize: c_int) c_int;
93 | pub const union_LZ4_streamDecode_u = extern union {
94 | minStateSize: [32]u8,
95 | internal_donotuse: LZ4_streamDecode_t_internal,
96 | };
97 | pub const LZ4_streamDecode_t = union_LZ4_streamDecode_u;
98 | pub extern fn LZ4_createStreamDecode() [*c]LZ4_streamDecode_t;
99 | pub extern fn LZ4_freeStreamDecode(LZ4_stream: [*c]LZ4_streamDecode_t) c_int;
100 | pub extern fn LZ4_setStreamDecode(LZ4_streamDecode: [*c]LZ4_streamDecode_t, dictionary: [*c]const u8, dictSize: c_int) c_int;
101 | pub extern fn LZ4_decoderRingBufferSize(maxBlockSize: c_int) c_int;
102 | pub extern fn LZ4_decompress_safe_continue(LZ4_streamDecode: [*c]LZ4_streamDecode_t, src: [*c]const u8, dst: [*c]u8, srcSize: c_int, dstCapacity: c_int) c_int;
103 | pub extern fn LZ4_decompress_safe_usingDict(src: [*c]const u8, dst: [*c]u8, srcSize: c_int, dstCapacity: c_int, dictStart: [*c]const u8, dictSize: c_int) c_int;
104 | pub extern fn LZ4_decompress_safe_partial_usingDict(src: [*c]const u8, dst: [*c]u8, compressedSize: c_int, targetOutputSize: c_int, maxOutputSize: c_int, dictStart: [*c]const u8, dictSize: c_int) c_int;
105 | pub const __u_char = u8;
106 | pub const __u_short = c_ushort;
107 | pub const __u_int = c_uint;
108 | pub const __u_long = c_ulong;
109 | pub const __int8_t = i8;
110 | pub const __uint8_t = u8;
111 | pub const __int16_t = c_short;
112 | pub const __uint16_t = c_ushort;
113 | pub const __int32_t = c_int;
114 | pub const __uint32_t = c_uint;
115 | pub const __int64_t = c_long;
116 | pub const __uint64_t = c_ulong;
117 | pub const __int_least8_t = __int8_t;
118 | pub const __uint_least8_t = __uint8_t;
119 | pub const __int_least16_t = __int16_t;
120 | pub const __uint_least16_t = __uint16_t;
121 | pub const __int_least32_t = __int32_t;
122 | pub const __uint_least32_t = __uint32_t;
123 | pub const __int_least64_t = __int64_t;
124 | pub const __uint_least64_t = __uint64_t;
125 | pub const __quad_t = c_long;
126 | pub const __u_quad_t = c_ulong;
127 | pub const __intmax_t = c_long;
128 | pub const __uintmax_t = c_ulong;
129 | pub const __dev_t = c_ulong;
130 | pub const __uid_t = c_uint;
131 | pub const __gid_t = c_uint;
132 | pub const __ino_t = c_ulong;
133 | pub const __ino64_t = c_ulong;
134 | pub const __mode_t = c_uint;
135 | pub const __nlink_t = c_ulong;
136 | pub const __off_t = c_long;
137 | pub const __off64_t = c_long;
138 | pub const __pid_t = c_int;
139 | pub const __fsid_t = extern struct {
140 | __val: [2]c_int,
141 | };
142 | pub const __clock_t = c_long;
143 | pub const __rlim_t = c_ulong;
144 | pub const __rlim64_t = c_ulong;
145 | pub const __id_t = c_uint;
146 | pub const __time_t = c_long;
147 | pub const __useconds_t = c_uint;
148 | pub const __suseconds_t = c_long;
149 | pub const __suseconds64_t = c_long;
150 | pub const __daddr_t = c_int;
151 | pub const __key_t = c_int;
152 | pub const __clockid_t = c_int;
153 | pub const __timer_t = ?*anyopaque;
154 | pub const __blksize_t = c_long;
155 | pub const __blkcnt_t = c_long;
156 | pub const __blkcnt64_t = c_long;
157 | pub const __fsblkcnt_t = c_ulong;
158 | pub const __fsblkcnt64_t = c_ulong;
159 | pub const __fsfilcnt_t = c_ulong;
160 | pub const __fsfilcnt64_t = c_ulong;
161 | pub const __fsword_t = c_long;
162 | pub const __ssize_t = c_long;
163 | pub const __syscall_slong_t = c_long;
164 | pub const __syscall_ulong_t = c_ulong;
165 | pub const __loff_t = __off64_t;
166 | pub const __caddr_t = [*c]u8;
167 | pub const __intptr_t = c_long;
168 | pub const __socklen_t = c_uint;
169 | pub const __sig_atomic_t = c_int;
170 | pub const int_least8_t = __int_least8_t;
171 | pub const int_least16_t = __int_least16_t;
172 | pub const int_least32_t = __int_least32_t;
173 | pub const int_least64_t = __int_least64_t;
174 | pub const uint_least8_t = __uint_least8_t;
175 | pub const uint_least16_t = __uint_least16_t;
176 | pub const uint_least32_t = __uint_least32_t;
177 | pub const uint_least64_t = __uint_least64_t;
178 | pub const int_fast8_t = i8;
179 | pub const int_fast16_t = c_long;
180 | pub const int_fast32_t = c_long;
181 | pub const int_fast64_t = c_long;
182 | pub const uint_fast8_t = u8;
183 | pub const uint_fast16_t = c_ulong;
184 | pub const uint_fast32_t = c_ulong;
185 | pub const uint_fast64_t = c_ulong;
186 | pub const intmax_t = __intmax_t;
187 | pub const uintmax_t = __uintmax_t;
188 | pub const LZ4_i8 = i8;
189 | pub const LZ4_u16 = u16;
190 | pub extern fn LZ4_initStream(buffer: ?*anyopaque, size: usize) [*c]LZ4_stream_t;
191 | pub const LZ4_streamDecode_t_internal = extern struct {
192 | externalDict: [*c]const LZ4_byte,
193 | prefixEnd: [*c]const LZ4_byte,
194 | extDictSize: usize,
195 | prefixSize: usize,
196 | };
197 | pub extern fn LZ4_compress(src: [*c]const u8, dest: [*c]u8, srcSize: c_int) c_int;
198 | pub extern fn LZ4_compress_limitedOutput(src: [*c]const u8, dest: [*c]u8, srcSize: c_int, maxOutputSize: c_int) c_int;
199 | pub extern fn LZ4_compress_withState(state: ?*anyopaque, source: [*c]const u8, dest: [*c]u8, inputSize: c_int) c_int;
200 | pub extern fn LZ4_compress_limitedOutput_withState(state: ?*anyopaque, source: [*c]const u8, dest: [*c]u8, inputSize: c_int, maxOutputSize: c_int) c_int;
201 | pub extern fn LZ4_compress_continue(LZ4_streamPtr: [*c]LZ4_stream_t, source: [*c]const u8, dest: [*c]u8, inputSize: c_int) c_int;
202 | pub extern fn LZ4_compress_limitedOutput_continue(LZ4_streamPtr: [*c]LZ4_stream_t, source: [*c]const u8, dest: [*c]u8, inputSize: c_int, maxOutputSize: c_int) c_int;
203 | pub extern fn LZ4_uncompress(source: [*c]const u8, dest: [*c]u8, outputSize: c_int) c_int;
204 | pub extern fn LZ4_uncompress_unknownOutputSize(source: [*c]const u8, dest: [*c]u8, @"isize": c_int, maxOutputSize: c_int) c_int;
205 | pub extern fn LZ4_create(inputBuffer: [*c]u8) ?*anyopaque;
206 | pub extern fn LZ4_sizeofStreamState() c_int;
207 | pub extern fn LZ4_resetStreamState(state: ?*anyopaque, inputBuffer: [*c]u8) c_int;
208 | pub extern fn LZ4_slideInputBuffer(state: ?*anyopaque) [*c]u8;
209 | pub extern fn LZ4_decompress_safe_withPrefix64k(src: [*c]const u8, dst: [*c]u8, compressedSize: c_int, maxDstSize: c_int) c_int;
210 | pub extern fn LZ4_decompress_fast_withPrefix64k(src: [*c]const u8, dst: [*c]u8, originalSize: c_int) c_int;
211 | pub extern fn LZ4_decompress_fast(src: [*c]const u8, dst: [*c]u8, originalSize: c_int) c_int;
212 | pub extern fn LZ4_decompress_fast_continue(LZ4_streamDecode: [*c]LZ4_streamDecode_t, src: [*c]const u8, dst: [*c]u8, originalSize: c_int) c_int;
213 | pub extern fn LZ4_decompress_fast_usingDict(src: [*c]const u8, dst: [*c]u8, originalSize: c_int, dictStart: [*c]const u8, dictSize: c_int) c_int;
214 | pub extern fn LZ4_resetStream(streamPtr: [*c]LZ4_stream_t) void;
215 | pub const __INTMAX_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `L`"); // (no file):66:9
216 | pub const __UINTMAX_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `UL`"); // (no file):72:9
217 | pub const __INT64_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `L`"); // (no file):163:9
218 | pub const __UINT32_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `U`"); // (no file):185:9
219 | pub const __UINT64_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `UL`"); // (no file):193:9
220 | pub const __seg_gs = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // (no file):315:9
221 | pub const __seg_fs = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // (no file):316:9
222 | pub const offsetof = @compileError("unable to translate macro: undefined identifier `__builtin_offsetof`"); // /home/theseyan/zig/lib/include/stddef.h:104:9
223 | pub const LZ4LIB_VISIBILITY = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // deps/lz4/lib/lz4.h:87:13
224 | pub const LZ4_QUOTE = @compileError("unable to translate C expr: unexpected token '#'"); // deps/lz4/lib/lz4.h:108:9
225 | pub const __GLIBC_USE = @compileError("unable to translate macro: undefined identifier `__GLIBC_USE_`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/features.h:186:9
226 | pub const __glibc_has_attribute = @compileError("unable to translate macro: undefined identifier `__has_attribute`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:44:10
227 | pub const __glibc_has_extension = @compileError("unable to translate macro: undefined identifier `__has_extension`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:54:10
228 | pub const __THROW = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:78:11
229 | pub const __THROWNL = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:79:11
230 | pub const __NTH = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:80:11
231 | pub const __NTHNL = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:81:11
232 | pub const __CONCAT = @compileError("unable to translate C expr: unexpected token '##'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:123:9
233 | pub const __STRING = @compileError("unable to translate C expr: unexpected token '#'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:124:9
234 | pub const __warnattr = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:158:10
235 | pub const __errordecl = @compileError("unable to translate C expr: unexpected token 'extern'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:159:10
236 | pub const __flexarr = @compileError("unable to translate C expr: unexpected token '['"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:167:10
237 | pub const __REDIRECT = @compileError("unable to translate macro: undefined identifier `__asm__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:198:10
238 | pub const __REDIRECT_NTH = @compileError("unable to translate macro: undefined identifier `__asm__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:205:11
239 | pub const __REDIRECT_NTHNL = @compileError("unable to translate macro: undefined identifier `__asm__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:207:11
240 | pub const __ASMNAME2 = @compileError("unable to translate C expr: unexpected token 'Identifier'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:211:10
241 | pub const __attribute_malloc__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:232:10
242 | pub const __attribute_alloc_size__ = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:243:10
243 | pub const __attribute_pure__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:250:10
244 | pub const __attribute_const__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:257:10
245 | pub const __attribute_maybe_unused__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:263:10
246 | pub const __attribute_used__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:272:10
247 | pub const __attribute_noinline__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:273:10
248 | pub const __attribute_deprecated__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:281:10
249 | pub const __attribute_deprecated_msg__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:291:10
250 | pub const __attribute_format_arg__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:304:10
251 | pub const __attribute_format_strfmon__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:314:10
252 | pub const __nonnull = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:324:11
253 | pub const __returns_nonnull = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:337:10
254 | pub const __attribute_warn_unused_result__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:346:10
255 | pub const __always_inline = @compileError("unable to translate macro: undefined identifier `__inline`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:364:10
256 | pub const __attribute_artificial__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:373:10
257 | pub const __extern_inline = @compileError("unable to translate macro: undefined identifier `__inline`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:391:11
258 | pub const __extern_always_inline = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:392:11
259 | pub const __restrict_arr = @compileError("unable to translate macro: undefined identifier `__restrict`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:435:10
260 | pub const __attribute_copy__ = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:484:10
261 | pub const __LDBL_REDIR2_DECL = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:560:10
262 | pub const __LDBL_REDIR_DECL = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:561:10
263 | pub const __glibc_macro_warning1 = @compileError("unable to translate macro: undefined identifier `_Pragma`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:575:10
264 | pub const __glibc_macro_warning = @compileError("unable to translate macro: undefined identifier `GCC`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:576:10
265 | pub const __attr_access = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:612:11
266 | pub const __attr_access_none = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:613:11
267 | pub const __attr_dealloc = @compileError("unable to translate C expr: unexpected token 'Eof'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:623:10
268 | pub const __attribute_returns_twice__ = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // /home/theseyan/zig/lib/libc/include/generic-glibc/sys/cdefs.h:630:10
269 | pub const __STD_TYPE = @compileError("unable to translate C expr: unexpected token 'typedef'"); // /home/theseyan/zig/lib/libc/include/generic-glibc/bits/types.h:137:10
270 | pub const __FSID_T_TYPE = @compileError("unable to translate macro: undefined identifier `__val`"); // /home/theseyan/zig/lib/libc/include/x86_64-linux-gnu/bits/typesizes.h:73:9
271 | pub const LZ4_DEPRECATED = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // deps/lz4/lib/lz4.h:704:13
272 | pub const __llvm__ = @as(c_int, 1);
273 | pub const __clang__ = @as(c_int, 1);
274 | pub const __clang_major__ = @as(c_int, 13);
275 | pub const __clang_minor__ = @as(c_int, 0);
276 | pub const __clang_patchlevel__ = @as(c_int, 1);
277 | pub const __clang_version__ = "13.0.1 (git@github.com:ziglang/zig-bootstrap.git 81f0e6c5b902ead84753490db4f0007d08df964a)";
278 | pub const __GNUC__ = @as(c_int, 4);
279 | pub const __GNUC_MINOR__ = @as(c_int, 2);
280 | pub const __GNUC_PATCHLEVEL__ = @as(c_int, 1);
281 | pub const __GXX_ABI_VERSION = @as(c_int, 1002);
282 | pub const __ATOMIC_RELAXED = @as(c_int, 0);
283 | pub const __ATOMIC_CONSUME = @as(c_int, 1);
284 | pub const __ATOMIC_ACQUIRE = @as(c_int, 2);
285 | pub const __ATOMIC_RELEASE = @as(c_int, 3);
286 | pub const __ATOMIC_ACQ_REL = @as(c_int, 4);
287 | pub const __ATOMIC_SEQ_CST = @as(c_int, 5);
288 | pub const __OPENCL_MEMORY_SCOPE_WORK_ITEM = @as(c_int, 0);
289 | pub const __OPENCL_MEMORY_SCOPE_WORK_GROUP = @as(c_int, 1);
290 | pub const __OPENCL_MEMORY_SCOPE_DEVICE = @as(c_int, 2);
291 | pub const __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES = @as(c_int, 3);
292 | pub const __OPENCL_MEMORY_SCOPE_SUB_GROUP = @as(c_int, 4);
293 | pub const __PRAGMA_REDEFINE_EXTNAME = @as(c_int, 1);
294 | pub const __VERSION__ = "Clang 13.0.1 (git@github.com:ziglang/zig-bootstrap.git 81f0e6c5b902ead84753490db4f0007d08df964a)";
295 | pub const __OBJC_BOOL_IS_BOOL = @as(c_int, 0);
296 | pub const __CONSTANT_CFSTRINGS__ = @as(c_int, 1);
297 | pub const __clang_literal_encoding__ = "UTF-8";
298 | pub const __clang_wide_literal_encoding__ = "UTF-32";
299 | pub const __ORDER_LITTLE_ENDIAN__ = @as(c_int, 1234);
300 | pub const __ORDER_BIG_ENDIAN__ = @as(c_int, 4321);
301 | pub const __ORDER_PDP_ENDIAN__ = @as(c_int, 3412);
302 | pub const __BYTE_ORDER__ = __ORDER_LITTLE_ENDIAN__;
303 | pub const __LITTLE_ENDIAN__ = @as(c_int, 1);
304 | pub const _LP64 = @as(c_int, 1);
305 | pub const __LP64__ = @as(c_int, 1);
306 | pub const __CHAR_BIT__ = @as(c_int, 8);
307 | pub const __SCHAR_MAX__ = @as(c_int, 127);
308 | pub const __SHRT_MAX__ = @as(c_int, 32767);
309 | pub const __INT_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
310 | pub const __LONG_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
311 | pub const __LONG_LONG_MAX__ = @as(c_longlong, 9223372036854775807);
312 | pub const __WCHAR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
313 | pub const __WINT_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
314 | pub const __INTMAX_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
315 | pub const __SIZE_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
316 | pub const __UINTMAX_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
317 | pub const __PTRDIFF_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
318 | pub const __INTPTR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
319 | pub const __UINTPTR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
320 | pub const __SIZEOF_DOUBLE__ = @as(c_int, 8);
321 | pub const __SIZEOF_FLOAT__ = @as(c_int, 4);
322 | pub const __SIZEOF_INT__ = @as(c_int, 4);
323 | pub const __SIZEOF_LONG__ = @as(c_int, 8);
324 | pub const __SIZEOF_LONG_DOUBLE__ = @as(c_int, 16);
325 | pub const __SIZEOF_LONG_LONG__ = @as(c_int, 8);
326 | pub const __SIZEOF_POINTER__ = @as(c_int, 8);
327 | pub const __SIZEOF_SHORT__ = @as(c_int, 2);
328 | pub const __SIZEOF_PTRDIFF_T__ = @as(c_int, 8);
329 | pub const __SIZEOF_SIZE_T__ = @as(c_int, 8);
330 | pub const __SIZEOF_WCHAR_T__ = @as(c_int, 4);
331 | pub const __SIZEOF_WINT_T__ = @as(c_int, 4);
332 | pub const __SIZEOF_INT128__ = @as(c_int, 16);
333 | pub const __INTMAX_TYPE__ = c_long;
334 | pub const __INTMAX_FMTd__ = "ld";
335 | pub const __INTMAX_FMTi__ = "li";
336 | pub const __UINTMAX_TYPE__ = c_ulong;
337 | pub const __UINTMAX_FMTo__ = "lo";
338 | pub const __UINTMAX_FMTu__ = "lu";
339 | pub const __UINTMAX_FMTx__ = "lx";
340 | pub const __UINTMAX_FMTX__ = "lX";
341 | pub const __INTMAX_WIDTH__ = @as(c_int, 64);
342 | pub const __PTRDIFF_TYPE__ = c_long;
343 | pub const __PTRDIFF_FMTd__ = "ld";
344 | pub const __PTRDIFF_FMTi__ = "li";
345 | pub const __PTRDIFF_WIDTH__ = @as(c_int, 64);
346 | pub const __INTPTR_TYPE__ = c_long;
347 | pub const __INTPTR_FMTd__ = "ld";
348 | pub const __INTPTR_FMTi__ = "li";
349 | pub const __INTPTR_WIDTH__ = @as(c_int, 64);
350 | pub const __SIZE_TYPE__ = c_ulong;
351 | pub const __SIZE_FMTo__ = "lo";
352 | pub const __SIZE_FMTu__ = "lu";
353 | pub const __SIZE_FMTx__ = "lx";
354 | pub const __SIZE_FMTX__ = "lX";
355 | pub const __SIZE_WIDTH__ = @as(c_int, 64);
356 | pub const __WCHAR_TYPE__ = c_int;
357 | pub const __WCHAR_WIDTH__ = @as(c_int, 32);
358 | pub const __WINT_TYPE__ = c_uint;
359 | pub const __WINT_WIDTH__ = @as(c_int, 32);
360 | pub const __SIG_ATOMIC_WIDTH__ = @as(c_int, 32);
361 | pub const __SIG_ATOMIC_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
362 | pub const __CHAR16_TYPE__ = c_ushort;
363 | pub const __CHAR32_TYPE__ = c_uint;
364 | pub const __UINTMAX_WIDTH__ = @as(c_int, 64);
365 | pub const __UINTPTR_TYPE__ = c_ulong;
366 | pub const __UINTPTR_FMTo__ = "lo";
367 | pub const __UINTPTR_FMTu__ = "lu";
368 | pub const __UINTPTR_FMTx__ = "lx";
369 | pub const __UINTPTR_FMTX__ = "lX";
370 | pub const __UINTPTR_WIDTH__ = @as(c_int, 64);
371 | pub const __FLT_DENORM_MIN__ = @as(f32, 1.40129846e-45);
372 | pub const __FLT_HAS_DENORM__ = @as(c_int, 1);
373 | pub const __FLT_DIG__ = @as(c_int, 6);
374 | pub const __FLT_DECIMAL_DIG__ = @as(c_int, 9);
375 | pub const __FLT_EPSILON__ = @as(f32, 1.19209290e-7);
376 | pub const __FLT_HAS_INFINITY__ = @as(c_int, 1);
377 | pub const __FLT_HAS_QUIET_NAN__ = @as(c_int, 1);
378 | pub const __FLT_MANT_DIG__ = @as(c_int, 24);
379 | pub const __FLT_MAX_10_EXP__ = @as(c_int, 38);
380 | pub const __FLT_MAX_EXP__ = @as(c_int, 128);
381 | pub const __FLT_MAX__ = @as(f32, 3.40282347e+38);
382 | pub const __FLT_MIN_10_EXP__ = -@as(c_int, 37);
383 | pub const __FLT_MIN_EXP__ = -@as(c_int, 125);
384 | pub const __FLT_MIN__ = @as(f32, 1.17549435e-38);
385 | pub const __DBL_DENORM_MIN__ = 4.9406564584124654e-324;
386 | pub const __DBL_HAS_DENORM__ = @as(c_int, 1);
387 | pub const __DBL_DIG__ = @as(c_int, 15);
388 | pub const __DBL_DECIMAL_DIG__ = @as(c_int, 17);
389 | pub const __DBL_EPSILON__ = 2.2204460492503131e-16;
390 | pub const __DBL_HAS_INFINITY__ = @as(c_int, 1);
391 | pub const __DBL_HAS_QUIET_NAN__ = @as(c_int, 1);
392 | pub const __DBL_MANT_DIG__ = @as(c_int, 53);
393 | pub const __DBL_MAX_10_EXP__ = @as(c_int, 308);
394 | pub const __DBL_MAX_EXP__ = @as(c_int, 1024);
395 | pub const __DBL_MAX__ = 1.7976931348623157e+308;
396 | pub const __DBL_MIN_10_EXP__ = -@as(c_int, 307);
397 | pub const __DBL_MIN_EXP__ = -@as(c_int, 1021);
398 | pub const __DBL_MIN__ = 2.2250738585072014e-308;
399 | pub const __LDBL_DENORM_MIN__ = @as(c_longdouble, 3.64519953188247460253e-4951);
400 | pub const __LDBL_HAS_DENORM__ = @as(c_int, 1);
401 | pub const __LDBL_DIG__ = @as(c_int, 18);
402 | pub const __LDBL_DECIMAL_DIG__ = @as(c_int, 21);
403 | pub const __LDBL_EPSILON__ = @as(c_longdouble, 1.08420217248550443401e-19);
404 | pub const __LDBL_HAS_INFINITY__ = @as(c_int, 1);
405 | pub const __LDBL_HAS_QUIET_NAN__ = @as(c_int, 1);
406 | pub const __LDBL_MANT_DIG__ = @as(c_int, 64);
407 | pub const __LDBL_MAX_10_EXP__ = @as(c_int, 4932);
408 | pub const __LDBL_MAX_EXP__ = @as(c_int, 16384);
409 | pub const __LDBL_MAX__ = @as(c_longdouble, 1.18973149535723176502e+4932);
410 | pub const __LDBL_MIN_10_EXP__ = -@as(c_int, 4931);
411 | pub const __LDBL_MIN_EXP__ = -@as(c_int, 16381);
412 | pub const __LDBL_MIN__ = @as(c_longdouble, 3.36210314311209350626e-4932);
413 | pub const __POINTER_WIDTH__ = @as(c_int, 64);
414 | pub const __BIGGEST_ALIGNMENT__ = @as(c_int, 16);
415 | pub const __WINT_UNSIGNED__ = @as(c_int, 1);
416 | pub const __INT8_TYPE__ = i8;
417 | pub const __INT8_FMTd__ = "hhd";
418 | pub const __INT8_FMTi__ = "hhi";
419 | pub const __INT8_C_SUFFIX__ = "";
420 | pub const __INT16_TYPE__ = c_short;
421 | pub const __INT16_FMTd__ = "hd";
422 | pub const __INT16_FMTi__ = "hi";
423 | pub const __INT16_C_SUFFIX__ = "";
424 | pub const __INT32_TYPE__ = c_int;
425 | pub const __INT32_FMTd__ = "d";
426 | pub const __INT32_FMTi__ = "i";
427 | pub const __INT32_C_SUFFIX__ = "";
428 | pub const __INT64_TYPE__ = c_long;
429 | pub const __INT64_FMTd__ = "ld";
430 | pub const __INT64_FMTi__ = "li";
431 | pub const __UINT8_TYPE__ = u8;
432 | pub const __UINT8_FMTo__ = "hho";
433 | pub const __UINT8_FMTu__ = "hhu";
434 | pub const __UINT8_FMTx__ = "hhx";
435 | pub const __UINT8_FMTX__ = "hhX";
436 | pub const __UINT8_C_SUFFIX__ = "";
437 | pub const __UINT8_MAX__ = @as(c_int, 255);
438 | pub const __INT8_MAX__ = @as(c_int, 127);
439 | pub const __UINT16_TYPE__ = c_ushort;
440 | pub const __UINT16_FMTo__ = "ho";
441 | pub const __UINT16_FMTu__ = "hu";
442 | pub const __UINT16_FMTx__ = "hx";
443 | pub const __UINT16_FMTX__ = "hX";
444 | pub const __UINT16_C_SUFFIX__ = "";
445 | pub const __UINT16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
446 | pub const __INT16_MAX__ = @as(c_int, 32767);
447 | pub const __UINT32_TYPE__ = c_uint;
448 | pub const __UINT32_FMTo__ = "o";
449 | pub const __UINT32_FMTu__ = "u";
450 | pub const __UINT32_FMTx__ = "x";
451 | pub const __UINT32_FMTX__ = "X";
452 | pub const __UINT32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
453 | pub const __INT32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
454 | pub const __UINT64_TYPE__ = c_ulong;
455 | pub const __UINT64_FMTo__ = "lo";
456 | pub const __UINT64_FMTu__ = "lu";
457 | pub const __UINT64_FMTx__ = "lx";
458 | pub const __UINT64_FMTX__ = "lX";
459 | pub const __UINT64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
460 | pub const __INT64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
461 | pub const __INT_LEAST8_TYPE__ = i8;
462 | pub const __INT_LEAST8_MAX__ = @as(c_int, 127);
463 | pub const __INT_LEAST8_FMTd__ = "hhd";
464 | pub const __INT_LEAST8_FMTi__ = "hhi";
465 | pub const __UINT_LEAST8_TYPE__ = u8;
466 | pub const __UINT_LEAST8_MAX__ = @as(c_int, 255);
467 | pub const __UINT_LEAST8_FMTo__ = "hho";
468 | pub const __UINT_LEAST8_FMTu__ = "hhu";
469 | pub const __UINT_LEAST8_FMTx__ = "hhx";
470 | pub const __UINT_LEAST8_FMTX__ = "hhX";
471 | pub const __INT_LEAST16_TYPE__ = c_short;
472 | pub const __INT_LEAST16_MAX__ = @as(c_int, 32767);
473 | pub const __INT_LEAST16_FMTd__ = "hd";
474 | pub const __INT_LEAST16_FMTi__ = "hi";
475 | pub const __UINT_LEAST16_TYPE__ = c_ushort;
476 | pub const __UINT_LEAST16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
477 | pub const __UINT_LEAST16_FMTo__ = "ho";
478 | pub const __UINT_LEAST16_FMTu__ = "hu";
479 | pub const __UINT_LEAST16_FMTx__ = "hx";
480 | pub const __UINT_LEAST16_FMTX__ = "hX";
481 | pub const __INT_LEAST32_TYPE__ = c_int;
482 | pub const __INT_LEAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
483 | pub const __INT_LEAST32_FMTd__ = "d";
484 | pub const __INT_LEAST32_FMTi__ = "i";
485 | pub const __UINT_LEAST32_TYPE__ = c_uint;
486 | pub const __UINT_LEAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
487 | pub const __UINT_LEAST32_FMTo__ = "o";
488 | pub const __UINT_LEAST32_FMTu__ = "u";
489 | pub const __UINT_LEAST32_FMTx__ = "x";
490 | pub const __UINT_LEAST32_FMTX__ = "X";
491 | pub const __INT_LEAST64_TYPE__ = c_long;
492 | pub const __INT_LEAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
493 | pub const __INT_LEAST64_FMTd__ = "ld";
494 | pub const __INT_LEAST64_FMTi__ = "li";
495 | pub const __UINT_LEAST64_TYPE__ = c_ulong;
496 | pub const __UINT_LEAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
497 | pub const __UINT_LEAST64_FMTo__ = "lo";
498 | pub const __UINT_LEAST64_FMTu__ = "lu";
499 | pub const __UINT_LEAST64_FMTx__ = "lx";
500 | pub const __UINT_LEAST64_FMTX__ = "lX";
501 | pub const __INT_FAST8_TYPE__ = i8;
502 | pub const __INT_FAST8_MAX__ = @as(c_int, 127);
503 | pub const __INT_FAST8_FMTd__ = "hhd";
504 | pub const __INT_FAST8_FMTi__ = "hhi";
505 | pub const __UINT_FAST8_TYPE__ = u8;
506 | pub const __UINT_FAST8_MAX__ = @as(c_int, 255);
507 | pub const __UINT_FAST8_FMTo__ = "hho";
508 | pub const __UINT_FAST8_FMTu__ = "hhu";
509 | pub const __UINT_FAST8_FMTx__ = "hhx";
510 | pub const __UINT_FAST8_FMTX__ = "hhX";
511 | pub const __INT_FAST16_TYPE__ = c_short;
512 | pub const __INT_FAST16_MAX__ = @as(c_int, 32767);
513 | pub const __INT_FAST16_FMTd__ = "hd";
514 | pub const __INT_FAST16_FMTi__ = "hi";
515 | pub const __UINT_FAST16_TYPE__ = c_ushort;
516 | pub const __UINT_FAST16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
517 | pub const __UINT_FAST16_FMTo__ = "ho";
518 | pub const __UINT_FAST16_FMTu__ = "hu";
519 | pub const __UINT_FAST16_FMTx__ = "hx";
520 | pub const __UINT_FAST16_FMTX__ = "hX";
521 | pub const __INT_FAST32_TYPE__ = c_int;
522 | pub const __INT_FAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
523 | pub const __INT_FAST32_FMTd__ = "d";
524 | pub const __INT_FAST32_FMTi__ = "i";
525 | pub const __UINT_FAST32_TYPE__ = c_uint;
526 | pub const __UINT_FAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
527 | pub const __UINT_FAST32_FMTo__ = "o";
528 | pub const __UINT_FAST32_FMTu__ = "u";
529 | pub const __UINT_FAST32_FMTx__ = "x";
530 | pub const __UINT_FAST32_FMTX__ = "X";
531 | pub const __INT_FAST64_TYPE__ = c_long;
532 | pub const __INT_FAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
533 | pub const __INT_FAST64_FMTd__ = "ld";
534 | pub const __INT_FAST64_FMTi__ = "li";
535 | pub const __UINT_FAST64_TYPE__ = c_ulong;
536 | pub const __UINT_FAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
537 | pub const __UINT_FAST64_FMTo__ = "lo";
538 | pub const __UINT_FAST64_FMTu__ = "lu";
539 | pub const __UINT_FAST64_FMTx__ = "lx";
540 | pub const __UINT_FAST64_FMTX__ = "lX";
541 | pub const __USER_LABEL_PREFIX__ = "";
542 | pub const __FINITE_MATH_ONLY__ = @as(c_int, 0);
543 | pub const __GNUC_STDC_INLINE__ = @as(c_int, 1);
544 | pub const __GCC_ATOMIC_TEST_AND_SET_TRUEVAL = @as(c_int, 1);
545 | pub const __CLANG_ATOMIC_BOOL_LOCK_FREE = @as(c_int, 2);
546 | pub const __CLANG_ATOMIC_CHAR_LOCK_FREE = @as(c_int, 2);
547 | pub const __CLANG_ATOMIC_CHAR16_T_LOCK_FREE = @as(c_int, 2);
548 | pub const __CLANG_ATOMIC_CHAR32_T_LOCK_FREE = @as(c_int, 2);
549 | pub const __CLANG_ATOMIC_WCHAR_T_LOCK_FREE = @as(c_int, 2);
550 | pub const __CLANG_ATOMIC_SHORT_LOCK_FREE = @as(c_int, 2);
551 | pub const __CLANG_ATOMIC_INT_LOCK_FREE = @as(c_int, 2);
552 | pub const __CLANG_ATOMIC_LONG_LOCK_FREE = @as(c_int, 2);
553 | pub const __CLANG_ATOMIC_LLONG_LOCK_FREE = @as(c_int, 2);
554 | pub const __CLANG_ATOMIC_POINTER_LOCK_FREE = @as(c_int, 2);
555 | pub const __GCC_ATOMIC_BOOL_LOCK_FREE = @as(c_int, 2);
556 | pub const __GCC_ATOMIC_CHAR_LOCK_FREE = @as(c_int, 2);
557 | pub const __GCC_ATOMIC_CHAR16_T_LOCK_FREE = @as(c_int, 2);
558 | pub const __GCC_ATOMIC_CHAR32_T_LOCK_FREE = @as(c_int, 2);
559 | pub const __GCC_ATOMIC_WCHAR_T_LOCK_FREE = @as(c_int, 2);
560 | pub const __GCC_ATOMIC_SHORT_LOCK_FREE = @as(c_int, 2);
561 | pub const __GCC_ATOMIC_INT_LOCK_FREE = @as(c_int, 2);
562 | pub const __GCC_ATOMIC_LONG_LOCK_FREE = @as(c_int, 2);
563 | pub const __GCC_ATOMIC_LLONG_LOCK_FREE = @as(c_int, 2);
564 | pub const __GCC_ATOMIC_POINTER_LOCK_FREE = @as(c_int, 2);
565 | pub const __NO_INLINE__ = @as(c_int, 1);
566 | pub const __PIC__ = @as(c_int, 2);
567 | pub const __pic__ = @as(c_int, 2);
568 | pub const __FLT_EVAL_METHOD__ = @as(c_int, 0);
569 | pub const __FLT_RADIX__ = @as(c_int, 2);
570 | pub const __DECIMAL_DIG__ = __LDBL_DECIMAL_DIG__;
571 | pub const __SSP_STRONG__ = @as(c_int, 2);
572 | pub const __GCC_ASM_FLAG_OUTPUTS__ = @as(c_int, 1);
573 | pub const __code_model_small__ = @as(c_int, 1);
574 | pub const __amd64__ = @as(c_int, 1);
575 | pub const __amd64 = @as(c_int, 1);
576 | pub const __x86_64 = @as(c_int, 1);
577 | pub const __x86_64__ = @as(c_int, 1);
578 | pub const __SEG_GS = @as(c_int, 1);
579 | pub const __SEG_FS = @as(c_int, 1);
580 | pub const __k8 = @as(c_int, 1);
581 | pub const __k8__ = @as(c_int, 1);
582 | pub const __tune_k8__ = @as(c_int, 1);
583 | pub const __REGISTER_PREFIX__ = "";
584 | pub const __NO_MATH_INLINES = @as(c_int, 1);
585 | pub const __AES__ = @as(c_int, 1);
586 | pub const __VAES__ = @as(c_int, 1);
587 | pub const __PCLMUL__ = @as(c_int, 1);
588 | pub const __VPCLMULQDQ__ = @as(c_int, 1);
589 | pub const __LAHF_SAHF__ = @as(c_int, 1);
590 | pub const __LZCNT__ = @as(c_int, 1);
591 | pub const __RDRND__ = @as(c_int, 1);
592 | pub const __FSGSBASE__ = @as(c_int, 1);
593 | pub const __BMI__ = @as(c_int, 1);
594 | pub const __BMI2__ = @as(c_int, 1);
595 | pub const __POPCNT__ = @as(c_int, 1);
596 | pub const __PRFCHW__ = @as(c_int, 1);
597 | pub const __RDSEED__ = @as(c_int, 1);
598 | pub const __ADX__ = @as(c_int, 1);
599 | pub const __MOVBE__ = @as(c_int, 1);
600 | pub const __FMA__ = @as(c_int, 1);
601 | pub const __F16C__ = @as(c_int, 1);
602 | pub const __GFNI__ = @as(c_int, 1);
603 | pub const __AVX512CD__ = @as(c_int, 1);
604 | pub const __AVX512VPOPCNTDQ__ = @as(c_int, 1);
605 | pub const __AVX512VNNI__ = @as(c_int, 1);
606 | pub const __AVX512DQ__ = @as(c_int, 1);
607 | pub const __AVX512BITALG__ = @as(c_int, 1);
608 | pub const __AVX512BW__ = @as(c_int, 1);
609 | pub const __AVX512VL__ = @as(c_int, 1);
610 | pub const __AVX512VBMI__ = @as(c_int, 1);
611 | pub const __AVX512VBMI2__ = @as(c_int, 1);
612 | pub const __AVX512IFMA__ = @as(c_int, 1);
613 | pub const __AVX512VP2INTERSECT__ = @as(c_int, 1);
614 | pub const __SHA__ = @as(c_int, 1);
615 | pub const __FXSR__ = @as(c_int, 1);
616 | pub const __XSAVE__ = @as(c_int, 1);
617 | pub const __XSAVEOPT__ = @as(c_int, 1);
618 | pub const __XSAVEC__ = @as(c_int, 1);
619 | pub const __XSAVES__ = @as(c_int, 1);
620 | pub const __CLFLUSHOPT__ = @as(c_int, 1);
621 | pub const __CLWB__ = @as(c_int, 1);
622 | pub const __SHSTK__ = @as(c_int, 1);
623 | pub const __RDPID__ = @as(c_int, 1);
624 | pub const __MOVDIRI__ = @as(c_int, 1);
625 | pub const __MOVDIR64B__ = @as(c_int, 1);
626 | pub const __INVPCID__ = @as(c_int, 1);
627 | pub const __AVX512F__ = @as(c_int, 1);
628 | pub const __AVX2__ = @as(c_int, 1);
629 | pub const __AVX__ = @as(c_int, 1);
630 | pub const __SSE4_2__ = @as(c_int, 1);
631 | pub const __SSE4_1__ = @as(c_int, 1);
632 | pub const __SSSE3__ = @as(c_int, 1);
633 | pub const __SSE3__ = @as(c_int, 1);
634 | pub const __SSE2__ = @as(c_int, 1);
635 | pub const __SSE2_MATH__ = @as(c_int, 1);
636 | pub const __SSE__ = @as(c_int, 1);
637 | pub const __SSE_MATH__ = @as(c_int, 1);
638 | pub const __MMX__ = @as(c_int, 1);
639 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 = @as(c_int, 1);
640 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 = @as(c_int, 1);
641 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 = @as(c_int, 1);
642 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 = @as(c_int, 1);
643 | pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 = @as(c_int, 1);
644 | pub const __SIZEOF_FLOAT128__ = @as(c_int, 16);
645 | pub const unix = @as(c_int, 1);
646 | pub const __unix = @as(c_int, 1);
647 | pub const __unix__ = @as(c_int, 1);
648 | pub const linux = @as(c_int, 1);
649 | pub const __linux = @as(c_int, 1);
650 | pub const __linux__ = @as(c_int, 1);
651 | pub const __ELF__ = @as(c_int, 1);
652 | pub const __gnu_linux__ = @as(c_int, 1);
653 | pub const __FLOAT128__ = @as(c_int, 1);
654 | pub const __STDC__ = @as(c_int, 1);
655 | pub const __STDC_HOSTED__ = @as(c_int, 1);
656 | pub const __STDC_VERSION__ = @as(c_long, 201710);
657 | pub const __STDC_UTF_16__ = @as(c_int, 1);
658 | pub const __STDC_UTF_32__ = @as(c_int, 1);
659 | pub const __GLIBC_MINOR__ = @as(c_int, 31);
660 | pub const _DEBUG = @as(c_int, 1);
661 | pub const __GCC_HAVE_DWARF2_CFI_ASM = @as(c_int, 1);
662 | pub const LZ4_H_2983827168210 = "";
663 | pub const __STDDEF_H = "";
664 | pub const __need_ptrdiff_t = "";
665 | pub const __need_size_t = "";
666 | pub const __need_wchar_t = "";
667 | pub const __need_NULL = "";
668 | pub const __need_STDDEF_H_misc = "";
669 | pub const _PTRDIFF_T = "";
670 | pub const _SIZE_T = "";
671 | pub const _WCHAR_T = "";
672 | pub const NULL = @import("std").zig.c_translation.cast(?*anyopaque, @as(c_int, 0));
673 | pub const __CLANG_MAX_ALIGN_T_DEFINED = "";
674 | pub const LZ4LIB_API = LZ4LIB_VISIBILITY;
675 | pub const LZ4_VERSION_MAJOR = @as(c_int, 1);
676 | pub const LZ4_VERSION_MINOR = @as(c_int, 9);
677 | pub const LZ4_VERSION_RELEASE = @as(c_int, 4);
678 | pub const LZ4_VERSION_NUMBER = (((LZ4_VERSION_MAJOR * @as(c_int, 100)) * @as(c_int, 100)) + (LZ4_VERSION_MINOR * @as(c_int, 100))) + LZ4_VERSION_RELEASE;
679 | pub const LZ4_LIB_VERSION = LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE;
680 | pub inline fn LZ4_EXPAND_AND_QUOTE(str: anytype) @TypeOf(LZ4_QUOTE(str)) {
681 | return LZ4_QUOTE(str);
682 | }
683 | pub const LZ4_VERSION_STRING = LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION);
684 | pub const LZ4_MEMORY_USAGE_MIN = @as(c_int, 10);
685 | pub const LZ4_MEMORY_USAGE_DEFAULT = @as(c_int, 14);
686 | pub const LZ4_MEMORY_USAGE_MAX = @as(c_int, 20);
687 | pub const LZ4_MEMORY_USAGE = LZ4_MEMORY_USAGE_DEFAULT;
688 | pub const LZ4_MAX_INPUT_SIZE = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x7E000000, .hexadecimal);
689 | pub inline fn LZ4_COMPRESSBOUND(@"isize": anytype) @TypeOf(if (@import("std").zig.c_translation.cast(c_uint, @"isize") > @import("std").zig.c_translation.cast(c_uint, LZ4_MAX_INPUT_SIZE)) @as(c_int, 0) else (@"isize" + (@"isize" / @as(c_int, 255))) + @as(c_int, 16)) {
690 | return if (@import("std").zig.c_translation.cast(c_uint, @"isize") > @import("std").zig.c_translation.cast(c_uint, LZ4_MAX_INPUT_SIZE)) @as(c_int, 0) else (@"isize" + (@"isize" / @as(c_int, 255))) + @as(c_int, 16);
691 | }
692 | pub inline fn LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize: anytype) @TypeOf((@import("std").zig.c_translation.promoteIntLiteral(c_int, 65536, .decimal) + @as(c_int, 14)) + maxBlockSize) {
693 | return (@import("std").zig.c_translation.promoteIntLiteral(c_int, 65536, .decimal) + @as(c_int, 14)) + maxBlockSize;
694 | }
695 | pub const LZ4_H_98237428734687 = "";
696 | pub const LZ4_HASHLOG = LZ4_MEMORY_USAGE - @as(c_int, 2);
697 | pub const LZ4_HASHTABLESIZE = @as(c_int, 1) << LZ4_MEMORY_USAGE;
698 | pub const LZ4_HASH_SIZE_U32 = @as(c_int, 1) << LZ4_HASHLOG;
699 | pub const __CLANG_STDINT_H = "";
700 | pub const _STDINT_H = @as(c_int, 1);
701 | pub const __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION = "";
702 | pub const _FEATURES_H = @as(c_int, 1);
703 | pub const __KERNEL_STRICT_NAMES = "";
704 | pub inline fn __GNUC_PREREQ(maj: anytype, min: anytype) @TypeOf(((__GNUC__ << @as(c_int, 16)) + __GNUC_MINOR__) >= ((maj << @as(c_int, 16)) + min)) {
705 | return ((__GNUC__ << @as(c_int, 16)) + __GNUC_MINOR__) >= ((maj << @as(c_int, 16)) + min);
706 | }
707 | pub inline fn __glibc_clang_prereq(maj: anytype, min: anytype) @TypeOf(((__clang_major__ << @as(c_int, 16)) + __clang_minor__) >= ((maj << @as(c_int, 16)) + min)) {
708 | return ((__clang_major__ << @as(c_int, 16)) + __clang_minor__) >= ((maj << @as(c_int, 16)) + min);
709 | }
710 | pub const _DEFAULT_SOURCE = @as(c_int, 1);
711 | pub const __GLIBC_USE_ISOC2X = @as(c_int, 0);
712 | pub const __USE_ISOC11 = @as(c_int, 1);
713 | pub const __USE_ISOC99 = @as(c_int, 1);
714 | pub const __USE_ISOC95 = @as(c_int, 1);
715 | pub const __USE_POSIX_IMPLICITLY = @as(c_int, 1);
716 | pub const _POSIX_SOURCE = @as(c_int, 1);
717 | pub const _POSIX_C_SOURCE = @as(c_long, 200809);
718 | pub const __USE_POSIX = @as(c_int, 1);
719 | pub const __USE_POSIX2 = @as(c_int, 1);
720 | pub const __USE_POSIX199309 = @as(c_int, 1);
721 | pub const __USE_POSIX199506 = @as(c_int, 1);
722 | pub const __USE_XOPEN2K = @as(c_int, 1);
723 | pub const __USE_XOPEN2K8 = @as(c_int, 1);
724 | pub const _ATFILE_SOURCE = @as(c_int, 1);
725 | pub const __WORDSIZE = @as(c_int, 64);
726 | pub const __WORDSIZE_TIME64_COMPAT32 = @as(c_int, 1);
727 | pub const __SYSCALL_WORDSIZE = @as(c_int, 64);
728 | pub const __TIMESIZE = __WORDSIZE;
729 | pub const __USE_MISC = @as(c_int, 1);
730 | pub const __USE_ATFILE = @as(c_int, 1);
731 | pub const __USE_FORTIFY_LEVEL = @as(c_int, 0);
732 | pub const __GLIBC_USE_DEPRECATED_GETS = @as(c_int, 0);
733 | pub const __GLIBC_USE_DEPRECATED_SCANF = @as(c_int, 0);
734 | pub const _STDC_PREDEF_H = @as(c_int, 1);
735 | pub const __STDC_IEC_559__ = @as(c_int, 1);
736 | pub const __STDC_IEC_559_COMPLEX__ = @as(c_int, 1);
737 | pub const __STDC_ISO_10646__ = @as(c_long, 201706);
738 | pub const __GNU_LIBRARY__ = @as(c_int, 6);
739 | pub const __GLIBC__ = @as(c_int, 2);
740 | pub inline fn __GLIBC_PREREQ(maj: anytype, min: anytype) @TypeOf(((__GLIBC__ << @as(c_int, 16)) + __GLIBC_MINOR__) >= ((maj << @as(c_int, 16)) + min)) {
741 | return ((__GLIBC__ << @as(c_int, 16)) + __GLIBC_MINOR__) >= ((maj << @as(c_int, 16)) + min);
742 | }
743 | pub const _SYS_CDEFS_H = @as(c_int, 1);
744 | pub inline fn __glibc_has_builtin(name: anytype) @TypeOf(__has_builtin(name)) {
745 | return __has_builtin(name);
746 | }
747 | pub const __LEAF = "";
748 | pub const __LEAF_ATTR = "";
749 | pub inline fn __P(args: anytype) @TypeOf(args) {
750 | return args;
751 | }
752 | pub inline fn __PMT(args: anytype) @TypeOf(args) {
753 | return args;
754 | }
755 | pub const __ptr_t = ?*anyopaque;
756 | pub const __BEGIN_DECLS = "";
757 | pub const __END_DECLS = "";
758 | pub inline fn __bos(ptr: anytype) @TypeOf(__builtin_object_size(ptr, __USE_FORTIFY_LEVEL > @as(c_int, 1))) {
759 | return __builtin_object_size(ptr, __USE_FORTIFY_LEVEL > @as(c_int, 1));
760 | }
761 | pub inline fn __bos0(ptr: anytype) @TypeOf(__builtin_object_size(ptr, @as(c_int, 0))) {
762 | return __builtin_object_size(ptr, @as(c_int, 0));
763 | }
764 | pub inline fn __glibc_objsize0(__o: anytype) @TypeOf(__bos0(__o)) {
765 | return __bos0(__o);
766 | }
767 | pub inline fn __glibc_objsize(__o: anytype) @TypeOf(__bos(__o)) {
768 | return __bos(__o);
769 | }
770 | pub const __glibc_c99_flexarr_available = @as(c_int, 1);
771 | pub inline fn __ASMNAME(cname: anytype) @TypeOf(__ASMNAME2(__USER_LABEL_PREFIX__, cname)) {
772 | return __ASMNAME2(__USER_LABEL_PREFIX__, cname);
773 | }
774 | pub const __wur = "";
775 | pub const __fortify_function = __extern_always_inline ++ __attribute_artificial__;
776 | pub inline fn __glibc_unlikely(cond: anytype) @TypeOf(__builtin_expect(cond, @as(c_int, 0))) {
777 | return __builtin_expect(cond, @as(c_int, 0));
778 | }
779 | pub inline fn __glibc_likely(cond: anytype) @TypeOf(__builtin_expect(cond, @as(c_int, 1))) {
780 | return __builtin_expect(cond, @as(c_int, 1));
781 | }
782 | pub const __attribute_nonstring__ = "";
783 | pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI = @as(c_int, 0);
784 | pub inline fn __LDBL_REDIR1(name: anytype, proto: anytype, alias: anytype) @TypeOf(name ++ proto) {
785 | _ = alias;
786 | return name ++ proto;
787 | }
788 | pub inline fn __LDBL_REDIR(name: anytype, proto: anytype) @TypeOf(name ++ proto) {
789 | return name ++ proto;
790 | }
791 | pub inline fn __LDBL_REDIR1_NTH(name: anytype, proto: anytype, alias: anytype) @TypeOf(name ++ proto ++ __THROW) {
792 | _ = alias;
793 | return name ++ proto ++ __THROW;
794 | }
795 | pub inline fn __LDBL_REDIR_NTH(name: anytype, proto: anytype) @TypeOf(name ++ proto ++ __THROW) {
796 | return name ++ proto ++ __THROW;
797 | }
798 | pub inline fn __REDIRECT_LDBL(name: anytype, proto: anytype, alias: anytype) @TypeOf(__REDIRECT(name, proto, alias)) {
799 | return __REDIRECT(name, proto, alias);
800 | }
801 | pub inline fn __REDIRECT_NTH_LDBL(name: anytype, proto: anytype, alias: anytype) @TypeOf(__REDIRECT_NTH(name, proto, alias)) {
802 | return __REDIRECT_NTH(name, proto, alias);
803 | }
804 | pub const __HAVE_GENERIC_SELECTION = @as(c_int, 1);
805 | pub const __attr_dealloc_free = "";
806 | pub const __stub___compat_bdflush = "";
807 | pub const __stub_chflags = "";
808 | pub const __stub_fchflags = "";
809 | pub const __stub_gtty = "";
810 | pub const __stub_revoke = "";
811 | pub const __stub_setlogin = "";
812 | pub const __stub_sigreturn = "";
813 | pub const __stub_stty = "";
814 | pub const __GLIBC_USE_LIB_EXT2 = @as(c_int, 0);
815 | pub const __GLIBC_USE_IEC_60559_BFP_EXT = @as(c_int, 0);
816 | pub const __GLIBC_USE_IEC_60559_BFP_EXT_C2X = @as(c_int, 0);
817 | pub const __GLIBC_USE_IEC_60559_EXT = @as(c_int, 0);
818 | pub const __GLIBC_USE_IEC_60559_FUNCS_EXT = @as(c_int, 0);
819 | pub const __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X = @as(c_int, 0);
820 | pub const __GLIBC_USE_IEC_60559_TYPES_EXT = @as(c_int, 0);
821 | pub const _BITS_TYPES_H = @as(c_int, 1);
822 | pub const __S16_TYPE = c_short;
823 | pub const __U16_TYPE = c_ushort;
824 | pub const __S32_TYPE = c_int;
825 | pub const __U32_TYPE = c_uint;
826 | pub const __SLONGWORD_TYPE = c_long;
827 | pub const __ULONGWORD_TYPE = c_ulong;
828 | pub const __SQUAD_TYPE = c_long;
829 | pub const __UQUAD_TYPE = c_ulong;
830 | pub const __SWORD_TYPE = c_long;
831 | pub const __UWORD_TYPE = c_ulong;
832 | pub const __SLONG32_TYPE = c_int;
833 | pub const __ULONG32_TYPE = c_uint;
834 | pub const __S64_TYPE = c_long;
835 | pub const __U64_TYPE = c_ulong;
836 | pub const _BITS_TYPESIZES_H = @as(c_int, 1);
837 | pub const __SYSCALL_SLONG_TYPE = __SLONGWORD_TYPE;
838 | pub const __SYSCALL_ULONG_TYPE = __ULONGWORD_TYPE;
839 | pub const __DEV_T_TYPE = __UQUAD_TYPE;
840 | pub const __UID_T_TYPE = __U32_TYPE;
841 | pub const __GID_T_TYPE = __U32_TYPE;
842 | pub const __INO_T_TYPE = __SYSCALL_ULONG_TYPE;
843 | pub const __INO64_T_TYPE = __UQUAD_TYPE;
844 | pub const __MODE_T_TYPE = __U32_TYPE;
845 | pub const __NLINK_T_TYPE = __SYSCALL_ULONG_TYPE;
846 | pub const __FSWORD_T_TYPE = __SYSCALL_SLONG_TYPE;
847 | pub const __OFF_T_TYPE = __SYSCALL_SLONG_TYPE;
848 | pub const __OFF64_T_TYPE = __SQUAD_TYPE;
849 | pub const __PID_T_TYPE = __S32_TYPE;
850 | pub const __RLIM_T_TYPE = __SYSCALL_ULONG_TYPE;
851 | pub const __RLIM64_T_TYPE = __UQUAD_TYPE;
852 | pub const __BLKCNT_T_TYPE = __SYSCALL_SLONG_TYPE;
853 | pub const __BLKCNT64_T_TYPE = __SQUAD_TYPE;
854 | pub const __FSBLKCNT_T_TYPE = __SYSCALL_ULONG_TYPE;
855 | pub const __FSBLKCNT64_T_TYPE = __UQUAD_TYPE;
856 | pub const __FSFILCNT_T_TYPE = __SYSCALL_ULONG_TYPE;
857 | pub const __FSFILCNT64_T_TYPE = __UQUAD_TYPE;
858 | pub const __ID_T_TYPE = __U32_TYPE;
859 | pub const __CLOCK_T_TYPE = __SYSCALL_SLONG_TYPE;
860 | pub const __TIME_T_TYPE = __SYSCALL_SLONG_TYPE;
861 | pub const __USECONDS_T_TYPE = __U32_TYPE;
862 | pub const __SUSECONDS_T_TYPE = __SYSCALL_SLONG_TYPE;
863 | pub const __SUSECONDS64_T_TYPE = __SQUAD_TYPE;
864 | pub const __DADDR_T_TYPE = __S32_TYPE;
865 | pub const __KEY_T_TYPE = __S32_TYPE;
866 | pub const __CLOCKID_T_TYPE = __S32_TYPE;
867 | pub const __TIMER_T_TYPE = ?*anyopaque;
868 | pub const __BLKSIZE_T_TYPE = __SYSCALL_SLONG_TYPE;
869 | pub const __SSIZE_T_TYPE = __SWORD_TYPE;
870 | pub const __CPU_MASK_TYPE = __SYSCALL_ULONG_TYPE;
871 | pub const __OFF_T_MATCHES_OFF64_T = @as(c_int, 1);
872 | pub const __INO_T_MATCHES_INO64_T = @as(c_int, 1);
873 | pub const __RLIM_T_MATCHES_RLIM64_T = @as(c_int, 1);
874 | pub const __STATFS_MATCHES_STATFS64 = @as(c_int, 1);
875 | pub const __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 = @as(c_int, 1);
876 | pub const __FD_SETSIZE = @as(c_int, 1024);
877 | pub const _BITS_TIME64_H = @as(c_int, 1);
878 | pub const __TIME64_T_TYPE = __TIME_T_TYPE;
879 | pub const _BITS_WCHAR_H = @as(c_int, 1);
880 | pub const __WCHAR_MAX = __WCHAR_MAX__;
881 | pub const __WCHAR_MIN = -__WCHAR_MAX - @as(c_int, 1);
882 | pub const _BITS_STDINT_INTN_H = @as(c_int, 1);
883 | pub const _BITS_STDINT_UINTN_H = @as(c_int, 1);
884 | pub const __intptr_t_defined = "";
885 | pub const __INT64_C = @import("std").zig.c_translation.Macros.L_SUFFIX;
886 | pub const __UINT64_C = @import("std").zig.c_translation.Macros.UL_SUFFIX;
887 | pub const INT8_MIN = -@as(c_int, 128);
888 | pub const INT16_MIN = -@as(c_int, 32767) - @as(c_int, 1);
889 | pub const INT32_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal) - @as(c_int, 1);
890 | pub const INT64_MIN = -__INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal)) - @as(c_int, 1);
891 | pub const INT8_MAX = @as(c_int, 127);
892 | pub const INT16_MAX = @as(c_int, 32767);
893 | pub const INT32_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
894 | pub const INT64_MAX = __INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal));
895 | pub const UINT8_MAX = @as(c_int, 255);
896 | pub const UINT16_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
897 | pub const UINT32_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
898 | pub const UINT64_MAX = __UINT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 18446744073709551615, .decimal));
899 | pub const INT_LEAST8_MIN = -@as(c_int, 128);
900 | pub const INT_LEAST16_MIN = -@as(c_int, 32767) - @as(c_int, 1);
901 | pub const INT_LEAST32_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal) - @as(c_int, 1);
902 | pub const INT_LEAST64_MIN = -__INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal)) - @as(c_int, 1);
903 | pub const INT_LEAST8_MAX = @as(c_int, 127);
904 | pub const INT_LEAST16_MAX = @as(c_int, 32767);
905 | pub const INT_LEAST32_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
906 | pub const INT_LEAST64_MAX = __INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal));
907 | pub const UINT_LEAST8_MAX = @as(c_int, 255);
908 | pub const UINT_LEAST16_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal);
909 | pub const UINT_LEAST32_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
910 | pub const UINT_LEAST64_MAX = __UINT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 18446744073709551615, .decimal));
911 | pub const INT_FAST8_MIN = -@as(c_int, 128);
912 | pub const INT_FAST16_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal) - @as(c_int, 1);
913 | pub const INT_FAST32_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal) - @as(c_int, 1);
914 | pub const INT_FAST64_MIN = -__INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal)) - @as(c_int, 1);
915 | pub const INT_FAST8_MAX = @as(c_int, 127);
916 | pub const INT_FAST16_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
917 | pub const INT_FAST32_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
918 | pub const INT_FAST64_MAX = __INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal));
919 | pub const UINT_FAST8_MAX = @as(c_int, 255);
920 | pub const UINT_FAST16_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
921 | pub const UINT_FAST32_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
922 | pub const UINT_FAST64_MAX = __UINT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 18446744073709551615, .decimal));
923 | pub const INTPTR_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal) - @as(c_int, 1);
924 | pub const INTPTR_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
925 | pub const UINTPTR_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
926 | pub const INTMAX_MIN = -__INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal)) - @as(c_int, 1);
927 | pub const INTMAX_MAX = __INT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 9223372036854775807, .decimal));
928 | pub const UINTMAX_MAX = __UINT64_C(@import("std").zig.c_translation.promoteIntLiteral(c_int, 18446744073709551615, .decimal));
929 | pub const PTRDIFF_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal) - @as(c_int, 1);
930 | pub const PTRDIFF_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal);
931 | pub const SIG_ATOMIC_MIN = -@import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal) - @as(c_int, 1);
932 | pub const SIG_ATOMIC_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal);
933 | pub const SIZE_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal);
934 | pub const WCHAR_MIN = __WCHAR_MIN;
935 | pub const WCHAR_MAX = __WCHAR_MAX;
936 | pub const WINT_MIN = @as(c_uint, 0);
937 | pub const WINT_MAX = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal);
938 | pub inline fn INT8_C(c: anytype) @TypeOf(c) {
939 | return c;
940 | }
941 | pub inline fn INT16_C(c: anytype) @TypeOf(c) {
942 | return c;
943 | }
944 | pub inline fn INT32_C(c: anytype) @TypeOf(c) {
945 | return c;
946 | }
947 | pub const INT64_C = @import("std").zig.c_translation.Macros.L_SUFFIX;
948 | pub inline fn UINT8_C(c: anytype) @TypeOf(c) {
949 | return c;
950 | }
951 | pub inline fn UINT16_C(c: anytype) @TypeOf(c) {
952 | return c;
953 | }
954 | pub const UINT32_C = @import("std").zig.c_translation.Macros.U_SUFFIX;
955 | pub const UINT64_C = @import("std").zig.c_translation.Macros.UL_SUFFIX;
956 | pub const INTMAX_C = @import("std").zig.c_translation.Macros.L_SUFFIX;
957 | pub const UINTMAX_C = @import("std").zig.c_translation.Macros.UL_SUFFIX;
958 | pub const LZ4_STREAM_MINSIZE = (@as(c_ulong, 1) << LZ4_MEMORY_USAGE) + @as(c_int, 32);
959 | pub const LZ4_STREAMDECODE_MINSIZE = @as(c_int, 32);
960 | pub const LZ4_stream_u = union_LZ4_stream_u;
961 | pub const LZ4_streamDecode_u = union_LZ4_streamDecode_u;
962 |
--------------------------------------------------------------------------------