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