| ... | @@ -59,6 +59,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -59,6 +59,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 59 | // Exercise linker with LLVM backend | 59 | // Exercise linker with LLVM backend |
| 60 | // musl tests | 60 | // musl tests |
| 61 | elf_step.dependOn(testAbsSymbols(b, .{ .target = musl_target })); | 61 | elf_step.dependOn(testAbsSymbols(b, .{ .target = musl_target })); |
| | 62 | elf_step.dependOn(testComdatElimination(b, .{ .target = musl_target })); |
| 62 | elf_step.dependOn(testCommonSymbols(b, .{ .target = musl_target })); | 63 | elf_step.dependOn(testCommonSymbols(b, .{ .target = musl_target })); |
| 63 | elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = musl_target })); | 64 | elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = musl_target })); |
| 64 | elf_step.dependOn(testCommentString(b, .{ .target = musl_target })); | 65 | elf_step.dependOn(testCommentString(b, .{ .target = musl_target })); |
| ... | @@ -368,6 +369,97 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step { | ... | @@ -368,6 +369,97 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step { |
| 368 | return test_step; | 369 | return test_step; |
| 369 | } | 370 | } |
| 370 | | 371 | |
| | 372 | fn testComdatElimination(b: *Build, opts: Options) *Step { |
| | 373 | const test_step = addTestStep(b, "comdat-elimination", opts); |
| | 374 | |
| | 375 | const a_o = addObject(b, opts, .{ |
| | 376 | .name = "a", |
| | 377 | .cpp_source_bytes = |
| | 378 | \\#include <stdio.h> |
| | 379 | \\inline void foo() { |
| | 380 | \\ printf("calling foo in a\n"); |
| | 381 | \\} |
| | 382 | \\void hello() { |
| | 383 | \\ foo(); |
| | 384 | \\} |
| | 385 | , |
| | 386 | }); |
| | 387 | a_o.linkLibCpp(); |
| | 388 | |
| | 389 | const main_o = addObject(b, opts, .{ |
| | 390 | .name = "main", |
| | 391 | .cpp_source_bytes = |
| | 392 | \\#include <stdio.h> |
| | 393 | \\inline void foo() { |
| | 394 | \\ printf("calling foo in main\n"); |
| | 395 | \\} |
| | 396 | \\void hello(); |
| | 397 | \\int main() { |
| | 398 | \\ foo(); |
| | 399 | \\ hello(); |
| | 400 | \\ return 0; |
| | 401 | \\} |
| | 402 | , |
| | 403 | }); |
| | 404 | main_o.linkLibCpp(); |
| | 405 | |
| | 406 | { |
| | 407 | const exe = addExecutable(b, opts, .{ |
| | 408 | .name = "main1", |
| | 409 | }); |
| | 410 | exe.addObject(a_o); |
| | 411 | exe.addObject(main_o); |
| | 412 | exe.linkLibCpp(); |
| | 413 | |
| | 414 | const run = addRunArtifact(exe); |
| | 415 | run.expectStdOutEqual( |
| | 416 | \\calling foo in a |
| | 417 | \\calling foo in a |
| | 418 | \\ |
| | 419 | ); |
| | 420 | test_step.dependOn(&run.step); |
| | 421 | |
| | 422 | const check = exe.checkObject(); |
| | 423 | check.checkInSymtab(); |
| | 424 | // This weird looking double assertion uses the fact that once we find the symbol in |
| | 425 | // the symtab, we do not reset the cursor and do subsequent checks from that point onwards. |
| | 426 | // If this is the case, and COMDAT elimination works correctly we should only have one instance |
| | 427 | // of foo() function. |
| | 428 | check.checkContains("_Z3foov"); |
| | 429 | check.checkNotPresent("_Z3foov"); |
| | 430 | test_step.dependOn(&check.step); |
| | 431 | } |
| | 432 | |
| | 433 | { |
| | 434 | const exe = addExecutable(b, opts, .{ |
| | 435 | .name = "main2", |
| | 436 | }); |
| | 437 | exe.addObject(main_o); |
| | 438 | exe.addObject(a_o); |
| | 439 | exe.linkLibCpp(); |
| | 440 | |
| | 441 | const run = addRunArtifact(exe); |
| | 442 | run.expectStdOutEqual( |
| | 443 | \\calling foo in main |
| | 444 | \\calling foo in main |
| | 445 | \\ |
| | 446 | ); |
| | 447 | test_step.dependOn(&run.step); |
| | 448 | |
| | 449 | const check = exe.checkObject(); |
| | 450 | check.checkInSymtab(); |
| | 451 | // This weird looking double assertion uses the fact that once we find the symbol in |
| | 452 | // the symtab, we do not reset the cursor and do subsequent checks from that point onwards. |
| | 453 | // If this is the case, and COMDAT elimination works correctly we should only have one instance |
| | 454 | // of foo() function. |
| | 455 | check.checkContains("_Z3foov"); |
| | 456 | check.checkNotPresent("_Z3foov"); |
| | 457 | test_step.dependOn(&check.step); |
| | 458 | } |
| | 459 | |
| | 460 | return test_step; |
| | 461 | } |
| | 462 | |
| 371 | fn testCommentString(b: *Build, opts: Options) *Step { | 463 | fn testCommentString(b: *Build, opts: Options) *Step { |
| 372 | const test_step = addTestStep(b, "comment-string", opts); | 464 | const test_step = addTestStep(b, "comment-string", opts); |
| 373 | | 465 | |