about summary refs log tree commit diff
path: root/tests/run-make/fmt-write-bloat/rmake.rs
blob: a38abe2eda5dc7582e7c3fcba9e9a1df15f8cfac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Before #78122, writing any `fmt::Arguments` would trigger the inclusion of `usize` formatting
//! and padding code in the resulting binary, because indexing used in `fmt::write` would generate
//! code using `panic_bounds_check`, which prints the index and length.
//!
//! These bounds checks are not necessary, as `fmt::Arguments` never contains any out-of-bounds
//! indexes. The test is a `run-make` test, because it needs to check the result after linking. A
//! codegen or assembly test doesn't check the parts that will be pulled in from `core` by the
//! linker.
//!
//! In this test, we try to check that the `usize` formatting and padding code are not present in
//! the final binary by checking that panic symbols such as `panic_bounds_check` are **not**
//! present.
//!
//! Some CI jobs try to run faster by disabling debug assertions (through setting
//! `NO_DEBUG_ASSERTIONS=1`). If std debug assertions are disabled, then we can check for the
//! absence of additional `usize` formatting and padding related symbols.

// ignore-tidy-linelength

//@ ignore-cross-compile

use std::path::Path;

use run_make_support::env::std_debug_assertions_enabled;
use run_make_support::llvm::{llvm_filecheck, llvm_pdbutil};
use run_make_support::symbols::object_contains_any_symbol_substring;
use run_make_support::{is_windows_msvc, rfs, rustc};

fn main() {
    let expect_no_panic_symbols = Path::new("expect_no_panic_symbols");
    rustc().input("main.rs").output(&expect_no_panic_symbols).opt().run();

    let expect_panic_symbols = Path::new("expect_panic_symbols");
    rustc().input("main.rs").output(&expect_panic_symbols).run();

    if is_windows_msvc() {
        // FIXME(#143737): use actual DIA wrappers instead of parsing `llvm-pdbutil` textual output.

        let expect_no_filecheck_pattern = r#"
            CHECK: main
            CHECK-NOT: {{.*}}Display{{.*}}
            CHECK-NOT: {{.*}}panic_bounds_check{{.*}}
        "#;
        let expect_no_filecheck_path = Path::new("expect_no_panic_symbols_filecheck.txt");
        rfs::write(&expect_no_filecheck_path, expect_no_filecheck_pattern);

        let expect_no_panic_symbols_pdbutil_dump = llvm_pdbutil()
            .arg("dump")
            .arg("-publics")
            .input(expect_no_panic_symbols.with_extension("pdb"))
            .run();
        llvm_filecheck()
            .patterns(expect_no_filecheck_path)
            .stdin_buf(expect_no_panic_symbols_pdbutil_dump.stdout_utf8())
            .run();

        let expect_filecheck_pattern = r#"
            CHECK: main
            CHECK: {{.*}}core{{.*}}fmt{{.*}}write{{.*}}
            CHECK: {{.*}}core{{.*}}panicking{{.*}}panic_fmt{{.*}}
            // _ZN4core3fmt3num3imp54_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize...
            CHECK: {{.*}}Display{{.*}}
            CHECK-NOT: {{.*}}panic_bounds_check{{.*}}
        "#;
        let expect_filecheck_path = Path::new("expect_panic_symbols_filecheck.txt");
        rfs::write(&expect_filecheck_path, expect_filecheck_pattern);

        let expect_panic_symbols_pdbutil_dump = llvm_pdbutil()
            .arg("dump")
            .arg("-publics")
            .input(expect_panic_symbols.with_extension("pdb"))
            .run();
        llvm_filecheck()
            .patterns(expect_filecheck_path)
            .stdin_buf(expect_panic_symbols_pdbutil_dump.stdout_utf8())
            .run();
    } else {
        // panic machinery identifiers, these should not appear in the final binary
        let mut panic_syms = vec!["panic_bounds_check", "Debug"];
        if std_debug_assertions_enabled() {
            // If std debug assertions are allowed, we need to allow these, otherwise, add them to
            // the list of symbols to deny.
            panic_syms.extend_from_slice(&["panicking", "panic_fmt", "pad_integral", "Display"]);
        }

        assert!(!object_contains_any_symbol_substring(&expect_no_panic_symbols, &panic_syms));
        assert!(object_contains_any_symbol_substring(&expect_panic_symbols, &panic_syms));
    }
}