mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-10-28 19:00:52 +08:00
342 lines
11 KiB
Zig
342 lines
11 KiB
Zig
pub fn addCases(ctx: *LinkContext) void {
|
|
if (ctx.target.result.isMinGW())
|
|
@import("link/mingw.zig").addCases(ctx);
|
|
|
|
if (ctx.includeTest("static-lib")) |case| {
|
|
const obj1 = case.addObject(.{
|
|
.name = "obj1",
|
|
.name_prefix = false,
|
|
.name_target = false,
|
|
.use_llvm = true,
|
|
.use_lld = true,
|
|
.c_source_bytes =
|
|
\\int foo1 = 1;
|
|
\\int foo2 = 2;
|
|
\\unsigned int fooBar() {
|
|
\\ return foo1 + foo2;
|
|
\\}
|
|
,
|
|
});
|
|
const obj2 = case.addObject(.{
|
|
.name = "this_is_a_long_name",
|
|
.name_prefix = false,
|
|
.name_target = false,
|
|
.zig_source_bytes =
|
|
\\fn fooWeak() callconv(.c) usize {
|
|
\\ return 0xaabbccddaabbccdd;
|
|
\\}
|
|
\\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
|
|
\\export var foo_strong: usize = 0x1122334411223344;
|
|
\\comptime {
|
|
\\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak });
|
|
\\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
|
|
\\}
|
|
,
|
|
});
|
|
|
|
const lib = case.addLibrary(.static, .{
|
|
.name = "lib",
|
|
.name_prefix = false,
|
|
.name_target = false,
|
|
});
|
|
lib.root_module.addObject(obj1);
|
|
lib.root_module.addObject(obj2);
|
|
|
|
case.verifyObjdump(lib.getEmittedBin(), &.{
|
|
"-s",
|
|
"--elements=file-type",
|
|
"--symbols",
|
|
"--only-symbol=foo",
|
|
}, .{ .use_llvm = true });
|
|
|
|
const exe = case.addExecutable(.{
|
|
.name = "test",
|
|
.zig_source_bytes =
|
|
\\extern fn fooBar() c_uint;
|
|
\\extern fn fooWeak() usize;
|
|
\\extern var foo_array: [2]u16;
|
|
\\extern var foo_strong: usize;
|
|
\\extern var foo_strong_alias: usize;
|
|
\\pub fn main() !u8 {
|
|
\\ return @intFromBool(0xcd003365cd00df35 != fooBar() +
|
|
\\ fooWeak() +
|
|
\\ foo_array[1] +
|
|
\\ foo_strong +
|
|
\\ foo_strong_alias);
|
|
\\}
|
|
,
|
|
});
|
|
exe.root_module.linkLibrary(lib);
|
|
|
|
const run = case.addRunArtifact(exe);
|
|
run.addCheck(.{ .expect_term = .{ .exited = 0 } });
|
|
}
|
|
|
|
if (ctx.includeTest("tls")) |case| {
|
|
const obj = case.addObject(.{
|
|
.name = "obj",
|
|
.zig_source_bytes =
|
|
\\threadlocal var threadlocal_var: u32 = 1234;
|
|
\\threadlocal var threadlocal_arr: [4]u16 = .{ 0x1111, 0x2222, 0x3333, 0x4444, };
|
|
\\export fn threadlocal_read(a: *u32, b: *u16) void {
|
|
\\ a.* = threadlocal_var;
|
|
\\ b.* = threadlocal_arr[3];
|
|
\\}
|
|
\\export fn threadlocal_write(a: u32, b: u16) void {
|
|
\\ threadlocal_var = a;
|
|
\\ threadlocal_arr[3] = b;
|
|
\\}
|
|
,
|
|
});
|
|
|
|
case.verifyObjdump(obj.getEmittedBin(), &.{
|
|
"-s",
|
|
"--symbols",
|
|
"--only-symbol=threadlocal",
|
|
"--only-symbol=tls",
|
|
}, .{ .use_llvm = true });
|
|
|
|
const exe = case.addExecutable(.{
|
|
.name = "test",
|
|
.zig_source_bytes =
|
|
\\extern fn threadlocal_read(a: *u32, b: *u16) void;
|
|
\\extern fn threadlocal_write(a: u32, b: u16) void;
|
|
\\threadlocal var threadlocal_foo: u64 = 0xcafecafecafecafe;
|
|
\\pub fn main() !u8 {
|
|
\\ var a: u32 = undefined;
|
|
\\ var b: u16 = undefined;
|
|
\\ threadlocal_read(&a, &b);
|
|
\\ if (a != 1234 or b != 0x4444) return 1;
|
|
\\ if (threadlocal_foo != 0xcafecafecafecafe) return 2;
|
|
\\ threadlocal_write(0xabcdabcd, 0x5555);
|
|
\\ threadlocal_foo = 1;
|
|
\\ threadlocal_read(&a, &b);
|
|
\\ if (a != 0xabcdabcd or b != 0x5555) return 3;
|
|
\\ if (threadlocal_foo != 1) return 4;
|
|
\\ return 0;
|
|
\\}
|
|
,
|
|
});
|
|
exe.root_module.addObject(obj);
|
|
|
|
const run = case.addRunArtifact(exe);
|
|
run.addCheck(.{ .expect_term = .{ .exited = 0 } });
|
|
}
|
|
|
|
if (ctx.includeTest("dynamic-lib-code")) |case| {
|
|
const lib = case.addLibrary(.dynamic, .{
|
|
.name = "lib",
|
|
.name_target = false,
|
|
.zig_source_bytes =
|
|
\\export fn foo1() callconv(.c) u64 {
|
|
\\ return 0x1122334411223344;
|
|
\\}
|
|
\\export fn foo2() callconv(.c) u64 {
|
|
\\ return 0xaabbccddaabbccdd;
|
|
\\}
|
|
,
|
|
});
|
|
|
|
case.verifyObjdump(lib.getEmittedBin(), &.{
|
|
"-s",
|
|
"--exports",
|
|
"--only-symbol=foo",
|
|
}, .{ .os = true });
|
|
|
|
if (ctx.target.result.os.tag == .windows) {
|
|
case.verifyObjdump(lib.getEmittedImplib(), &.{
|
|
"-s",
|
|
"--exports=sort",
|
|
"--only-symbol=foo",
|
|
}, .{ .sub_name = "implib", .os = true, .arch = true });
|
|
}
|
|
|
|
const exe = case.addExecutable(.{
|
|
.name = "test",
|
|
.zig_source_bytes =
|
|
\\extern fn foo1() u64;
|
|
\\pub fn main() !u8 {
|
|
\\ const foo2 = @extern(
|
|
\\ *const fn () callconv(.c) u64,
|
|
\\ .{ .name = "foo2", .is_dll_import = true },
|
|
\\ );
|
|
\\ return @intFromBool(0xbbde0021bbde0021 != foo1() + foo2());
|
|
\\}
|
|
,
|
|
});
|
|
exe.root_module.linkLibrary(lib);
|
|
|
|
const run = case.addRunArtifact(exe);
|
|
run.addCheck(.{ .expect_term = .{ .exited = 0 } });
|
|
}
|
|
|
|
if (ctx.includeTest("dynamic-lib-data")) |case| {
|
|
const lib = case.addLibrary(.dynamic, .{
|
|
.name = "lib",
|
|
.name_target = false,
|
|
.zig_source_bytes =
|
|
\\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
|
|
\\export var foo_strong: usize = 0x1122334411223344;
|
|
\\comptime {
|
|
\\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
|
|
\\}
|
|
,
|
|
});
|
|
|
|
case.verifyObjdump(lib.getEmittedBin(), &.{
|
|
"-s",
|
|
"--exports",
|
|
"--only-symbol=foo",
|
|
}, .{});
|
|
|
|
if (ctx.target.result.os.tag == .windows) {
|
|
case.verifyObjdump(lib.getEmittedImplib(), &.{
|
|
"-s",
|
|
"--exports=sort",
|
|
"--only-symbol=foo",
|
|
}, .{ .sub_name = "implib", .os = true, .arch = true });
|
|
}
|
|
|
|
const exe = case.addExecutable(.{
|
|
.name = "test",
|
|
.zig_source_bytes =
|
|
\\pub fn main() !u8 {
|
|
\\ const foo_array = @extern(*[2]u16, .{ .name = "foo_array", .is_dll_import = true });
|
|
\\ const foo_strong = @extern(*usize, .{ .name = "foo_strong", .is_dll_import = true });
|
|
\\ const foo_strong_alias = @extern(*usize, .{ .name = "foo_strong_alias", .is_dll_import = true });
|
|
\\ return @intFromBool(0x2244668822451255 !=
|
|
\\ foo_array[1] +
|
|
\\ foo_strong.* +
|
|
\\ foo_strong_alias.*);
|
|
\\}
|
|
,
|
|
});
|
|
exe.root_module.linkLibrary(lib);
|
|
|
|
const run = case.addRunArtifact(exe);
|
|
run.addCheck(.{ .expect_term = .{ .exited = 0 } });
|
|
}
|
|
|
|
if (ctx.includeTest("abs-symbol")) |case| {
|
|
const abs = case.addObject(.{
|
|
.name = "abs",
|
|
.use_llvm = true, // TODO: .globl not supported on self-hosted
|
|
.use_lld = true,
|
|
.asm_source_bytes =
|
|
\\.globl foo
|
|
\\foo = 0xcafecafe
|
|
\\
|
|
,
|
|
});
|
|
|
|
const abs_reloc = case.addObject(.{
|
|
.name = "abs_reloc",
|
|
.use_llvm = true, // TODO: .globl not supported on self-hosted
|
|
.use_lld = true,
|
|
.asm_source_bytes =
|
|
\\.data
|
|
\\.globl foo_copy
|
|
\\foo_copy:
|
|
\\.long foo
|
|
,
|
|
});
|
|
|
|
case.verifyObjdump(abs_reloc.getEmittedBin(), &.{
|
|
"-s",
|
|
"--relocs",
|
|
}, .{ .arch = true });
|
|
|
|
const exe = case.addExecutable(.{
|
|
.name = "test",
|
|
.zig_source_bytes =
|
|
\\extern var foo_copy: u32;
|
|
\\pub fn main() !u8 {
|
|
\\ return @intFromBool(foo_copy != 0xcafecafe);
|
|
\\}
|
|
,
|
|
});
|
|
exe.root_module.addObject(abs);
|
|
exe.root_module.addObject(abs_reloc);
|
|
|
|
const run = case.addRunArtifact(exe);
|
|
run.addCheck(.{ .expect_term = .{ .exited = 0 } });
|
|
|
|
if (!ctx.use_llvm) {
|
|
const exe_reloc_err = case.addExecutable(.{
|
|
.name = "test-reloc-err",
|
|
.zig_source_bytes =
|
|
\\extern const foo: u32;
|
|
\\pub fn main() !u8 {
|
|
\\ return @intFromBool(foo != 0xcafecafe);
|
|
\\}
|
|
,
|
|
});
|
|
exe_reloc_err.root_module.addObject(abs);
|
|
case.expectLinkErrors(exe_reloc_err, .{
|
|
.contains = "error: absolute symbol 'foo' targeted by invalid relocation type: /?/",
|
|
});
|
|
}
|
|
}
|
|
|
|
if (ctx.includeTest("explicit-extern-lib-name")) |case| {
|
|
// TODO: Lld.zig does not look at explicit inputs to resolve explicit extern lib names
|
|
if (ctx.use_llvm) return;
|
|
|
|
const lib1 = case.addLibrary(.dynamic, .{
|
|
.name = "lib1",
|
|
.name_target = false,
|
|
.zig_source_bytes =
|
|
\\export fn foo() u8 {
|
|
\\ return 43;
|
|
\\}
|
|
,
|
|
});
|
|
|
|
const lib2 = case.addLibrary(.dynamic, .{
|
|
.name = "lib2",
|
|
.name_target = false,
|
|
.zig_source_bytes =
|
|
\\export fn foo() u8 {
|
|
\\ return 42;
|
|
\\}
|
|
,
|
|
});
|
|
|
|
const lib3 = case.addLibrary(.static, .{
|
|
.name = "lib3",
|
|
.zig_source_bytes =
|
|
\\extern fn foo() u8;
|
|
\\export fn callFoo() u8 {
|
|
\\ return foo();
|
|
\\}
|
|
,
|
|
});
|
|
|
|
const exe = case.addExecutable(.{
|
|
.name = "test",
|
|
.zig_source_bytes =
|
|
\\extern "explicit-extern-lib-name-lib2" fn foo() u8;
|
|
\\extern fn callFoo() u8;
|
|
\\pub fn main() !u8 {
|
|
\\ return foo() + callFoo();
|
|
\\}
|
|
,
|
|
});
|
|
exe.root_module.linkLibrary(lib1);
|
|
exe.root_module.linkLibrary(lib2);
|
|
// exe.root_module.addLibraryPath(.{
|
|
// .generated = .{
|
|
// .index = lib2.getEmittedBin().generated.index,
|
|
// .up = 1,
|
|
// },
|
|
// });
|
|
exe.root_module.linkLibrary(lib3);
|
|
|
|
const run = case.addRunArtifact(exe);
|
|
run.addCheck(.{ .expect_term = .{ .exited = 84 } });
|
|
}
|
|
}
|
|
|
|
const LinkContext = @import("tests.zig").LinkContext;
|
|
const std = @import("std");
|