1#[derive(Clone, Copy, Debug, PartialEq)]
2pub enum Endianness {
3 Little,
4 Big,
5}
6
7#[derive(Clone, Copy, Debug, PartialEq)]
8pub struct ArchConfig {
9 pub name: &'static str,
10 pub pointer_size: usize,
11 pub cache_line_size: usize,
12 pub max_align: usize,
13 pub endianness: Endianness,
14}
15
16pub const X86_64_SYSV: ArchConfig = ArchConfig {
17 name: "x86_64",
18 pointer_size: 8,
19 cache_line_size: 64,
20 max_align: 16,
21 endianness: Endianness::Little,
22};
23
24pub const AARCH64: ArchConfig = ArchConfig {
25 name: "aarch64",
26 pointer_size: 8,
27 cache_line_size: 64,
28 max_align: 16,
29 endianness: Endianness::Little,
30};
31
32pub const AARCH64_APPLE: ArchConfig = ArchConfig {
33 name: "aarch64-apple",
34 pointer_size: 8,
35 cache_line_size: 128,
36 max_align: 16,
37 endianness: Endianness::Little,
38};
39
40pub const WASM32: ArchConfig = ArchConfig {
41 name: "wasm32",
42 pointer_size: 4,
43 cache_line_size: 64,
44 max_align: 8,
45 endianness: Endianness::Little,
46};
47
48pub const RISCV64: ArchConfig = ArchConfig {
49 name: "riscv64",
50 pointer_size: 8,
51 cache_line_size: 64,
52 max_align: 16,
53 endianness: Endianness::Little,
54};
55
56pub const CORTEX_M: ArchConfig = ArchConfig {
62 name: "cortex_m",
63 pointer_size: 4,
64 cache_line_size: 0,
65 max_align: 8,
66 endianness: Endianness::Little,
67};
68
69pub const CORTEX_M4: ArchConfig = ArchConfig {
74 name: "cortex_m4",
75 pointer_size: 4,
76 cache_line_size: 32,
77 max_align: 8,
78 endianness: Endianness::Little,
79};
80
81pub const AVR: ArchConfig = ArchConfig {
86 name: "avr",
87 pointer_size: 2,
88 cache_line_size: 0,
89 max_align: 1,
90 endianness: Endianness::Little,
91};
92
93pub fn with_overrides(
98 base: &ArchConfig,
99 cache_line_size: Option<usize>,
100 word_size: Option<usize>,
101) -> &'static ArchConfig {
102 let ptr = word_size.unwrap_or(base.pointer_size);
103 let max_align = if word_size.is_some() {
104 if ptr <= 4 { 8 } else { base.max_align }
106 } else {
107 base.max_align
108 };
109 Box::leak(Box::new(ArchConfig {
110 name: "custom",
111 pointer_size: ptr,
112 cache_line_size: cache_line_size.unwrap_or(base.cache_line_size),
113 max_align,
114 endianness: base.endianness,
115 }))
116}
117
118pub fn arch_by_name(name: &str) -> Option<&'static ArchConfig> {
129 match name {
130 "x86_64" => Some(&X86_64_SYSV),
132 "aarch64" => Some(&AARCH64),
133 "aarch64_apple" => Some(&AARCH64_APPLE),
134 "wasm32" => Some(&WASM32),
135 "riscv64" => Some(&RISCV64),
136 "cortex_m" => Some(&CORTEX_M),
137 "cortex_m4" => Some(&CORTEX_M4),
138 "avr" => Some(&AVR),
139 _ => arch_by_triple(name),
141 }
142}
143
144pub fn arch_by_triple(triple: &str) -> Option<&'static ArchConfig> {
146 if triple.starts_with("x86_64-") {
147 Some(&X86_64_SYSV)
148 } else if triple.starts_with("aarch64-apple-") {
149 Some(&AARCH64_APPLE)
151 } else if triple.starts_with("aarch64-") {
152 Some(&AARCH64)
153 } else if triple.starts_with("wasm32-") {
154 Some(&WASM32)
155 } else if triple.starts_with("riscv64") {
156 Some(&RISCV64)
157 } else if triple.starts_with("thumbv6m-")
159 || triple.starts_with("thumbv7m-")
160 || triple.starts_with("thumbv8m.base-")
161 {
162 Some(&CORTEX_M)
163 } else if triple.starts_with("thumbv7em-") || triple.starts_with("thumbv8m.main-") {
165 Some(&CORTEX_M4)
166 } else if triple.starts_with("avr-") {
168 Some(&AVR)
169 } else {
170 None
171 }
172}
173
174#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn short_names_resolve() {
182 assert_eq!(arch_by_name("x86_64"), Some(&X86_64_SYSV));
183 assert_eq!(arch_by_name("aarch64"), Some(&AARCH64));
184 assert_eq!(arch_by_name("aarch64_apple"), Some(&AARCH64_APPLE));
185 assert_eq!(arch_by_name("wasm32"), Some(&WASM32));
186 assert_eq!(arch_by_name("riscv64"), Some(&RISCV64));
187 }
188
189 #[test]
190 fn target_triples_resolve() {
191 assert_eq!(arch_by_name("x86_64-unknown-linux-gnu"), Some(&X86_64_SYSV));
192 assert_eq!(arch_by_name("x86_64-pc-windows-msvc"), Some(&X86_64_SYSV));
193 assert_eq!(arch_by_name("aarch64-unknown-linux-gnu"), Some(&AARCH64));
194 assert_eq!(arch_by_name("aarch64-linux-android"), Some(&AARCH64));
195 assert_eq!(arch_by_name("aarch64-apple-darwin"), Some(&AARCH64_APPLE));
197 assert_eq!(arch_by_name("aarch64-apple-ios"), Some(&AARCH64_APPLE));
198 assert_eq!(arch_by_name("wasm32-unknown-unknown"), Some(&WASM32));
199 assert_eq!(arch_by_name("riscv64gc-unknown-linux-gnu"), Some(&RISCV64));
200 }
201
202 #[test]
203 fn unknown_triple_returns_none() {
204 assert_eq!(arch_by_name("mips-unknown-linux-gnu"), None);
205 assert_eq!(arch_by_name("totally-bogus"), None);
206 }
207
208 #[test]
209 fn apple_aarch64_has_128_byte_cache_line() {
210 let cfg = arch_by_name("aarch64-apple-darwin").unwrap();
211 assert_eq!(cfg.cache_line_size, 128);
212 }
213
214 #[test]
215 fn cortex_m_short_names() {
216 assert_eq!(arch_by_name("cortex_m"), Some(&CORTEX_M));
217 assert_eq!(arch_by_name("cortex_m4"), Some(&CORTEX_M4));
218 assert_eq!(arch_by_name("avr"), Some(&AVR));
219 }
220
221 #[test]
222 fn cortex_m_no_cache_variants() {
223 assert_eq!(arch_by_name("thumbv6m-none-eabi"), Some(&CORTEX_M));
225 assert_eq!(
226 arch_by_name("thumbv6m-none-eabi").unwrap().cache_line_size,
227 0
228 );
229 assert_eq!(arch_by_name("thumbv7m-none-eabi"), Some(&CORTEX_M));
231 assert_eq!(arch_by_name("thumbv8m.base-none-eabi"), Some(&CORTEX_M));
233 }
234
235 #[test]
236 fn cortex_m4_cached_variants() {
237 assert_eq!(arch_by_name("thumbv7em-none-eabi"), Some(&CORTEX_M4));
239 assert_eq!(arch_by_name("thumbv7em-none-eabihf"), Some(&CORTEX_M4));
240 assert_eq!(
241 arch_by_name("thumbv7em-none-eabi").unwrap().cache_line_size,
242 32
243 );
244 assert_eq!(arch_by_name("thumbv8m.main-none-eabi"), Some(&CORTEX_M4));
246 assert_eq!(arch_by_name("thumbv8m.main-none-eabihf"), Some(&CORTEX_M4));
247 }
248
249 #[test]
250 fn avr_triple() {
251 assert_eq!(arch_by_name("avr-unknown-gnu-atmega328p"), Some(&AVR));
252 assert_eq!(arch_by_name("avr").unwrap().pointer_size, 2);
253 assert_eq!(arch_by_name("avr").unwrap().cache_line_size, 0);
254 }
255
256 #[test]
257 fn cortex_m_has_4_byte_pointers() {
258 assert_eq!(CORTEX_M.pointer_size, 4);
259 assert_eq!(CORTEX_M4.pointer_size, 4);
260 }
261}