test(C1.1): cSourceCacheKey — content key for compiled #source units
Source bytes, declared-header CONTENT (header edits invalidate), defines/flags/include dirs in order, LLVM version, and target triple/sysroot all participate; section tags keep equal strings in different roles distinct. Pure function + variance property tests; nothing consumes it yet.
This commit is contained in:
68
src/c_import.test.zig
Normal file
68
src/c_import.test.zig
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const c_import = @import("c_import.zig");
|
||||||
|
|
||||||
|
const SRC = "int f(void) { return 1; }";
|
||||||
|
const HDR = "int f(void);";
|
||||||
|
const VER = "19.1.7";
|
||||||
|
|
||||||
|
const none: []const []const u8 = &.{};
|
||||||
|
|
||||||
|
fn baseKey() u64 {
|
||||||
|
return c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=1"}, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: stable when nothing changes" {
|
||||||
|
try std.testing.expectEqual(baseKey(), baseKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: source bytes vary the key" {
|
||||||
|
const other = c_import.cSourceCacheKey("int f(void) { return 2; }", &.{HDR}, &.{"A=1"}, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != other);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: declared header content varies the key" {
|
||||||
|
const other = c_import.cSourceCacheKey(SRC, &.{"int f(void); int g(void);"}, &.{"A=1"}, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != other);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: defines vary the key (value and order)" {
|
||||||
|
const v2 = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=2"}, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != v2);
|
||||||
|
|
||||||
|
const ab = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{ "A=1", "B=1" }, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
const ba = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{ "B=1", "A=1" }, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(ab != ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: flags vary the key" {
|
||||||
|
const other = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=1"}, &.{"-O3"}, &.{"inc"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != other);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: a define is not a flag (same string, different role)" {
|
||||||
|
const as_define = c_import.cSourceCacheKey(SRC, none, &.{"X"}, none, none, VER, null, null);
|
||||||
|
const as_flag = c_import.cSourceCacheKey(SRC, none, none, &.{"X"}, none, VER, null, null);
|
||||||
|
try std.testing.expect(as_define != as_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: include dirs vary the key" {
|
||||||
|
const other = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=1"}, &.{"-O2"}, &.{"other"}, VER, "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != other);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: llvm version varies the key" {
|
||||||
|
const other = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=1"}, &.{"-O2"}, &.{"inc"}, "20.0.0", "arm64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != other);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "cSourceCacheKey: triple and sysroot vary the key; absent is not empty" {
|
||||||
|
const other_triple = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=1"}, &.{"-O2"}, &.{"inc"}, VER, "x86_64-apple-darwin", "/sdk");
|
||||||
|
try std.testing.expect(baseKey() != other_triple);
|
||||||
|
|
||||||
|
const other_sysroot = c_import.cSourceCacheKey(SRC, &.{HDR}, &.{"A=1"}, &.{"-O2"}, &.{"inc"}, VER, "arm64-apple-darwin", "/ndk");
|
||||||
|
try std.testing.expect(baseKey() != other_sysroot);
|
||||||
|
|
||||||
|
const absent = c_import.cSourceCacheKey(SRC, none, none, none, none, VER, null, null);
|
||||||
|
const empty = c_import.cSourceCacheKey(SRC, none, none, none, none, VER, "", "");
|
||||||
|
try std.testing.expect(absent != empty);
|
||||||
|
}
|
||||||
@@ -33,6 +33,50 @@ pub const CImportInfo = struct {
|
|||||||
flags: []const []const u8,
|
flags: []const []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Cache key for one compiled `#source` member. Everything that can
|
||||||
|
/// change the produced object participates: the source bytes, the
|
||||||
|
/// unit's declared `#include` headers BY CONTENT (editing a declared
|
||||||
|
/// header invalidates), defines / flags / include dirs in declaration
|
||||||
|
/// order, the LLVM version, and the cross-target (triple + sysroot).
|
||||||
|
/// Section tags keep equal strings in different roles distinct (a
|
||||||
|
/// define never aliases a flag, an absent triple never aliases an
|
||||||
|
/// empty one). Transitive includes of the .c itself do NOT
|
||||||
|
/// participate — the block's declared surface is the invalidation
|
||||||
|
/// boundary.
|
||||||
|
pub fn cSourceCacheKey(
|
||||||
|
source_bytes: []const u8,
|
||||||
|
header_bytes: []const []const u8,
|
||||||
|
defines: []const []const u8,
|
||||||
|
flags: []const []const u8,
|
||||||
|
include_dirs: []const []const u8,
|
||||||
|
llvm_version: []const u8,
|
||||||
|
triple: ?[]const u8,
|
||||||
|
sysroot: ?[]const u8,
|
||||||
|
) u64 {
|
||||||
|
const Wyhash = std.hash.Wyhash;
|
||||||
|
var key = Wyhash.hash(0, "sx-c-import-v1");
|
||||||
|
key = Wyhash.hash(key, source_bytes);
|
||||||
|
key = Wyhash.hash(key, "\x01headers");
|
||||||
|
for (header_bytes) |hb| key = Wyhash.hash(key, hb);
|
||||||
|
key = Wyhash.hash(key, "\x01defines");
|
||||||
|
for (defines) |d| key = Wyhash.hash(key, d);
|
||||||
|
key = Wyhash.hash(key, "\x01flags");
|
||||||
|
for (flags) |f| key = Wyhash.hash(key, f);
|
||||||
|
key = Wyhash.hash(key, "\x01incdirs");
|
||||||
|
for (include_dirs) |inc| key = Wyhash.hash(key, inc);
|
||||||
|
key = Wyhash.hash(key, "\x01llvm");
|
||||||
|
key = Wyhash.hash(key, llvm_version);
|
||||||
|
if (triple) |t| {
|
||||||
|
key = Wyhash.hash(key, "\x01triple");
|
||||||
|
key = Wyhash.hash(key, t);
|
||||||
|
}
|
||||||
|
if (sysroot) |sr| {
|
||||||
|
key = Wyhash.hash(key, "\x01sysroot");
|
||||||
|
key = Wyhash.hash(key, sr);
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle returned from loadCObjectsForJIT — caller must call unload() after JIT.
|
/// Handle returned from loadCObjectsForJIT — caller must call unload() after JIT.
|
||||||
pub const CImportHandle = struct {
|
pub const CImportHandle = struct {
|
||||||
dylib_handle: ?*anyopaque = null,
|
dylib_handle: ?*anyopaque = null,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub const imports = @import("imports.zig");
|
|||||||
pub const imports_tests = @import("imports.test.zig");
|
pub const imports_tests = @import("imports.test.zig");
|
||||||
pub const core = @import("core.zig");
|
pub const core = @import("core.zig");
|
||||||
pub const c_import = @import("c_import.zig");
|
pub const c_import = @import("c_import.zig");
|
||||||
|
pub const c_import_tests = @import("c_import.test.zig");
|
||||||
pub const ir = @import("ir/ir.zig");
|
pub const ir = @import("ir/ir.zig");
|
||||||
|
|
||||||
pub const lsp = struct {
|
pub const lsp = struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user