]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_llvm/attributes.rs
Clarify some methods around instance instantiation via comments and clearer names.
[rust.git] / src / librustc_codegen_llvm / attributes.rs
index 3f2a51b45bd0645fbf56f1b9ff0d0b30a6e5f422..fc1b365cf90ce57cfbeaf1a54a3d8ea83e0df4c8 100644 (file)
@@ -2,24 +2,24 @@
 
 use std::ffi::CString;
 
-use rustc::hir::CodegenFnAttrFlags;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc::session::config::{OptLevel, Sanitizer};
 use rustc::session::Session;
-use rustc::session::config::{Sanitizer, OptLevel};
-use rustc::ty::{self, TyCtxt, Ty};
 use rustc::ty::layout::HasTyCtxt;
 use rustc::ty::query::Providers;
-use rustc_data_structures::small_c_str::SmallCStr;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::const_cstr;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_target::abi::call::Conv;
-use rustc_data_structures::const_cstr;
 use rustc_target::spec::PanicStrategy;
-use rustc_codegen_ssa::traits::*;
 
 use crate::abi::FnAbi;
 use crate::attributes;
-use crate::llvm::{self, Attribute};
 use crate::llvm::AttributePlace::Function;
+use crate::llvm::{self, Attribute};
 use crate::llvm_util;
 pub use syntax::attr::{self, InlineAttr, OptimizeAttr};
 
 fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
     use self::InlineAttr::*;
     match inline {
-        Hint   => Attribute::InlineHint.apply_llfn(Function, val),
+        Hint => Attribute::InlineHint.apply_llfn(Function, val),
         Always => Attribute::AlwaysInline.apply_llfn(Function, val),
-        Never  => {
+        Never => {
             if cx.tcx().sess.target.target.arch != "amdgpu" {
                 Attribute::NoInline.apply_llfn(Function, val);
             }
-        },
-        None   => {
+        }
+        None => {
             Attribute::InlineHint.unapply_llfn(Function, val);
             Attribute::AlwaysInline.unapply_llfn(Function, val);
             Attribute::NoInline.unapply_llfn(Function, val);
-        },
+        }
     };
 }
 
@@ -66,9 +66,21 @@ fn naked(val: &'ll Value, is_naked: bool) {
 
 pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     if cx.sess().must_not_eliminate_frame_pointers() {
-        llvm::AddFunctionAttrStringValue(
-            llfn, llvm::AttributePlace::Function,
-            const_cstr!("no-frame-pointer-elim"), const_cstr!("true"));
+        if llvm_util::get_major_version() >= 8 {
+            llvm::AddFunctionAttrStringValue(
+                llfn,
+                llvm::AttributePlace::Function,
+                const_cstr!("frame-pointer"),
+                const_cstr!("all"),
+            );
+        } else {
+            llvm::AddFunctionAttrStringValue(
+                llfn,
+                llvm::AttributePlace::Function,
+                const_cstr!("no-frame-pointer-elim"),
+                const_cstr!("true"),
+            );
+        }
     }
 }
 
@@ -81,12 +93,16 @@ fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
 
         // The function name varies on platforms.
         // See test/CodeGen/mcount.c in clang.
-        let mcount_name = CString::new(
-            cx.sess().target.target.options.target_mcount.as_str().as_bytes()).unwrap();
+        let mcount_name =
+            CString::new(cx.sess().target.target.options.target_mcount.as_str().as_bytes())
+                .unwrap();
 
         llvm::AddFunctionAttrStringValue(
-            llfn, llvm::AttributePlace::Function,
-            const_cstr!("instrument-function-entry-inlined"), &mcount_name);
+            llfn,
+            llvm::AttributePlace::Function,
+            const_cstr!("instrument-function-entry-inlined"),
+            &mcount_name,
+        );
     }
 }
 
@@ -94,16 +110,15 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     // Only use stack probes if the target specification indicates that we
     // should be using stack probes
     if !cx.sess().target.target.options.stack_probes {
-        return
+        return;
     }
 
     // Currently stack probes seem somewhat incompatible with the address
     // sanitizer and thread sanitizer. With asan we're already protected from
     // stack overflow anyway so we don't really need stack probes regardless.
     match cx.sess().opts.debugging_opts.sanitizer {
-        Some(Sanitizer::Address) |
-        Some(Sanitizer::Thread) => return,
-        _ => {},
+        Some(Sanitizer::Address) | Some(Sanitizer::Thread) => return,
+        _ => {}
     }
 
     // probestack doesn't play nice either with `-C profile-generate`.
