Rust · 15573 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 fixture(name: &str) -> PathBuf {
14 let path = PathBuf::from("tests/fixtures").join(name);
15 assert!(path.exists(), "missing test fixture {}", path.display());
16 path
17 }
18
19 fn capture_text(request: CaptureRequest, stage: Stage) -> String {
20 let result = capture_from_path(&request).expect("capture should succeed");
21 match result.get(stage) {
22 Some(CapturedStage::Text(text)) => text.clone(),
23 Some(CapturedStage::Run(_)) => panic!("expected text stage for {}", stage.as_str()),
24 None => panic!("missing requested stage {}", stage.as_str()),
25 }
26 }
27
28 #[test]
29 fn integer16_formatted_read_uses_wide_runtime_symbols() {
30 let source = program("integer16_format_read.f90");
31
32 let opt_ir = capture_text(
33 CaptureRequest {
34 input: source.clone(),
35 requested: BTreeSet::from([Stage::OptIr]),
36 opt_level: OptLevel::O2,
37 },
38 Stage::OptIr,
39 );
40 assert!(
41 opt_ir.contains("call @afs_fmt_read_int128("),
42 "optimized IR should route formatted integer(16) input through the wide format reader:\n{}",
43 opt_ir
44 );
45 assert!(
46 opt_ir.contains("call @afs_fmt_read_int("),
47 "optimized IR should keep descriptor-indexed formatted reads for the trailing scalar:\n{}",
48 opt_ir
49 );
50
51 let asm = capture_text(
52 CaptureRequest {
53 input: source,
54 requested: BTreeSet::from([Stage::Asm]),
55 opt_level: OptLevel::O2,
56 },
57 Stage::Asm,
58 );
59 assert!(asm.contains("_afs_fmt_read_int128"));
60 assert!(asm.contains("_afs_fmt_read_int"));
61 }
62
63 #[test]
64 fn integer16_formatted_read_runs_across_all_opt_levels() {
65 for level in [
66 OptLevel::O0,
67 OptLevel::O1,
68 OptLevel::O2,
69 OptLevel::O3,
70 OptLevel::Os,
71 OptLevel::Ofast,
72 ] {
73 let result = capture_from_path(&CaptureRequest {
74 input: program("integer16_format_read.f90"),
75 requested: BTreeSet::from([Stage::Run]),
76 opt_level: level,
77 })
78 .unwrap_or_else(|e| {
79 panic!(
80 "formatted integer(16) input should run at {:?}:\n{}",
81 level, e
82 )
83 });
84
85 let run = result
86 .get(Stage::Run)
87 .and_then(CapturedStage::as_run)
88 .expect("missing run capture");
89
90 assert_eq!(
91 run.exit_code, 0,
92 "expected successful formatted integer(16) read run at {:?}:\n{:#?}",
93 level, run
94 );
95 assert!(run
96 .stdout
97 .contains("170141183460469231731687303715884105727"));
98 assert!(run.stdout.contains("42"));
99 }
100 }
101
102 #[test]
103 fn integer16_formatted_read_object_snapshot_is_deterministic_at_o2() {
104 let source = program("integer16_format_read.f90");
105 let first = capture_text(
106 CaptureRequest {
107 input: source.clone(),
108 requested: BTreeSet::from([Stage::Obj]),
109 opt_level: OptLevel::O2,
110 },
111 Stage::Obj,
112 );
113 let second = capture_text(
114 CaptureRequest {
115 input: source,
116 requested: BTreeSet::from([Stage::Obj]),
117 opt_level: OptLevel::O2,
118 },
119 Stage::Obj,
120 );
121
122 assert_eq!(first, second);
123 }
124
125 #[test]
126 fn integer16_formatted_read_targets_use_wide_runtime_symbols() {
127 let source = program("integer16_format_read_targets.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_read_int128("),
139 "optimized IR should route formatted integer(16) lvalue reads through the wide reader:\n{}",
140 opt_ir
141 );
142 assert!(
143 opt_ir.contains("call @afs_fmt_read_int("),
144 "optimized IR should still route the trailing scalar component read through the scalar reader:\n{}",
145 opt_ir
146 );
147
148 let asm = capture_text(
149 CaptureRequest {
150 input: source,
151 requested: BTreeSet::from([Stage::Asm]),
152 opt_level: OptLevel::O2,
153 },
154 Stage::Asm,
155 );
156 assert!(asm.contains("_afs_fmt_read_int128"));
157 assert!(asm.contains("_afs_fmt_read_int"));
158 }
159
160 #[test]
161 fn integer16_formatted_read_targets_run_across_all_opt_levels() {
162 for level in [
163 OptLevel::O0,
164 OptLevel::O1,
165 OptLevel::O2,
166 OptLevel::O3,
167 OptLevel::Os,
168 OptLevel::Ofast,
169 ] {
170 let result = capture_from_path(&CaptureRequest {
171 input: program("integer16_format_read_targets.f90"),
172 requested: BTreeSet::from([Stage::Run]),
173 opt_level: level,
174 })
175 .unwrap_or_else(|e| {
176 panic!(
177 "formatted integer(16) lvalue read should run at {:?}:\n{}",
178 level, e
179 )
180 });
181
182 let run = result
183 .get(Stage::Run)
184 .and_then(CapturedStage::as_run)
185 .expect("missing run capture");
186
187 assert_eq!(
188 run.exit_code, 0,
189 "expected successful formatted integer(16) lvalue read run at {:?}:\n{:#?}",
190 level, run
191 );
192 for needle in [
193 "11",
194 "-170141183460469231731687303715884105727",
195 "33",
196 "9",
197 "170141183460469231731687303715884105727",
198 "7",
199 ] {
200 assert!(
201 run.stdout.contains(needle),
202 "expected stdout to contain '{}' at {:?}:\n{:#?}",
203 needle,
204 level,
205 run
206 );
207 }
208 }
209 }
210
211 #[test]
212 fn integer16_formatted_read_targets_object_snapshot_is_deterministic_at_o2() {
213 let source = program("integer16_format_read_targets.f90");
214 let first = capture_text(
215 CaptureRequest {
216 input: source.clone(),
217 requested: BTreeSet::from([Stage::Obj]),
218 opt_level: OptLevel::O2,
219 },
220 Stage::Obj,
221 );
222 let second = capture_text(
223 CaptureRequest {
224 input: source,
225 requested: BTreeSet::from([Stage::Obj]),
226 opt_level: OptLevel::O2,
227 },
228 Stage::Obj,
229 );
230
231 assert_eq!(first, second);
232 }
233
234 #[test]
235 fn integer16_formatted_read_arrays_use_wide_runtime_symbols() {
236 let source = program("integer16_format_read_arrays.f90");
237
238 let opt_ir = capture_text(
239 CaptureRequest {
240 input: source.clone(),
241 requested: BTreeSet::from([Stage::OptIr]),
242 opt_level: OptLevel::O2,
243 },
244 Stage::OptIr,
245 );
246 assert!(
247 opt_ir.contains("call @afs_fmt_read_int128("),
248 "optimized IR should route formatted integer(16) array reads through the wide reader:\n{}",
249 opt_ir
250 );
251
252 let asm = capture_text(
253 CaptureRequest {
254 input: source,
255 requested: BTreeSet::from([Stage::Asm]),
256 opt_level: OptLevel::O2,
257 },
258 Stage::Asm,
259 );
260 assert!(asm.contains("_afs_fmt_read_int128"));
261 }
262
263 #[test]
264 fn integer16_formatted_read_arrays_run_across_all_opt_levels() {
265 for level in [
266 OptLevel::O0,
267 OptLevel::O1,
268 OptLevel::O2,
269 OptLevel::O3,
270 OptLevel::Os,
271 OptLevel::Ofast,
272 ] {
273 let result = capture_from_path(&CaptureRequest {
274 input: program("integer16_format_read_arrays.f90"),
275 requested: BTreeSet::from([Stage::Run]),
276 opt_level: level,
277 })
278 .unwrap_or_else(|e| {
279 panic!(
280 "formatted integer(16) array reads should run at {:?}:\n{}",
281 level, e
282 )
283 });
284
285 let run = result
286 .get(Stage::Run)
287 .and_then(CapturedStage::as_run)
288 .expect("missing run capture");
289
290 assert_eq!(
291 run.exit_code, 0,
292 "expected successful formatted integer(16) array read run at {:?}:\n{:#?}",
293 level, run
294 );
295 assert!(run
296 .stdout
297 .contains("11 170141183460469231731687303715884105727 33"));
298 assert!(run
299 .stdout
300 .contains("66 -170141183460469231731687303715884105727 44"));
301 }
302 }
303
304 #[test]
305 fn integer16_formatted_read_arrays_object_snapshot_is_deterministic_at_o2() {
306 let source = program("integer16_format_read_arrays.f90");
307 let first = capture_text(
308 CaptureRequest {
309 input: source.clone(),
310 requested: BTreeSet::from([Stage::Obj]),
311 opt_level: OptLevel::O2,
312 },
313 Stage::Obj,
314 );
315 let second = capture_text(
316 CaptureRequest {
317 input: source,
318 requested: BTreeSet::from([Stage::Obj]),
319 opt_level: OptLevel::O2,
320 },
321 Stage::Obj,
322 );
323
324 assert_eq!(first, second);
325 }
326
327 #[test]
328 fn integer16_formatted_read_sections_use_wide_runtime_symbols() {
329 let source = program("integer16_format_read_sections.f90");
330
331 let opt_ir = capture_text(
332 CaptureRequest {
333 input: source.clone(),
334 requested: BTreeSet::from([Stage::OptIr]),
335 opt_level: OptLevel::O2,
336 },
337 Stage::OptIr,
338 );
339 assert!(
340 opt_ir.contains("call @afs_fmt_read_int128("),
341 "optimized IR should route formatted integer(16) section reads through the wide reader:\n{}",
342 opt_ir
343 );
344
345 let asm = capture_text(
346 CaptureRequest {
347 input: source,
348 requested: BTreeSet::from([Stage::Asm]),
349 opt_level: OptLevel::O2,
350 },
351 Stage::Asm,
352 );
353 assert!(asm.contains("_afs_fmt_read_int128"));
354 }
355
356 #[test]
357 fn integer16_formatted_read_sections_run_across_all_opt_levels() {
358 for level in [
359 OptLevel::O0,
360 OptLevel::O1,
361 OptLevel::O2,
362 OptLevel::O3,
363 OptLevel::Os,
364 OptLevel::Ofast,
365 ] {
366 let result = capture_from_path(&CaptureRequest {
367 input: program("integer16_format_read_sections.f90"),
368 requested: BTreeSet::from([Stage::Run]),
369 opt_level: level,
370 })
371 .unwrap_or_else(|e| {
372 panic!(
373 "formatted integer(16) section reads should run at {:?}:\n{}",
374 level, e
375 )
376 });
377
378 let run = result
379 .get(Stage::Run)
380 .and_then(CapturedStage::as_run)
381 .expect("missing run capture");
382
383 assert_eq!(
384 run.exit_code, 0,
385 "expected successful formatted integer(16) section read run at {:?}:\n{:#?}",
386 level, run
387 );
388 assert!(run.stdout.contains("101 202"));
389 assert!(run.stdout.contains("606 505 404 303"));
390 }
391 }
392
393 #[test]
394 fn integer16_formatted_read_sections_object_snapshot_is_deterministic_at_o2() {
395 let source = program("integer16_format_read_sections.f90");
396 let first = capture_text(
397 CaptureRequest {
398 input: source.clone(),
399 requested: BTreeSet::from([Stage::Obj]),
400 opt_level: OptLevel::O2,
401 },
402 Stage::Obj,
403 );
404 let second = capture_text(
405 CaptureRequest {
406 input: source,
407 requested: BTreeSet::from([Stage::Obj]),
408 opt_level: OptLevel::O2,
409 },
410 Stage::Obj,
411 );
412
413 assert_eq!(first, second);
414 }
415
416 #[test]
417 fn integer16_formatted_read_alloc_section_uses_descriptor_bounds_and_wide_reader() {
418 let source = fixture("integer16_format_read_alloc_section.f90");
419
420 let ir = capture_text(
421 CaptureRequest {
422 input: source.clone(),
423 requested: BTreeSet::from([Stage::Ir]),
424 opt_level: OptLevel::O0,
425 },
426 Stage::Ir,
427 );
428 assert!(ir.contains("call @afs_fmt_read_int128("));
429 assert!(!ir.contains("call @afs_create_section("));
430
431 let asm = capture_text(
432 CaptureRequest {
433 input: source,
434 requested: BTreeSet::from([Stage::Asm]),
435 opt_level: OptLevel::O2,
436 },
437 Stage::Asm,
438 );
439 assert!(asm.contains("_afs_fmt_read_int128"));
440 }
441
442 #[test]
443 fn integer16_formatted_read_alloc_section_object_snapshot_is_deterministic_at_o2() {
444 let source = fixture("integer16_format_read_alloc_section.f90");
445 let first = capture_text(
446 CaptureRequest {
447 input: source.clone(),
448 requested: BTreeSet::from([Stage::Obj]),
449 opt_level: OptLevel::O2,
450 },
451 Stage::Obj,
452 );
453 let second = capture_text(
454 CaptureRequest {
455 input: source,
456 requested: BTreeSet::from([Stage::Obj]),
457 opt_level: OptLevel::O2,
458 },
459 Stage::Obj,
460 );
461
462 assert_eq!(first, second);
463 }
464
465 #[test]
466 fn integer16_formatted_read_alloc_reverse_section_uses_wide_reader() {
467 let source = fixture("integer16_format_read_alloc_reverse_section.f90");
468
469 let opt_ir = capture_text(
470 CaptureRequest {
471 input: source.clone(),
472 requested: BTreeSet::from([Stage::OptIr]),
473 opt_level: OptLevel::O2,
474 },
475 Stage::OptIr,
476 );
477 assert!(opt_ir.contains("call @afs_fmt_read_int128("));
478
479 let asm = capture_text(
480 CaptureRequest {
481 input: source,
482 requested: BTreeSet::from([Stage::Asm]),
483 opt_level: OptLevel::O2,
484 },
485 Stage::Asm,
486 );
487 assert!(asm.contains("_afs_fmt_read_int128"));
488 }
489
490 #[test]
491 fn integer16_formatted_read_alloc_reverse_section_runs_across_all_opt_levels() {
492 for level in [
493 OptLevel::O1,
494 OptLevel::O2,
495 OptLevel::O3,
496 OptLevel::Os,
497 OptLevel::Ofast,
498 ] {
499 let result = capture_from_path(&CaptureRequest {
500 input: fixture("integer16_format_read_alloc_reverse_section.f90"),
501 requested: BTreeSet::from([Stage::Run]),
502 opt_level: level,
503 })
504 .unwrap_or_else(|e| {
505 panic!(
506 "allocatable formatted integer(16) reverse section read should run at {:?}:\n{}",
507 level, e
508 )
509 });
510
511 let run = result
512 .get(Stage::Run)
513 .and_then(CapturedStage::as_run)
514 .expect("missing run capture");
515
516 assert_eq!(
517 run.exit_code, 0,
518 "expected successful allocatable reverse section read run at {:?}:\n{:#?}",
519 level, run
520 );
521 assert!(run.stdout.contains("8"));
522 }
523 }
524
525 #[test]
526 fn integer16_formatted_read_alloc_reverse_section_object_snapshot_is_deterministic_at_o2() {
527 let source = fixture("integer16_format_read_alloc_reverse_section.f90");
528 let first = capture_text(
529 CaptureRequest {
530 input: source.clone(),
531 requested: BTreeSet::from([Stage::Obj]),
532 opt_level: OptLevel::O2,
533 },
534 Stage::Obj,
535 );
536 let second = capture_text(
537 CaptureRequest {
538 input: source,
539 requested: BTreeSet::from([Stage::Obj]),
540 opt_level: OptLevel::O2,
541 },
542 Stage::Obj,
543 );
544
545 assert_eq!(first, second);
546 }
547