Rust · 6620 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 program(name: &str) -> PathBuf {
8 let path = PathBuf::from("test_programs").join(name);
9 assert!(path.exists(), "missing program 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 #[test]
23 fn integer16_print_uses_wide_writer_in_ir_and_asm() {
24 let source = program("integer16_print.f90");
25
26 let opt_ir = capture_text(
27 CaptureRequest {
28 input: source.clone(),
29 requested: BTreeSet::from([Stage::OptIr]),
30 opt_level: OptLevel::O2,
31 },
32 Stage::OptIr,
33 );
34 assert!(
35 opt_ir.contains("call @afs_write_int128("),
36 "optimized IR should route integer(16) print through the wide runtime writer:\n{}",
37 opt_ir
38 );
39
40 let asm = capture_text(
41 CaptureRequest {
42 input: source,
43 requested: BTreeSet::from([Stage::Asm]),
44 opt_level: OptLevel::O2,
45 },
46 Stage::Asm,
47 );
48 assert!(
49 asm.contains("_afs_write_int128"),
50 "assembly should reference the wide runtime writer symbol:\n{}",
51 asm
52 );
53 }
54
55 #[test]
56 fn integer16_print_runs_across_all_opt_levels() {
57 for level in [
58 OptLevel::O0,
59 OptLevel::O1,
60 OptLevel::O2,
61 OptLevel::O3,
62 OptLevel::Os,
63 OptLevel::Ofast,
64 ] {
65 let result = capture_from_path(&CaptureRequest {
66 input: program("integer16_print.f90"),
67 requested: BTreeSet::from([Stage::Run]),
68 opt_level: level,
69 })
70 .unwrap_or_else(|e| panic!("integer(16) print should run at {:?}:\n{}", level, e));
71
72 let run = result
73 .get(Stage::Run)
74 .and_then(CapturedStage::as_run)
75 .expect("missing run capture");
76
77 assert_eq!(
78 run.exit_code, 0,
79 "expected successful integer(16) print run at {:?}:\n{:#?}",
80 level, run
81 );
82 assert!(
83 run.stdout
84 .contains("170141183460469231731687303715884105727"),
85 "wide positive integer(16) print should survive at {:?}:\n{}",
86 level,
87 run.stdout
88 );
89 assert!(
90 run.stdout
91 .contains("-170141183460469231731687303715884105727"),
92 "wide negative integer(16) print should survive at {:?}:\n{}",
93 level,
94 run.stdout
95 );
96 }
97 }
98
99 #[test]
100 fn integer16_print_object_snapshot_is_deterministic_at_o2() {
101 let source = program("integer16_print.f90");
102 let first = capture_text(
103 CaptureRequest {
104 input: source.clone(),
105 requested: BTreeSet::from([Stage::Obj]),
106 opt_level: OptLevel::O2,
107 },
108 Stage::Obj,
109 );
110 let second = capture_text(
111 CaptureRequest {
112 input: source,
113 requested: BTreeSet::from([Stage::Obj]),
114 opt_level: OptLevel::O2,
115 },
116 Stage::Obj,
117 );
118
119 assert_eq!(
120 first, second,
121 "integer(16) print object snapshots should be deterministic at O2"
122 );
123 }
124
125 #[test]
126 fn integer16_formatted_write_uses_wide_push_in_ir_and_asm() {
127 let source = program("integer16_format.f90");
128
129 let opt_ir = capture_text(
130 CaptureRequest {
131 input: source.clone(),
132 requested: BTreeSet::from([Stage::OptIr]),
133 opt_level: OptLevel::O2,
134 },
135 Stage::OptIr,
136 );
137 assert!(
138 opt_ir.contains("call @afs_fmt_push_int128("),
139 "optimized IR should route formatted integer(16) output through the wide format push:\n{}",
140 opt_ir
141 );
142
143 let asm = capture_text(
144 CaptureRequest {
145 input: source,
146 requested: BTreeSet::from([Stage::Asm]),
147 opt_level: OptLevel::O2,
148 },
149 Stage::Asm,
150 );
151 assert!(
152 asm.contains("_afs_fmt_push_int128"),
153 "assembly should reference the wide format push symbol:\n{}",
154 asm
155 );
156 }
157
158 #[test]
159 fn integer16_formatted_write_runs_across_all_opt_levels() {
160 for level in [
161 OptLevel::O0,
162 OptLevel::O1,
163 OptLevel::O2,
164 OptLevel::O3,
165 OptLevel::Os,
166 OptLevel::Ofast,
167 ] {
168 let result = capture_from_path(&CaptureRequest {
169 input: program("integer16_format.f90"),
170 requested: BTreeSet::from([Stage::Run]),
171 opt_level: level,
172 })
173 .unwrap_or_else(|e| {
174 panic!(
175 "formatted integer(16) write should run at {:?}:\n{}",
176 level, e
177 )
178 });
179
180 let run = result
181 .get(Stage::Run)
182 .and_then(CapturedStage::as_run)
183 .expect("missing run capture");
184
185 assert_eq!(
186 run.exit_code, 0,
187 "expected successful formatted integer(16) write run at {:?}:\n{:#?}",
188 level, run
189 );
190 assert!(
191 run.stdout
192 .contains("170141183460469231731687303715884105727"),
193 "wide positive formatted integer(16) output should survive at {:?}:\n{}",
194 level,
195 run.stdout
196 );
197 assert!(
198 run.stdout
199 .contains("-170141183460469231731687303715884105727"),
200 "wide negative formatted integer(16) output should survive at {:?}:\n{}",
201 level,
202 run.stdout
203 );
204 }
205 }
206
207 #[test]
208 fn integer16_formatted_write_object_snapshot_is_deterministic_at_o2() {
209 let source = program("integer16_format.f90");
210 let first = capture_text(
211 CaptureRequest {
212 input: source.clone(),
213 requested: BTreeSet::from([Stage::Obj]),
214 opt_level: OptLevel::O2,
215 },
216 Stage::Obj,
217 );
218 let second = capture_text(
219 CaptureRequest {
220 input: source,
221 requested: BTreeSet::from([Stage::Obj]),
222 opt_level: OptLevel::O2,
223 },
224 Stage::Obj,
225 );
226
227 assert_eq!(
228 first, second,
229 "formatted integer(16) write object snapshots should be deterministic at O2"
230 );
231 }
232