1use std::path::Path;
23
24use rucc_diag::SourceBytes;
25
26pub const DIR: &str = "<builtin>";
32
33const HEADERS: &[(&str, &str)] = &[
39 ("arm_neon.h", include_str!("../runtime/include/arm_neon.h")),
40 ("avx512bwintrin.h", include_str!("../runtime/include/avx512bwintrin.h")),
41 ("avx512fintrin.h", include_str!("../runtime/include/avx512fintrin.h")),
42 ("avx512vlintrin.h", include_str!("../runtime/include/avx512vlintrin.h")),
43 ("avx512vpopcntdqintrin.h", include_str!("../runtime/include/avx512vpopcntdqintrin.h")),
44 ("cpuid.h", include_str!("../runtime/include/cpuid.h")),
45 ("emmintrin.h", include_str!("../runtime/include/emmintrin.h")),
46 ("float.h", include_str!("../runtime/include/float.h")),
47 ("immintrin.h", include_str!("../runtime/include/immintrin.h")),
48 ("iso646.h", include_str!("../runtime/include/iso646.h")),
49 ("limits.h", include_str!("../runtime/include/limits.h")),
50 ("mm_malloc.h", include_str!("../runtime/include/mm_malloc.h")),
51 ("mmintrin.h", include_str!("../runtime/include/mmintrin.h")),
52 ("nmmintrin.h", include_str!("../runtime/include/nmmintrin.h")),
53 ("popcntintrin.h", include_str!("../runtime/include/popcntintrin.h")),
54 ("smmintrin.h", include_str!("../runtime/include/smmintrin.h")),
55 ("stdalign.h", include_str!("../runtime/include/stdalign.h")),
56 ("stdarg.h", include_str!("../runtime/include/stdarg.h")),
57 ("stdatomic.h", include_str!("../runtime/include/stdatomic.h")),
58 ("stdbool.h", include_str!("../runtime/include/stdbool.h")),
59 ("stddef.h", include_str!("../runtime/include/stddef.h")),
60 ("stdint.h", include_str!("../runtime/include/stdint.h")),
61 ("stdnoreturn.h", include_str!("../runtime/include/stdnoreturn.h")),
62 ("vpclmulqdqintrin.h", include_str!("../runtime/include/vpclmulqdqintrin.h")),
63 ("x86intrin.h", include_str!("../runtime/include/x86intrin.h")),
64 ("xmmintrin.h", include_str!("../runtime/include/xmmintrin.h")),
65 ("xsaveintrin.h", include_str!("../runtime/include/xsaveintrin.h")),
66];
67
68#[must_use]
70pub fn names() -> Vec<&'static str> {
71 HEADERS.iter().map(|&(name, _)| name).collect()
72}
73
74#[must_use]
76pub fn header(name: &str) -> Option<&'static str> {
77 HEADERS.iter().find(|&&(have, _)| have == name).map(|&(_, text)| text)
78}
79
80#[must_use]
85pub fn read(path: &Path) -> Option<SourceBytes> {
86 if path.parent() != Some(Path::new(DIR)) {
87 return None;
88 }
89 let name = path.file_name()?.to_str()?;
90 header(name).map(SourceBytes::new)
91}
92
93#[cfg(test)]
94mod tests {
95 use std::path::PathBuf;
96
97 use super::*;
98
99 #[test]
100 fn the_shipped_headers_are_read_by_the_name_the_search_path_builds() {
101 let path = PathBuf::from(DIR).join("stdarg.h");
102 let bytes = read(&path).expect("stdarg.h is shipped");
103 let text = String::from_utf8(bytes.as_ref().to_vec()).expect("utf-8");
104 assert!(text.contains("__builtin_va_list"));
105 }
106
107 #[test]
108 fn nothing_outside_the_builtin_directory_is_answered() {
109 assert!(read(Path::new("/usr/include/stdarg.h")).is_none());
110 assert!(read(Path::new("stdarg.h")).is_none());
111 assert!(read(&PathBuf::from(DIR).join("stdio.h")).is_none());
112 assert!(read(&PathBuf::from(DIR).join("sys").join("stdarg.h")).is_none());
113 }
114
115 #[test]
116 fn the_list_is_sorted_so_that_a_new_header_has_one_place_to_go() {
117 let mut sorted = names();
118 sorted.sort_unstable();
119 assert_eq!(names(), sorted);
120 }
121
122 #[test]
126 fn every_header_guards_itself_under_its_own_name() {
127 for &(name, text) in HEADERS {
128 let guard = format!("__RUCC_{}", name.trim_end_matches(".h").to_uppercase());
129 assert!(text.contains(&guard), "{name} does not mention {guard}");
130 }
131 }
132}