Skip to main content

hkalbasi_rustc_ap_miropt_test_tools/
lib.rs

1use std::fs;
2use std::path::Path;
3
4pub struct MiroptTestFiles {
5    pub expected_file: std::path::PathBuf,
6    pub from_file: String,
7    pub to_file: Option<String>,
8    /// Vec of passes under test to be dumped
9    pub passes: Vec<String>,
10}
11
12pub enum PanicStrategy {
13    Unwind,
14    Abort,
15}
16
17pub fn output_file_suffix(
18    testfile: &Path,
19    bit_width: u32,
20    panic_strategy: PanicStrategy,
21) -> String {
22    let mut each_bit_width = false;
23    let mut each_panic_strategy = false;
24    for line in fs::read_to_string(testfile).unwrap().lines() {
25        if line == "// EMIT_MIR_FOR_EACH_BIT_WIDTH" {
26            each_bit_width = true;
27        }
28        if line == "// EMIT_MIR_FOR_EACH_PANIC_STRATEGY" {
29            each_panic_strategy = true;
30        }
31    }
32
33    let mut suffix = String::new();
34    if each_bit_width {
35        suffix.push_str(&format!(".{}bit", bit_width));
36    }
37    if each_panic_strategy {
38        match panic_strategy {
39            PanicStrategy::Unwind => suffix.push_str(".panic-unwind"),
40            PanicStrategy::Abort => suffix.push_str(".panic-abort"),
41        }
42    }
43    suffix
44}
45
46pub fn files_for_miropt_test(
47    testfile: &std::path::Path,
48    bit_width: u32,
49    panic_strategy: PanicStrategy,
50) -> Vec<MiroptTestFiles> {
51    let mut out = Vec::new();
52    let test_file_contents = fs::read_to_string(&testfile).unwrap();
53
54    let test_dir = testfile.parent().unwrap();
55    let test_crate = testfile.file_stem().unwrap().to_str().unwrap().replace('-', "_");
56
57    let suffix = output_file_suffix(testfile, bit_width, panic_strategy);
58
59    for l in test_file_contents.lines() {
60        if l.starts_with("// EMIT_MIR ") {
61            let test_name = l.trim_start_matches("// EMIT_MIR ").trim();
62            let mut test_names = test_name.split(' ');
63            // sometimes we specify two files so that we get a diff between the two files
64            let test_name = test_names.next().unwrap();
65            let mut expected_file;
66            let from_file;
67            let to_file;
68            let mut passes = Vec::new();
69
70            if test_name.ends_with(".diff") {
71                let trimmed = test_name.trim_end_matches(".diff");
72                passes.push(trimmed.split('.').last().unwrap().to_owned());
73                let test_against = format!("{}.after.mir", trimmed);
74                from_file = format!("{}.before.mir", trimmed);
75                expected_file = format!("{}{}.diff", trimmed, suffix);
76                assert!(test_names.next().is_none(), "two mir pass names specified for MIR diff");
77                to_file = Some(test_against);
78            } else if let Some(first_pass) = test_names.next() {
79                let second_pass = test_names.next().unwrap();
80                if let Some((first_pass_name, _)) = first_pass.split_once('.') {
81                    passes.push(first_pass_name.to_owned());
82                }
83                if let Some((second_pass_name, _)) = second_pass.split_once('.') {
84                    passes.push(second_pass_name.to_owned());
85                }
86                assert!(test_names.next().is_none(), "three mir pass names specified for MIR diff");
87
88                expected_file =
89                    format!("{}{}.{}-{}.diff", test_name, suffix, first_pass, second_pass);
90                let second_file = format!("{}.{}.mir", test_name, second_pass);
91                from_file = format!("{}.{}.mir", test_name, first_pass);
92                to_file = Some(second_file);
93            } else {
94                let ext_re = regex::Regex::new(r#"(\.(mir|dot|html))$"#).unwrap();
95                let cap = ext_re
96                    .captures_iter(test_name)
97                    .next()
98                    .expect("test_name has an invalid extension");
99                let extension = cap.get(1).unwrap().as_str();
100
101                expected_file =
102                    format!("{}{}{}", test_name.trim_end_matches(extension), suffix, extension,);
103                from_file = test_name.to_string();
104                assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump");
105                to_file = None;
106                // the pass name is the third to last string in the test name
107                // this gets pushed into passes
108                passes.push(
109                    test_name.split('.').rev().nth(2).expect("invalid test format").to_string(),
110                );
111            };
112            if !expected_file.starts_with(&test_crate) {
113                expected_file = format!("{}.{}", test_crate, expected_file);
114            }
115            let expected_file = test_dir.join(expected_file);
116
117            out.push(MiroptTestFiles { expected_file, from_file, to_file, passes });
118        }
119    }
120
121    out
122}