Rust · 2465 bytes Raw Blame History
1 use std::collections::BTreeSet;
2 use std::path::PathBuf;
3
4 use armfortas::driver::OptLevel;
5 use armfortas::testing::{capture_from_path, CaptureRequest, CapturedStage, Stage};
6
7 fn fixture(name: &str) -> PathBuf {
8 let path = PathBuf::from("test_programs").join(name);
9 assert!(path.exists(), "missing test fixture {}", path.display());
10 path
11 }
12
13 fn capture_text(request: CaptureRequest, stage: Stage) -> String {
14 let result = capture_from_path(&request).expect("capture should succeed");
15 match result.get(stage) {
16 Some(CapturedStage::Text(text)) => text.clone(),
17 Some(CapturedStage::Run(_)) => panic!("expected text stage for {}", stage.as_str()),
18 None => panic!("missing requested stage {}", stage.as_str()),
19 }
20 }
21
22 fn function_sections(ir: &str) -> Vec<&str> {
23 ir.match_indices(" func @")
24 .map(|(idx, _)| {
25 let rest = &ir[idx..];
26 let end = rest
27 .find("\n }\n")
28 .unwrap_or_else(|| panic!("unterminated function section in:\n{}", rest));
29 &rest[..end + "\n }".len()]
30 })
31 .collect()
32 }
33
34 fn function_name<'a>(func_section: &'a str) -> &'a str {
35 let header = func_section.lines().next().expect("function header").trim();
36 let rest = header
37 .strip_prefix("func @")
38 .expect("function header prefix");
39 let end = rest
40 .find(|ch: char| ch == ' ' || ch == '(')
41 .unwrap_or(rest.len());
42 &rest[..end]
43 }
44
45 #[test]
46 fn o0_lowers_whole_array_elemental_assignment_through_concurrent_map() {
47 let source = fixture("elemental_array_map.f90");
48
49 let raw_ir = capture_text(
50 CaptureRequest {
51 input: source,
52 requested: BTreeSet::from([Stage::Ir]),
53 opt_level: OptLevel::O0,
54 },
55 Stage::Ir,
56 );
57 let raw_sections = function_sections(&raw_ir);
58 assert_eq!(
59 raw_sections.len(),
60 2,
61 "raw IR should include the program body plus one elemental scalar helper:\n{}",
62 raw_ir
63 );
64 let scalar_body_name = function_name(raw_sections[1]);
65
66 assert!(
67 raw_ir.matches("doconc_check_").count() >= 2,
68 "two elemental whole-array assignments should lower through DO CONCURRENT blocks:\n{}",
69 raw_ir
70 );
71 assert!(
72 raw_ir.contains(&format!("call @{}(", scalar_body_name)),
73 "lowered IR should still call the elemental scalar body per element:\n{}",
74 raw_ir
75 );
76 }
77