]> git.proxmox.com Git - rustc.git/blame - src/librustc_codegen_llvm/llvm_util.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc_codegen_llvm / llvm_util.rs
CommitLineData
9fa01778
XL
1use crate::back::write::create_informational_target_machine;
2use crate::llvm;
7cac9316 3use syntax_pos::symbol::Symbol;
7cac9316
XL
4use rustc::session::Session;
5use rustc::session::config::PrintRequest;
9fa01778 6use rustc_target::spec::MergeFunctions;
2c00a5a8 7use libc::c_int;
0531ce1d 8use std::ffi::CString;
83c7162d 9use syntax::feature_gate::UnstableFeatures;
7cac9316 10
b7449926
XL
11use std::str;
12use std::slice;
7cac9316
XL
13use std::sync::atomic::{AtomicBool, Ordering};
14use std::sync::Once;
15
2c00a5a8
XL
16static POISONED: AtomicBool = AtomicBool::new(false);
17static INIT: Once = Once::new();
18
19pub(crate) fn init(sess: &Session) {
7cac9316
XL
20 unsafe {
21 // Before we touch LLVM, make sure that multithreading is enabled.
7cac9316
XL
22 INIT.call_once(|| {
23 if llvm::LLVMStartMultithreaded() != 1 {
24 // use an extra bool to make sure that all future usage of LLVM
25 // cannot proceed despite the Once not running more than once.
26 POISONED.store(true, Ordering::SeqCst);
27 }
28
29 configure_llvm(sess);
30 });
31
32 if POISONED.load(Ordering::SeqCst) {
33 bug!("couldn't enable multi-threaded LLVM");
34 }
35 }
36}
37
2c00a5a8
XL
38fn require_inited() {
39 INIT.call_once(|| bug!("llvm is not initialized"));
40 if POISONED.load(Ordering::SeqCst) {
41 bug!("couldn't enable multi-threaded LLVM");
42 }
43}
44
7cac9316 45unsafe fn configure_llvm(sess: &Session) {
0bf4aa26
XL
46 let n_args = sess.opts.cg.llvm_args.len();
47 let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
48 let mut llvm_args = Vec::with_capacity(n_args + 1);
49
50 llvm::LLVMRustInstallFatalErrorHandler();
7cac9316
XL
51
52 {
53 let mut add = |arg: &str| {
54 let s = CString::new(arg).unwrap();
55 llvm_args.push(s.as_ptr());
56 llvm_c_strs.push(s);
57 };
58 add("rustc"); // fake program name
59 if sess.time_llvm_passes() { add("-time-passes"); }
60 if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
0531ce1d
XL
61 if sess.opts.debugging_opts.disable_instrumentation_preinliner {
62 add("-disable-preinline");
63 }
a1dfa0c6 64 if llvm::LLVMRustIsRustLLVM() {
9fa01778
XL
65 match sess.opts.debugging_opts.merge_functions
66 .unwrap_or(sess.target.target.options.merge_functions) {
67 MergeFunctions::Disabled |
68 MergeFunctions::Trampolines => {}
69 MergeFunctions::Aliases => {
70 add("-mergefunc-use-aliases");
71 }
72 }
a1dfa0c6 73 }
7cac9316 74
0731742a
XL
75 // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
76 // during inlining. Unfortunately these may block other optimizations.
77 add("-preserve-alignment-assumptions-during-inlining=false");
78
7cac9316
XL
79 for arg in &sess.opts.cg.llvm_args {
80 add(&(*arg));
81 }
82 }
83
84 llvm::LLVMInitializePasses();
85
b7449926 86 ::rustc_llvm::initialize_available_targets();
7cac9316
XL
87
88 llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
89 llvm_args.as_ptr());
90}
91
0531ce1d
XL
92// WARNING: the features after applying `to_llvm_feature` must be known
93// to LLVM or the feature detection code will walk past the end of the feature
94// array, leading to crashes.
95
83c7162d 96const ARM_WHITELIST: &[(&str, Option<&str>)] = &[
b7449926 97 ("aclass", Some("arm_target_feature")),
8faf50e0
XL
98 ("mclass", Some("arm_target_feature")),
99 ("rclass", Some("arm_target_feature")),
100 ("dsp", Some("arm_target_feature")),
83c7162d 101 ("neon", Some("arm_target_feature")),
b7449926 102 ("v5te", Some("arm_target_feature")),
9fa01778 103 ("v6", Some("arm_target_feature")),
b7449926
XL
104 ("v6k", Some("arm_target_feature")),
105 ("v6t2", Some("arm_target_feature")),
83c7162d 106 ("v7", Some("arm_target_feature")),
9fa01778 107 ("v8", Some("arm_target_feature")),
83c7162d
XL
108 ("vfp2", Some("arm_target_feature")),
109 ("vfp3", Some("arm_target_feature")),
110 ("vfp4", Some("arm_target_feature")),
111];
112
113const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[
114 ("fp", Some("aarch64_target_feature")),
115 ("neon", Some("aarch64_target_feature")),
116 ("sve", Some("aarch64_target_feature")),
117 ("crc", Some("aarch64_target_feature")),
118 ("crypto", Some("aarch64_target_feature")),
119 ("ras", Some("aarch64_target_feature")),
120 ("lse", Some("aarch64_target_feature")),
121 ("rdm", Some("aarch64_target_feature")),
122 ("fp16", Some("aarch64_target_feature")),
123 ("rcpc", Some("aarch64_target_feature")),
124 ("dotprod", Some("aarch64_target_feature")),
125 ("v8.1a", Some("aarch64_target_feature")),
126 ("v8.2a", Some("aarch64_target_feature")),
127 ("v8.3a", Some("aarch64_target_feature")),
128];
129
130const X86_WHITELIST: &[(&str, Option<&str>)] = &[
0731742a 131 ("adx", Some("adx_target_feature")),
83c7162d
XL
132 ("aes", None),
133 ("avx", None),
134 ("avx2", None),
135 ("avx512bw", Some("avx512_target_feature")),
136 ("avx512cd", Some("avx512_target_feature")),
137 ("avx512dq", Some("avx512_target_feature")),
138 ("avx512er", Some("avx512_target_feature")),
139 ("avx512f", Some("avx512_target_feature")),
140 ("avx512ifma", Some("avx512_target_feature")),
141 ("avx512pf", Some("avx512_target_feature")),
142 ("avx512vbmi", Some("avx512_target_feature")),
143 ("avx512vl", Some("avx512_target_feature")),
144 ("avx512vpopcntdq", Some("avx512_target_feature")),
145 ("bmi1", None),
146 ("bmi2", None),
0731742a 147 ("cmpxchg16b", Some("cmpxchg16b_target_feature")),
83c7162d
XL
148 ("fma", None),
149 ("fxsr", None),
150 ("lzcnt", None),
151 ("mmx", Some("mmx_target_feature")),
9fa01778 152 ("movbe", Some("movbe_target_feature")),
83c7162d
XL
153 ("pclmulqdq", None),
154 ("popcnt", None),
155 ("rdrand", None),
156 ("rdseed", None),
157 ("sha", None),
158 ("sse", None),
159 ("sse2", None),
160 ("sse3", None),
161 ("sse4.1", None),
162 ("sse4.2", None),
163 ("sse4a", Some("sse4a_target_feature")),
164 ("ssse3", None),
165 ("tbm", Some("tbm_target_feature")),
166 ("xsave", None),
167 ("xsavec", None),
168 ("xsaveopt", None),
169 ("xsaves", None),
170];
171
172const HEXAGON_WHITELIST: &[(&str, Option<&str>)] = &[
173 ("hvx", Some("hexagon_target_feature")),
174 ("hvx-double", Some("hexagon_target_feature")),
175];
176
177const POWERPC_WHITELIST: &[(&str, Option<&str>)] = &[
178 ("altivec", Some("powerpc_target_feature")),
179 ("power8-altivec", Some("powerpc_target_feature")),
180 ("power9-altivec", Some("powerpc_target_feature")),
181 ("power8-vector", Some("powerpc_target_feature")),
182 ("power9-vector", Some("powerpc_target_feature")),
183 ("vsx", Some("powerpc_target_feature")),
184];
185
186const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[
187 ("fp64", Some("mips_target_feature")),
188 ("msa", Some("mips_target_feature")),
189];
0531ce1d 190
b7449926
XL
191const WASM_WHITELIST: &[(&str, Option<&str>)] = &[
192 ("simd128", Some("wasm_target_feature")),
193 ("atomics", Some("wasm_target_feature")),
194];
195
0531ce1d 196/// When rustdoc is running, provide a list of all known features so that all their respective
a1dfa0c6 197/// primitives may be documented.
0531ce1d
XL
198///
199/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
200/// iterator!
83c7162d 201pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<&'static str>)> {
0531ce1d
XL
202 ARM_WHITELIST.iter().cloned()
203 .chain(AARCH64_WHITELIST.iter().cloned())
204 .chain(X86_WHITELIST.iter().cloned())
205 .chain(HEXAGON_WHITELIST.iter().cloned())
206 .chain(POWERPC_WHITELIST.iter().cloned())
207 .chain(MIPS_WHITELIST.iter().cloned())
b7449926 208 .chain(WASM_WHITELIST.iter().cloned())
0531ce1d 209}
3b2f2976 210
0531ce1d
XL
211pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
212 let arch = if sess.target.target.arch == "x86_64" {
213 "x86"
214 } else {
215 &*sess.target.target.arch
216 };
217 match (arch, s) {
218 ("x86", "pclmulqdq") => "pclmul",
219 ("x86", "rdrand") => "rdrnd",
220 ("x86", "bmi1") => "bmi",
0731742a 221 ("x86", "cmpxchg16b") => "cx16",
83c7162d 222 ("aarch64", "fp") => "fp-armv8",
0531ce1d
XL
223 ("aarch64", "fp16") => "fullfp16",
224 (_, s) => s,
225 }
226}
ff7c6d11 227
7cac9316 228pub fn target_features(sess: &Session) -> Vec<Symbol> {
9fa01778 229 let target_machine = create_informational_target_machine(sess, true);
0531ce1d
XL
230 target_feature_whitelist(sess)
231 .iter()
83c7162d
XL
232 .filter_map(|&(feature, gate)| {
233 if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
234 Some(feature)
235 } else {
236 None
237 }
238 })
0531ce1d
XL
239 .filter(|feature| {
240 let llvm_feature = to_llvm_feature(sess, feature);
241 let cstr = CString::new(llvm_feature).unwrap();
242 unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
243 })
244 .map(|feature| Symbol::intern(feature)).collect()
2c00a5a8 245}
7cac9316 246
83c7162d
XL
247pub fn target_feature_whitelist(sess: &Session)
248 -> &'static [(&'static str, Option<&'static str>)]
249{
0531ce1d 250 match &*sess.target.target.arch {
7cac9316 251 "arm" => ARM_WHITELIST,
abe05a73 252 "aarch64" => AARCH64_WHITELIST,
7cac9316
XL
253 "x86" | "x86_64" => X86_WHITELIST,
254 "hexagon" => HEXAGON_WHITELIST,
ff7c6d11 255 "mips" | "mips64" => MIPS_WHITELIST,
3b2f2976 256 "powerpc" | "powerpc64" => POWERPC_WHITELIST,
a1dfa0c6
XL
257 // wasm32 on emscripten does not support these target features
258 "wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST,
7cac9316 259 _ => &[],
0531ce1d 260 }
7cac9316
XL
261}
262
263pub fn print_version() {
2c00a5a8 264 // Can be called without initializing LLVM
7cac9316
XL
265 unsafe {
266 println!("LLVM version: {}.{}",
267 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
268 }
269}
270
a1dfa0c6
XL
271pub fn get_major_version() -> u32 {
272 unsafe { llvm::LLVMRustVersionMajor() }
273}
274
7cac9316 275pub fn print_passes() {
2c00a5a8 276 // Can be called without initializing LLVM
7cac9316
XL
277 unsafe { llvm::LLVMRustPrintPasses(); }
278}
279
2c00a5a8
XL
280pub(crate) fn print(req: PrintRequest, sess: &Session) {
281 require_inited();
9fa01778 282 let tm = create_informational_target_machine(sess, true);
7cac9316
XL
283 unsafe {
284 match req {
285 PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
286 PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
94b46f34 287 _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
7cac9316
XL
288 }
289 }
290}
b7449926
XL
291
292pub fn target_cpu(sess: &Session) -> &str {
293 let name = match sess.opts.cg.target_cpu {
294 Some(ref s) => &**s,
295 None => &*sess.target.target.options.cpu
296 };
297 if name != "native" {
298 return name
299 }
300
301 unsafe {
302 let mut len = 0;
303 let ptr = llvm::LLVMRustGetHostCPUName(&mut len);
304 str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap()
305 }
306}