1#![deny(missing_docs)]
5
6use cranelift_codegen::isa;
7use cranelift_codegen::settings::Configurable;
8use target_lexicon::Triple;
9
10#[cfg(all(target_arch = "riscv64", target_os = "linux"))]
11mod riscv;
12
13pub fn builder() -> Result<isa::Builder, &'static str> {
17 builder_with_options(true)
18}
19
20pub fn builder_with_options(infer_native_flags: bool) -> Result<isa::Builder, &'static str> {
28 let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err {
29 isa::LookupError::SupportDisabled => "support for architecture disabled at compile time",
30 isa::LookupError::Unsupported => "unsupported architecture",
31 })?;
32 if infer_native_flags {
33 self::infer_native_flags(&mut isa_builder)?;
34 }
35 Ok(isa_builder)
36}
37
38pub fn infer_native_flags(isa_builder: &mut dyn Configurable) -> Result<(), &'static str> {
46 #[cfg(target_arch = "x86_64")]
47 {
48 if !std::is_x86_feature_detected!("sse2") {
49 return Err("x86 support requires SSE2");
50 }
51
52 if std::is_x86_feature_detected!("sse3") {
53 isa_builder.enable("has_sse3").unwrap();
54 }
55 if std::is_x86_feature_detected!("ssse3") {
56 isa_builder.enable("has_ssse3").unwrap();
57 }
58 if std::is_x86_feature_detected!("sse4.1") {
59 isa_builder.enable("has_sse41").unwrap();
60 }
61 if std::is_x86_feature_detected!("sse4.2") {
62 isa_builder.enable("has_sse42").unwrap();
63 }
64 if std::is_x86_feature_detected!("popcnt") {
65 isa_builder.enable("has_popcnt").unwrap();
66 }
67 if std::is_x86_feature_detected!("avx") {
68 isa_builder.enable("has_avx").unwrap();
69 }
70 if std::is_x86_feature_detected!("avx2") {
71 isa_builder.enable("has_avx2").unwrap();
72 }
73 if std::is_x86_feature_detected!("fma") {
74 isa_builder.enable("has_fma").unwrap();
75 }
76 if std::is_x86_feature_detected!("bmi1") {
77 isa_builder.enable("has_bmi1").unwrap();
78 }
79 if std::is_x86_feature_detected!("bmi2") {
80 isa_builder.enable("has_bmi2").unwrap();
81 }
82 if std::is_x86_feature_detected!("avx512bitalg") {
83 isa_builder.enable("has_avx512bitalg").unwrap();
84 }
85 if std::is_x86_feature_detected!("avx512dq") {
86 isa_builder.enable("has_avx512dq").unwrap();
87 }
88 if std::is_x86_feature_detected!("avx512f") {
89 isa_builder.enable("has_avx512f").unwrap();
90 }
91 if std::is_x86_feature_detected!("avx512vl") {
92 isa_builder.enable("has_avx512vl").unwrap();
93 }
94 if std::is_x86_feature_detected!("avx512vbmi") {
95 isa_builder.enable("has_avx512vbmi").unwrap();
96 }
97 if std::is_x86_feature_detected!("lzcnt") {
98 isa_builder.enable("has_lzcnt").unwrap();
99 }
100 }
101
102 #[cfg(target_arch = "aarch64")]
103 {
104 if std::arch::is_aarch64_feature_detected!("lse") {
105 isa_builder.enable("has_lse").unwrap();
106 }
107
108 if std::arch::is_aarch64_feature_detected!("paca") {
109 isa_builder.enable("has_pauth").unwrap();
110 }
111
112 if cfg!(target_os = "macos") {
113 isa_builder.enable("sign_return_address").unwrap();
115 isa_builder.enable("sign_return_address_with_bkey").unwrap();
117 }
118 }
119
120 #[cfg(all(target_arch = "s390x", target_os = "linux"))]
123 {
124 let v = unsafe { libc::getauxval(libc::AT_HWCAP) };
125 const HWCAP_S390X_VXRS_EXT2: libc::c_ulong = 32768;
126 if (v & HWCAP_S390X_VXRS_EXT2) != 0 {
127 isa_builder.enable("has_vxrs_ext2").unwrap();
128 isa_builder.enable("has_mie2").unwrap();
131 }
132 }
133
134 #[cfg(all(target_arch = "riscv64", target_os = "linux"))]
137 {
138 riscv::hwcap_detect(isa_builder)?;
142
143 let _ = riscv::cpuinfo_detect(isa_builder);
146 }
147
148 let _ = isa_builder;
151 Ok(())
152}
153
154#[cfg(test)]
155mod tests {
156 use super::builder;
157 use cranelift_codegen::isa::CallConv;
158 use cranelift_codegen::settings;
159
160 #[test]
161 fn test() {
162 if let Ok(isa_builder) = builder() {
163 let flag_builder = settings::builder();
164 let isa = isa_builder
165 .finish(settings::Flags::new(flag_builder))
166 .unwrap();
167
168 if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
169 assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64);
170 } else if cfg!(unix) {
171 assert_eq!(isa.default_call_conv(), CallConv::SystemV);
172 } else if cfg!(windows) {
173 assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall);
174 }
175
176 if cfg!(target_pointer_width = "64") {
177 assert_eq!(isa.pointer_bits(), 64);
178 } else if cfg!(target_pointer_width = "32") {
179 assert_eq!(isa.pointer_bits(), 32);
180 } else if cfg!(target_pointer_width = "16") {
181 assert_eq!(isa.pointer_bits(), 16);
182 }
183 }
184 }
185}
186
187pub const VERSION: &str = env!("CARGO_PKG_VERSION");