1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use syntax_pos
::symbol
::Symbol
;
12 use back
::write
::create_target_machine
;
14 use rustc
::session
::Session
;
15 use rustc
::session
::config
::PrintRequest
;
16 use libc
::{c_int, c_char}
;
17 use std
::ffi
::CString
;
19 use std
::sync
::atomic
::{AtomicBool, Ordering}
;
22 pub fn init(sess
: &Session
) {
24 // Before we touch LLVM, make sure that multithreading is enabled.
25 static POISONED
: AtomicBool
= AtomicBool
::new(false);
26 static INIT
: Once
= Once
::new();
28 if llvm
::LLVMStartMultithreaded() != 1 {
29 // use an extra bool to make sure that all future usage of LLVM
30 // cannot proceed despite the Once not running more than once.
31 POISONED
.store(true, Ordering
::SeqCst
);
37 if POISONED
.load(Ordering
::SeqCst
) {
38 bug
!("couldn't enable multi-threaded LLVM");
43 unsafe fn configure_llvm(sess
: &Session
) {
44 let mut llvm_c_strs
= Vec
::new();
45 let mut llvm_args
= Vec
::new();
48 let mut add
= |arg
: &str| {
49 let s
= CString
::new(arg
).unwrap();
50 llvm_args
.push(s
.as_ptr());
53 add("rustc"); // fake program name
54 if sess
.time_llvm_passes() { add("-time-passes"); }
55 if sess
.print_llvm_passes() { add("-debug-pass=Structure"); }
57 for arg
in &sess
.opts
.cg
.llvm_args
{
62 llvm
::LLVMInitializePasses();
64 llvm
::initialize_available_targets();
66 llvm
::LLVMRustSetLLVMOptions(llvm_args
.len() as c_int
,
70 // WARNING: the features must be known to LLVM or the feature
71 // detection code will walk past the end of the feature array,
72 // leading to crashes.
74 const ARM_WHITELIST
: &'
static [&'
static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];
76 const X86_WHITELIST
: &'
static [&'
static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
77 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
78 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
79 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
81 const HEXAGON_WHITELIST
: &'
static [&'
static str] = &["hvx\0", "hvx-double\0"];
83 const POWERPC_WHITELIST
: &'
static [&'
static str] = &["altivec\0",
84 "power8-altivec\0", "power9-altivec\0",
85 "power8-vector\0", "power9-vector\0",
88 pub fn target_features(sess
: &Session
) -> Vec
<Symbol
> {
89 let target_machine
= create_target_machine(sess
);
91 let whitelist
= match &*sess
.target
.target
.arch
{
92 "arm" => ARM_WHITELIST
,
93 "x86" | "x86_64" => X86_WHITELIST
,
94 "hexagon" => HEXAGON_WHITELIST
,
95 "powerpc" | "powerpc64" => POWERPC_WHITELIST
,
99 let mut features
= Vec
::new();
100 for feat
in whitelist
{
101 assert_eq
!(feat
.chars().last(), Some('
\0'
));
102 if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) }
{
103 features
.push(Symbol
::intern(&feat
[..feat
.len() - 1]));
109 pub fn print_version() {
111 println
!("LLVM version: {}.{}",
112 llvm
::LLVMRustVersionMajor(), llvm
::LLVMRustVersionMinor());
116 pub fn print_passes() {
117 unsafe { llvm::LLVMRustPrintPasses(); }
120 pub fn print(req
: PrintRequest
, sess
: &Session
) {
121 let tm
= create_target_machine(sess
);
124 PrintRequest
::TargetCPUs
=> llvm
::LLVMRustPrintTargetCPUs(tm
),
125 PrintRequest
::TargetFeatures
=> llvm
::LLVMRustPrintTargetFeatures(tm
),
126 _
=> bug
!("rustc_trans can't handle print request: {:?}", req
),
131 pub fn enable_llvm_debug() {
132 unsafe { llvm::LLVMRustSetDebug(1); }