test/link/elf: test COMDAT elimination

This commit is contained in:
Jakub Konka 2024-07-25 11:53:39 +02:00
parent 494ae149e0
commit fa09276510

View File

@ -59,6 +59,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
// Exercise linker with LLVM backend
// musl tests
elf_step.dependOn(testAbsSymbols(b, .{ .target = musl_target }));
elf_step.dependOn(testComdatElimination(b, .{ .target = musl_target }));
elf_step.dependOn(testCommonSymbols(b, .{ .target = musl_target }));
elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = musl_target }));
elf_step.dependOn(testCommentString(b, .{ .target = musl_target }));
@ -368,6 +369,97 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step {
return test_step;
}
fn testComdatElimination(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "comdat-elimination", opts);
const a_o = addObject(b, opts, .{
.name = "a",
.cpp_source_bytes =
\\#include <stdio.h>
\\inline void foo() {
\\ printf("calling foo in a\n");
\\}
\\void hello() {
\\ foo();
\\}
,
});
a_o.linkLibCpp();
const main_o = addObject(b, opts, .{
.name = "main",
.cpp_source_bytes =
\\#include <stdio.h>
\\inline void foo() {
\\ printf("calling foo in main\n");
\\}
\\void hello();
\\int main() {
\\ foo();
\\ hello();
\\ return 0;
\\}
,
});
main_o.linkLibCpp();
{
const exe = addExecutable(b, opts, .{
.name = "main1",
});
exe.addObject(a_o);
exe.addObject(main_o);
exe.linkLibCpp();
const run = addRunArtifact(exe);
run.expectStdOutEqual(
\\calling foo in a
\\calling foo in a
\\
);
test_step.dependOn(&run.step);
const check = exe.checkObject();
check.checkInSymtab();
// This weird looking double assertion uses the fact that once we find the symbol in
// the symtab, we do not reset the cursor and do subsequent checks from that point onwards.
// If this is the case, and COMDAT elimination works correctly we should only have one instance
// of foo() function.
check.checkContains("_Z3foov");
check.checkNotPresent("_Z3foov");
test_step.dependOn(&check.step);
}
{
const exe = addExecutable(b, opts, .{
.name = "main2",
});
exe.addObject(main_o);
exe.addObject(a_o);
exe.linkLibCpp();
const run = addRunArtifact(exe);
run.expectStdOutEqual(
\\calling foo in main
\\calling foo in main
\\
);
test_step.dependOn(&run.step);
const check = exe.checkObject();
check.checkInSymtab();
// This weird looking double assertion uses the fact that once we find the symbol in
// the symtab, we do not reset the cursor and do subsequent checks from that point onwards.
// If this is the case, and COMDAT elimination works correctly we should only have one instance
// of foo() function.
check.checkContains("_Z3foov");
check.checkNotPresent("_Z3foov");
test_step.dependOn(&check.step);
}
return test_step;
}
fn testCommentString(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "comment-string", opts);