1 use crate::back
::write
::create_informational_target_machine
;
3 use syntax_pos
::symbol
::Symbol
;
4 use rustc
::session
::Session
;
5 use rustc
::session
::config
::PrintRequest
;
6 use rustc_target
::spec
::{MergeFunctions, PanicStrategy}
;
9 use rustc_feature
::UnstableFeatures
;
10 use syntax
::symbol
::sym
;
15 use std
::sync
::atomic
::{AtomicBool, Ordering}
;
18 static POISONED
: AtomicBool
= AtomicBool
::new(false);
19 static INIT
: Once
= Once
::new();
21 pub(crate) fn init(sess
: &Session
) {
23 // Before we touch LLVM, make sure that multithreading is enabled.
25 if llvm
::LLVMStartMultithreaded() != 1 {
26 // use an extra bool to make sure that all future usage of LLVM
27 // cannot proceed despite the Once not running more than once.
28 POISONED
.store(true, Ordering
::SeqCst
);
34 if POISONED
.load(Ordering
::SeqCst
) {
35 bug
!("couldn't enable multi-threaded LLVM");
41 INIT
.call_once(|| bug
!("llvm is not initialized"));
42 if POISONED
.load(Ordering
::SeqCst
) {
43 bug
!("couldn't enable multi-threaded LLVM");
47 unsafe fn configure_llvm(sess
: &Session
) {
48 let n_args
= sess
.opts
.cg
.llvm_args
.len();
49 let mut llvm_c_strs
= Vec
::with_capacity(n_args
+ 1);
50 let mut llvm_args
= Vec
::with_capacity(n_args
+ 1);
52 llvm
::LLVMRustInstallFatalErrorHandler();
55 let mut add
= |arg
: &str| {
56 let s
= CString
::new(arg
).unwrap();
57 llvm_args
.push(s
.as_ptr());
60 add("rustc"); // fake program name
61 if sess
.time_llvm_passes() { add("-time-passes"); }
62 if sess
.print_llvm_passes() { add("-debug-pass=Structure"); }
63 if sess
.opts
.debugging_opts
.disable_instrumentation_preinliner
{
64 add("-disable-preinline");
66 if sess
.opts
.debugging_opts
.generate_arange_section
{
67 add("-generate-arange-section");
69 if get_major_version() >= 8 {
70 match sess
.opts
.debugging_opts
.merge_functions
71 .unwrap_or(sess
.target
.target
.options
.merge_functions
) {
72 MergeFunctions
::Disabled
|
73 MergeFunctions
::Trampolines
=> {}
74 MergeFunctions
::Aliases
=> {
75 add("-mergefunc-use-aliases");
80 if sess
.target
.target
.target_os
== "emscripten" &&
81 sess
.panic_strategy() == PanicStrategy
::Unwind
{
82 add("-enable-emscripten-cxx-exceptions");
85 // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
86 // during inlining. Unfortunately these may block other optimizations.
87 add("-preserve-alignment-assumptions-during-inlining=false");
89 for arg
in &sess
.opts
.cg
.llvm_args
{
94 llvm
::LLVMInitializePasses();
96 ::rustc_llvm
::initialize_available_targets();
98 llvm
::LLVMRustSetLLVMOptions(llvm_args
.len() as c_int
,
102 // WARNING: the features after applying `to_llvm_feature` must be known
103 // to LLVM or the feature detection code will walk past the end of the feature
104 // array, leading to crashes.
106 const ARM_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
107 ("aclass", Some(sym
::arm_target_feature
)),
108 ("mclass", Some(sym
::arm_target_feature
)),
109 ("rclass", Some(sym
::arm_target_feature
)),
110 ("dsp", Some(sym
::arm_target_feature
)),
111 ("neon", Some(sym
::arm_target_feature
)),
112 ("crc", Some(sym
::arm_target_feature
)),
113 ("crypto", Some(sym
::arm_target_feature
)),
114 ("v5te", Some(sym
::arm_target_feature
)),
115 ("v6", Some(sym
::arm_target_feature
)),
116 ("v6k", Some(sym
::arm_target_feature
)),
117 ("v6t2", Some(sym
::arm_target_feature
)),
118 ("v7", Some(sym
::arm_target_feature
)),
119 ("v8", Some(sym
::arm_target_feature
)),
120 ("vfp2", Some(sym
::arm_target_feature
)),
121 ("vfp3", Some(sym
::arm_target_feature
)),
122 ("vfp4", Some(sym
::arm_target_feature
)),
125 const AARCH64_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
126 ("fp", Some(sym
::aarch64_target_feature
)),
127 ("neon", Some(sym
::aarch64_target_feature
)),
128 ("sve", Some(sym
::aarch64_target_feature
)),
129 ("crc", Some(sym
::aarch64_target_feature
)),
130 ("crypto", Some(sym
::aarch64_target_feature
)),
131 ("ras", Some(sym
::aarch64_target_feature
)),
132 ("lse", Some(sym
::aarch64_target_feature
)),
133 ("rdm", Some(sym
::aarch64_target_feature
)),
134 ("fp16", Some(sym
::aarch64_target_feature
)),
135 ("rcpc", Some(sym
::aarch64_target_feature
)),
136 ("dotprod", Some(sym
::aarch64_target_feature
)),
137 ("v8.1a", Some(sym
::aarch64_target_feature
)),
138 ("v8.2a", Some(sym
::aarch64_target_feature
)),
139 ("v8.3a", Some(sym
::aarch64_target_feature
)),
142 const X86_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
143 ("adx", Some(sym
::adx_target_feature
)),
147 ("avx512bw", Some(sym
::avx512_target_feature
)),
148 ("avx512cd", Some(sym
::avx512_target_feature
)),
149 ("avx512dq", Some(sym
::avx512_target_feature
)),
150 ("avx512er", Some(sym
::avx512_target_feature
)),
151 ("avx512f", Some(sym
::avx512_target_feature
)),
152 ("avx512ifma", Some(sym
::avx512_target_feature
)),
153 ("avx512pf", Some(sym
::avx512_target_feature
)),
154 ("avx512vbmi", Some(sym
::avx512_target_feature
)),
155 ("avx512vl", Some(sym
::avx512_target_feature
)),
156 ("avx512vpopcntdq", Some(sym
::avx512_target_feature
)),
159 ("cmpxchg16b", Some(sym
::cmpxchg16b_target_feature
)),
160 ("f16c", Some(sym
::f16c_target_feature
)),
164 ("mmx", Some(sym
::mmx_target_feature
)),
165 ("movbe", Some(sym
::movbe_target_feature
)),
170 ("rtm", Some(sym
::rtm_target_feature
)),
177 ("sse4a", Some(sym
::sse4a_target_feature
)),
179 ("tbm", Some(sym
::tbm_target_feature
)),
186 const HEXAGON_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
187 ("hvx", Some(sym
::hexagon_target_feature
)),
188 ("hvx-length128b", Some(sym
::hexagon_target_feature
)),
191 const POWERPC_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
192 ("altivec", Some(sym
::powerpc_target_feature
)),
193 ("power8-altivec", Some(sym
::powerpc_target_feature
)),
194 ("power9-altivec", Some(sym
::powerpc_target_feature
)),
195 ("power8-vector", Some(sym
::powerpc_target_feature
)),
196 ("power9-vector", Some(sym
::powerpc_target_feature
)),
197 ("vsx", Some(sym
::powerpc_target_feature
)),
200 const MIPS_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
201 ("fp64", Some(sym
::mips_target_feature
)),
202 ("msa", Some(sym
::mips_target_feature
)),
205 const WASM_WHITELIST
: &[(&str, Option
<Symbol
>)] = &[
206 ("simd128", Some(sym
::wasm_target_feature
)),
207 ("atomics", Some(sym
::wasm_target_feature
)),
210 /// When rustdoc is running, provide a list of all known features so that all their respective
211 /// primitives may be documented.
213 /// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
215 pub fn all_known_features() -> impl Iterator
<Item
=(&'
static str, Option
<Symbol
>)> {
216 ARM_WHITELIST
.iter().cloned()
217 .chain(AARCH64_WHITELIST
.iter().cloned())
218 .chain(X86_WHITELIST
.iter().cloned())
219 .chain(HEXAGON_WHITELIST
.iter().cloned())
220 .chain(POWERPC_WHITELIST
.iter().cloned())
221 .chain(MIPS_WHITELIST
.iter().cloned())
222 .chain(WASM_WHITELIST
.iter().cloned())
225 pub fn to_llvm_feature
<'a
>(sess
: &Session
, s
: &'a
str) -> &'a
str {
226 let arch
= if sess
.target
.target
.arch
== "x86_64" {
229 &*sess
.target
.target
.arch
232 ("x86", "pclmulqdq") => "pclmul",
233 ("x86", "rdrand") => "rdrnd",
234 ("x86", "bmi1") => "bmi",
235 ("x86", "cmpxchg16b") => "cx16",
236 ("aarch64", "fp") => "fp-armv8",
237 ("aarch64", "fp16") => "fullfp16",
242 pub fn target_features(sess
: &Session
) -> Vec
<Symbol
> {
243 let target_machine
= create_informational_target_machine(sess
, true);
244 target_feature_whitelist(sess
)
246 .filter_map(|&(feature
, gate
)| {
247 if UnstableFeatures
::from_environment().is_nightly_build() || gate
.is_none() {
254 let llvm_feature
= to_llvm_feature(sess
, feature
);
255 let cstr
= CString
::new(llvm_feature
).unwrap();
256 unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
258 .map(|feature
| Symbol
::intern(feature
)).collect()
261 pub fn target_feature_whitelist(sess
: &Session
)
262 -> &'
static [(&'
static str, Option
<Symbol
>)]
264 match &*sess
.target
.target
.arch
{
265 "arm" => ARM_WHITELIST
,
266 "aarch64" => AARCH64_WHITELIST
,
267 "x86" | "x86_64" => X86_WHITELIST
,
268 "hexagon" => HEXAGON_WHITELIST
,
269 "mips" | "mips64" => MIPS_WHITELIST
,
270 "powerpc" | "powerpc64" => POWERPC_WHITELIST
,
271 "wasm32" => WASM_WHITELIST
,
276 pub fn print_version() {
277 // Can be called without initializing LLVM
279 println
!("LLVM version: {}.{}",
280 llvm
::LLVMRustVersionMajor(), llvm
::LLVMRustVersionMinor());
284 pub fn get_major_version() -> u32 {
285 unsafe { llvm::LLVMRustVersionMajor() }
288 pub fn print_passes() {
289 // Can be called without initializing LLVM
290 unsafe { llvm::LLVMRustPrintPasses(); }
293 pub(crate) fn print(req
: PrintRequest
, sess
: &Session
) {
295 let tm
= create_informational_target_machine(sess
, true);
298 PrintRequest
::TargetCPUs
=> llvm
::LLVMRustPrintTargetCPUs(tm
),
299 PrintRequest
::TargetFeatures
=> llvm
::LLVMRustPrintTargetFeatures(tm
),
300 _
=> bug
!("rustc_codegen_llvm can't handle print request: {:?}", req
),
305 pub fn target_cpu(sess
: &Session
) -> &str {
306 let name
= match sess
.opts
.cg
.target_cpu
{
308 None
=> &*sess
.target
.target
.options
.cpu
310 if name
!= "native" {
316 let ptr
= llvm
::LLVMRustGetHostCPUName(&mut len
);
317 str::from_utf8(slice
::from_raw_parts(ptr
as *const u8, len
)).unwrap()