@@ -119,17 +134,16 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     // Flag our internal `__rust_probestack` function as the stack probe symbol.
     // This is defined in the `compiler-builtins` crate for each architecture.
     llvm::AddFunctionAttrStringValue(
-        llfn, llvm::AttributePlace::Function,
-        const_cstr!("probe-stack"), const_cstr!("__rust_probestack"));
+        llfn,
+        llvm::AttributePlace::Function,
+        const_cstr!("probe-stack"),
+        const_cstr!("__rust_probestack"),
+    );
 }
 
 fn translate_obsolete_target_features(feature: &str) -> &str {
-    const LLVM9_FEATURE_CHANGES: &[(&str, &str)] = &[
-        ("+fp-only-sp", "-fp64"),
-        ("-fp-only-sp", "+fp64"),
-        ("+d16", "-d32"),
-        ("-d16", "+d32"),
-    ];
+    const LLVM9_FEATURE_CHANGES: &[(&str, &str)] =
+        &[("+fp-only-sp", "-fp64"), ("-fp-only-sp", "+fp64"), ("+d16", "-d32"), ("-d16", "+d32")];
     if llvm_util::get_major_version() >= 9 {
         for &(old, new) in LLVM9_FEATURE_CHANGES {
             if feature == old {
@@ -147,13 +161,19 @@ fn translate_obsolete_target_features(feature: &str) -> &str {
 }
 
 pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
-    const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
-        "crt-static",
-    ];
+    const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
 
-    let cmdline = sess.opts.cg.target_feature.split(',')
+    let cmdline = sess
+        .opts
+        .cg
+        .target_feature
+        .split(',')
         .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)));
-    sess.target.target.options.features.split(',')
+    sess.target
+        .target
+        .options
+        .features
+        .split(',')
         .chain(cmdline)
         .filter(|l| !l.is_empty())
         .map(translate_obsolete_target_features)
@@ -162,10 +182,11 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
 pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess));
     llvm::AddFunctionAttrStringValue(
-            llfn,
-            llvm::AttributePlace::Function,
-            const_cstr!("target-cpu"),
-            target_cpu.as_c_str());
+        llfn,
+        llvm::AttributePlace::Function,
+        const_cstr!("target-cpu"),
+        target_cpu.as_c_str(),
+    );
 }
 
 /// Sets the `NonLazyBind` LLVM attribute on a given function,
@@ -183,7 +204,7 @@ pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) {
             llvm::Attribute::MinSize.unapply_llfn(Function, llfn);
             llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
             llvm::Attribute::OptimizeNone.unapply_llfn(Function, llfn);
-        },
+        }
         OptLevel::SizeMin => {
             llvm::Attribute::MinSize.apply_llfn(Function, llfn);
             llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
@@ -198,7 +219,6 @@ pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) {
     }
 }
 
-
 /// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
 /// attributes.
 pub fn from_fn_attrs(
@@ -226,7 +246,7 @@ pub fn from_fn_attrs(
     }
 
     // FIXME(eddyb) consolidate these two `inline` calls (and avoid overwrites).
-    if instance.def.is_inline(cx.tcx) {
+    if instance.def.requires_inline(cx.tcx) {
         inline(cx, llfn, attributes::InlineAttr::Hint);
     }
 
@@ -248,8 +268,7 @@ pub fn from_fn_attrs(
     //
     // You can also find more info on why Windows is whitelisted here in:
     //      https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
-    if !cx.sess().no_landing_pads() ||
-       cx.sess().target.target.options.requires_uwtable {
+    if !cx.sess().no_landing_pads() || cx.sess().target.target.options.requires_uwtable {
         attributes::emit_uwtable(llfn, true);
     }
 
@@ -267,46 +286,48 @@ pub fn from_fn_attrs(
         naked(llfn, true);
     }
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
-        Attribute::NoAlias.apply_llfn(
-            llvm::AttributePlace::ReturnValue, llfn);
+        Attribute::NoAlias.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
     }
 
-    unwind(llfn, if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind {
-        // In panic=abort mode we assume nothing can unwind anywhere, so
-        // optimize based on this!
-        false
-    } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
-        // If a specific #[unwind] attribute is present, use that.
-        true
-    } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
-        // Special attribute for allocator functions, which can't unwind.
-        false
-    } else {
-        if fn_abi.conv == Conv::Rust {
-            // Any Rust method (or `extern "Rust" fn` or `extern
-            // "rust-call" fn`) is explicitly allowed to unwind
-            // (unless it has no-unwind attribute, handled above).
+    unwind(
+        llfn,
+        if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind {
+            // In panic=abort mode we assume nothing can unwind anywhere, so
+            // optimize based on this!
+            false
+        } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
+            // If a specific #[unwind] attribute is present, use that.
             true
-        } else {
-            // Anything else is either:
-            //
-            //  1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
-            //
-            //  2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
-            //
-            // Foreign items (case 1) are assumed to not unwind; it is
-            // UB otherwise. (At least for now; see also
-            // rust-lang/rust#63909 and Rust RFC 2753.)
-            //
-            // Items defined in Rust with non-Rust ABIs (case 2) are also
-            // not supposed to unwind. Whether this should be enforced
-            // (versus stating it is UB) and *how* it would be enforced
-            // is currently under discussion; see rust-lang/rust#58794.
-            //
-            // In either case, we mark item as explicitly nounwind.
+        } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
+            // Special attribute for allocator functions, which can't unwind.
             false
-        }
-    });
+        } else {
+            if fn_abi.conv == Conv::Rust {
+                // Any Rust method (or `extern "Rust" fn` or `extern
+                // "rust-call" fn`) is explicitly allowed to unwind
+                // (unless it has no-unwind attribute, handled above).
+                true
+            } else {
+                // Anything else is either:
+                //
+                //  1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
+                //
+                //  2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
+                //
+                // Foreign items (case 1) are assumed to not unwind; it is
+                // UB otherwise. (At least for now; see also
+                // rust-lang/rust#63909 and Rust RFC 2753.)
+                //
+                // Items defined in Rust with non-Rust ABIs (case 2) are also
+                // not supposed to unwind. Whether this should be enforced
+                // (versus stating it is UB) and *how* it would be enforced
+                // is currently under discussion; see rust-lang/rust#58794.
+                //
+                // In either case, we mark item as explicitly nounwind.
+                false
+            }
+        },
+    );
 
     // Always annotate functions with the target-cpu they are compiled for.
     // Without this, ThinLTO won't inline Rust functions into Clang generated
