]> git.proxmox.com Git - rustc.git/blob - library/stdarch/crates/stdarch-gen/src/main.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / library / stdarch / crates / stdarch-gen / src / main.rs
1 use std::env;
2 use std::fs::File;
3 use std::io::prelude::*;
4 use std::io::{self, BufReader};
5 use std::path::PathBuf;
6
7 const IN: &str = "neon.spec";
8 const ARM_OUT: &str = "generated.rs";
9 const AARCH64_OUT: &str = "generated.rs";
10
11 const UINT_TYPES: [&str; 6] = [
12 "uint8x8_t",
13 "uint8x16_t",
14 "uint16x4_t",
15 "uint16x8_t",
16 "uint32x2_t",
17 "uint32x4_t",
18 ];
19
20 const UINT_TYPES_64: [&str; 2] = ["uint64x1_t", "uint64x2_t"];
21
22 const INT_TYPES: [&str; 6] = [
23 "int8x8_t",
24 "int8x16_t",
25 "int16x4_t",
26 "int16x8_t",
27 "int32x2_t",
28 "int32x4_t",
29 ];
30
31 const INT_TYPES_64: [&str; 2] = ["int64x1_t", "int64x2_t"];
32
33 const FLOAT_TYPES: [&str; 2] = [
34 //"float8x8_t", not supported by rust
35 //"float8x16_t", not supported by rust
36 //"float16x4_t", not supported by rust
37 //"float16x8_t", not supported by rust
38 "float32x2_t",
39 "float32x4_t",
40 ];
41
42 const FLOAT_TYPES_64: [&str; 2] = [
43 //"float8x8_t", not supported by rust
44 //"float8x16_t", not supported by rust
45 //"float16x4_t", not supported by rust
46 //"float16x8_t", not supported by rust
47 "float64x1_t",
48 "float64x2_t",
49 ];
50
51 fn type_len(t: &str) -> usize {
52 match t {
53 "int8x8_t" => 8,
54 "int8x16_t" => 16,
55 "int16x4_t" => 4,
56 "int16x8_t" => 8,
57 "int32x2_t" => 2,
58 "int32x4_t" => 4,
59 "int64x1_t" => 1,
60 "int64x2_t" => 2,
61 "uint8x8_t" => 8,
62 "uint8x16_t" => 16,
63 "uint16x4_t" => 4,
64 "uint16x8_t" => 8,
65 "uint32x2_t" => 2,
66 "uint32x4_t" => 4,
67 "uint64x1_t" => 1,
68 "uint64x2_t" => 2,
69 "float16x4_t" => 4,
70 "float16x8_t" => 8,
71 "float32x2_t" => 2,
72 "float32x4_t" => 4,
73 "float64x1_t" => 1,
74 "float64x2_t" => 2,
75 "poly64x1_t" => 1,
76 "poly64x2_t" => 2,
77 _ => panic!("unknown type: {}", t),
78 }
79 }
80
81 fn type_to_suffix(t: &str) -> &str {
82 match t {
83 "int8x8_t" => "_s8",
84 "int8x16_t" => "q_s8",
85 "int16x4_t" => "_s16",
86 "int16x8_t" => "q_s16",
87 "int32x2_t" => "_s32",
88 "int32x4_t" => "q_s32",
89 "int64x1_t" => "_s64",
90 "int64x2_t" => "q_s64",
91 "uint8x8_t" => "_u8",
92 "uint8x16_t" => "q_u8",
93 "uint16x4_t" => "_u16",
94 "uint16x8_t" => "q_u16",
95 "uint32x2_t" => "_u32",
96 "uint32x4_t" => "q_u32",
97 "uint64x1_t" => "_u64",
98 "uint64x2_t" => "q_u64",
99 "float16x4_t" => "_f16",
100 "float16x8_t" => "q_f16",
101 "float32x2_t" => "_f32",
102 "float32x4_t" => "q_f32",
103 "float64x1_t" => "_f64",
104 "float64x2_t" => "q_f64",
105 "poly64x1_t" => "_p64",
106 "poly64x2_t" => "q_p64",
107 _ => panic!("unknown type: {}", t),
108 }
109 }
110
111 fn type_to_global_type(t: &str) -> &str {
112 match t {
113 "int8x8_t" => "i8x8",
114 "int8x16_t" => "i8x16",
115 "int16x4_t" => "i16x4",
116 "int16x8_t" => "i16x8",
117 "int32x2_t" => "i32x2",
118 "int32x4_t" => "i32x4",
119 "int64x1_t" => "i64x1",
120 "int64x2_t" => "i64x2",
121 "uint8x8_t" => "u8x8",
122 "uint8x16_t" => "u8x16",
123 "uint16x4_t" => "u16x4",
124 "uint16x8_t" => "u16x8",
125 "uint32x2_t" => "u32x2",
126 "uint32x4_t" => "u32x4",
127 "uint64x1_t" => "u64x1",
128 "uint64x2_t" => "u64x2",
129 "float16x4_t" => "f16x4",
130 "float16x8_t" => "f16x8",
131 "float32x2_t" => "f32x2",
132 "float32x4_t" => "f32x4",
133 "float64x1_t" => "f64",
134 "float64x2_t" => "f64x2",
135 "poly64x1_t" => "i64x1",
136 "poly64x2_t" => "i64x2",
137 _ => panic!("unknown type: {}", t),
138 }
139 }
140
141 // fn type_to_native_type(t: &str) -> &str {
142 // match t {
143 // "int8x8_t" => "i8",
144 // "int8x16_t" => "i8",
145 // "int16x4_t" => "i16",
146 // "int16x8_t" => "i16",
147 // "int32x2_t" => "i32",
148 // "int32x4_t" => "i32",
149 // "int64x1_t" => "i64",
150 // "int64x2_t" => "i64",
151 // "uint8x8_t" => "u8",
152 // "uint8x16_t" => "u8",
153 // "uint16x4_t" => "u16",
154 // "uint16x8_t" => "u16",
155 // "uint32x2_t" => "u32",
156 // "uint32x4_t" => "u32",
157 // "uint64x1_t" => "u64",
158 // "uint64x2_t" => "u64",
159 // "float16x4_t" => "f16",
160 // "float16x8_t" => "f16",
161 // "float32x2_t" => "f32",
162 // "float32x4_t" => "f32",
163 // "float64x1_t" => "f64",
164 // "float64x2_t" => "f64",
165 // "poly64x1_t" => "i64",
166 // "poly64x2_t" => "i64",
167 // _ => panic!("unknown type: {}", t),
168 // }
169 // }
170
171 fn type_to_ext(t: &str) -> &str {
172 match t {
173 "int8x8_t" => "v8i8",
174 "int8x16_t" => "v16i8",
175 "int16x4_t" => "v4i16",
176 "int16x8_t" => "v8i16",
177 "int32x2_t" => "v2i32",
178 "int32x4_t" => "v4i32",
179 "int64x1_t" => "v1i64",
180 "int64x2_t" => "v2i64",
181 "uint8x8_t" => "v8i8",
182 "uint8x16_t" => "v16i8",
183 "uint16x4_t" => "v4i16",
184 "uint16x8_t" => "v8i16",
185 "uint32x2_t" => "v2i32",
186 "uint32x4_t" => "v4i32",
187 "uint64x1_t" => "v1i64",
188 "uint64x2_t" => "v2i64",
189 "float16x4_t" => "v4f16",
190 "float16x8_t" => "v8f16",
191 "float32x2_t" => "v2f32",
192 "float32x4_t" => "v4f32",
193 "float64x1_t" => "v1f64",
194 "float64x2_t" => "v2f64",
195 /*
196 "poly64x1_t" => "i64x1",
197 "poly64x2_t" => "i64x2",
198 */
199 _ => panic!("unknown type for extension: {}", t),
200 }
201 }
202
203 fn values(t: &str, vs: &[String]) -> String {
204 if vs.len() == 1 && !t.contains('x') {
205 format!(": {} = {}", t, vs[0])
206 } else if vs.len() == 1 && type_to_global_type(t) == "f64" {
207 format!(": {} = {}", type_to_global_type(t), vs[0])
208 } else {
209 format!(
210 ": {} = {}::new({})",
211 type_to_global_type(t),
212 type_to_global_type(t),
213 vs.iter()
214 .map(|v| map_val(type_to_global_type(t), v))
215 //.map(|v| format!("{}{}", v, type_to_native_type(t)))
216 .collect::<Vec<_>>()
217 .join(", ")
218 )
219 }
220 }
221
222 fn max_val(t: &str) -> &'static str {
223 match &t[..3] {
224 "u8x" => "0xFF",
225 "u16" => "0xFF_FF",
226 "u32" => "0xFF_FF_FF_FF",
227 "u64" => "0xFF_FF_FF_FF_FF_FF_FF_FF",
228 "i8x" => "0x7F",
229 "i16" => "0x7F_FF",
230 "i32" => "0x7F_FF_FF_FF",
231 "i64" => "0x7F_FF_FF_FF_FF_FF_FF_FF",
232 "f32" => "3.40282347e+38",
233 "f64" => "1.7976931348623157e+308",
234 _ => panic!("No TRUE for type {}", t),
235 }
236 }
237
238 fn min_val(t: &str) -> &'static str {
239 match &t[..3] {
240 "u8x" => "0",
241 "u16" => "0",
242 "u32" => "0",
243 "u64" => "0",
244 "i8x" => "-128",
245 "i16" => "-32768",
246 "i32" => "-2147483648",
247 "i64" => "-9223372036854775808",
248 "f32" => "-3.40282347e+38",
249 "f64" => "-1.7976931348623157e+308",
250 _ => panic!("No TRUE for type {}", t),
251 }
252 }
253
254 fn true_val(t: &str) -> &'static str {
255 match &t[..3] {
256 "u8x" => "0xFF",
257 "u16" => "0xFF_FF",
258 "u32" => "0xFF_FF_FF_FF",
259 "u64" => "0xFF_FF_FF_FF_FF_FF_FF_FF",
260 _ => panic!("No TRUE for type {}", t),
261 }
262 }
263
264 fn ff_val(t: &str) -> &'static str {
265 match &t[..3] {
266 "u8x" => "0xFF",
267 "u16" => "0xFF_FF",
268 "u32" => "0xFF_FF_FF_FF",
269 "u64" => "0xFF_FF_FF_FF_FF_FF_FF_FF",
270 "i8x" => "0xFF",
271 "i16" => "0xFF_FF",
272 "i32" => "0xFF_FF_FF_FF",
273 "i64" => "0xFF_FF_FF_FF_FF_FF_FF_FF",
274 _ => panic!("No TRUE for type {}", t),
275 }
276 }
277
278 fn false_val(_t: &str) -> &'static str {
279 "0"
280 }
281 fn map_val<'v>(t: &str, v: &'v str) -> &'v str {
282 match v {
283 "FALSE" => false_val(t),
284 "TRUE" => true_val(t),
285 "MAX" => min_val(t),
286 "MIN" => max_val(t),
287 "FF" => ff_val(t),
288 o => o,
289 }
290 }
291
292 #[allow(clippy::too_many_arguments)]
293 fn gen_aarch64(
294 current_comment: &str,
295 current_fn: &Option<String>,
296 name: &str,
297 current_aarch64: &Option<String>,
298 link_aarch64: &Option<String>,
299 in_t: &str,
300 out_t: &str,
301 current_tests: &[(Vec<String>, Vec<String>, Vec<String>)],
302 ) -> (String, String) {
303 let _global_t = type_to_global_type(in_t);
304 let _global_ret_t = type_to_global_type(out_t);
305 let current_fn = if let Some(current_fn) = current_fn.clone() {
306 if link_aarch64.is_some() {
307 panic!("[{}] Can't specify link and fn at the same time.", name)
308 }
309 current_fn
310 } else {
311 if link_aarch64.is_none() {
312 panic!("[{}] Either fn or link-aarch have to be specified.", name)
313 }
314 format!("{}_", name)
315 };
316 let current_aarch64 = current_aarch64.clone().unwrap();
317 let ext_c = if let Some(link_aarch64) = link_aarch64.clone() {
318 let ext = type_to_ext(in_t);
319
320 format!(
321 r#"#[allow(improper_ctypes)]
322 extern "C" {{
323 #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.{}")]
324 fn {}(a: {}, a: {}) -> {};
325 }}
326 "#,
327 link_aarch64.replace("_EXT_", ext),
328 current_fn,
329 in_t,
330 in_t,
331 out_t
332 )
333 } else {
334 String::new()
335 };
336 let function = format!(
337 r#"
338 {}
339 #[inline]
340 #[target_feature(enable = "neon")]
341 #[cfg_attr(test, assert_instr({}))]
342 pub unsafe fn {}(a: {}, b: {}) -> {} {{
343 {}{}(a, b)
344 }}
345 "#,
346 current_comment, current_aarch64, name, in_t, in_t, out_t, ext_c, current_fn,
347 );
348
349 let test = gen_test(name, &in_t, &out_t, current_tests, type_len(in_t));
350 (function, test)
351 }
352
353 fn gen_test(
354 name: &str,
355 in_t: &str,
356 out_t: &str,
357 current_tests: &[(Vec<String>, Vec<String>, Vec<String>)],
358 len: usize,
359 ) -> String {
360 let mut test = format!(
361 r#"
362 #[simd_test(enable = "neon")]
363 unsafe fn test_{}() {{"#,
364 name,
365 );
366 for (a, b, e) in current_tests {
367 let a: Vec<String> = a.iter().take(len).cloned().collect();
368 let b: Vec<String> = b.iter().take(len).cloned().collect();
369 let e: Vec<String> = e.iter().take(len).cloned().collect();
370 let t = format!(
371 r#"
372 let a{};
373 let b{};
374 let e{};
375 let r: {} = transmute({}(transmute(a), transmute(b)));
376 assert_eq!(r, e);
377 "#,
378 values(in_t, &a),
379 values(in_t, &b),
380 values(out_t, &e),
381 type_to_global_type(out_t),
382 name
383 );
384 test.push_str(&t);
385 }
386 test.push_str(" }\n");
387 test
388 }
389
390 #[allow(clippy::too_many_arguments)]
391 fn gen_arm(
392 current_comment: &str,
393 current_fn: &Option<String>,
394 name: &str,
395 current_arm: &str,
396 link_arm: &Option<String>,
397 current_aarch64: &Option<String>,
398 link_aarch64: &Option<String>,
399 in_t: &str,
400 out_t: &str,
401 current_tests: &[(Vec<String>, Vec<String>, Vec<String>)],
402 ) -> (String, String) {
403 let _global_t = type_to_global_type(in_t);
404 let _global_ret_t = type_to_global_type(out_t);
405 let current_aarch64 = current_aarch64
406 .clone()
407 .unwrap_or_else(|| current_arm.to_string());
408
409 let current_fn = if let Some(current_fn) = current_fn.clone() {
410 if link_aarch64.is_some() || link_arm.is_some() {
411 panic!(
412 "[{}] Can't specify link and function at the same time. {} / {:?} / {:?}",
413 name, current_fn, link_aarch64, link_arm
414 )
415 }
416 current_fn
417 } else {
418 if link_aarch64.is_none() || link_arm.is_none() {
419 panic!(
420 "[{}] Either fn or link-arm and link-aarch have to be specified.",
421 name
422 )
423 }
424 format!("{}_", name)
425 };
426
427 let ext_c =
428 if let (Some(link_arm), Some(link_aarch64)) = (link_arm.clone(), link_aarch64.clone()) {
429 let ext = type_to_ext(in_t);
430
431 format!(
432 r#"#[allow(improper_ctypes)]
433 extern "C" {{
434 #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.{}")]
435 #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.{}")]
436 fn {}(a: {}, b: {}) -> {};
437 }}
438 "#,
439 link_arm.replace("_EXT_", ext),
440 link_aarch64.replace("_EXT_", ext),
441 current_fn,
442 in_t,
443 in_t,
444 out_t
445 )
446 } else {
447 String::new()
448 };
449
450 let function = format!(
451 r#"
452 {}
453 #[inline]
454 #[target_feature(enable = "neon")]
455 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
456 #[cfg_attr(all(test, target_arch = "arm"), assert_instr({}))]
457 #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr({}))]
458 pub unsafe fn {}(a: {}, b: {}) -> {} {{
459 {}{}(a, b)
460 }}
461 "#,
462 current_comment,
463 expand_intrinsic(&current_arm, in_t),
464 expand_intrinsic(&current_aarch64, in_t),
465 name,
466 in_t,
467 in_t,
468 out_t,
469 ext_c,
470 current_fn,
471 );
472 let test = gen_test(name, &in_t, &out_t, current_tests, type_len(in_t));
473
474 (function, test)
475 }
476
477 fn expand_intrinsic(intr: &str, t: &str) -> String {
478 if intr.ends_with('.') {
479 let ext = match t {
480 "int8x8_t" => "i8",
481 "int8x16_t" => "i8",
482 "int16x4_t" => "i16",
483 "int16x8_t" => "i16",
484 "int32x2_t" => "i32",
485 "int32x4_t" => "i32",
486 "int64x1_t" => "i64",
487 "int64x2_t" => "i64",
488 "uint8x8_t" => "i8",
489 "uint8x16_t" => "i8",
490 "uint16x4_t" => "i16",
491 "uint16x8_t" => "i16",
492 "uint32x2_t" => "i32",
493 "uint32x4_t" => "i32",
494 "uint64x1_t" => "i64",
495 "uint64x2_t" => "i64",
496 "float16x4_t" => "f16",
497 "float16x8_t" => "f16",
498 "float32x2_t" => "f32",
499 "float32x4_t" => "f32",
500 "float64x1_t" => "f64",
501 "float64x2_t" => "f64",
502 /*
503 "poly64x1_t" => "i64x1",
504 "poly64x2_t" => "i64x2",
505 */
506 _ => panic!("unknown type for extension: {}", t),
507 };
508 format!(r#""{}{}""#, intr, ext)
509 } else if intr.ends_with(".s") {
510 let ext = match t {
511 "int8x8_t" => "s8",
512 "int8x16_t" => "s8",
513 "int16x4_t" => "s16",
514 "int16x8_t" => "s16",
515 "int32x2_t" => "s32",
516 "int32x4_t" => "s32",
517 "int64x1_t" => "s64",
518 "int64x2_t" => "s64",
519 "uint8x8_t" => "u8",
520 "uint8x16_t" => "u8",
521 "uint16x4_t" => "u16",
522 "uint16x8_t" => "u16",
523 "uint32x2_t" => "u32",
524 "uint32x4_t" => "u32",
525 "uint64x1_t" => "u64",
526 "uint64x2_t" => "u64",
527 "float16x4_t" => "f16",
528 "float16x8_t" => "f16",
529 "float32x2_t" => "f32",
530 "float32x4_t" => "f32",
531 "float64x1_t" => "f64",
532 "float64x2_t" => "f64",
533 /*
534 "poly64x1_t" => "i64x1",
535 "poly64x2_t" => "i64x2",
536 */
537 _ => panic!("unknown type for extension: {}", t),
538 };
539 format!(r#""{}{}""#, &intr[..intr.len() - 1], ext)
540 } else {
541 intr.to_string()
542 }
543 }
544
545 fn main() -> io::Result<()> {
546 let args: Vec<String> = env::args().collect();
547 let in_file = args.get(1).cloned().unwrap_or_else(|| IN.to_string());
548
549 let f = File::open(in_file).expect("Failed to open neon.spec");
550 let f = BufReader::new(f);
551
552 let mut current_comment = String::new();
553 let mut current_name: Option<String> = None;
554 let mut current_fn: Option<String> = None;
555 let mut current_arm: Option<String> = None;
556 let mut current_aarch64: Option<String> = None;
557 let mut link_arm: Option<String> = None;
558 let mut link_aarch64: Option<String> = None;
559 let mut a: Vec<String> = Vec::new();
560 let mut b: Vec<String> = Vec::new();
561 let mut current_tests: Vec<(Vec<String>, Vec<String>, Vec<String>)> = Vec::new();
562
563 //
564 // THIS FILE IS GENERATED FORM neon.spec DO NOT CHANGE IT MANUALLY
565 //
566 let mut out_arm = String::from(
567 r#"// This code is automatically generated. DO NOT MODIFY.
568 //
569 // Instead, modify `crates/stdarch-gen/neon.spec` and run the following command to re-generate this file:
570 //
571 // ```
572 // OUT_DIR=`pwd`/crates/core_arch cargo run -p stdarch-gen -- crates/stdarch-gen/neon.spec
573 // ```
574 use super::*;
575 #[cfg(test)]
576 use stdarch_test::assert_instr;
577 "#,
578 );
579 let mut tests_arm = String::from(
580 r#"
581 #[cfg(test)]
582 #[allow(overflowing_literals)]
583 mod test {
584 use super::*;
585 use crate::core_arch::simd::*;
586 use std::mem::transmute;
587 use stdarch_test::simd_test;
588 "#,
589 );
590 //
591 // THIS FILE IS GENERATED FORM neon.spec DO NOT CHANGE IT MANUALLY
592 //
593 let mut out_aarch64 = String::from(
594 r#"// This code is automatically generated. DO NOT MODIFY.
595 //
596 // Instead, modify `crates/stdarch-gen/neon.spec` and run the following command to re-generate this file:
597 //
598 // ```
599 // OUT_DIR=`pwd`/crates/core_arch cargo run -p stdarch-gen -- crates/stdarch-gen/neon.spec
600 // ```
601 use super::*;
602 #[cfg(test)]
603 use stdarch_test::assert_instr;
604 "#,
605 );
606 let mut tests_aarch64 = String::from(
607 r#"
608 #[cfg(test)]
609 mod test {
610 use super::*;
611 use crate::core_arch::simd::*;
612 use std::mem::transmute;
613 use stdarch_test::simd_test;
614 "#,
615 );
616
617 for line in f.lines() {
618 let line = line.unwrap();
619 if line.is_empty() {
620 continue;
621 }
622 if line.starts_with("/// ") {
623 current_comment = line;
624 current_name = None;
625 current_fn = None;
626 current_arm = None;
627 current_aarch64 = None;
628 link_aarch64 = None;
629 link_arm = None;
630 current_tests = Vec::new();
631 } else if line.starts_with("//") {
632 } else if line.starts_with("name = ") {
633 current_name = Some(String::from(&line[7..]));
634 } else if line.starts_with("fn = ") {
635 current_fn = Some(String::from(&line[5..]));
636 } else if line.starts_with("arm = ") {
637 current_arm = Some(String::from(&line[6..]));
638 } else if line.starts_with("aarch64 = ") {
639 current_aarch64 = Some(String::from(&line[10..]));
640 } else if line.starts_with("a = ") {
641 a = line[4..].split(',').map(|v| v.trim().to_string()).collect();
642 } else if line.starts_with("b = ") {
643 b = line[4..].split(',').map(|v| v.trim().to_string()).collect();
644 } else if line.starts_with("validate ") {
645 let e = line[9..].split(',').map(|v| v.trim().to_string()).collect();
646 current_tests.push((a.clone(), b.clone(), e));
647 } else if line.starts_with("link-aarch64 = ") {
648 link_aarch64 = Some(String::from(&line[15..]));
649 } else if line.starts_with("link-arm = ") {
650 link_arm = Some(String::from(&line[11..]));
651 } else if line.starts_with("generate ") {
652 let line = &line[9..];
653 let types: Vec<String> = line
654 .split(',')
655 .map(|v| v.trim().to_string())
656 .flat_map(|v| match v.as_str() {
657 "uint*_t" => UINT_TYPES.iter().map(|v| v.to_string()).collect(),
658 "uint64x*_t" => UINT_TYPES_64.iter().map(|v| v.to_string()).collect(),
659 "int*_t" => INT_TYPES.iter().map(|v| v.to_string()).collect(),
660 "int64x*_t" => INT_TYPES_64.iter().map(|v| v.to_string()).collect(),
661 "float*_t" => FLOAT_TYPES.iter().map(|v| v.to_string()).collect(),
662 "float64x*_t" => FLOAT_TYPES_64.iter().map(|v| v.to_string()).collect(),
663 _ => vec![v],
664 })
665 .collect();
666
667 for line in types {
668 let spec: Vec<&str> = line.split(':').map(|e| e.trim()).collect();
669 let in_t;
670 let out_t;
671 if spec.len() == 1 {
672 in_t = spec[0];
673 out_t = spec[0];
674 } else if spec.len() == 2 {
675 in_t = spec[0];
676 out_t = spec[1];
677 } else {
678 panic!("Bad spec: {}", line)
679 }
680 let current_name = current_name.clone().unwrap();
681 let name = format!("{}{}", current_name, type_to_suffix(in_t),);
682
683 if let Some(current_arm) = current_arm.clone() {
684 let (function, test) = gen_arm(
685 &current_comment,
686 &current_fn,
687 &name,
688 &current_arm,
689 &link_arm,
690 &current_aarch64,
691 &link_aarch64,
692 &in_t,
693 &out_t,
694 &current_tests,
695 );
696 out_arm.push_str(&function);
697 tests_arm.push_str(&test);
698 } else {
699 let (function, test) = gen_aarch64(
700 &current_comment,
701 &current_fn,
702 &name,
703 &current_aarch64,
704 &link_aarch64,
705 &in_t,
706 &out_t,
707 &current_tests,
708 );
709 out_aarch64.push_str(&function);
710 tests_aarch64.push_str(&test);
711 }
712 }
713 }
714 }
715 tests_arm.push('}');
716 tests_arm.push('\n');
717 tests_aarch64.push('}');
718 tests_aarch64.push('\n');
719
720 let arm_out_path: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap())
721 .join("src")
722 .join("arm")
723 .join("neon");
724 std::fs::create_dir_all(&arm_out_path)?;
725
726 let mut file_arm = File::create(arm_out_path.join(ARM_OUT))?;
727 file_arm.write_all(out_arm.as_bytes())?;
728 file_arm.write_all(tests_arm.as_bytes())?;
729
730 let aarch64_out_path: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap())
731 .join("src")
732 .join("aarch64")
733 .join("neon");
734 std::fs::create_dir_all(&aarch64_out_path)?;
735
736 let mut file_aarch = File::create(aarch64_out_path.join(AARCH64_OUT))?;
737 file_aarch.write_all(out_aarch64.as_bytes())?;
738 file_aarch.write_all(tests_aarch64.as_bytes())?;
739 /*
740 if let Err(e) = Command::new("rustfmt")
741 .arg(&arm_out_path)
742 .arg(&aarch64_out_path)
743 .status() {
744 eprintln!("Could not format `{}`: {}", arm_out_path.to_str().unwrap(), e);
745 eprintln!("Could not format `{}`: {}", aarch64_out_path.to_str().unwrap(), e);
746 };
747 */
748 Ok(())
749 }