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 ("pmmintrin.h", include_str!("../runtime/include/pmmintrin.h")),
54 ("popcntintrin.h", include_str!("../runtime/include/popcntintrin.h")),
55 ("smmintrin.h", include_str!("../runtime/include/smmintrin.h")),
56 ("stdalign.h", include_str!("../runtime/include/stdalign.h")),
57 ("stdarg.h", include_str!("../runtime/include/stdarg.h")),
58 ("stdatomic.h", include_str!("../runtime/include/stdatomic.h")),
59 ("stdbool.h", include_str!("../runtime/include/stdbool.h")),
60 ("stddef.h", include_str!("../runtime/include/stddef.h")),
61 ("stdint.h", include_str!("../runtime/include/stdint.h")),
62 ("stdnoreturn.h", include_str!("../runtime/include/stdnoreturn.h")),
63 ("tmmintrin.h", include_str!("../runtime/include/tmmintrin.h")),
64 ("vpclmulqdqintrin.h", include_str!("../runtime/include/vpclmulqdqintrin.h")),
65 ("x86intrin.h", include_str!("../runtime/include/x86intrin.h")),
66 ("xmmintrin.h", include_str!("../runtime/include/xmmintrin.h")),
67 ("xsaveintrin.h", include_str!("../runtime/include/xsaveintrin.h")),
68];
69
70#[must_use]
72pub fn names() -> Vec<&'static str> {
73 HEADERS.iter().map(|&(name, _)| name).collect()
74}
75
76#[must_use]
78pub fn header(name: &str) -> Option<&'static str> {
79 HEADERS.iter().find(|&&(have, _)| have == name).map(|&(_, text)| text)
80}
81
82#[must_use]
87pub fn read(path: &Path) -> Option<SourceBytes> {
88 if path.parent() != Some(Path::new(DIR)) {
89 return None;
90 }
91 let name = path.file_name()?.to_str()?;
92 header(name).map(SourceBytes::new)
93}
94
95#[cfg(test)]
96mod tests {
97 use std::path::PathBuf;
98
99 use super::*;
100
101 #[test]
102 fn the_shipped_headers_are_read_by_the_name_the_search_path_builds() {
103 let path = PathBuf::from(DIR).join("stdarg.h");
104 let bytes = read(&path).expect("stdarg.h is shipped");
105 let text = String::from_utf8(bytes.as_ref().to_vec()).expect("utf-8");
106 assert!(text.contains("__builtin_va_list"));
107 }
108
109 #[test]
110 fn nothing_outside_the_builtin_directory_is_answered() {
111 assert!(read(Path::new("/usr/include/stdarg.h")).is_none());
112 assert!(read(Path::new("stdarg.h")).is_none());
113 assert!(read(&PathBuf::from(DIR).join("stdio.h")).is_none());
114 assert!(read(&PathBuf::from(DIR).join("sys").join("stdarg.h")).is_none());
115 }
116
117 #[test]
118 fn the_list_is_sorted_so_that_a_new_header_has_one_place_to_go() {
119 let mut sorted = names();
120 sorted.sort_unstable();
121 assert_eq!(names(), sorted);
122 }
123
124 #[test]
128 fn every_header_guards_itself_under_its_own_name() {
129 for &(name, text) in HEADERS {
130 let guard = format!("__RUCC_{}", name.trim_end_matches(".h").to_uppercase());
131 assert!(text.contains(&guard), "{name} does not mention {guard}");
132 }
133 }
134}