build.rs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  1. extern crate cast;
  2. extern crate rand;
  3. use std::collections::HashMap;
  4. use std::fmt::Write as FmtWrite;
  5. use std::fs::{self, OpenOptions};
  6. use std::io::Write;
  7. use std::hash::{Hash, Hasher};
  8. use std::path::PathBuf;
  9. use std::{env, mem};
  10. use std::fmt;
  11. use self::cast::{f32, f64, u32, u64, u128, i32, i64, i128};
  12. use self::rand::Rng;
  13. const NTESTS: usize = 1_000;
  14. fn main() {
  15. let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
  16. let out_file = out_dir.join("generated.rs");
  17. drop(fs::remove_file(&out_file));
  18. let target = env::var("TARGET").unwrap();
  19. let target_arch_arm =
  20. target.contains("arm") ||
  21. target.contains("thumb");
  22. let target_arch_mips = target.contains("mips");
  23. // TODO accept NaNs. We don't do that right now because we can't check
  24. // for NaN-ness on the thumb targets (due to missing intrinsics)
  25. // float/add.rs
  26. gen(|(a, b): (MyF64, MyF64)| {
  27. let c = a.0 + b.0;
  28. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  29. None
  30. } else {
  31. Some(c)
  32. }
  33. },
  34. "builtins::float::add::__adddf3(a, b)");
  35. gen(|(a, b): (MyF32, MyF32)| {
  36. let c = a.0 + b.0;
  37. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  38. None
  39. } else {
  40. Some(c)
  41. }
  42. },
  43. "builtins::float::add::__addsf3(a, b)");
  44. if target_arch_arm {
  45. gen(|(a, b): (MyF64, MyF64)| {
  46. let c = a.0 + b.0;
  47. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  48. None
  49. } else {
  50. Some(c)
  51. }
  52. },
  53. "builtins::float::add::__adddf3vfp(a, b)");
  54. gen(|(a, b): (LargeF32, LargeF32)| {
  55. let c = a.0 + b.0;
  56. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  57. None
  58. } else {
  59. Some(c)
  60. }
  61. },
  62. "builtins::float::add::__addsf3vfp(a, b)");
  63. }
  64. // float/cmp.rs
  65. gen(|(a, b): (MyF64, MyF64)| {
  66. let (a, b) = (a.0, b.0);
  67. if a.is_nan() || b.is_nan() {
  68. return None;
  69. }
  70. if a.is_nan() || b.is_nan() {
  71. Some(-1)
  72. } else if a < b {
  73. Some(-1)
  74. } else if a > b {
  75. Some(1)
  76. } else {
  77. Some(0)
  78. }
  79. },
  80. "builtins::float::cmp::__gedf2(a, b)");
  81. gen(|(a, b): (MyF32, MyF32)| {
  82. let (a, b) = (a.0, b.0);
  83. if a.is_nan() || b.is_nan() {
  84. return None;
  85. }
  86. if a.is_nan() || b.is_nan() {
  87. Some(-1)
  88. } else if a < b {
  89. Some(-1)
  90. } else if a > b {
  91. Some(1)
  92. } else {
  93. Some(0)
  94. }
  95. },
  96. "builtins::float::cmp::__gesf2(a, b)");
  97. gen(|(a, b): (MyF64, MyF64)| {
  98. let (a, b) = (a.0, b.0);
  99. if a.is_nan() || b.is_nan() {
  100. return None;
  101. }
  102. if a.is_nan() || b.is_nan() {
  103. Some(1)
  104. } else if a < b {
  105. Some(-1)
  106. } else if a > b {
  107. Some(1)
  108. } else {
  109. Some(0)
  110. }
  111. },
  112. "builtins::float::cmp::__ledf2(a, b)");
  113. gen(|(a, b): (MyF32, MyF32)| {
  114. let (a, b) = (a.0, b.0);
  115. if a.is_nan() || b.is_nan() {
  116. return None;
  117. }
  118. if a.is_nan() || b.is_nan() {
  119. Some(1)
  120. } else if a < b {
  121. Some(-1)
  122. } else if a > b {
  123. Some(1)
  124. } else {
  125. Some(0)
  126. }
  127. },
  128. "builtins::float::cmp::__lesf2(a, b)");
  129. gen(|(a, b): (MyF32, MyF32)| {
  130. let c = a.0.is_nan() || b.0.is_nan();
  131. Some(c as i32)
  132. },
  133. "builtins::float::cmp::__unordsf2(a, b)");
  134. gen(|(a, b): (MyF64, MyF64)| {
  135. let c = a.0.is_nan() || b.0.is_nan();
  136. Some(c as i32)
  137. },
  138. "builtins::float::cmp::__unorddf2(a, b)");
  139. if target_arch_arm {
  140. gen(|(a, b): (MyF32, MyF32)| {
  141. if a.0.is_nan() || b.0.is_nan() {
  142. return None;
  143. }
  144. let c = (a.0 <= b.0) as i32;
  145. Some(c)
  146. },
  147. "builtins::float::cmp::__aeabi_fcmple(a, b)");
  148. gen(|(a, b): (MyF32, MyF32)| {
  149. if a.0.is_nan() || b.0.is_nan() {
  150. return None;
  151. }
  152. let c = (a.0 >= b.0) as i32;
  153. Some(c)
  154. },
  155. "builtins::float::cmp::__aeabi_fcmpge(a, b)");
  156. gen(|(a, b): (MyF32, MyF32)| {
  157. if a.0.is_nan() || b.0.is_nan() {
  158. return None;
  159. }
  160. let c = (a.0 == b.0) as i32;
  161. Some(c)
  162. },
  163. "builtins::float::cmp::__aeabi_fcmpeq(a, b)");
  164. gen(|(a, b): (MyF32, MyF32)| {
  165. if a.0.is_nan() || b.0.is_nan() {
  166. return None;
  167. }
  168. let c = (a.0 < b.0) as i32;
  169. Some(c)
  170. },
  171. "builtins::float::cmp::__aeabi_fcmplt(a, b)");
  172. gen(|(a, b): (MyF32, MyF32)| {
  173. if a.0.is_nan() || b.0.is_nan() {
  174. return None;
  175. }
  176. let c = (a.0 > b.0) as i32;
  177. Some(c)
  178. },
  179. "builtins::float::cmp::__aeabi_fcmpgt(a, b)");
  180. gen(|(a, b): (MyF64, MyF64)| {
  181. if a.0.is_nan() || b.0.is_nan() {
  182. return None;
  183. }
  184. let c = (a.0 <= b.0) as i32;
  185. Some(c)
  186. },
  187. "builtins::float::cmp::__aeabi_dcmple(a, b)");
  188. gen(|(a, b): (MyF64, MyF64)| {
  189. if a.0.is_nan() || b.0.is_nan() {
  190. return None;
  191. }
  192. let c = (a.0 >= b.0) as i32;
  193. Some(c)
  194. },
  195. "builtins::float::cmp::__aeabi_dcmpge(a, b)");
  196. gen(|(a, b): (MyF64, MyF64)| {
  197. if a.0.is_nan() || b.0.is_nan() {
  198. return None;
  199. }
  200. let c = (a.0 == b.0) as i32;
  201. Some(c)
  202. },
  203. "builtins::float::cmp::__aeabi_dcmpeq(a, b)");
  204. gen(|(a, b): (MyF64, MyF64)| {
  205. if a.0.is_nan() || b.0.is_nan() {
  206. return None;
  207. }
  208. let c = (a.0 < b.0) as i32;
  209. Some(c)
  210. },
  211. "builtins::float::cmp::__aeabi_dcmplt(a, b)");
  212. gen(|(a, b): (MyF64, MyF64)| {
  213. if a.0.is_nan() || b.0.is_nan() {
  214. return None;
  215. }
  216. let c = (a.0 > b.0) as i32;
  217. Some(c)
  218. },
  219. "builtins::float::cmp::__aeabi_dcmpgt(a, b)");
  220. gen(|(a, b): (LargeF32, LargeF32)| {
  221. if a.0.is_nan() || b.0.is_nan() {
  222. return None;
  223. }
  224. Some((a.0 >= b.0) as i32)
  225. },
  226. "builtins::float::cmp::__gesf2vfp(a, b)");
  227. gen(|(a, b): (MyF64, MyF64)| {
  228. if a.0.is_nan() || b.0.is_nan() {
  229. return None;
  230. }
  231. Some((a.0 >= b.0) as i32)
  232. },
  233. "builtins::float::cmp::__gedf2vfp(a, b)");
  234. gen(|(a, b): (LargeF32, LargeF32)| {
  235. if a.0.is_nan() || b.0.is_nan() {
  236. return None;
  237. }
  238. Some((a.0 > b.0) as i32)
  239. },
  240. "builtins::float::cmp::__gtsf2vfp(a, b)");
  241. gen(|(a, b): (MyF64, MyF64)| {
  242. if a.0.is_nan() || b.0.is_nan() {
  243. return None;
  244. }
  245. Some((a.0 > b.0) as i32)
  246. },
  247. "builtins::float::cmp::__gtdf2vfp(a, b)");
  248. gen(|(a, b): (LargeF32, LargeF32)| {
  249. if a.0.is_nan() || b.0.is_nan() {
  250. return None;
  251. }
  252. Some((a.0 < b.0) as i32)
  253. },
  254. "builtins::float::cmp::__ltsf2vfp(a, b)");
  255. gen(|(a, b): (MyF64, MyF64)| {
  256. if a.0.is_nan() || b.0.is_nan() {
  257. return None;
  258. }
  259. Some((a.0 < b.0) as i32)
  260. },
  261. "builtins::float::cmp::__ltdf2vfp(a, b)");
  262. gen(|(a, b): (LargeF32, LargeF32)| {
  263. if a.0.is_nan() || b.0.is_nan() {
  264. return None;
  265. }
  266. Some((a.0 <= b.0) as i32)
  267. },
  268. "builtins::float::cmp::__lesf2vfp(a, b)");
  269. gen(|(a, b): (MyF64, MyF64)| {
  270. if a.0.is_nan() || b.0.is_nan() {
  271. return None;
  272. }
  273. Some((a.0 <= b.0) as i32)
  274. },
  275. "builtins::float::cmp::__ledf2vfp(a, b)");
  276. gen(|(a, b): (LargeF32, LargeF32)| {
  277. if a.0.is_nan() || b.0.is_nan() {
  278. return None;
  279. }
  280. Some((a.0 != b.0) as i32)
  281. },
  282. "builtins::float::cmp::__nesf2vfp(a, b)");
  283. gen(|(a, b): (MyF64, MyF64)| {
  284. if a.0.is_nan() || b.0.is_nan() {
  285. return None;
  286. }
  287. Some((a.0 != b.0) as i32)
  288. },
  289. "builtins::float::cmp::__nedf2vfp(a, b)");
  290. gen(|(a, b): (LargeF32, LargeF32)| {
  291. if a.0.is_nan() || b.0.is_nan() {
  292. return None;
  293. }
  294. Some((a.0 == b.0) as i32)
  295. },
  296. "builtins::float::cmp::__eqsf2vfp(a, b)");
  297. gen(|(a, b): (MyF64, MyF64)| {
  298. if a.0.is_nan() || b.0.is_nan() {
  299. return None;
  300. }
  301. Some((a.0 == b.0) as i32)
  302. },
  303. "builtins::float::cmp::__eqdf2vfp(a, b)");
  304. }
  305. // float/extend.rs
  306. gen(|a: MyF32| {
  307. if a.0.is_nan() {
  308. return None;
  309. }
  310. Some(f64(a.0))
  311. },
  312. "builtins::float::extend::__extendsfdf2(a)");
  313. if target_arch_arm {
  314. gen(|a: LargeF32| {
  315. if a.0.is_nan() {
  316. return None;
  317. }
  318. Some(f64(a.0))
  319. },
  320. "builtins::float::extend::__extendsfdf2vfp(a)");
  321. }
  322. // float/conv.rs
  323. gen(|a: MyF64| i64(a.0).ok(),
  324. "builtins::float::conv::__fixdfdi(a)");
  325. gen(|a: MyF64| i32(a.0).ok(),
  326. "builtins::float::conv::__fixdfsi(a)");
  327. gen(|a: MyF32| i64(a.0).ok(),
  328. "builtins::float::conv::__fixsfdi(a)");
  329. gen(|a: MyF32| i32(a.0).ok(),
  330. "builtins::float::conv::__fixsfsi(a)");
  331. gen(|a: MyF32| i128(a.0).ok(),
  332. "builtins::float::conv::__fixsfti(a)");
  333. gen(|a: MyF64| i128(a.0).ok(),
  334. "builtins::float::conv::__fixdfti(a)");
  335. gen(|a: MyF64| u64(a.0).ok(),
  336. "builtins::float::conv::__fixunsdfdi(a)");
  337. gen(|a: MyF64| u32(a.0).ok(),
  338. "builtins::float::conv::__fixunsdfsi(a)");
  339. gen(|a: MyF32| u64(a.0).ok(),
  340. "builtins::float::conv::__fixunssfdi(a)");
  341. gen(|a: MyF32| u32(a.0).ok(),
  342. "builtins::float::conv::__fixunssfsi(a)");
  343. gen(|a: MyF32| u128(a.0).ok(),
  344. "builtins::float::conv::__fixunssfti(a)");
  345. gen(|a: MyF64| u128(a.0).ok(),
  346. "builtins::float::conv::__fixunsdfti(a)");
  347. gen(|a: MyI64| Some(f64(a.0)),
  348. "builtins::float::conv::__floatdidf(a)");
  349. gen(|a: MyI32| Some(f64(a.0)),
  350. "builtins::float::conv::__floatsidf(a)");
  351. gen(|a: MyI32| Some(f32(a.0)),
  352. "builtins::float::conv::__floatsisf(a)");
  353. gen(|a: MyU64| Some(f64(a.0)),
  354. "builtins::float::conv::__floatundidf(a)");
  355. gen(|a: MyU32| Some(f64(a.0)),
  356. "builtins::float::conv::__floatunsidf(a)");
  357. gen(|a: MyU32| Some(f32(a.0)),
  358. "builtins::float::conv::__floatunsisf(a)");
  359. gen(|a: MyU128| f32(a.0).ok(),
  360. "builtins::float::conv::__floatuntisf(a)");
  361. if !target_arch_mips {
  362. gen(|a: MyI128| Some(f32(a.0)),
  363. "builtins::float::conv::__floattisf(a)");
  364. gen(|a: MyI128| Some(f64(a.0)),
  365. "builtins::float::conv::__floattidf(a)");
  366. gen(|a: MyU128| Some(f64(a.0)),
  367. "builtins::float::conv::__floatuntidf(a)");
  368. }
  369. // float/pow.rs
  370. gen(|(a, b): (MyF64, MyI32)| {
  371. let c = a.0.powi(b.0);
  372. if a.0.is_nan() || c.is_nan() {
  373. None
  374. } else {
  375. Some(c)
  376. }
  377. },
  378. "builtins::float::pow::__powidf2(a, b)");
  379. gen(|(a, b): (MyF32, MyI32)| {
  380. let c = a.0.powi(b.0);
  381. if a.0.is_nan() || c.is_nan() {
  382. None
  383. } else {
  384. Some(c)
  385. }
  386. },
  387. "builtins::float::pow::__powisf2(a, b)");
  388. // float/sub.rs
  389. gen(|(a, b): (MyF64, MyF64)| {
  390. let c = a.0 - b.0;
  391. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  392. None
  393. } else {
  394. Some(c)
  395. }
  396. },
  397. "builtins::float::sub::__subdf3(a, b)");
  398. gen(|(a, b): (MyF32, MyF32)| {
  399. let c = a.0 - b.0;
  400. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  401. None
  402. } else {
  403. Some(c)
  404. }
  405. },
  406. "builtins::float::sub::__subsf3(a, b)");
  407. if target_arch_arm {
  408. gen(|(a, b): (MyF64, MyF64)| {
  409. let c = a.0 - b.0;
  410. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  411. None
  412. } else {
  413. Some(c)
  414. }
  415. },
  416. "builtins::float::sub::__subdf3vfp(a, b)");
  417. gen(|(a, b): (LargeF32, LargeF32)| {
  418. let c = a.0 - b.0;
  419. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  420. None
  421. } else {
  422. Some(c)
  423. }
  424. },
  425. "builtins::float::sub::__subsf3vfp(a, b)");
  426. }
  427. // float/mul.rs
  428. gen(|(a, b): (MyF64, MyF64)| {
  429. let c = a.0 * b.0;
  430. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  431. None
  432. } else {
  433. Some(c)
  434. }
  435. },
  436. "builtins::float::mul::__muldf3(a, b)");
  437. gen(|(a, b): (LargeF32, LargeF32)| {
  438. let c = a.0 * b.0;
  439. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  440. None
  441. } else {
  442. Some(c)
  443. }
  444. },
  445. "builtins::float::mul::__mulsf3(a, b)");
  446. if target_arch_arm {
  447. gen(|(a, b): (MyF64, MyF64)| {
  448. let c = a.0 * b.0;
  449. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  450. None
  451. } else {
  452. Some(c)
  453. }
  454. },
  455. "builtins::float::mul::__muldf3vfp(a, b)");
  456. gen(|(a, b): (LargeF32, LargeF32)| {
  457. let c = a.0 * b.0;
  458. if a.0.is_nan() || b.0.is_nan() || c.is_nan() {
  459. None
  460. } else {
  461. Some(c)
  462. }
  463. },
  464. "builtins::float::mul::__mulsf3vfp(a, b)");
  465. }
  466. // float/div.rs
  467. gen(|(a, b): (MyF64, MyF64)| {
  468. if b.0 == 0.0 {
  469. return None
  470. }
  471. let c = a.0 / b.0;
  472. if a.0.is_nan() || b.0.is_nan() || c.is_nan() ||
  473. c.abs() <= unsafe { mem::transmute(4503599627370495u64) }
  474. {
  475. None
  476. } else {
  477. Some(c)
  478. }
  479. },
  480. "builtins::float::div::__divdf3(a, b)");
  481. gen(|(a, b): (LargeF32, LargeF32)| {
  482. if b.0 == 0.0 {
  483. return None
  484. }
  485. let c = a.0 / b.0;
  486. if a.0.is_nan() || b.0.is_nan() || c.is_nan() ||
  487. c.abs() <= unsafe { mem::transmute(16777215u32) }
  488. {
  489. None
  490. } else {
  491. Some(c)
  492. }
  493. },
  494. "builtins::float::div::__divsf3(a, b)");
  495. if target_arch_arm {
  496. gen(|(a, b): (MyF64, MyF64)| {
  497. if b.0 == 0.0 {
  498. return None
  499. }
  500. let c = a.0 / b.0;
  501. if a.0.is_nan() || b.0.is_nan() || c.is_nan() ||
  502. c.abs() <= unsafe { mem::transmute(4503599627370495u64) }
  503. {
  504. None
  505. } else {
  506. Some(c)
  507. }
  508. },
  509. "builtins::float::div::__divdf3vfp(a, b)");
  510. gen(|(a, b): (LargeF32, LargeF32)| {
  511. if b.0 == 0.0 {
  512. return None
  513. }
  514. let c = a.0 / b.0;
  515. if a.0.is_nan() || b.0.is_nan() || c.is_nan() ||
  516. c.abs() <= unsafe { mem::transmute(16777215u32) }
  517. {
  518. None
  519. } else {
  520. Some(c)
  521. }
  522. },
  523. "builtins::float::div::__divsf3vfp(a, b)");
  524. }
  525. // int/addsub.rs
  526. gen(|(a, b): (MyU128, MyU128)| Some(a.0.wrapping_add(b.0)),
  527. "builtins::int::addsub::rust_u128_add(a, b)");
  528. gen(|(a, b): (MyI128, MyI128)| Some(a.0.wrapping_add(b.0)),
  529. "builtins::int::addsub::rust_i128_add(a, b)");
  530. gen(|(a, b): (MyU128, MyU128)| Some(a.0.overflowing_add(b.0)),
  531. "builtins::int::addsub::rust_u128_addo(a, b)");
  532. gen(|(a, b): (MyI128, MyI128)| Some(a.0.overflowing_add(b.0)),
  533. "builtins::int::addsub::rust_i128_addo(a, b)");
  534. gen(|(a, b): (MyU128, MyU128)| Some(a.0.wrapping_sub(b.0)),
  535. "builtins::int::addsub::rust_u128_sub(a, b)");
  536. gen(|(a, b): (MyI128, MyI128)| Some(a.0.wrapping_sub(b.0)),
  537. "builtins::int::addsub::rust_i128_sub(a, b)");
  538. gen(|(a, b): (MyU128, MyU128)| Some(a.0.overflowing_sub(b.0)),
  539. "builtins::int::addsub::rust_u128_subo(a, b)");
  540. gen(|(a, b): (MyI128, MyI128)| Some(a.0.overflowing_sub(b.0)),
  541. "builtins::int::addsub::rust_i128_subo(a, b)");
  542. // int/mul.rs
  543. gen(|(a, b): (MyU64, MyU64)| Some(a.0.wrapping_mul(b.0)),
  544. "builtins::int::mul::__muldi3(a, b)");
  545. gen(|(a, b): (MyI64, MyI64)| Some(a.0.overflowing_mul(b.0)),
  546. "{
  547. let mut o = 2;
  548. let c = builtins::int::mul::__mulodi4(a, b, &mut o);
  549. (c, match o { 0 => false, 1 => true, _ => panic!() })
  550. }");
  551. gen(|(a, b): (MyI32, MyI32)| Some(a.0.overflowing_mul(b.0)),
  552. "{
  553. let mut o = 2;
  554. let c = builtins::int::mul::__mulosi4(a, b, &mut o);
  555. (c, match o { 0 => false, 1 => true, _ => panic!() })
  556. }");
  557. gen(|(a, b): (MyI128, MyI128)| Some(a.0.wrapping_mul(b.0)),
  558. "builtins::int::mul::__multi3(a, b)");
  559. if !target_arch_mips { // FIXME(#137)
  560. gen(|(a, b): (MyI128, MyI128)| Some(a.0.overflowing_mul(b.0)),
  561. "{
  562. let mut o = 2;
  563. let c = builtins::int::mul::__muloti4(a, b, &mut o);
  564. (c, match o { 0 => false, 1 => true, _ => panic!() })
  565. }");
  566. }
  567. // int/sdiv.rs
  568. gen(|(a, b): (MyI64, MyI64)| {
  569. if b.0 == 0 {
  570. None
  571. } else {
  572. Some(a.0 / b.0)
  573. }
  574. },
  575. "builtins::int::sdiv::__divdi3(a, b)");
  576. gen(|(a, b): (MyI64, MyI64)| {
  577. if b.0 == 0 {
  578. None
  579. } else {
  580. Some((a.0 / b.0, a.0 % b.0))
  581. }
  582. },
  583. "{
  584. let mut r = 0;
  585. (builtins::int::sdiv::__divmoddi4(a, b, &mut r), r)
  586. }");
  587. gen(|(a, b): (MyI32, MyI32)| {
  588. if b.0 == 0 {
  589. None
  590. } else {
  591. Some((a.0 / b.0, a.0 % b.0))
  592. }
  593. },
  594. "{
  595. let mut r = 0;
  596. (builtins::int::sdiv::__divmodsi4(a, b, &mut r), r)
  597. }");
  598. gen(|(a, b): (MyI32, MyI32)| {
  599. if b.0 == 0 {
  600. None
  601. } else {
  602. Some(a.0 / b.0)
  603. }
  604. },
  605. "builtins::int::sdiv::__divsi3(a, b)");
  606. gen(|(a, b): (MyI32, MyI32)| {
  607. if b.0 == 0 {
  608. None
  609. } else {
  610. Some(a.0 % b.0)
  611. }
  612. },
  613. "builtins::int::sdiv::__modsi3(a, b)");
  614. gen(|(a, b): (MyI64, MyI64)| {
  615. if b.0 == 0 {
  616. None
  617. } else {
  618. Some(a.0 % b.0)
  619. }
  620. },
  621. "builtins::int::sdiv::__moddi3(a, b)");
  622. if !target_arch_mips { // FIXME(#137)
  623. gen(|(a, b): (MyI128, MyI128)| {
  624. if b.0 == 0 {
  625. None
  626. } else {
  627. Some(a.0 / b.0)
  628. }
  629. },
  630. "builtins::int::sdiv::__divti3(a, b)");
  631. gen(|(a, b): (MyI128, MyI128)| {
  632. if b.0 == 0 {
  633. None
  634. } else {
  635. Some(a.0 % b.0)
  636. }
  637. },
  638. "builtins::int::sdiv::__modti3(a, b)");
  639. }
  640. // int/shift.rs
  641. gen(|(a, b): (MyU64, MyU32)| Some(a.0 << (b.0 % 64)),
  642. "builtins::int::shift::__ashldi3(a, b % 64)");
  643. gen(|(a, b): (MyU128, MyU32)| Some(a.0 << (b.0 % 128)),
  644. "builtins::int::shift::__ashlti3(a, b % 128)");
  645. gen(|(a, b): (MyI64, MyU32)| Some(a.0 >> (b.0 % 64)),
  646. "builtins::int::shift::__ashrdi3(a, b % 64)");
  647. gen(|(a, b): (MyI128, MyU32)| Some(a.0 >> (b.0 % 128)),
  648. "builtins::int::shift::__ashrti3(a, b % 128)");
  649. gen(|(a, b): (MyU64, MyU32)| Some(a.0 >> (b.0 % 64)),
  650. "builtins::int::shift::__lshrdi3(a, b % 64)");
  651. gen(|(a, b): (MyU128, MyU32)| Some(a.0 >> (b.0 % 128)),
  652. "builtins::int::shift::__lshrti3(a, b % 128)");
  653. // int/udiv.rs
  654. gen(|(a, b): (MyU64, MyU64)| {
  655. if b.0 == 0 {
  656. None
  657. } else {
  658. Some(a.0 / b.0)
  659. }
  660. },
  661. "builtins::int::udiv::__udivdi3(a, b)");
  662. gen(|(a, b): (MyU64, MyU64)| {
  663. if b.0 == 0 {
  664. None
  665. } else {
  666. Some((a.0 / b.0, a.0 % b.0))
  667. }
  668. },
  669. "{
  670. let mut r = 0;
  671. (builtins::int::udiv::__udivmoddi4(a, b, Some(&mut r)), r)
  672. }");
  673. gen(|(a, b): (MyU32, MyU32)| {
  674. if b.0 == 0 {
  675. None
  676. } else {
  677. Some((a.0 / b.0, a.0 % b.0))
  678. }
  679. },
  680. "{
  681. let mut r = 0;
  682. (builtins::int::udiv::__udivmodsi4(a, b, Some(&mut r)), r)
  683. }");
  684. gen(|(a, b): (MyU32, MyU32)| {
  685. if b.0 == 0 {
  686. None
  687. } else {
  688. Some(a.0 / b.0)
  689. }
  690. },
  691. "builtins::int::udiv::__udivsi3(a, b)");
  692. gen(|(a, b): (MyU32, MyU32)| {
  693. if b.0 == 0 {
  694. None
  695. } else {
  696. Some(a.0 % b.0)
  697. }
  698. },
  699. "builtins::int::udiv::__umodsi3(a, b)");
  700. gen(|(a, b): (MyU64, MyU64)| {
  701. if b.0 == 0 {
  702. None
  703. } else {
  704. Some(a.0 % b.0)
  705. }
  706. },
  707. "builtins::int::udiv::__umoddi3(a, b)");
  708. if !target_arch_mips { // FIXME(#137)
  709. gen(|(a, b): (MyU128, MyU128)| {
  710. if b.0 == 0 {
  711. None
  712. } else {
  713. Some(a.0 / b.0)
  714. }
  715. },
  716. "builtins::int::udiv::__udivti3(a, b)");
  717. gen(|(a, b): (MyU128, MyU128)| {
  718. if b.0 == 0 {
  719. None
  720. } else {
  721. Some(a.0 % b.0)
  722. }
  723. },
  724. "builtins::int::udiv::__umodti3(a, b)");
  725. gen(|(a, b): (MyU128, MyU128)| {
  726. if b.0 == 0 {
  727. None
  728. } else {
  729. Some((a.0 / b.0, a.0 % b.0))
  730. }
  731. },
  732. "{
  733. let mut r = 0;
  734. (builtins::int::udiv::__udivmodti4(a, b, Some(&mut r)), r)
  735. }");
  736. }
  737. // count leading zeros
  738. gen(|a: MyU128| {
  739. Some((a as usize).leading_zeros())
  740. },
  741. "{
  742. builtins::int::__clzsi2(a as usize)
  743. }");
  744. }
  745. macro_rules! gen_float {
  746. ($name:ident,
  747. $fty:ident,
  748. $uty:ident,
  749. $bits:expr,
  750. $significand_bits:expr) => {
  751. pub fn $name<R>(rng: &mut R) -> $fty
  752. where
  753. R: Rng,
  754. {
  755. const BITS: u8 = $bits;
  756. const SIGNIFICAND_BITS: u8 = $significand_bits;
  757. const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1;
  758. const SIGN_MASK: $uty = (1 << (BITS - 1));
  759. const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK);
  760. fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty {
  761. unsafe {
  762. mem::transmute(((sign as $uty) << (BITS - 1)) |
  763. ((exponent & EXPONENT_MASK) <<
  764. SIGNIFICAND_BITS) |
  765. (significand & SIGNIFICAND_MASK))
  766. }
  767. }
  768. if rng.gen_weighted_bool(10) {
  769. // Special values
  770. *rng.choose(&[-0.0,
  771. 0.0,
  772. ::std::$fty::MIN,
  773. ::std::$fty::MIN_POSITIVE,
  774. ::std::$fty::MAX,
  775. ::std::$fty::NAN,
  776. ::std::$fty::INFINITY,
  777. -::std::$fty::INFINITY])
  778. .unwrap()
  779. } else if rng.gen_weighted_bool(10) {
  780. // NaN patterns
  781. mk_f32(rng.gen(), rng.gen(), 0)
  782. } else if rng.gen() {
  783. // Denormalized
  784. mk_f32(rng.gen(), 0, rng.gen())
  785. } else {
  786. // Random anything
  787. mk_f32(rng.gen(), rng.gen(), rng.gen())
  788. }
  789. }
  790. }
  791. }
  792. gen_float!(gen_f32, f32, u32, 32, 23);
  793. gen_float!(gen_f64, f64, u64, 64, 52);
  794. macro_rules! gen_large_float {
  795. ($name:ident,
  796. $fty:ident,
  797. $uty:ident,
  798. $bits:expr,
  799. $significand_bits:expr) => {
  800. pub fn $name<R>(rng: &mut R) -> $fty
  801. where
  802. R: Rng,
  803. {
  804. const BITS: u8 = $bits;
  805. const SIGNIFICAND_BITS: u8 = $significand_bits;
  806. const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1;
  807. const SIGN_MASK: $uty = (1 << (BITS - 1));
  808. const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK);
  809. fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty {
  810. unsafe {
  811. mem::transmute(((sign as $uty) << (BITS - 1)) |
  812. ((exponent & EXPONENT_MASK) <<
  813. SIGNIFICAND_BITS) |
  814. (significand & SIGNIFICAND_MASK))
  815. }
  816. }
  817. if rng.gen_weighted_bool(10) {
  818. // Special values
  819. *rng.choose(&[-0.0,
  820. 0.0,
  821. ::std::$fty::MIN,
  822. ::std::$fty::MIN_POSITIVE,
  823. ::std::$fty::MAX,
  824. ::std::$fty::NAN,
  825. ::std::$fty::INFINITY,
  826. -::std::$fty::INFINITY])
  827. .unwrap()
  828. } else if rng.gen_weighted_bool(10) {
  829. // NaN patterns
  830. mk_f32(rng.gen(), rng.gen(), 0)
  831. } else if rng.gen() {
  832. // Denormalized
  833. mk_f32(rng.gen(), 0, rng.gen())
  834. } else {
  835. // Random anything
  836. rng.gen::<$fty>()
  837. }
  838. }
  839. }
  840. }
  841. gen_large_float!(gen_large_f32, f32, u32, 32, 23);
  842. gen_large_float!(gen_large_f64, f64, u64, 64, 52);
  843. trait TestInput: rand::Rand + Hash + Eq + fmt::Debug {
  844. fn ty_name() -> String;
  845. fn generate_lets(container: &str, cnt: &mut u8) -> String;
  846. fn generate_static(&self, dst: &mut String);
  847. }
  848. trait TestOutput {
  849. fn ty_name() -> String;
  850. fn generate_static(&self, dst: &mut String);
  851. fn generate_expr(container: &str) -> String;
  852. }
  853. fn gen<F, A, R>(mut generate: F, test: &str)
  854. where F: FnMut(A) -> Option<R>,
  855. A: TestInput + Copy,
  856. R: TestOutput,
  857. {
  858. let rng = &mut rand::thread_rng();
  859. let testname = test.split("::")
  860. .last()
  861. .unwrap()
  862. .split("(")
  863. .next()
  864. .unwrap();
  865. let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
  866. let out_file = out_dir.join("generated.rs");
  867. let mut testcases = HashMap::new();
  868. let mut n = NTESTS;
  869. while n > 0 {
  870. let input: A = rng.gen();
  871. if testcases.contains_key(&input) {
  872. continue
  873. }
  874. let output = match generate(input) {
  875. Some(o) => o,
  876. None => continue,
  877. };
  878. testcases.insert(input, output);
  879. n -= 1;
  880. }
  881. let mut contents = String::new();
  882. contents.push_str(&format!("mod {} {{\nuse super::*;\n", testname));
  883. contents.push_str("#[test]\n");
  884. contents.push_str("fn test() {\n");
  885. contents.push_str(&format!("static TESTS: [({}, {}); {}] = [\n",
  886. A::ty_name(),
  887. R::ty_name(),
  888. NTESTS));
  889. for (input, output) in testcases {
  890. contents.push_str(" (");
  891. input.generate_static(&mut contents);
  892. contents.push_str(", ");
  893. output.generate_static(&mut contents);
  894. contents.push_str("),\n");
  895. }
  896. contents.push_str("];\n");
  897. contents.push_str(&format!(r#"
  898. for &(inputs, output) in TESTS.iter() {{
  899. {}
  900. assert_eq!({}, {}, "inputs {{:?}}", inputs)
  901. }}
  902. "#,
  903. A::generate_lets("inputs", &mut 0),
  904. R::generate_expr("output"),
  905. test,
  906. ));
  907. contents.push_str("\n}\n");
  908. contents.push_str("\n}\n");
  909. OpenOptions::new()
  910. .write(true)
  911. .append(true)
  912. .create(true)
  913. .open(out_file)
  914. .unwrap()
  915. .write_all(contents.as_bytes())
  916. .unwrap();
  917. }
  918. macro_rules! my_float {
  919. ($(struct $name:ident($inner:ident) = $gen:ident;)*) => ($(
  920. #[derive(Debug, Clone, Copy)]
  921. struct $name($inner);
  922. impl TestInput for $name {
  923. fn ty_name() -> String {
  924. format!("u{}", &stringify!($inner)[1..])
  925. }
  926. fn generate_lets(container: &str, cnt: &mut u8) -> String {
  927. let me = *cnt;
  928. *cnt += 1;
  929. format!("let {} = {}::from_bits({});\n",
  930. (b'a' + me) as char,
  931. stringify!($inner),
  932. container)
  933. }
  934. fn generate_static(&self, dst: &mut String) {
  935. write!(dst, "{}", self.0.to_bits()).unwrap();
  936. }
  937. }
  938. impl rand::Rand for $name {
  939. fn rand<R: rand::Rng>(r: &mut R) -> $name {
  940. $name($gen(r))
  941. }
  942. }
  943. impl Hash for $name {
  944. fn hash<H: Hasher>(&self, h: &mut H) {
  945. self.0.to_bits().hash(h)
  946. }
  947. }
  948. impl PartialEq for $name {
  949. fn eq(&self, other: &$name) -> bool {
  950. self.0.to_bits() == other.0.to_bits()
  951. }
  952. }
  953. impl Eq for $name {}
  954. )*)
  955. }
  956. my_float! {
  957. struct MyF64(f64) = gen_f64;
  958. struct LargeF64(f64) = gen_large_f64;
  959. struct MyF32(f32) = gen_f32;
  960. struct LargeF32(f32) = gen_large_f32;
  961. }
  962. macro_rules! my_integer {
  963. ($(struct $name:ident($inner:ident);)*) => ($(
  964. #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
  965. struct $name($inner);
  966. impl TestInput for $name {
  967. fn ty_name() -> String {
  968. stringify!($inner).to_string()
  969. }
  970. fn generate_lets(container: &str, cnt: &mut u8) -> String {
  971. let me = *cnt;
  972. *cnt += 1;
  973. format!("let {} = {};\n",
  974. (b'a' + me) as char,
  975. container)
  976. }
  977. fn generate_static(&self, dst: &mut String) {
  978. write!(dst, "{}", self.0).unwrap();
  979. }
  980. }
  981. impl rand::Rand for $name {
  982. fn rand<R: rand::Rng>(rng: &mut R) -> $name {
  983. let bits = (0 as $inner).count_zeros();
  984. let mut mk = || {
  985. if rng.gen_weighted_bool(10) {
  986. *rng.choose(&[
  987. ::std::$inner::MAX >> (bits / 2),
  988. 0,
  989. ::std::$inner::MIN >> (bits / 2),
  990. ]).unwrap()
  991. } else {
  992. rng.gen::<$inner>()
  993. }
  994. };
  995. let a = mk();
  996. let b = mk();
  997. $name((a << (bits / 2)) | (b & (!0 << (bits / 2))))
  998. }
  999. }
  1000. )*)
  1001. }
  1002. my_integer! {
  1003. struct MyI32(i32);
  1004. struct MyI64(i64);
  1005. struct MyI128(i128);
  1006. struct MyU32(u32);
  1007. struct MyU64(u64);
  1008. struct MyU128(u128);
  1009. }
  1010. impl<A, B> TestInput for (A, B)
  1011. where A: TestInput,
  1012. B: TestInput,
  1013. {
  1014. fn ty_name() -> String {
  1015. format!("({}, {})", A::ty_name(), B::ty_name())
  1016. }
  1017. fn generate_lets(container: &str, cnt: &mut u8) -> String {
  1018. format!("{}{}",
  1019. A::generate_lets(&format!("{}.0", container), cnt),
  1020. B::generate_lets(&format!("{}.1", container), cnt))
  1021. }
  1022. fn generate_static(&self, dst: &mut String) {
  1023. dst.push_str("(");
  1024. self.0.generate_static(dst);
  1025. dst.push_str(", ");
  1026. self.1.generate_static(dst);
  1027. dst.push_str(")");
  1028. }
  1029. }
  1030. impl TestOutput for f64 {
  1031. fn ty_name() -> String {
  1032. "u64".to_string()
  1033. }
  1034. fn generate_static(&self, dst: &mut String) {
  1035. write!(dst, "{}", self.to_bits()).unwrap();
  1036. }
  1037. fn generate_expr(container: &str) -> String {
  1038. format!("f64::from_bits({})", container)
  1039. }
  1040. }
  1041. impl TestOutput for f32 {
  1042. fn ty_name() -> String {
  1043. "u32".to_string()
  1044. }
  1045. fn generate_static(&self, dst: &mut String) {
  1046. write!(dst, "{}", self.to_bits()).unwrap();
  1047. }
  1048. fn generate_expr(container: &str) -> String {
  1049. format!("f32::from_bits({})", container)
  1050. }
  1051. }
  1052. macro_rules! plain_test_output {
  1053. ($($i:tt)*) => ($(
  1054. impl TestOutput for $i {
  1055. fn ty_name() -> String {
  1056. stringify!($i).to_string()
  1057. }
  1058. fn generate_static(&self, dst: &mut String) {
  1059. write!(dst, "{}", self).unwrap();
  1060. }
  1061. fn generate_expr(container: &str) -> String {
  1062. container.to_string()
  1063. }
  1064. }
  1065. )*)
  1066. }
  1067. plain_test_output!(i32 i64 i128 u32 u64 u128 bool);
  1068. impl<A, B> TestOutput for (A, B)
  1069. where A: TestOutput,
  1070. B: TestOutput,
  1071. {
  1072. fn ty_name() -> String {
  1073. format!("({}, {})", A::ty_name(), B::ty_name())
  1074. }
  1075. fn generate_static(&self, dst: &mut String) {
  1076. dst.push_str("(");
  1077. self.0.generate_static(dst);
  1078. dst.push_str(", ");
  1079. self.1.generate_static(dst);
  1080. dst.push_str(")");
  1081. }
  1082. fn generate_expr(container: &str) -> String {
  1083. container.to_string()
  1084. }
  1085. }