@@ -315,22 +336,21 @@ pub fn from_fn_attrs(
 
     let features = llvm_target_features(cx.tcx.sess)
         .map(|s| s.to_string())
-        .chain(
-            codegen_fn_attrs.target_features
-                .iter()
-                .map(|f| {
-                    let feature = &f.as_str();
-                    format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
-                })
-        )
+        .chain(codegen_fn_attrs.target_features.iter().map(|f| {
+            let feature = &f.as_str();
+            format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+        }))
         .collect::<Vec<String>>()
         .join(",");
 
     if !features.is_empty() {
         let val = CString::new(features).unwrap();
         llvm::AddFunctionAttrStringValue(
-            llfn, llvm::AttributePlace::Function,
-            const_cstr!("target-features"), &val);
+            llfn,
+            llvm::AttributePlace::Function,
+            const_cstr!("target-features"),
+            &val,
+        );
     }
 
     // Note that currently the `wasm-import-module` doesn't do anything, but
@@ -345,9 +365,8 @@ pub fn from_fn_attrs(
                 &module,
             );
 
-            let name = codegen_fn_attrs.link_name.unwrap_or_else(|| {
-                cx.tcx.item_name(instance.def_id())
-            });
+            let name =
+                codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id()));
             let name = CString::new(&name.as_str()[..]).unwrap();
             llvm::AddFunctionAttrStringValue(
                 llfn,
@@ -365,14 +384,15 @@ pub fn provide(providers: &mut Providers<'_>) {
         if tcx.sess.opts.actually_rustdoc {
             // rustdoc needs to be able to document functions that use all the features, so
             // whitelist them all
-            tcx.arena.alloc(llvm_util::all_known_features()
-                .map(|(a, b)| (a.to_string(), b))
-                .collect())
+            tcx.arena
+                .alloc(llvm_util::all_known_features().map(|(a, b)| (a.to_string(), b)).collect())
         } else {
-            tcx.arena.alloc(llvm_util::target_feature_whitelist(tcx.sess)
-                .iter()
-                .map(|&(a, b)| (a.to_string(), b))
-                .collect())
+            tcx.arena.alloc(
+                llvm_util::target_feature_whitelist(tcx.sess)
+                    .iter()
+                    .map(|&(a, b)| (a.to_string(), b))
+                    .collect(),
+            )
         }
     };
 
@@ -386,15 +406,14 @@ pub fn provide_extern(providers: &mut Providers<'_>) {
         // `#[link(wasm_import_module = "...")]` for example.
         let native_libs = tcx.native_libraries(cnum);
 
-        let def_id_to_native_lib = native_libs.iter().filter_map(|lib|
-            lib.foreign_module.map(|id| (id, lib))
-        ).collect::<FxHashMap<_, _>>();
+        let def_id_to_native_lib = native_libs
+            .iter()
+            .filter_map(|lib| lib.foreign_module.map(|id| (id, lib)))
+            .collect::<FxHashMap<_, _>>();
 
         let mut ret = FxHashMap::default();
         for lib in tcx.foreign_modules(cnum).iter() {
-            let module = def_id_to_native_lib
-                .get(&lib.def_id)
-                .and_then(|s| s.wasm_import_module);
+            let module = def_id_to_native_lib.get(&lib.def_id).and_then(|s| s.wasm_import_module);
             let module = match module {
                 Some(s) => s,
                 None => continue,
@@ -410,7 +429,5 @@ pub fn provide_extern(providers: &mut Providers<'_>) {
 }
 
 fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<CString> {
-    tcx.wasm_import_module_map(id.krate)
-        .get(&id)
-        .map(|s| CString::new(&s[..]).unwrap())
+    tcx.wasm_import_module_map(id.krate).get(&id).map(|s| CString::new(&s[..]).unwrap())
 }