Merge branch 'zig1' into zig0-0.15.2
# Conflicts: # build.zig # stage0/sema.c # stage0/stages_test.zig
This commit is contained in:
84
build.zig
84
build.zig
@@ -9,6 +9,7 @@ const InstallDirectoryOptions = std.Build.InstallDirectoryOptions;
|
||||
const assert = std.debug.assert;
|
||||
const DevEnv = @import("src/dev.zig").Env;
|
||||
const ValueInterpretMode = enum { direct, by_name };
|
||||
const corpus = @import("stage0/corpus.zig");
|
||||
|
||||
const zig0_headers = &[_][]const u8{
|
||||
"air.h",
|
||||
@@ -1699,25 +1700,9 @@ fn addZig0TestStep(
|
||||
test_timeout: ?[]const u8,
|
||||
exe_options: *std.Build.Step.Options,
|
||||
) void {
|
||||
// Step 1: Compile Zig test code to .o (cached independently of C objects).
|
||||
// NOTE: test_mod does NOT import zig_internals — stage0 tests are fast.
|
||||
const test_mod = b.createModule(.{
|
||||
.root_source_file = b.path("stage0_test_root.zig"),
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
.valgrind = true,
|
||||
});
|
||||
test_mod.addIncludePath(b.path("stage0"));
|
||||
test_mod.linkSystemLibrary("c", .{});
|
||||
|
||||
const test_obj = b.addTest(.{
|
||||
.root_module = test_mod,
|
||||
.emit_object = true,
|
||||
.use_llvm = false,
|
||||
.use_lld = false,
|
||||
});
|
||||
|
||||
// Step 1b: Compile Zig dumper module (depends on zig_internals, cached separately).
|
||||
// Step 0: Build AIR generator and generate air_bundle.zig.
|
||||
// The generator uses zig_internals to compile source files and
|
||||
// produces pre-computed AIR data + tag names in a single Zig file.
|
||||
const zig_internals_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/test_exports.zig"),
|
||||
});
|
||||
@@ -1738,25 +1723,72 @@ fn addZig0TestStep(
|
||||
// processing empty Air. ReleaseFast elides the safety check.
|
||||
const dumper_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/verbose_air.zig"),
|
||||
.target = target,
|
||||
.target = b.graph.host,
|
||||
.optimize = .ReleaseFast,
|
||||
.valgrind = true,
|
||||
});
|
||||
dumper_mod.addImport("zig_internals", zig_internals_mod);
|
||||
dumper_mod.linkSystemLibrary("c", .{});
|
||||
|
||||
const dumper_obj = b.addObject(.{
|
||||
.name = "verbose_dumper",
|
||||
.root_module = dumper_mod,
|
||||
const gen_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/verbose_air_gen.zig"),
|
||||
.target = b.graph.host,
|
||||
.optimize = .ReleaseFast,
|
||||
});
|
||||
gen_mod.addImport("verbose_air", dumper_mod);
|
||||
gen_mod.addImport("zig_internals", zig_internals_mod);
|
||||
gen_mod.linkSystemLibrary("c", .{});
|
||||
|
||||
const gen_exe = b.addExecutable(.{
|
||||
.name = "air_gen",
|
||||
.root_module = gen_mod,
|
||||
});
|
||||
|
||||
// Step 2: Link test_obj + dumper_obj + C objects into final executable.
|
||||
// Run generator: air_gen <output_dir> [<name> <resolved_path>]...
|
||||
const gen_run = b.addRunArtifact(gen_exe);
|
||||
const air_dir = gen_run.addOutputDirectoryArg("air");
|
||||
// Add corpus files as name/path pairs.
|
||||
for (corpus.files[0..corpus.num_passing]) |path| {
|
||||
gen_run.addArg(path);
|
||||
gen_run.addFileArg(b.path(path));
|
||||
}
|
||||
// Add sema unit test files.
|
||||
for (corpus.sema_unit_tests) |path| {
|
||||
gen_run.addArg(path);
|
||||
gen_run.addFileArg(b.path(path));
|
||||
}
|
||||
|
||||
// Step 1: Compile Zig test code to .o (cached independently of C objects).
|
||||
// NOTE: test_mod does NOT import zig_internals — stage0 tests are fast.
|
||||
const test_mod = b.createModule(.{
|
||||
.root_source_file = b.path("stage0_test_root.zig"),
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
.valgrind = true,
|
||||
});
|
||||
test_mod.addIncludePath(b.path("stage0"));
|
||||
test_mod.linkSystemLibrary("c", .{});
|
||||
// Make pre-computed AIR data available to tests.
|
||||
test_mod.addAnonymousImport("air_tag_names", .{
|
||||
.root_source_file = air_dir.path(b, "tag_names.zig"),
|
||||
});
|
||||
test_mod.addAnonymousImport("air_data", .{
|
||||
.root_source_file = air_dir.path(b, "air_data.zig"),
|
||||
});
|
||||
|
||||
const test_obj = b.addTest(.{
|
||||
.root_module = test_mod,
|
||||
.emit_object = true,
|
||||
.use_llvm = false,
|
||||
.use_lld = false,
|
||||
});
|
||||
|
||||
// Step 2: Link test_obj + C objects into final executable.
|
||||
// No more dumper_obj — AIR is pre-computed at build time.
|
||||
const link_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
link_mod.addObject(test_obj);
|
||||
link_mod.addObject(dumper_obj);
|
||||
addZig0CSources(b, link_mod, cc, optimize);
|
||||
link_mod.linkSystemLibrary("c", .{});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ const Package = zig_internals.Package;
|
||||
const Air = zig_internals.Air;
|
||||
|
||||
/// Matches C `Air` struct layout (air.h).
|
||||
const CAir = extern struct {
|
||||
pub const CAir = extern struct {
|
||||
inst_len: u32,
|
||||
inst_cap: u32,
|
||||
inst_tags: ?[*]u8,
|
||||
@@ -22,13 +22,13 @@ const CAir = extern struct {
|
||||
};
|
||||
|
||||
/// Matches C `SemaFuncAir` struct layout (sema.h).
|
||||
const CSemaFuncAir = extern struct {
|
||||
pub const CSemaFuncAir = extern struct {
|
||||
name: ?[*:0]u8,
|
||||
func_ip: u32, // InternPoolIndex
|
||||
air: CAir,
|
||||
};
|
||||
|
||||
const CompileAirResult = extern struct {
|
||||
pub const CompileAirResult = extern struct {
|
||||
items: ?[*]CSemaFuncAir,
|
||||
len: u32,
|
||||
callback_count: u32,
|
||||
@@ -132,7 +132,7 @@ export fn zig_compile_air(
|
||||
};
|
||||
}
|
||||
|
||||
export fn zig_compile_air_free(result: *CompileAirResult) void {
|
||||
pub export fn zig_compile_air_free(result: *CompileAirResult) void {
|
||||
const gpa = std.heap.c_allocator;
|
||||
if (result.items) |items| {
|
||||
for (items[0..result.len]) |*f| {
|
||||
@@ -153,7 +153,7 @@ fn setErr(buf: *[err_buf_size]u8, comptime fmt: []const u8, args: anytype) void
|
||||
buf[written.len] = 0;
|
||||
}
|
||||
|
||||
fn zigCompileAirImpl(
|
||||
pub fn zigCompileAirImpl(
|
||||
src_path: []const u8,
|
||||
module_root_opt: ?[]const u8,
|
||||
err_buf: *[err_buf_size]u8,
|
||||
|
||||
232
src/verbose_air_gen.zig
Normal file
232
src/verbose_air_gen.zig
Normal file
@@ -0,0 +1,232 @@
|
||||
// verbose_air_gen.zig — Build-time generator for pre-computed AIR data.
|
||||
// Compiles each source file via the Zig compiler pipeline and writes
|
||||
// binary .air files + a tag_names.zig into an output directory.
|
||||
//
|
||||
// Usage: air_gen <output_dir> [<name> <resolved_path>]...
|
||||
// output_dir: directory to write .air files and tag_names.zig
|
||||
// name: repo-relative path (used as file name, e.g. "lib/foo.zig" -> "lib/foo.zig.air")
|
||||
// resolved_path: filesystem path to compile
|
||||
|
||||
const std = @import("std");
|
||||
pub const std_options: std.Options = .{ .log_level = .warn };
|
||||
const verbose_air = @import("verbose_air");
|
||||
const zig_internals = @import("zig_internals");
|
||||
const Air = zig_internals.Air;
|
||||
|
||||
pub fn main() !void {
|
||||
const gpa = std.heap.c_allocator;
|
||||
const args = try std.process.argsAlloc(gpa);
|
||||
if (args.len < 2) {
|
||||
std.debug.print("usage: air_gen <output_dir> [<name> <resolved_path>]...\n", .{});
|
||||
return error.InvalidArguments;
|
||||
}
|
||||
|
||||
const output_dir_path = args[1];
|
||||
const pairs = args[2..];
|
||||
if (pairs.len % 2 != 0) {
|
||||
std.debug.print("error: arguments must be pairs of <name> <resolved_path>\n", .{});
|
||||
return error.InvalidArguments;
|
||||
}
|
||||
const num_entries = pairs.len / 2;
|
||||
|
||||
var output_dir = try std.fs.cwd().openDir(output_dir_path, .{});
|
||||
defer output_dir.close();
|
||||
|
||||
// Derive repo_root by stripping the name suffix from the first resolved path.
|
||||
// e.g. name="lib/std/crypto.zig", resolved="/home/user/zig1/lib/std/crypto.zig"
|
||||
// => repo_root="/home/user/zig1"
|
||||
if (num_entries == 0) return;
|
||||
const first_name = pairs[0];
|
||||
const first_resolved = pairs[1];
|
||||
const repo_root = blk: {
|
||||
if (first_resolved.len >= first_name.len and
|
||||
std.mem.eql(u8, first_resolved[first_resolved.len - first_name.len ..], first_name))
|
||||
{
|
||||
break :blk first_resolved[0 .. first_resolved.len - first_name.len];
|
||||
}
|
||||
break :blk std.fs.path.dirname(first_resolved) orelse ".";
|
||||
};
|
||||
|
||||
// Create a symlink workaround so that files in lib/std/ are not seen as
|
||||
// belonging to both 'root' and 'std' modules. We symlink repo_root into
|
||||
// a temp directory and pass all paths through the symlink.
|
||||
// The temp directory must be OUTSIDE the output_dir to avoid confusing the
|
||||
// Zig build system's cache (it would follow the symlink back into the repo).
|
||||
const tmp_dir_path = "/tmp/zig-air-gen";
|
||||
|
||||
std.fs.makeDirAbsolute(tmp_dir_path) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => {},
|
||||
else => {
|
||||
std.debug.print("error creating tmp directory: {s}\n", .{@errorName(err)});
|
||||
return err;
|
||||
},
|
||||
};
|
||||
var tmp_dir = std.fs.openDirAbsolute(tmp_dir_path, .{}) catch |err| {
|
||||
std.debug.print("error opening tmp directory: {s}\n", .{@errorName(err)});
|
||||
return err;
|
||||
};
|
||||
defer tmp_dir.close();
|
||||
defer std.fs.deleteTreeAbsolute(tmp_dir_path) catch {};
|
||||
|
||||
tmp_dir.symLink(repo_root, "root", .{ .is_directory = true }) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => {},
|
||||
else => {
|
||||
std.debug.print("error creating symlink: {s}\n", .{@errorName(err)});
|
||||
return err;
|
||||
},
|
||||
};
|
||||
|
||||
for (0..num_entries) |i| {
|
||||
const name = pairs[i * 2];
|
||||
const resolved = pairs[i * 2 + 1];
|
||||
_ = resolved;
|
||||
|
||||
// Construct paths through the symlink to avoid the "file exists in
|
||||
// modules 'root' and 'std'" error.
|
||||
const src_path = try std.fmt.allocPrint(gpa, "{s}/root/{s}", .{ tmp_dir_path, name });
|
||||
defer gpa.free(src_path);
|
||||
const module_root = try std.fmt.allocPrint(gpa, "{s}/root", .{tmp_dir_path});
|
||||
defer gpa.free(module_root);
|
||||
|
||||
const data = processSource(gpa, src_path, module_root) catch |err| {
|
||||
std.debug.print("FAIL: {s} ({s}): {s}\n", .{ name, src_path, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
defer gpa.free(data);
|
||||
|
||||
// Write {name}.air, creating subdirectories as needed.
|
||||
const air_name = try std.fmt.allocPrint(gpa, "{s}.air", .{name});
|
||||
defer gpa.free(air_name);
|
||||
|
||||
if (std.fs.path.dirname(air_name)) |dir| {
|
||||
output_dir.makePath(dir) catch |err| {
|
||||
std.debug.print("error creating directory '{s}': {s}\n", .{ dir, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
var file = output_dir.createFile(air_name, .{}) catch |err| {
|
||||
std.debug.print("error creating file '{s}': {s}\n", .{ air_name, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
defer file.close();
|
||||
file.writeAll(data) catch |err| {
|
||||
std.debug.print("error writing file '{s}': {s}\n", .{ air_name, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
// Write tag_names.zig
|
||||
{
|
||||
var out: std.ArrayListUnmanaged(u8) = .empty;
|
||||
defer out.deinit(gpa);
|
||||
const writer = out.writer(gpa);
|
||||
|
||||
try writer.writeAll("// Generated by verbose_air_gen. Do not edit.\n\n");
|
||||
const tag_count = @typeInfo(Air.Inst.Tag).@"enum".fields.len;
|
||||
try writer.print("pub const names: [{d}][:0]const u8 = .{{\n", .{tag_count});
|
||||
inline for (@typeInfo(Air.Inst.Tag).@"enum".fields) |field| {
|
||||
try writer.print(" \"{s}\",\n", .{field.name});
|
||||
}
|
||||
try writer.writeAll("};\n");
|
||||
|
||||
var file = try output_dir.createFile("tag_names.zig", .{});
|
||||
defer file.close();
|
||||
try file.writeAll(out.items);
|
||||
}
|
||||
|
||||
// Write air_data.zig — helper that bridges @embedFile for test code.
|
||||
// Because @embedFile resolves relative to the source file (not --embed-dir),
|
||||
// this file must live alongside the .air files so it can find them.
|
||||
{
|
||||
var file = try output_dir.createFile("air_data.zig", .{});
|
||||
defer file.close();
|
||||
try file.writeAll(
|
||||
\\// Generated by verbose_air_gen. Do not edit.
|
||||
\\pub fn getData(comptime path: []const u8) []const u8 {
|
||||
\\ return @embedFile(path ++ ".air");
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile a source file and return the binary AIR data.
|
||||
/// Binary format:
|
||||
/// func_count: u32 (little-endian)
|
||||
/// Per function:
|
||||
/// name_len: u32
|
||||
/// name: [name_len]u8
|
||||
/// inst_len: u32
|
||||
/// inst_tags: [inst_len]u8
|
||||
/// inst_datas: [inst_len * 8]u8
|
||||
/// extra_len: u32
|
||||
/// extra: [extra_len * 4]u8
|
||||
fn processSource(gpa: std.mem.Allocator, src_path: []const u8, module_root: []const u8) ![]const u8 {
|
||||
var err_buf: [256]u8 = .{0} ** 256;
|
||||
|
||||
const result = verbose_air.zigCompileAirImpl(
|
||||
src_path,
|
||||
module_root,
|
||||
&err_buf,
|
||||
) catch |err| {
|
||||
std.debug.print("zigCompileAirImpl error for {s}: {s} ({s})\n", .{
|
||||
src_path,
|
||||
std.mem.sliceTo(&err_buf, 0),
|
||||
@errorName(err),
|
||||
});
|
||||
return err;
|
||||
};
|
||||
|
||||
if (err_buf[0] != 0) {
|
||||
std.debug.print("zigCompileAirImpl error for {s}: {s}\n", .{
|
||||
src_path,
|
||||
std.mem.sliceTo(&err_buf, 0),
|
||||
});
|
||||
return error.CompileError;
|
||||
}
|
||||
|
||||
const funcs = if (result.items) |items| items[0..result.len] else &[_]verbose_air.CSemaFuncAir{};
|
||||
defer {
|
||||
var r = result;
|
||||
verbose_air.zig_compile_air_free(&r);
|
||||
}
|
||||
|
||||
// Serialize to binary format.
|
||||
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||
|
||||
// func_count
|
||||
try buf.writer(gpa).writeInt(u32, @intCast(funcs.len), .little);
|
||||
|
||||
for (funcs) |*f| {
|
||||
const w = buf.writer(gpa);
|
||||
// name
|
||||
const name = if (f.name) |n| std.mem.span(n) else "";
|
||||
try w.writeInt(u32, @intCast(name.len), .little);
|
||||
try w.writeAll(name);
|
||||
|
||||
// inst_tags + inst_datas
|
||||
const inst_len = f.air.inst_len;
|
||||
try w.writeInt(u32, inst_len, .little);
|
||||
if (inst_len > 0) {
|
||||
if (f.air.inst_tags) |tags| {
|
||||
try w.writeAll(tags[0..inst_len]);
|
||||
}
|
||||
if (f.air.inst_datas) |datas| {
|
||||
try w.writeAll(datas[0 .. inst_len * 8]);
|
||||
}
|
||||
}
|
||||
|
||||
// extra
|
||||
const extra_len = f.air.extra_len;
|
||||
try w.writeInt(u32, extra_len, .little);
|
||||
if (extra_len > 0) {
|
||||
if (f.air.extra) |extra| {
|
||||
const bytes = std.mem.sliceAsBytes(extra[0..extra_len]);
|
||||
try w.writeAll(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return try buf.toOwnedSlice(gpa);
|
||||
}
|
||||
296
stage0/corpus.zig
Normal file
296
stage0/corpus.zig
Normal file
@@ -0,0 +1,296 @@
|
||||
/// Corpus files for stages testing, sorted by size.
|
||||
/// Paths are repo-relative (no "../" prefix).
|
||||
/// `num_passing` controls how many files are tested and pre-generated.
|
||||
/// Both build.zig and stages_test.zig import this file.
|
||||
/// To enable more tests: just increment `num_passing`.
|
||||
pub const num_passing: usize = 66;
|
||||
|
||||
pub const files = [_][]const u8{
|
||||
"lib/std/crypto/codecs.zig", // 165
|
||||
"lib/std/os/uefi/tables/table_header.zig", // 214
|
||||
"lib/std/zig/llvm.zig", // 247
|
||||
"lib/compiler_rt/neghf2.zig", // 265
|
||||
"lib/compiler_rt/negxf2.zig", // 265
|
||||
"lib/compiler_rt/absvdi2.zig", // 311
|
||||
"lib/compiler_rt/absvsi2.zig", // 311
|
||||
"lib/compiler_rt/absvti2.zig", // 314
|
||||
"lib/compiler_rt/addhf3.zig", // 319
|
||||
"lib/compiler_rt/addxf3.zig", // 323
|
||||
"lib/compiler_rt/mulhf3.zig", // 323
|
||||
"lib/compiler_rt/mulxf3.zig", // 323
|
||||
"lib/compiler_rt/truncxfdf2.zig", // 333
|
||||
"lib/compiler_rt/truncxfsf2.zig", // 333
|
||||
"lib/std/crypto/pcurves/p256/field.zig", // 338
|
||||
"lib/compiler_rt/fixhfdi.zig", // 341
|
||||
"lib/compiler_rt/fixhfsi.zig", // 341
|
||||
"lib/compiler_rt/fixxfdi.zig", // 341
|
||||
"lib/compiler_rt/fixxfsi.zig", // 341
|
||||
"lib/compiler_rt/unordhf2.zig", // 341
|
||||
"lib/compiler_rt/unordxf2.zig", // 341
|
||||
"lib/std/crypto/pcurves/secp256k1/field.zig", // 343
|
||||
"lib/compiler_rt/divhf3.zig", // 344
|
||||
"lib/compiler_rt/floatdihf.zig", // 347
|
||||
"lib/compiler_rt/floatdixf.zig", // 347
|
||||
"lib/compiler_rt/floatsihf.zig", // 347
|
||||
"lib/compiler_rt/floatsixf.zig", // 347
|
||||
"lib/compiler_rt/fixunshfdi.zig", // 350
|
||||
"lib/compiler_rt/fixunshfsi.zig", // 350
|
||||
"lib/compiler_rt/fixunsxfdi.zig", // 350
|
||||
"lib/compiler_rt/fixunsxfsi.zig", // 350
|
||||
"lib/compiler_rt/floatundihf.zig", // 353
|
||||
"lib/compiler_rt/floatundixf.zig", // 353
|
||||
"lib/compiler_rt/floatunsixf.zig", // 353
|
||||
"lib/compiler_rt/truncxfhf2.zig", // 356
|
||||
"lib/compiler_rt/floatunsihf.zig", // 357
|
||||
"lib/compiler_rt/trunctfhf2.zig", // 359
|
||||
"lib/compiler_rt/extendsfxf2.zig", // 360
|
||||
"lib/compiler/aro/backend.zig", // 362
|
||||
"lib/compiler_rt/extenddfxf2.zig", // 364
|
||||
"lib/std/compress.zig", // 372
|
||||
"lib/compiler_rt/extendhfdf2.zig", // 373
|
||||
"lib/compiler_rt/extendhfxf2.zig", // 373
|
||||
"lib/compiler_rt/extendhftf2.zig", // 376
|
||||
"lib/std/crypto/pcurves/p384/field.zig", // 376
|
||||
"lib/compiler_rt/subxf3.zig", // 399
|
||||
"lib/compiler_rt/subhf3.zig", // 406
|
||||
"lib/compiler_rt/negtf2.zig", // 409
|
||||
"lib/std/os/linux/bpf/btf_ext.zig", // 419
|
||||
"lib/compiler_rt/muldc3.zig", // 425
|
||||
"lib/compiler_rt/mulhc3.zig", // 425
|
||||
"lib/compiler_rt/mulsc3.zig", // 425
|
||||
"lib/compiler_rt/mulxc3.zig", // 425
|
||||
"lib/compiler_rt/divdc3.zig", // 434
|
||||
"lib/compiler_rt/divhc3.zig", // 434
|
||||
"lib/compiler_rt/divsc3.zig", // 434
|
||||
"lib/compiler_rt/divxc3.zig", // 434
|
||||
"lib/std/math/complex/abs.zig", // 452
|
||||
"lib/c/common.zig", // 457
|
||||
"lib/std/math/complex/arg.zig", // 458
|
||||
"lib/std/math/complex/conj.zig", // 484
|
||||
"lib/std/math/scalbn.zig", // 503
|
||||
"lib/compiler_rt/negdf2.zig", // 530
|
||||
"lib/compiler_rt/negsf2.zig", // 530
|
||||
"lib/std/Random/SplitMix64.zig", // 530
|
||||
"lib/std/os/uefi/protocol/shell_parameters.zig", // 544
|
||||
// --- files below this line are not yet passing ---
|
||||
"lib/compiler_rt/gexf2.zig", // 531
|
||||
"lib/c/strings.zig", // 549
|
||||
"lib/compiler_rt/fixdfei.zig", // 564
|
||||
"lib/compiler_rt/fixhfei.zig", // 564
|
||||
"lib/compiler_rt/fixsfei.zig", // 564
|
||||
"lib/compiler_rt/fixxfei.zig", // 564
|
||||
"lib/compiler_rt/fixtfei.zig", // 565
|
||||
"lib/compiler_rt/floateidf.zig", // 569
|
||||
"lib/compiler_rt/floateihf.zig", // 569
|
||||
"lib/compiler_rt/floateisf.zig", // 569
|
||||
"lib/compiler_rt/floateixf.zig", // 569
|
||||
"lib/c/inttypes.zig", // 570
|
||||
"lib/compiler_rt/floateitf.zig", // 571
|
||||
"lib/compiler_rt/fixunsdfei.zig", // 575
|
||||
"lib/compiler_rt/fixunshfei.zig", // 575
|
||||
"lib/compiler_rt/fixunssfei.zig", // 575
|
||||
"lib/compiler_rt/fixunsxfei.zig", // 575
|
||||
"lib/compiler_rt/fixunstfei.zig", // 576
|
||||
"lib/compiler_rt/floatuneidf.zig", // 577
|
||||
"lib/compiler_rt/floatuneihf.zig", // 577
|
||||
"lib/compiler_rt/floatuneisf.zig", // 577
|
||||
"lib/compiler_rt/floatuneixf.zig", // 577
|
||||
"lib/std/math/complex/cos.zig", // 577
|
||||
"lib/compiler_rt/floatuneitf.zig", // 579
|
||||
"lib/compiler_rt/multc3.zig", // 581
|
||||
"lib/compiler_rt/divtc3.zig", // 590
|
||||
"lib/compiler_rt/adddf3.zig", // 594
|
||||
"lib/compiler_rt/addsf3.zig", // 594
|
||||
"lib/compiler_rt/muldf3.zig", // 598
|
||||
"lib/compiler_rt/mulsf3.zig", // 598
|
||||
"lib/compiler_rt/truncdfsf2.zig", // 600
|
||||
"lib/std/math/complex/acos.zig", // 608
|
||||
"lib/std/math/complex/pow.zig", // 608
|
||||
"lib/compiler_rt/fixdfsi.zig", // 616
|
||||
"lib/compiler_rt/fixsfsi.zig", // 616
|
||||
"lib/compiler_rt/truncdfhf2.zig", // 616
|
||||
"lib/compiler_rt/floatsidf.zig", // 619
|
||||
"lib/compiler_rt/floatsisf.zig", // 619
|
||||
"lib/std/math/complex/log.zig", // 620
|
||||
"lib/std/math/complex/sin.zig", // 620
|
||||
"lib/std/math/complex/tan.zig", // 626
|
||||
"lib/compiler_rt/fixunsdfsi.zig", // 628
|
||||
"lib/compiler_rt/fixunssfsi.zig", // 628
|
||||
"lib/compiler_rt/floatunsidf.zig", // 628
|
||||
"lib/compiler_rt/floatunsisf.zig", // 628
|
||||
"lib/std/math/complex/proj.zig", // 628
|
||||
"lib/compiler_rt/unorddf2.zig", // 634
|
||||
"lib/compiler_rt/unordsf2.zig", // 634
|
||||
"lib/std/math/complex/asinh.zig", // 641
|
||||
"lib/std/dwarf/EH.zig", // 643
|
||||
"lib/compiler_rt/extendsfdf2.zig", // 644
|
||||
"lib/std/math/complex/atanh.zig", // 645
|
||||
"lib/compiler_rt/unordtf2.zig", // 656
|
||||
"lib/std/Target/generic.zig", // 665
|
||||
"lib/compiler_rt/absv.zig", // 671
|
||||
"lib/std/math/complex/acosh.zig", // 678
|
||||
"lib/compiler_rt/fixdfdi.zig", // 701
|
||||
"lib/compiler_rt/fixsfdi.zig", // 701
|
||||
"lib/compiler_rt/floatdidf.zig", // 704
|
||||
"lib/compiler_rt/floatdisf.zig", // 704
|
||||
"lib/compiler_rt/floattidf.zig", // 712
|
||||
"lib/compiler_rt/floattihf.zig", // 712
|
||||
"lib/compiler_rt/floattisf.zig", // 712
|
||||
"lib/compiler_rt/floattixf.zig", // 712
|
||||
"lib/compiler_rt/fixdfti.zig", // 713
|
||||
"lib/compiler_rt/fixhfti.zig", // 713
|
||||
"lib/compiler_rt/fixsfti.zig", // 713
|
||||
"lib/compiler_rt/fixunsdfdi.zig", // 713
|
||||
"lib/compiler_rt/fixunssfdi.zig", // 713
|
||||
"lib/compiler_rt/fixxfti.zig", // 713
|
||||
"lib/compiler_rt/floatundidf.zig", // 713
|
||||
"lib/compiler_rt/floatundisf.zig", // 713
|
||||
"lib/compiler_rt/floatuntidf.zig", // 724
|
||||
"lib/compiler_rt/floatuntihf.zig", // 724
|
||||
"lib/compiler_rt/floatuntisf.zig", // 724
|
||||
"lib/compiler_rt/floatuntixf.zig", // 724
|
||||
"lib/compiler_rt/addtf3.zig", // 725
|
||||
"lib/compiler_rt/fixunsdfti.zig", // 731
|
||||
"lib/compiler_rt/fixunshfti.zig", // 731
|
||||
"lib/compiler_rt/fixunssfti.zig", // 731
|
||||
"lib/compiler_rt/fixunsxfti.zig", // 731
|
||||
"lib/compiler_rt/trunctfdf2.zig", // 731
|
||||
"lib/compiler_rt/trunctfsf2.zig", // 731
|
||||
"lib/compiler_rt/subdf3.zig", // 735
|
||||
"lib/compiler_rt/subsf3.zig", // 735
|
||||
"lib/compiler_rt/fixtfdi.zig", // 736
|
||||
"lib/compiler_rt/fixtfsi.zig", // 736
|
||||
"lib/compiler_rt/multf3.zig", // 737
|
||||
"lib/std/math/big.zig", // 746
|
||||
"lib/compiler_rt/floatditf.zig", // 748
|
||||
"lib/compiler_rt/floatsitf.zig", // 748
|
||||
"lib/std/math/complex/asin.zig", // 750
|
||||
"lib/compiler_rt/fixunstfdi.zig", // 754
|
||||
"lib/compiler_rt/fixunstfsi.zig", // 754
|
||||
"lib/init/src/root.zig", // 755
|
||||
"lib/compiler_rt/floatunditf.zig", // 761
|
||||
"lib/compiler_rt/floatunsitf.zig", // 761
|
||||
"lib/compiler_rt/udivti3.zig", // 770
|
||||
"lib/compiler_rt/extenddftf2.zig", // 781
|
||||
"lib/compiler_rt/extendsftf2.zig", // 781
|
||||
"lib/std/Build/Step/Fail.zig", // 831
|
||||
"lib/std/crypto/test.zig", // 835
|
||||
"lib/compiler_rt/bswapsi2_test.zig", // 840
|
||||
"lib/compiler_rt/umodti3.zig", // 846
|
||||
"lib/std/os/windows/crypt32.zig", // 850
|
||||
"lib/compiler_rt/subvsi3.zig", // 860
|
||||
"lib/compiler_rt/fixtfti.zig", // 867
|
||||
"lib/compiler_rt/floattitf.zig", // 872
|
||||
"lib/compiler_rt/addvsi3.zig", // 874
|
||||
"lib/compiler_rt/bcmp.zig", // 874
|
||||
"lib/compiler_rt/memset.zig", // 876
|
||||
"lib/compiler_rt/truncsfhf2.zig", // 881
|
||||
"lib/compiler_rt/subtf3.zig", // 884
|
||||
"lib/compiler_rt/divti3_test.zig", // 886
|
||||
"lib/compiler_rt/udivmodti4.zig", // 886
|
||||
"lib/compiler_rt/floatuntitf.zig", // 888
|
||||
"lib/compiler_rt/fixunstfti.zig", // 891
|
||||
"lib/std/compress/lzma2.zig", // 894
|
||||
"lib/compiler_rt/mulvsi3.zig", // 902
|
||||
"lib/compiler_rt/bitreversesi2_test.zig", // 910
|
||||
"lib/compiler_rt/extendhfsf2.zig", // 920
|
||||
"lib/compiler_rt/memcmp.zig", // 931
|
||||
"lib/compiler_rt/subvdi3.zig", // 932
|
||||
"lib/init/src/main.zig", // 936
|
||||
"lib/compiler_rt/gehf2.zig", // 960
|
||||
"lib/compiler_rt/divsf3_test.zig", // 982
|
||||
"lib/compiler_rt/paritysi2_test.zig", // 989
|
||||
"lib/std/math/expo2.zig", // 995
|
||||
};
|
||||
|
||||
pub const sema_unit_tests = [_][]const u8{
|
||||
"stage0/sema_tests/empty.zig",
|
||||
"stage0/sema_tests/const_decl.zig",
|
||||
"stage0/sema_tests/empty_void_function.zig",
|
||||
"stage0/sema_tests/return_integer.zig",
|
||||
"stage0/sema_tests/identity_function.zig",
|
||||
"stage0/sema_tests/add_two_args.zig",
|
||||
"stage0/sema_tests/add_comptime_int.zig",
|
||||
"stage0/sema_tests/sub_two_args.zig",
|
||||
"stage0/sema_tests/xor_two_args.zig",
|
||||
"stage0/sema_tests/xor_comptime_int.zig",
|
||||
"stage0/sema_tests/bitcast_u32_to_f32.zig",
|
||||
"stage0/sema_tests/bitcast_f32_to_u32.zig",
|
||||
"stage0/sema_tests/as_node.zig",
|
||||
"stage0/sema_tests/local_const_binding.zig",
|
||||
"stage0/sema_tests/multiple_operations.zig",
|
||||
"stage0/sema_tests/neghf2_inline_equivalent.zig",
|
||||
"stage0/sema_tests/mul_two_args.zig",
|
||||
"stage0/sema_tests/compare_lt.zig",
|
||||
"stage0/sema_tests/compare_eq.zig",
|
||||
"stage0/sema_tests/bit_shift_right.zig",
|
||||
"stage0/sema_tests/mul_comptime_int.zig",
|
||||
"stage0/sema_tests/chain_of_casts.zig",
|
||||
"stage0/sema_tests/mixed_arithmetic_and_bitwise.zig",
|
||||
"stage0/sema_tests/shift_and_mask.zig",
|
||||
"stage0/sema_tests/f32_arithmetic.zig",
|
||||
"stage0/sema_tests/multi_param_function.zig",
|
||||
"stage0/sema_tests/nested_bitcast_xor.zig",
|
||||
"stage0/sema_tests/pointer_param_identity.zig",
|
||||
"stage0/sema_tests/store_to_pointer.zig",
|
||||
"stage0/sema_tests/sub_comptime.zig",
|
||||
"stage0/sema_tests/store_runtime_value.zig",
|
||||
"stage0/sema_tests/load_from_pointer.zig",
|
||||
"stage0/sema_tests/negate.zig",
|
||||
"stage0/sema_tests/bit_not.zig",
|
||||
"stage0/sema_tests/bit_shift_left.zig",
|
||||
"stage0/sema_tests/intcast.zig",
|
||||
"stage0/sema_tests/truncate.zig",
|
||||
"stage0/sema_tests/two_local_bindings.zig",
|
||||
"stage0/sema_tests/wrapping_add.zig",
|
||||
"stage0/sema_tests/wrapping_sub.zig",
|
||||
"stage0/sema_tests/wrapping_mul.zig",
|
||||
"stage0/sema_tests/bool_not.zig",
|
||||
"stage0/sema_tests/if_simple.zig",
|
||||
"stage0/sema_tests/wrapping_negate.zig",
|
||||
"stage0/sema_tests/clz.zig",
|
||||
"stage0/sema_tests/ctz.zig",
|
||||
"stage0/sema_tests/popcount.zig",
|
||||
"stage0/sema_tests/byteswap.zig",
|
||||
"stage0/sema_tests/float_cast_widen.zig",
|
||||
"stage0/sema_tests/float_cast_narrow.zig",
|
||||
"stage0/sema_tests/int_from_float.zig",
|
||||
"stage0/sema_tests/float_from_int.zig",
|
||||
"stage0/sema_tests/bitmask_shift_and.zig",
|
||||
"stage0/sema_tests/double_negate.zig",
|
||||
"stage0/sema_tests/return_ptr_type.zig",
|
||||
"stage0/sema_tests/float_cast_f16_to_f32.zig",
|
||||
"stage0/sema_tests/wrapping_add_comptime.zig",
|
||||
"stage0/sema_tests/byteswap_and_xor.zig",
|
||||
"stage0/sema_tests/same_file_inline_function_call.zig",
|
||||
"stage0/sema_tests/same_file_inline_call_with_bitcast_and_xor.zig",
|
||||
"stage0/sema_tests/same_file_inline_call_with_two_args.zig",
|
||||
"stage0/sema_tests/intfrombool.zig",
|
||||
"stage0/sema_tests/add_sat.zig",
|
||||
"stage0/sema_tests/sub_sat.zig",
|
||||
"stage0/sema_tests/mul_sat.zig",
|
||||
"stage0/sema_tests/shl_sat.zig",
|
||||
"stage0/sema_tests/bit_or.zig",
|
||||
"stage0/sema_tests/bit_and.zig",
|
||||
"stage0/sema_tests/f16_add.zig",
|
||||
"stage0/sema_tests/f64_mul.zig",
|
||||
"stage0/sema_tests/intcast_computed_dest_type.zig",
|
||||
"stage0/sema_tests/multiple_return_paths.zig",
|
||||
"stage0/sema_tests/if_with_early_return.zig",
|
||||
"stage0/sema_tests/var_bitcast_and_if.zig",
|
||||
"stage0/sema_tests/var_assignment_in_if.zig",
|
||||
"stage0/sema_tests/nested_if.zig",
|
||||
"stage0/sema_tests/wrapping_sub_in_expr.zig",
|
||||
"stage0/sema_tests/if_else_block_result.zig",
|
||||
"stage0/sema_tests/call_inside_runtime_conditional.zig",
|
||||
"stage0/sema_tests/inline_fn_with_call_inside_conditional.zig",
|
||||
"stage0/sema_tests/plus_eq_with_call_inside_conditional.zig",
|
||||
"stage0/sema_tests/inline_fn_with_plus_eq_call_inside_conditional.zig",
|
||||
"stage0/sema_tests/inline_fn_with_generic_call_inside_conditional.zig",
|
||||
"stage0/sema_tests/inline_fn_with_two_generic_calls_in_conditionals.zig",
|
||||
"stage0/sema_tests/inline_fn_with_plus_eq_call_inside_two_conditionals.zig",
|
||||
"stage0/sema_tests/abs_float.zig",
|
||||
"stage0/sema_tests/max_float.zig",
|
||||
"stage0/sema_tests/min_float.zig",
|
||||
"stage0/sema_tests/f64_div.zig",
|
||||
};
|
||||
@@ -5484,8 +5484,8 @@ static AirInstRef semaResolveSwitchComptime(
|
||||
const uint32_t* body = &sema->code.extra[body_start];
|
||||
|
||||
// Reserve BLOCK instruction (matches Zig line 11927-11931).
|
||||
// Data is undefined in upstream; use 0 so the dead-block
|
||||
// skip logic in the test comparison can handle it.
|
||||
// Data is undefined in upstream; zero it so the dead-block
|
||||
// skip rule in the test comparator fires correctly.
|
||||
AirInstData block_data;
|
||||
memset(&block_data, 0, sizeof(block_data));
|
||||
uint32_t block_inst
|
||||
|
||||
@@ -221,69 +221,128 @@ test "sema: function decl smoke test" {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Air raw comparison: C vs Zig
|
||||
// Air raw comparison: C vs pre-computed Zig AIR
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const ZigCompileAirResult = extern struct {
|
||||
items: ?[*]c.SemaFuncAir,
|
||||
len: u32,
|
||||
callback_count: u32,
|
||||
};
|
||||
extern fn zig_compile_air([*:0]const u8, ?[*:0]const u8, [*]u8) ZigCompileAirResult;
|
||||
extern fn zig_compile_air_free(*ZigCompileAirResult) void;
|
||||
const air_tag_names = @import("air_tag_names");
|
||||
|
||||
pub fn airCompareFromSource(source: [:0]const u8, c_func_air_list: c.SemaFuncAirList) !void {
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const f = tmp.dir.createFile("t.zig", .{}) catch return error.TmpFileCreate;
|
||||
f.writeAll(source) catch {
|
||||
f.close();
|
||||
return error.TmpFileWrite;
|
||||
};
|
||||
f.close();
|
||||
var path_buf: [std.fs.max_path_bytes:0]u8 = undefined;
|
||||
const tmp_path = tmp.dir.realpathZ("t.zig", &path_buf) catch return error.TmpFileCreate;
|
||||
path_buf[tmp_path.len] = 0;
|
||||
return airCompare(@ptrCast(tmp_path.ptr), null, c_func_air_list);
|
||||
/// A parsed function from the pre-computed AIR binary data.
|
||||
pub const PrecomputedFunc = struct {
|
||||
name: []const u8,
|
||||
air: c.Air,
|
||||
};
|
||||
|
||||
/// Parse pre-computed AIR from binary data (generated by air_gen).
|
||||
/// Binary format:
|
||||
/// func_count: u32 (little-endian)
|
||||
/// Per function:
|
||||
/// name_len: u32
|
||||
/// name: [name_len]u8
|
||||
/// inst_len: u32
|
||||
/// inst_tags: [inst_len]u8
|
||||
/// inst_datas: [inst_len * 8]u8
|
||||
/// extra_len: u32
|
||||
/// extra: [extra_len * 4]u8
|
||||
pub fn parsePrecomputedAir(gpa: std.mem.Allocator, data: []const u8) ![]PrecomputedFunc {
|
||||
var pos: usize = 0;
|
||||
|
||||
const func_count = readU32(data, &pos) orelse return error.InvalidAirData;
|
||||
const funcs = try gpa.alloc(PrecomputedFunc, func_count);
|
||||
errdefer gpa.free(funcs);
|
||||
|
||||
for (funcs) |*f| {
|
||||
// name
|
||||
const name_len = readU32(data, &pos) orelse return error.InvalidAirData;
|
||||
if (pos + name_len > data.len) return error.InvalidAirData;
|
||||
f.name = data[pos..][0..name_len];
|
||||
pos += name_len;
|
||||
|
||||
// inst_tags + inst_datas (allocate copies with proper alignment)
|
||||
const inst_len = readU32(data, &pos) orelse return error.InvalidAirData;
|
||||
|
||||
const tags: [*c]u8 = if (inst_len > 0) blk: {
|
||||
if (pos + inst_len > data.len) return error.InvalidAirData;
|
||||
const alloc = try gpa.alloc(u8, inst_len);
|
||||
@memcpy(alloc, data[pos..][0..inst_len]);
|
||||
break :blk alloc.ptr;
|
||||
} else null;
|
||||
pos += inst_len;
|
||||
|
||||
const datas: [*c]c.AirInstData = if (inst_len > 0) blk: {
|
||||
const datas_byte_len = inst_len * 8;
|
||||
if (pos + datas_byte_len > data.len) return error.InvalidAirData;
|
||||
const alloc = try gpa.alloc(c.AirInstData, inst_len);
|
||||
const alloc_bytes: [*]u8 = @ptrCast(alloc.ptr);
|
||||
@memcpy(alloc_bytes[0..datas_byte_len], data[pos..][0..datas_byte_len]);
|
||||
break :blk alloc.ptr;
|
||||
} else null;
|
||||
pos += inst_len * 8;
|
||||
|
||||
// extra (allocate copy with u32 alignment)
|
||||
const extra_len = readU32(data, &pos) orelse return error.InvalidAirData;
|
||||
const extra: [*c]u32 = if (extra_len > 0) blk: {
|
||||
const extra_byte_len = extra_len * 4;
|
||||
if (pos + extra_byte_len > data.len) return error.InvalidAirData;
|
||||
const alloc = try gpa.alloc(u32, extra_len);
|
||||
const alloc_bytes: [*]u8 = @ptrCast(alloc.ptr);
|
||||
@memcpy(alloc_bytes[0..extra_byte_len], data[pos..][0..extra_byte_len]);
|
||||
break :blk alloc.ptr;
|
||||
} else null;
|
||||
pos += extra_len * 4;
|
||||
|
||||
f.air = .{
|
||||
.inst_len = inst_len,
|
||||
.inst_cap = inst_len,
|
||||
.inst_tags = tags,
|
||||
.inst_datas = datas,
|
||||
.extra_len = extra_len,
|
||||
.extra_cap = extra_len,
|
||||
.extra = extra,
|
||||
};
|
||||
}
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
pub fn airCompare(
|
||||
src_path: [*:0]const u8,
|
||||
module_root: ?[*:0]const u8,
|
||||
c_func_air_list: c.SemaFuncAirList,
|
||||
) !void {
|
||||
var err_buf: [c.ZIG_COMPILE_ERR_BUF_SIZE]u8 = .{0} ** c.ZIG_COMPILE_ERR_BUF_SIZE;
|
||||
var zig_result = zig_compile_air(src_path, module_root, &err_buf);
|
||||
defer zig_compile_air_free(&zig_result);
|
||||
fn readU32(data: []const u8, pos: *usize) ?u32 {
|
||||
if (pos.* + 4 > data.len) return null;
|
||||
const val = std.mem.readInt(u32, data[pos.*..][0..4], .little);
|
||||
pos.* += 4;
|
||||
return val;
|
||||
}
|
||||
|
||||
if (err_buf[0] != 0) {
|
||||
std.debug.print("zig_compile_air error: {s}\n", .{std.mem.sliceTo(&err_buf, 0)});
|
||||
return error.ZigCompileError;
|
||||
pub fn freePrecomputedAir(gpa: std.mem.Allocator, funcs: []PrecomputedFunc) void {
|
||||
for (funcs) |f| {
|
||||
if (f.air.inst_tags) |t| gpa.free(t[0..f.air.inst_len]);
|
||||
if (f.air.inst_datas) |d| gpa.free(d[0..f.air.inst_len]);
|
||||
if (f.air.extra) |e| gpa.free(e[0..f.air.extra_len]);
|
||||
}
|
||||
gpa.free(funcs);
|
||||
}
|
||||
|
||||
// Canary: if C sema found functions, the Zig callback must have fired.
|
||||
if (c_func_air_list.len > 0 and zig_result.callback_count == 0) {
|
||||
std.debug.print("Canary: C sema produced {d} functions but Zig callback never fired\n", .{c_func_air_list.len});
|
||||
return error.AirCallbackNotFired;
|
||||
}
|
||||
|
||||
const zig_funcs = if (zig_result.items) |items| items[0..zig_result.len] else &[_]c.SemaFuncAir{};
|
||||
/// Compare C sema output against pre-computed AIR data.
|
||||
pub fn airComparePrecomputed(precomputed: []const PrecomputedFunc, c_func_air_list: c.SemaFuncAirList) !void {
|
||||
const c_funcs_ptr: ?[*]const c.SemaFuncAir = @ptrCast(c_func_air_list.items);
|
||||
const c_funcs = if (c_funcs_ptr) |items| items[0..c_func_air_list.len] else &[_]c.SemaFuncAir{};
|
||||
|
||||
// Compare functions that exist in both C and Zig output.
|
||||
// The C sema may produce fewer functions (e.g. missing import
|
||||
// resolution), so we iterate C functions and look them up in Zig.
|
||||
for (c_funcs) |*cf| {
|
||||
const c_name = if (cf.name) |n| std.mem.span(n) else "";
|
||||
const zf = airFindByName(zig_funcs, c_name) orelse {
|
||||
std.debug.print("C function '{s}' not found in Zig output\n", .{c_name});
|
||||
const pf = precomputedFindByName(precomputed, c_name) orelse {
|
||||
std.debug.print("C function '{s}' not found in pre-computed AIR\n", .{c_name});
|
||||
return error.AirMismatch;
|
||||
};
|
||||
try airCompareOne(c_name, &zf.air, &cf.air);
|
||||
try airCompareOne(c_name, &pf.air, &cf.air);
|
||||
}
|
||||
}
|
||||
|
||||
fn precomputedFindByName(funcs: []const PrecomputedFunc, name: []const u8) ?*const PrecomputedFunc {
|
||||
const bare_name = stripModulePrefix(name);
|
||||
for (funcs) |*f| {
|
||||
if (std.mem.eql(u8, bare_name, stripModulePrefix(f.name))) return f;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn cNameSpan(name: [*c]u8) []const u8 {
|
||||
const opt: ?[*:0]const u8 = @ptrCast(name);
|
||||
return if (opt) |n| std.mem.span(n) else "";
|
||||
@@ -298,23 +357,13 @@ fn stripModulePrefix(fqn: []const u8) []const u8 {
|
||||
fqn;
|
||||
}
|
||||
|
||||
fn airFindByName(funcs: []const c.SemaFuncAir, name: []const u8) ?*const c.SemaFuncAir {
|
||||
const bare_name = stripModulePrefix(name);
|
||||
for (funcs) |*f| {
|
||||
const c_name = cNameSpan(f.name);
|
||||
if (std.mem.eql(u8, bare_name, stripModulePrefix(c_name))) return f;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn cToOpt(comptime T: type, ptr: [*c]T) ?[*]const T {
|
||||
return if (ptr == null) null else @ptrCast(ptr);
|
||||
}
|
||||
|
||||
fn airTagNameSlice(tag_val: u8) []const u8 {
|
||||
return std.mem.span(air_tag_name(tag_val));
|
||||
return air_tag_names.names[tag_val];
|
||||
}
|
||||
extern fn air_tag_name(tag: u8) [*:0]const u8;
|
||||
|
||||
fn refKindStr(ref: u32) []const u8 {
|
||||
if (ref == 0xFFFFFFFF) return "none";
|
||||
@@ -791,586 +840,22 @@ fn airCompareOne(name: []const u8, zig_air: *const c.Air, c_air: *const c.Air) !
|
||||
}
|
||||
}
|
||||
|
||||
fn semaAirRawCheck(source: [:0]const u8) !void {
|
||||
// C pipeline: parse -> astgen -> sema
|
||||
var result = try semaCheck(source);
|
||||
defer result.deinit();
|
||||
|
||||
// Zig pipeline: compile source and compare Air arrays
|
||||
try airCompareFromSource(source, result.c_func_air_list);
|
||||
}
|
||||
|
||||
test "sema: Air raw C vs Zig comparison (empty)" {
|
||||
try semaAirRawCheck("");
|
||||
}
|
||||
|
||||
test "sema: Air raw C vs Zig comparison (const)" {
|
||||
try semaAirRawCheck("const x = 0;");
|
||||
}
|
||||
|
||||
test "sema air: empty void function" {
|
||||
try semaAirRawCheck("export fn f() void {}");
|
||||
}
|
||||
|
||||
test "sema air: return integer" {
|
||||
try semaAirRawCheck("export fn f() u32 { return 42; }");
|
||||
}
|
||||
|
||||
test "sema air: identity function" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x; }");
|
||||
}
|
||||
|
||||
test "sema air: add two args" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x + y; }");
|
||||
}
|
||||
|
||||
test "sema air: add comptime int" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x + 1; }");
|
||||
}
|
||||
|
||||
test "sema air: sub two args" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x - y; }");
|
||||
}
|
||||
|
||||
test "sema air: xor two args" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x ^ y; }");
|
||||
}
|
||||
|
||||
test "sema air: xor comptime int" {
|
||||
try semaAirRawCheck("export fn f(x: u16) u16 { return x ^ 0x8000; }");
|
||||
}
|
||||
|
||||
test "sema air: bitcast u32 to f32" {
|
||||
try semaAirRawCheck("export fn f(x: u32) f32 { return @bitCast(x); }");
|
||||
}
|
||||
|
||||
test "sema air: bitcast f32 to u32" {
|
||||
try semaAirRawCheck("export fn f(x: f32) u32 { return @bitCast(x); }");
|
||||
}
|
||||
|
||||
test "sema air: as node" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return @as(u32, x); }");
|
||||
}
|
||||
|
||||
test "sema air: local const binding" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { const y = x + 1; return y; }");
|
||||
}
|
||||
|
||||
test "sema air: multiple operations" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return (x + y) ^ 0xFF; }");
|
||||
}
|
||||
|
||||
test "sema air: neghf2 inline equivalent" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: f16) f16 {
|
||||
\\ return @bitCast(@as(u16, @bitCast(a)) ^ @as(u16, 0x8000));
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: mul two args" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x * y; }");
|
||||
}
|
||||
|
||||
// TODO: bool and/or require block merges and conditional analysis (bool_br_and).
|
||||
// test "sema air: bool and" {
|
||||
// try semaAirRawCheck("export fn f(x: bool, y: bool) bool { return x and y; }");
|
||||
// }
|
||||
|
||||
test "sema air: compare lt" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) bool { return x < y; }");
|
||||
}
|
||||
|
||||
test "sema air: compare eq" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) bool { return x == y; }");
|
||||
}
|
||||
|
||||
test "sema air: bit shift right" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x >> 1; }");
|
||||
}
|
||||
|
||||
test "sema air: mul comptime int" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x * 3; }");
|
||||
}
|
||||
|
||||
test "sema air: chain of casts" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u8) u32 {
|
||||
\\ const wide: u16 = @intCast(x);
|
||||
\\ return @intCast(wide);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: mixed arithmetic and bitwise" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: u32, b: u32) u32 {
|
||||
\\ return (a + b) & 0xFF;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: shift and mask" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32) u32 {
|
||||
\\ return (x >> 8) & 0xFF;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: f32 arithmetic" {
|
||||
try semaAirRawCheck("export fn f(x: f32, y: f32) f32 { return x + y; }");
|
||||
}
|
||||
|
||||
test "sema air: multi-param function" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: u32, b: u32, c: u32) u32 {
|
||||
\\ return (a + b) * c;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: nested bitcast xor" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: f32) f32 {
|
||||
\\ return @bitCast(@as(u32, @bitCast(a)) ^ @as(u32, 0x80000000));
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: pointer param identity" {
|
||||
try semaAirRawCheck("export fn f(x: *u32) *u32 { return x; }");
|
||||
}
|
||||
|
||||
test "sema air: store to pointer" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: *u32) void {
|
||||
\\ x.* = 42;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: sub comptime" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x - 1; }");
|
||||
}
|
||||
|
||||
test "sema air: store runtime value" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(p: *u32, x: u32) void {
|
||||
\\ p.* = x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: load from pointer" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(p: *u32) u32 {
|
||||
\\ return p.*;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: negate" {
|
||||
try semaAirRawCheck("export fn f(x: i32) i32 { return -x; }");
|
||||
}
|
||||
|
||||
test "sema air: bit not" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return ~x; }");
|
||||
}
|
||||
|
||||
test "sema air: bit shift left" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x << 1; }");
|
||||
}
|
||||
|
||||
test "sema air: intcast" {
|
||||
try semaAirRawCheck("export fn f(x: u16) u32 { return @intCast(x); }");
|
||||
}
|
||||
|
||||
test "sema air: truncate" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u16 { return @truncate(x); }");
|
||||
}
|
||||
|
||||
test "sema air: two local bindings" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32, y: u32) u32 {
|
||||
\\ const a = x + 1;
|
||||
\\ const b = y + 2;
|
||||
\\ return a ^ b;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: wrapping add" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x +% y; }");
|
||||
}
|
||||
|
||||
test "sema air: wrapping sub" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x -% y; }");
|
||||
}
|
||||
|
||||
test "sema air: wrapping mul" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x *% y; }");
|
||||
}
|
||||
|
||||
// test "sema air: div" {
|
||||
// // Requires zirDiv with safety checks (div_trunc + remainder check).
|
||||
// try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x / y; }");
|
||||
// }
|
||||
|
||||
test "sema air: bool not" {
|
||||
try semaAirRawCheck("export fn f(x: bool) bool { return !x; }");
|
||||
}
|
||||
|
||||
test "sema air: if simple" {
|
||||
// Requires condbr, block merging, conditional branching.
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32, y: u32) u32 {
|
||||
\\ if (x > y) return x;
|
||||
\\ return y;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: wrapping negate" {
|
||||
try semaAirRawCheck("export fn f(x: i32) i32 { return -%x; }");
|
||||
}
|
||||
|
||||
test "sema air: clz" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return @clz(x); }");
|
||||
}
|
||||
|
||||
test "sema air: ctz" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return @ctz(x); }");
|
||||
}
|
||||
|
||||
test "sema air: popcount" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return @popCount(x); }");
|
||||
}
|
||||
|
||||
test "sema air: byteswap" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return @byteSwap(x); }");
|
||||
}
|
||||
|
||||
test "sema air: float cast widen" {
|
||||
try semaAirRawCheck("export fn f(x: f32) f64 { return @floatCast(x); }");
|
||||
}
|
||||
|
||||
test "sema air: float cast narrow" {
|
||||
try semaAirRawCheck("export fn f(x: f64) f32 { return @floatCast(x); }");
|
||||
}
|
||||
|
||||
test "sema air: int from float" {
|
||||
try semaAirRawCheck("export fn f(x: f32) u32 { return @intFromFloat(x); }");
|
||||
}
|
||||
|
||||
test "sema air: float from int" {
|
||||
try semaAirRawCheck("export fn f(x: u32) f32 { return @floatFromInt(x); }");
|
||||
}
|
||||
|
||||
test "sema air: bitmask shift and" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return (x >> 16) & 0xFF; }");
|
||||
}
|
||||
|
||||
test "sema air: double negate" {
|
||||
try semaAirRawCheck("export fn f(x: i32) i32 { return -(-x); }");
|
||||
}
|
||||
|
||||
test "sema air: return ptr type" {
|
||||
try semaAirRawCheck("export fn f(p: *u32) *u32 { return p; }");
|
||||
}
|
||||
|
||||
test "sema air: float cast f16 to f32" {
|
||||
try semaAirRawCheck("export fn f(x: f16) f32 { return @floatCast(x); }");
|
||||
}
|
||||
|
||||
test "sema air: wrapping add comptime" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x +% 1; }");
|
||||
}
|
||||
|
||||
test "sema air: byteswap and xor" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32) u32 {
|
||||
\\ return @byteSwap(x) ^ 0xFF;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: same-file inline function call" {
|
||||
try semaAirRawCheck(
|
||||
\\inline fn negate(x: u16) u16 {
|
||||
\\ return ~x;
|
||||
\\}
|
||||
\\export fn f(a: u16) u16 {
|
||||
\\ return negate(a);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: same-file inline call with bitcast and xor" {
|
||||
try semaAirRawCheck(
|
||||
\\inline fn flip_sign(x: u16) u16 {
|
||||
\\ return x ^ 0x8000;
|
||||
\\}
|
||||
\\export fn f(a: u16) u16 {
|
||||
\\ return flip_sign(a);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: same-file inline call with two args" {
|
||||
try semaAirRawCheck(
|
||||
\\inline fn my_add(x: u32, y: u32) u32 {
|
||||
\\ return x + y;
|
||||
\\}
|
||||
\\export fn f(a: u32, b: u32) u32 {
|
||||
\\ return my_add(a, b);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: intFromBool" {
|
||||
try semaAirRawCheck("export fn f(x: bool) u32 { return @intFromBool(x); }");
|
||||
}
|
||||
|
||||
test "sema air: add_sat" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x +| y; }");
|
||||
}
|
||||
|
||||
test "sema air: sub_sat" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x -| y; }");
|
||||
}
|
||||
|
||||
test "sema air: mul_sat" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x *| y; }");
|
||||
}
|
||||
|
||||
test "sema air: shl_sat" {
|
||||
try semaAirRawCheck("export fn f(x: u32) u32 { return x <<| 1; }");
|
||||
}
|
||||
|
||||
test "sema air: bit_or" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x | y; }");
|
||||
}
|
||||
|
||||
test "sema air: bit_and" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x & y; }");
|
||||
}
|
||||
|
||||
test "sema air: f16 add" {
|
||||
try semaAirRawCheck("export fn f(x: f16, y: f16) f16 { return x + y; }");
|
||||
}
|
||||
|
||||
test "sema air: f64 mul" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return x * y; }");
|
||||
}
|
||||
|
||||
test "sema air: intcast computed dest type" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u16) u32 {
|
||||
\\ return @intCast(x);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: multiple return paths" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32) u32 {
|
||||
\\ return x + 1;
|
||||
\\}
|
||||
\\export fn g(x: u32) u32 {
|
||||
\\ return x * 2;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: if with early return" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32, y: u32) u32 {
|
||||
\\ if (x > y) return x;
|
||||
\\ return y;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: var bitcast and if" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: f16) u16 {
|
||||
\\ var x: u16 = @bitCast(a);
|
||||
\\ if (x > 100) {
|
||||
\\ x = x - 1;
|
||||
\\ }
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: var assignment in if" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: u32, b: u32) u32 {
|
||||
\\ var x = a;
|
||||
\\ if (b > a) {
|
||||
\\ x = b;
|
||||
\\ }
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: nested if" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: u32, b: u32) u32 {
|
||||
\\ if (a > 0) {
|
||||
\\ if (b > 0) return a + b;
|
||||
\\ return a;
|
||||
\\ }
|
||||
\\ return b;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: wrapping sub in expr" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ return a -% 1;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: if-else block result" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(a: u32, b: u32) u32 {
|
||||
\\ const x = if (a > b) a else b;
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: call inside runtime conditional" {
|
||||
try semaAirRawCheck(
|
||||
\\fn bar(p: *u32) void {
|
||||
\\ p.* += 1;
|
||||
\\}
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ var x: u32 = a;
|
||||
\\ if (a < 10) bar(&x);
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: inline fn with call inside conditional" {
|
||||
try semaAirRawCheck(
|
||||
\\fn bar(p: *u32) void {
|
||||
\\ p.* += 1;
|
||||
\\}
|
||||
\\inline fn baz(a: u32, x: *u32) void {
|
||||
\\ if (a < 10) bar(x);
|
||||
\\}
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ var x: u32 = a;
|
||||
\\ baz(a, &x);
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: += with call inside conditional" {
|
||||
try semaAirRawCheck(
|
||||
\\fn bar(p: *u32) u32 {
|
||||
\\ return p.* + 1;
|
||||
\\}
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ var x: u32 = a;
|
||||
\\ if (a < 10) x += bar(&x);
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: inline fn with += call inside conditional" {
|
||||
try semaAirRawCheck(
|
||||
\\fn bar(p: *u32) u32 {
|
||||
\\ return p.* + 1;
|
||||
\\}
|
||||
\\inline fn baz(a: u32, x: *u32) void {
|
||||
\\ if (a < 10) x.* += bar(x);
|
||||
\\}
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ var x: u32 = a;
|
||||
\\ baz(a, &x);
|
||||
\\ return x;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: inline fn with generic call inside conditional" {
|
||||
try semaAirRawCheck(
|
||||
\\fn normalize(comptime T: type, p: *T) i32 {
|
||||
\\ p.* +%= 1;
|
||||
\\ return 1;
|
||||
\\}
|
||||
\\inline fn mulf(comptime T: type, a: T) T {
|
||||
\\ var x: T = a;
|
||||
\\ var scale: i32 = 0;
|
||||
\\ if (x < 10) scale += normalize(T, &x);
|
||||
\\ return x +% @as(T, @intCast(@as(u32, @bitCast(scale))));
|
||||
\\}
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ return mulf(u32, a);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: inline fn with two generic calls in conditionals" {
|
||||
try semaAirRawCheck(
|
||||
\\fn normalize(comptime T: type, p: *T) i32 {
|
||||
\\ p.* +%= 1;
|
||||
\\ return 1;
|
||||
\\}
|
||||
\\inline fn mulf(comptime T: type, a: T, b: T) T {
|
||||
\\ var x: T = a;
|
||||
\\ var y: T = b;
|
||||
\\ var scale: i32 = 0;
|
||||
\\ if (x < 10) scale += normalize(T, &x);
|
||||
\\ if (y < 10) scale += normalize(T, &y);
|
||||
\\ return x +% y +% @as(T, @intCast(@as(u32, @bitCast(scale))));
|
||||
\\}
|
||||
\\export fn f(a: u32, b: u32) u32 {
|
||||
\\ return mulf(u32, a, b);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: inline fn with += call inside two conditionals" {
|
||||
try semaAirRawCheck(
|
||||
\\fn bar(p: *u32) u32 {
|
||||
\\ return p.* + 1;
|
||||
\\}
|
||||
\\inline fn baz(a: u32, x: *u32, y: *u32) void {
|
||||
\\ if (a < 10) x.* += bar(x);
|
||||
\\ if (a < 20) y.* += bar(y);
|
||||
\\}
|
||||
\\export fn f(a: u32) u32 {
|
||||
\\ var x: u32 = a;
|
||||
\\ var y: u32 = a;
|
||||
\\ baz(a, &x, &y);
|
||||
\\ return x +% y;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: @abs float" {
|
||||
try semaAirRawCheck("export fn f(x: f64) f64 { return @abs(x); }");
|
||||
}
|
||||
|
||||
test "sema air: @max float" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return @max(x, y); }");
|
||||
}
|
||||
|
||||
test "sema air: @min float" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return @min(x, y); }");
|
||||
}
|
||||
|
||||
test "sema air: f64 div" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return x / y; }");
|
||||
const corpus = @import("corpus.zig");
|
||||
|
||||
test "sema air: unit tests" {
|
||||
const gpa = std.testing.allocator;
|
||||
@setEvalBranchQuota(corpus.sema_unit_tests.len * 2);
|
||||
inline for (corpus.sema_unit_tests) |path| {
|
||||
const source: [:0]const u8 = @embedFile("../" ++ path);
|
||||
var result = try semaCheck(source);
|
||||
defer result.deinit();
|
||||
|
||||
const air_data = @import("air_data").getData(path);
|
||||
const precomputed = try parsePrecomputedAir(gpa, air_data);
|
||||
defer freePrecomputedAir(gpa, precomputed);
|
||||
airComparePrecomputed(precomputed, result.c_func_air_list) catch {
|
||||
std.debug.print("FAIL: {s}\n", .{path});
|
||||
return error.TestFailed;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
1
stage0/sema_tests/abs_float.zig
Normal file
1
stage0/sema_tests/abs_float.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f64) f64 { return @abs(x); }
|
||||
1
stage0/sema_tests/add_comptime_int.zig
Normal file
1
stage0/sema_tests/add_comptime_int.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x + 1; }
|
||||
1
stage0/sema_tests/add_sat.zig
Normal file
1
stage0/sema_tests/add_sat.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x +| y; }
|
||||
1
stage0/sema_tests/add_two_args.zig
Normal file
1
stage0/sema_tests/add_two_args.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x + y; }
|
||||
1
stage0/sema_tests/as_node.zig
Normal file
1
stage0/sema_tests/as_node.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return @as(u32, x); }
|
||||
1
stage0/sema_tests/bit_and.zig
Normal file
1
stage0/sema_tests/bit_and.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x & y; }
|
||||
1
stage0/sema_tests/bit_not.zig
Normal file
1
stage0/sema_tests/bit_not.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return ~x; }
|
||||
1
stage0/sema_tests/bit_or.zig
Normal file
1
stage0/sema_tests/bit_or.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x | y; }
|
||||
1
stage0/sema_tests/bit_shift_left.zig
Normal file
1
stage0/sema_tests/bit_shift_left.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x << 1; }
|
||||
1
stage0/sema_tests/bit_shift_right.zig
Normal file
1
stage0/sema_tests/bit_shift_right.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x >> 1; }
|
||||
1
stage0/sema_tests/bitcast_f32_to_u32.zig
Normal file
1
stage0/sema_tests/bitcast_f32_to_u32.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f32) u32 { return @bitCast(x); }
|
||||
1
stage0/sema_tests/bitcast_u32_to_f32.zig
Normal file
1
stage0/sema_tests/bitcast_u32_to_f32.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) f32 { return @bitCast(x); }
|
||||
1
stage0/sema_tests/bitmask_shift_and.zig
Normal file
1
stage0/sema_tests/bitmask_shift_and.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return (x >> 16) & 0xFF; }
|
||||
1
stage0/sema_tests/bool_not.zig
Normal file
1
stage0/sema_tests/bool_not.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: bool) bool { return !x; }
|
||||
1
stage0/sema_tests/byteswap.zig
Normal file
1
stage0/sema_tests/byteswap.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return @byteSwap(x); }
|
||||
3
stage0/sema_tests/byteswap_and_xor.zig
Normal file
3
stage0/sema_tests/byteswap_and_xor.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(x: u32) u32 {
|
||||
return @byteSwap(x) ^ 0xFF;
|
||||
}
|
||||
8
stage0/sema_tests/call_inside_runtime_conditional.zig
Normal file
8
stage0/sema_tests/call_inside_runtime_conditional.zig
Normal file
@@ -0,0 +1,8 @@
|
||||
fn bar(p: *u32) void {
|
||||
p.* += 1;
|
||||
}
|
||||
export fn f(a: u32) u32 {
|
||||
var x: u32 = a;
|
||||
if (a < 10) bar(&x);
|
||||
return x;
|
||||
}
|
||||
4
stage0/sema_tests/chain_of_casts.zig
Normal file
4
stage0/sema_tests/chain_of_casts.zig
Normal file
@@ -0,0 +1,4 @@
|
||||
export fn f(x: u8) u32 {
|
||||
const wide: u16 = @intCast(x);
|
||||
return @intCast(wide);
|
||||
}
|
||||
1
stage0/sema_tests/clz.zig
Normal file
1
stage0/sema_tests/clz.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return @clz(x); }
|
||||
1
stage0/sema_tests/compare_eq.zig
Normal file
1
stage0/sema_tests/compare_eq.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) bool { return x == y; }
|
||||
1
stage0/sema_tests/compare_lt.zig
Normal file
1
stage0/sema_tests/compare_lt.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) bool { return x < y; }
|
||||
1
stage0/sema_tests/const_decl.zig
Normal file
1
stage0/sema_tests/const_decl.zig
Normal file
@@ -0,0 +1 @@
|
||||
const x = 0;
|
||||
1
stage0/sema_tests/ctz.zig
Normal file
1
stage0/sema_tests/ctz.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return @ctz(x); }
|
||||
1
stage0/sema_tests/double_negate.zig
Normal file
1
stage0/sema_tests/double_negate.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: i32) i32 { return -(-x); }
|
||||
0
stage0/sema_tests/empty.zig
Normal file
0
stage0/sema_tests/empty.zig
Normal file
1
stage0/sema_tests/empty_void_function.zig
Normal file
1
stage0/sema_tests/empty_void_function.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f() void {}
|
||||
1
stage0/sema_tests/f16_add.zig
Normal file
1
stage0/sema_tests/f16_add.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f16, y: f16) f16 { return x + y; }
|
||||
1
stage0/sema_tests/f32_arithmetic.zig
Normal file
1
stage0/sema_tests/f32_arithmetic.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f32, y: f32) f32 { return x + y; }
|
||||
1
stage0/sema_tests/f64_div.zig
Normal file
1
stage0/sema_tests/f64_div.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f64, y: f64) f64 { return x / y; }
|
||||
1
stage0/sema_tests/f64_mul.zig
Normal file
1
stage0/sema_tests/f64_mul.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f64, y: f64) f64 { return x * y; }
|
||||
1
stage0/sema_tests/float_cast_f16_to_f32.zig
Normal file
1
stage0/sema_tests/float_cast_f16_to_f32.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f16) f32 { return @floatCast(x); }
|
||||
1
stage0/sema_tests/float_cast_narrow.zig
Normal file
1
stage0/sema_tests/float_cast_narrow.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f64) f32 { return @floatCast(x); }
|
||||
1
stage0/sema_tests/float_cast_widen.zig
Normal file
1
stage0/sema_tests/float_cast_widen.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f32) f64 { return @floatCast(x); }
|
||||
1
stage0/sema_tests/float_from_int.zig
Normal file
1
stage0/sema_tests/float_from_int.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) f32 { return @floatFromInt(x); }
|
||||
1
stage0/sema_tests/identity_function.zig
Normal file
1
stage0/sema_tests/identity_function.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x; }
|
||||
4
stage0/sema_tests/if_else_block_result.zig
Normal file
4
stage0/sema_tests/if_else_block_result.zig
Normal file
@@ -0,0 +1,4 @@
|
||||
export fn f(a: u32, b: u32) u32 {
|
||||
const x = if (a > b) a else b;
|
||||
return x;
|
||||
}
|
||||
4
stage0/sema_tests/if_simple.zig
Normal file
4
stage0/sema_tests/if_simple.zig
Normal file
@@ -0,0 +1,4 @@
|
||||
export fn f(x: u32, y: u32) u32 {
|
||||
if (x > y) return x;
|
||||
return y;
|
||||
}
|
||||
4
stage0/sema_tests/if_with_early_return.zig
Normal file
4
stage0/sema_tests/if_with_early_return.zig
Normal file
@@ -0,0 +1,4 @@
|
||||
export fn f(x: u32, y: u32) u32 {
|
||||
if (x > y) return x;
|
||||
return y;
|
||||
}
|
||||
11
stage0/sema_tests/inline_fn_with_call_inside_conditional.zig
Normal file
11
stage0/sema_tests/inline_fn_with_call_inside_conditional.zig
Normal file
@@ -0,0 +1,11 @@
|
||||
fn bar(p: *u32) void {
|
||||
p.* += 1;
|
||||
}
|
||||
inline fn baz(a: u32, x: *u32) void {
|
||||
if (a < 10) bar(x);
|
||||
}
|
||||
export fn f(a: u32) u32 {
|
||||
var x: u32 = a;
|
||||
baz(a, &x);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fn normalize(comptime T: type, p: *T) i32 {
|
||||
p.* +%= 1;
|
||||
return 1;
|
||||
}
|
||||
inline fn mulf(comptime T: type, a: T) T {
|
||||
var x: T = a;
|
||||
var scale: i32 = 0;
|
||||
if (x < 10) scale += normalize(T, &x);
|
||||
return x +% @as(T, @intCast(@as(u32, @bitCast(scale))));
|
||||
}
|
||||
export fn f(a: u32) u32 {
|
||||
return mulf(u32, a);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fn bar(p: *u32) u32 {
|
||||
return p.* + 1;
|
||||
}
|
||||
inline fn baz(a: u32, x: *u32) void {
|
||||
if (a < 10) x.* += bar(x);
|
||||
}
|
||||
export fn f(a: u32) u32 {
|
||||
var x: u32 = a;
|
||||
baz(a, &x);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fn bar(p: *u32) u32 {
|
||||
return p.* + 1;
|
||||
}
|
||||
inline fn baz(a: u32, x: *u32, y: *u32) void {
|
||||
if (a < 10) x.* += bar(x);
|
||||
if (a < 20) y.* += bar(y);
|
||||
}
|
||||
export fn f(a: u32) u32 {
|
||||
var x: u32 = a;
|
||||
var y: u32 = a;
|
||||
baz(a, &x, &y);
|
||||
return x +% y;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
fn normalize(comptime T: type, p: *T) i32 {
|
||||
p.* +%= 1;
|
||||
return 1;
|
||||
}
|
||||
inline fn mulf(comptime T: type, a: T, b: T) T {
|
||||
var x: T = a;
|
||||
var y: T = b;
|
||||
var scale: i32 = 0;
|
||||
if (x < 10) scale += normalize(T, &x);
|
||||
if (y < 10) scale += normalize(T, &y);
|
||||
return x +% y +% @as(T, @intCast(@as(u32, @bitCast(scale))));
|
||||
}
|
||||
export fn f(a: u32, b: u32) u32 {
|
||||
return mulf(u32, a, b);
|
||||
}
|
||||
1
stage0/sema_tests/int_from_float.zig
Normal file
1
stage0/sema_tests/int_from_float.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f32) u32 { return @intFromFloat(x); }
|
||||
1
stage0/sema_tests/intcast.zig
Normal file
1
stage0/sema_tests/intcast.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u16) u32 { return @intCast(x); }
|
||||
3
stage0/sema_tests/intcast_computed_dest_type.zig
Normal file
3
stage0/sema_tests/intcast_computed_dest_type.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(x: u16) u32 {
|
||||
return @intCast(x);
|
||||
}
|
||||
1
stage0/sema_tests/intfrombool.zig
Normal file
1
stage0/sema_tests/intfrombool.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: bool) u32 { return @intFromBool(x); }
|
||||
3
stage0/sema_tests/load_from_pointer.zig
Normal file
3
stage0/sema_tests/load_from_pointer.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(p: *u32) u32 {
|
||||
return p.*;
|
||||
}
|
||||
1
stage0/sema_tests/local_const_binding.zig
Normal file
1
stage0/sema_tests/local_const_binding.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { const y = x + 1; return y; }
|
||||
1
stage0/sema_tests/max_float.zig
Normal file
1
stage0/sema_tests/max_float.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f64, y: f64) f64 { return @max(x, y); }
|
||||
1
stage0/sema_tests/min_float.zig
Normal file
1
stage0/sema_tests/min_float.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: f64, y: f64) f64 { return @min(x, y); }
|
||||
3
stage0/sema_tests/mixed_arithmetic_and_bitwise.zig
Normal file
3
stage0/sema_tests/mixed_arithmetic_and_bitwise.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(a: u32, b: u32) u32 {
|
||||
return (a + b) & 0xFF;
|
||||
}
|
||||
1
stage0/sema_tests/mul_comptime_int.zig
Normal file
1
stage0/sema_tests/mul_comptime_int.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x * 3; }
|
||||
1
stage0/sema_tests/mul_sat.zig
Normal file
1
stage0/sema_tests/mul_sat.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x *| y; }
|
||||
1
stage0/sema_tests/mul_two_args.zig
Normal file
1
stage0/sema_tests/mul_two_args.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x * y; }
|
||||
3
stage0/sema_tests/multi_param_function.zig
Normal file
3
stage0/sema_tests/multi_param_function.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(a: u32, b: u32, c: u32) u32 {
|
||||
return (a + b) * c;
|
||||
}
|
||||
1
stage0/sema_tests/multiple_operations.zig
Normal file
1
stage0/sema_tests/multiple_operations.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return (x + y) ^ 0xFF; }
|
||||
6
stage0/sema_tests/multiple_return_paths.zig
Normal file
6
stage0/sema_tests/multiple_return_paths.zig
Normal file
@@ -0,0 +1,6 @@
|
||||
export fn f(x: u32) u32 {
|
||||
return x + 1;
|
||||
}
|
||||
export fn g(x: u32) u32 {
|
||||
return x * 2;
|
||||
}
|
||||
1
stage0/sema_tests/negate.zig
Normal file
1
stage0/sema_tests/negate.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: i32) i32 { return -x; }
|
||||
3
stage0/sema_tests/neghf2_inline_equivalent.zig
Normal file
3
stage0/sema_tests/neghf2_inline_equivalent.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(a: f16) f16 {
|
||||
return @bitCast(@as(u16, @bitCast(a)) ^ @as(u16, 0x8000));
|
||||
}
|
||||
3
stage0/sema_tests/nested_bitcast_xor.zig
Normal file
3
stage0/sema_tests/nested_bitcast_xor.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(a: f32) f32 {
|
||||
return @bitCast(@as(u32, @bitCast(a)) ^ @as(u32, 0x80000000));
|
||||
}
|
||||
7
stage0/sema_tests/nested_if.zig
Normal file
7
stage0/sema_tests/nested_if.zig
Normal file
@@ -0,0 +1,7 @@
|
||||
export fn f(a: u32, b: u32) u32 {
|
||||
if (a > 0) {
|
||||
if (b > 0) return a + b;
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fn bar(p: *u32) u32 {
|
||||
return p.* + 1;
|
||||
}
|
||||
export fn f(a: u32) u32 {
|
||||
var x: u32 = a;
|
||||
if (a < 10) x += bar(&x);
|
||||
return x;
|
||||
}
|
||||
1
stage0/sema_tests/pointer_param_identity.zig
Normal file
1
stage0/sema_tests/pointer_param_identity.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: *u32) *u32 { return x; }
|
||||
1
stage0/sema_tests/popcount.zig
Normal file
1
stage0/sema_tests/popcount.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return @popCount(x); }
|
||||
1
stage0/sema_tests/return_integer.zig
Normal file
1
stage0/sema_tests/return_integer.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f() u32 { return 42; }
|
||||
1
stage0/sema_tests/return_ptr_type.zig
Normal file
1
stage0/sema_tests/return_ptr_type.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(p: *u32) *u32 { return p; }
|
||||
@@ -0,0 +1,6 @@
|
||||
inline fn flip_sign(x: u16) u16 {
|
||||
return x ^ 0x8000;
|
||||
}
|
||||
export fn f(a: u16) u16 {
|
||||
return flip_sign(a);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
inline fn my_add(x: u32, y: u32) u32 {
|
||||
return x + y;
|
||||
}
|
||||
export fn f(a: u32, b: u32) u32 {
|
||||
return my_add(a, b);
|
||||
}
|
||||
6
stage0/sema_tests/same_file_inline_function_call.zig
Normal file
6
stage0/sema_tests/same_file_inline_function_call.zig
Normal file
@@ -0,0 +1,6 @@
|
||||
inline fn negate(x: u16) u16 {
|
||||
return ~x;
|
||||
}
|
||||
export fn f(a: u16) u16 {
|
||||
return negate(a);
|
||||
}
|
||||
3
stage0/sema_tests/shift_and_mask.zig
Normal file
3
stage0/sema_tests/shift_and_mask.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(x: u32) u32 {
|
||||
return (x >> 8) & 0xFF;
|
||||
}
|
||||
1
stage0/sema_tests/shl_sat.zig
Normal file
1
stage0/sema_tests/shl_sat.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x <<| 1; }
|
||||
3
stage0/sema_tests/store_runtime_value.zig
Normal file
3
stage0/sema_tests/store_runtime_value.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(p: *u32, x: u32) void {
|
||||
p.* = x;
|
||||
}
|
||||
3
stage0/sema_tests/store_to_pointer.zig
Normal file
3
stage0/sema_tests/store_to_pointer.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(x: *u32) void {
|
||||
x.* = 42;
|
||||
}
|
||||
1
stage0/sema_tests/sub_comptime.zig
Normal file
1
stage0/sema_tests/sub_comptime.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x - 1; }
|
||||
1
stage0/sema_tests/sub_sat.zig
Normal file
1
stage0/sema_tests/sub_sat.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x -| y; }
|
||||
1
stage0/sema_tests/sub_two_args.zig
Normal file
1
stage0/sema_tests/sub_two_args.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x - y; }
|
||||
1
stage0/sema_tests/truncate.zig
Normal file
1
stage0/sema_tests/truncate.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u16 { return @truncate(x); }
|
||||
5
stage0/sema_tests/two_local_bindings.zig
Normal file
5
stage0/sema_tests/two_local_bindings.zig
Normal file
@@ -0,0 +1,5 @@
|
||||
export fn f(x: u32, y: u32) u32 {
|
||||
const a = x + 1;
|
||||
const b = y + 2;
|
||||
return a ^ b;
|
||||
}
|
||||
7
stage0/sema_tests/var_assignment_in_if.zig
Normal file
7
stage0/sema_tests/var_assignment_in_if.zig
Normal file
@@ -0,0 +1,7 @@
|
||||
export fn f(a: u32, b: u32) u32 {
|
||||
var x = a;
|
||||
if (b > a) {
|
||||
x = b;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
7
stage0/sema_tests/var_bitcast_and_if.zig
Normal file
7
stage0/sema_tests/var_bitcast_and_if.zig
Normal file
@@ -0,0 +1,7 @@
|
||||
export fn f(a: f16) u16 {
|
||||
var x: u16 = @bitCast(a);
|
||||
if (x > 100) {
|
||||
x = x - 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
1
stage0/sema_tests/wrapping_add.zig
Normal file
1
stage0/sema_tests/wrapping_add.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x +% y; }
|
||||
1
stage0/sema_tests/wrapping_add_comptime.zig
Normal file
1
stage0/sema_tests/wrapping_add_comptime.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32) u32 { return x +% 1; }
|
||||
1
stage0/sema_tests/wrapping_mul.zig
Normal file
1
stage0/sema_tests/wrapping_mul.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x *% y; }
|
||||
1
stage0/sema_tests/wrapping_negate.zig
Normal file
1
stage0/sema_tests/wrapping_negate.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: i32) i32 { return -%x; }
|
||||
1
stage0/sema_tests/wrapping_sub.zig
Normal file
1
stage0/sema_tests/wrapping_sub.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x -% y; }
|
||||
3
stage0/sema_tests/wrapping_sub_in_expr.zig
Normal file
3
stage0/sema_tests/wrapping_sub_in_expr.zig
Normal file
@@ -0,0 +1,3 @@
|
||||
export fn f(a: u32) u32 {
|
||||
return a -% 1;
|
||||
}
|
||||
1
stage0/sema_tests/xor_comptime_int.zig
Normal file
1
stage0/sema_tests/xor_comptime_int.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u16) u16 { return x ^ 0x8000; }
|
||||
1
stage0/sema_tests/xor_two_args.zig
Normal file
1
stage0/sema_tests/xor_two_args.zig
Normal file
@@ -0,0 +1 @@
|
||||
export fn f(x: u32, y: u32) u32 { return x ^ y; }
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user