]> git.lizzy.rs Git - rust.git/commitdiff
Extract attribute handling code into a module
authorSimonas Kazlauskas <git@kazlauskas.me>
Sat, 28 Feb 2015 21:53:12 +0000 (23:53 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Fri, 3 Apr 2015 12:46:09 +0000 (15:46 +0300)
This commit causes no change in trans semantics, it just moves some functions around and
deduplicates them.

src/librustc_llvm/lib.rs
src/librustc_trans/trans/attributes.rs [new file with mode: 0644]
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/mod.rs
src/librustc_trans/trans/monomorphize.rs

index ae4687eac2fac75bd8bb6fd5ec8388f76a67ba90..3eaa354c5e6dad06129ae3e6d195e6cfb844c161 100644 (file)
@@ -157,7 +157,7 @@ pub enum DiagnosticSeverity {
 #[derive(Copy, Clone)]
 pub enum OtherAttribute {
     // The following are not really exposed in
-    // the LLVM c api so instead to add these
+    // the LLVM C api so instead to add these
     // we call a wrapper function in RustWrapper
     // that uses the C++ api.
     SanitizeAddressAttribute = 1 << 32,
@@ -958,6 +958,7 @@ pub fn LLVMGetOrInsertFunction(M: ModuleRef,
     pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
     pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
     pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
+    pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
 
     /* Operations on parameters */
     pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
new file mode 100644 (file)
index 0000000..7603442
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//! Set and unset common attributes on LLVM values.
+
+use llvm::{self, ValueRef, AttrHelper};
+use syntax::ast;
+use syntax::attr::InlineAttr;
+pub use syntax::attr::InlineAttr::*;
+use trans::context::CrateContext;
+
+use libc::{c_uint, c_ulonglong};
+
+/// Mark LLVM function to use split stack.
+#[inline]
+pub fn split_stack(val: ValueRef, set: bool) {
+    unsafe {
+        let attr = "split-stack\0".as_ptr() as *const _;
+        if set {
+            llvm::LLVMAddFunctionAttrString(val, llvm::FunctionIndex as c_uint, attr);
+        } else {
+            llvm::LLVMRemoveFunctionAttrString(val, llvm::FunctionIndex as c_uint, attr);
+        }
+    }
+}
+
+/// Mark LLVM function to use provided inline heuristic.
+#[inline]
+pub fn inline(val: ValueRef, inline: InlineAttr) {
+    match inline {
+        InlineHint   => llvm::SetFunctionAttribute(val, llvm::InlineHintAttribute),
+        InlineAlways => llvm::SetFunctionAttribute(val, llvm::AlwaysInlineAttribute),
+        InlineNever  => llvm::SetFunctionAttribute(val, llvm::NoInlineAttribute),
+        InlineNone   => {
+            let attr = llvm::InlineHintAttribute |
+                       llvm::AlwaysInlineAttribute |
+                       llvm::NoInlineAttribute;
+            unsafe {
+                llvm::LLVMRemoveFunctionAttr(val, attr.bits() as c_ulonglong)
+            }
+        },
+    };
+}
+
+/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
+#[inline]
+pub fn emit_uwtable(val: ValueRef, emit: bool) {
+    if emit {
+        llvm::SetFunctionAttribute(val, llvm::UWTableAttribute);
+    } else {
+        unsafe {
+            llvm::LLVMRemoveFunctionAttr(val, llvm::UWTableAttribute.bits() as c_ulonglong);
+        }
+    }
+}
+
+/// Tell LLVM whether the function can or cannot unwind.
+#[inline]
+#[allow(dead_code)] // possibly useful function
+pub fn unwind(val: ValueRef, can_unwind: bool) {
+    if can_unwind {
+        unsafe {
+            llvm::LLVMRemoveFunctionAttr(val, llvm::NoUnwindAttribute.bits() as c_ulonglong);
+        }
+    } else {
+        llvm::SetFunctionAttribute(val, llvm::NoUnwindAttribute);
+    }
+}
+
+/// Tell LLVM whether it should optimise function for size.
+#[inline]
+#[allow(dead_code)] // possibly useful function
+pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
+    if optimize {
+        llvm::SetFunctionAttribute(val, llvm::OptimizeForSizeAttribute);
+    } else {
+        unsafe {
+            llvm::LLVMRemoveFunctionAttr(val, llvm::OptimizeForSizeAttribute.bits() as c_ulonglong);
+        }
+    }
+}
+
+/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
+/// attributes.
+pub fn convert_fn_attrs_to_llvm(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
+    use syntax::attr::*;
+    inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
+
+    for attr in attrs {
+        if attr.check_name("no_stack_check") {
+            split_stack(llfn, false);
+        } else if attr.check_name("cold") {
+            unsafe {
+                llvm::LLVMAddFunctionAttribute(llfn,
+                                               llvm::FunctionIndex as c_uint,
+                                               llvm::ColdAttribute as u64)
+            }
+        } else if attr.check_name("allocator") {
+            llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
+        }
+    }
+}
index 321cd33bbeb2f76e0c46a153db3c0661600a4721..25750b6ec0e14171d03c9982b120ae6b500f7d9d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -7,21 +7,20 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
-// trans.rs: Translate the completed AST to the LLVM IR.
-//
-// Some functions here, such as trans_block and trans_expr, return a value --
-// the result of the translation to LLVM -- while others, such as trans_fn,
-// trans_impl, and trans_item, are called only for the side effect of adding a
-// particular definition to the LLVM IR output we're producing.
-//
-// Hopefully useful general knowledge about trans:
-//
-//   * There's no way to find out the Ty type of a ValueRef.  Doing so
-//     would be "trying to get the eggs out of an omelette" (credit:
-//     pcwalton).  You can, instead, find out its TypeRef by calling val_ty,
-//     but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int,
-//     int) and rec(x=int, y=int, z=int) will have the same TypeRef.
+//! Translate the completed AST to the LLVM IR.
+//!
+//! Some functions here, such as trans_block and trans_expr, return a value --
+//! the result of the translation to LLVM -- while others, such as trans_fn,
+//! trans_impl, and trans_item, are called only for the side effect of adding a
+//! particular definition to the LLVM IR output we're producing.
+//!
+//! Hopefully useful general knowledge about trans:
+//!
+//!   * There's no way to find out the Ty type of a ValueRef.  Doing so
+//!     would be "trying to get the eggs out of an omelette" (credit:
+//!     pcwalton).  You can, instead, find out its TypeRef by calling val_ty,
+//!     but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int,
+//!     int) and rec(x=int, y=int, z=int) will have the same TypeRef.
 
 #![allow(non_camel_case_types)]
 
@@ -33,7 +32,7 @@
 use back::link::mangle_exported_name;
 use back::{link, abi};
 use lint;
-use llvm::{AttrHelper, BasicBlockRef, Linkage, ValueRef, Vector, get_param};
+use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
 use llvm;
 use metadata::{csearch, encoder, loader};
 use middle::astencode;
@@ -46,6 +45,7 @@
 use session::Session;
 use trans::_match;
 use trans::adt;
+use trans::attributes;
 use trans::build::*;
 use trans::builder::{Builder, noname};
 use trans::callee;
@@ -204,7 +204,7 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
     llvm::SetUnnamedAddr(llfn, true);
 
     if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check {
-        set_split_stack(llfn);
+        attributes::split_stack(llfn, true);
     }
 
     llfn
@@ -245,7 +245,7 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
     let f = decl_rust_fn(ccx, fn_ty, name);
 
     let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
-    set_llvm_fn_attrs(ccx, &attrs[..], f);
+    attributes::convert_fn_attrs_to_llvm(ccx, &attrs[..], f);
 
     ccx.externs().borrow_mut().insert(name.to_string(), f);
     f
@@ -390,77 +390,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
 }
 
-#[allow(dead_code)] // useful
-pub fn set_optimize_for_size(f: ValueRef) {
-    llvm::SetFunctionAttribute(f, llvm::OptimizeForSizeAttribute)
-}
-
-pub fn set_no_inline(f: ValueRef) {
-    llvm::SetFunctionAttribute(f, llvm::NoInlineAttribute)
-}
-
-#[allow(dead_code)] // useful
-pub fn set_no_unwind(f: ValueRef) {
-    llvm::SetFunctionAttribute(f, llvm::NoUnwindAttribute)
-}
-
-// Tell LLVM to emit the information necessary to unwind the stack for the
-// function f.
-pub fn set_uwtable(f: ValueRef) {
-    llvm::SetFunctionAttribute(f, llvm::UWTableAttribute)
-}
-
-pub fn set_inline_hint(f: ValueRef) {
-    llvm::SetFunctionAttribute(f, llvm::InlineHintAttribute)
-}
-
-pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
-    use syntax::attr::{find_inline_attr, InlineAttr};
-    // Set the inline hint if there is one
-    match find_inline_attr(Some(ccx.sess().diagnostic()), attrs) {
-        InlineAttr::Hint   => set_inline_hint(llfn),
-        InlineAttr::Always => set_always_inline(llfn),
-        InlineAttr::Never  => set_no_inline(llfn),
-        InlineAttr::None   => { /* fallthrough */ }
-    }
-
-    for attr in attrs {
-        let mut used = true;
-        match &attr.name()[..] {
-            "no_stack_check" => unset_split_stack(llfn),
-            "cold" => unsafe {
-                llvm::LLVMAddFunctionAttribute(llfn,
-                                               llvm::FunctionIndex as c_uint,
-                                               llvm::ColdAttribute as uint64_t)
-            },
-            "allocator" => {
-                llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
-            }
-            _ => used = false,
-        }
-        if used {
-            attr::mark_used(attr);
-        }
-    }
-}
-
-pub fn set_always_inline(f: ValueRef) {
-    llvm::SetFunctionAttribute(f, llvm::AlwaysInlineAttribute)
-}
-
-pub fn set_split_stack(f: ValueRef) {
-    unsafe {
-        llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint,
-                                        "split-stack\0".as_ptr() as *const _);
-    }
-}
-
-pub fn unset_split_stack(f: ValueRef) {
-    unsafe {
-        llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint,
-                                           "split-stack\0".as_ptr() as *const _);
-    }
-}
 
 // Double-check that we never ask LLVM to declare the same symbol twice. It
 // silently mangles such symbols, breaking our linkage model.
@@ -898,7 +827,7 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 _ => {
                     let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, &name[..]);
                     let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
-                    set_llvm_fn_attrs(ccx, &attrs, llfn);
+                    attributes::convert_fn_attrs_to_llvm(ccx, &attrs, llfn);
                     llfn
                 }
             }
@@ -1708,7 +1637,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
 
     let _icx = push_ctxt("trans_closure");
-    set_uwtable(llfndecl);
+    attributes::emit_uwtable(llfndecl, true);
 
     debug!("trans_closure(..., param_substs={})",
            param_substs.repr(ccx.tcx()));
@@ -2312,7 +2241,7 @@ fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: String, node_id: ast::N
     // eh_personality functions need to be externally linkable.
     let def = ast_util::local_def(node_id);
     if ccx.tcx().lang_items.stack_exhausted() == Some(def) {
-        unset_split_stack(llfn);
+        attributes::split_stack(llfn, false);
         llvm::SetLinkage(llfn, llvm::ExternalLinkage);
     }
     if ccx.tcx().lang_items.eh_personality() == Some(def) {
@@ -2733,7 +2662,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                                                    sym,
                                                                    i.id)
                     };
-                    set_llvm_fn_attrs(ccx, &i.attrs, llfn);
+                    attributes::convert_fn_attrs_to_llvm(ccx, &i.attrs, llfn);
                     llfn
                 }
 
@@ -2794,7 +2723,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
                     let name = foreign::link_name(&*ni);
                     let llfn = foreign::register_foreign_item_fn(ccx, abi, ty, &name);
-                    set_llvm_fn_attrs(ccx, &ni.attrs, llfn);
+                    attributes::convert_fn_attrs_to_llvm(ccx, &ni.attrs, llfn);
                     llfn
                 }
                 ast::ForeignItemStatic(..) => {
@@ -2826,7 +2755,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                 }
                 _ => ccx.sess().bug("NodeVariant, shouldn't happen")
             };
-            set_inline_hint(llfn);
+            attributes::inline(llfn, attributes::InlineHint);
             llfn
         }
 
@@ -2848,7 +2777,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                     &struct_item.attrs);
             let llfn = register_fn(ccx, struct_item.span,
                                    sym, ctor_id, ty);
-            set_inline_hint(llfn);
+            attributes::inline(llfn, attributes::InlineHint);
             llfn
         }
 
@@ -2883,7 +2812,7 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId,
         } else {
             foreign::register_rust_fn_with_foreign_abi(ccx, span, sym, id)
         };
-        set_llvm_fn_attrs(ccx, &attrs, llfn);
+        attributes::convert_fn_attrs_to_llvm(ccx, &attrs, llfn);
         return llfn;
     } else {
         ccx.sess().span_bug(span, "expected bare rust function");
index c1aade3663e6e8f37ec7dde9f1547d95d961c546..e83ac8a5e0c9c56a78ccb2a14509112c1bd60691 100644 (file)
@@ -13,6 +13,7 @@
 use llvm::{ValueRef, get_param};
 use middle::mem_categorization::Typer;
 use trans::adt;
+use trans::attributes;
 use trans::base::*;
 use trans::build::*;
 use trans::callee::{self, ArgVals, Callee, TraitItem, MethodData};
@@ -164,7 +165,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
     let llfn = decl_internal_rust_fn(ccx, function_type, &symbol[..]);
 
     // set an inline hint for all closures
-    set_inline_hint(llfn);
+    attributes::inline(llfn, attributes::InlineHint);
 
     debug!("get_or_create_declaration_if_closure(): inserting new \
             closure {:?} (type {})",
index e154bc1d579ff6d3aded8695a2b4dacd12adfb3d..ce80c72b8478533dd63a1b187bbd00ab6eec1324 100644 (file)
@@ -13,6 +13,7 @@
 use llvm::{ValueRef, CallConv, get_param};
 use llvm;
 use middle::weak_lang_items;
+use trans::attributes;
 use trans::base::{llvm_linkage_by_name, push_ctxt};
 use trans::base;
 use trans::build::*;
@@ -612,7 +613,7 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                id, t.repr(tcx));
 
         let llfn = base::decl_internal_rust_fn(ccx, t, &ps[..]);
-        base::set_llvm_fn_attrs(ccx, attrs, llfn);
+        attributes::convert_fn_attrs_to_llvm(ccx, attrs, llfn);
         base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]);
         llfn
     }
index c7857d6a775f3f3163c81b191b5b5033f25b605e..0face6860dce533e9250e558c397f6de6b6f7812 100644 (file)
 #[macro_use]
 mod macros;
 
-mod inline;
-mod monomorphize;
-mod controlflow;
-mod glue;
-mod datum;
-mod callee;
-mod expr;
-mod common;
-mod context;
-mod consts;
-mod type_of;
+mod adt;
+mod asm;
+mod attributes;
+mod base;
+mod basic_block;
 mod build;
 mod builder;
-mod base;
-mod _match;
-mod closure;
-mod tvec;
-mod meth;
 mod cabi;
-mod cabi_x86;
-mod cabi_x86_64;
-mod cabi_x86_win64;
-mod cabi_arm;
 mod cabi_aarch64;
+mod cabi_arm;
 mod cabi_mips;
 mod cabi_powerpc;
+mod cabi_x86;
+mod cabi_x86_64;
+mod cabi_x86_win64;
+mod callee;
+mod cleanup;
+mod closure;
+mod common;
+mod consts;
+mod context;
+mod controlflow;
+mod datum;
+mod debuginfo;
+mod expr;
 mod foreign;
+mod glue;
+mod inline;
 mod intrinsic;
-mod debuginfo;
+mod llrepr;
 mod machine;
-mod adt;
-mod asm;
+mod _match;
+mod meth;
+mod monomorphize;
+mod tvec;
 mod type_;
+mod type_of;
 mod value;
-mod basic_block;
-mod llrepr;
-mod cleanup;
 
 #[derive(Copy, Clone)]
 pub struct ModuleTranslation {
index dcb21c5cd93b1459ba2a06d45b55088a8462e15d..fc08b1a107944cb8fd466522de4e9ec2127f6ce9 100644 (file)
@@ -17,7 +17,7 @@
 use middle::subst::{Subst, Substs};
 use middle::traits;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
-use trans::base::{set_llvm_fn_attrs, set_inline_hint};
+use trans::attributes;
 use trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use trans::base::{trans_fn, decl_internal_rust_fn};
 use trans::base;
@@ -151,7 +151,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     };
     let setup_lldecl = |lldecl, attrs: &[ast::Attribute]| {
         base::update_linkage(ccx, lldecl, None, base::OriginalTranslation);
-        set_llvm_fn_attrs(ccx, attrs, lldecl);
+        attributes::convert_fn_attrs_to_llvm(ccx, attrs, lldecl);
 
         let is_first = !ccx.available_monomorphizations().borrow().contains(&s);
         if is_first {
@@ -200,7 +200,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
             let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
             let d = mk_lldecl(abi::Rust);
-            set_inline_hint(d);
+            attributes::inline(d, attributes::InlineHint);
             match v.node.kind {
                 ast::TupleVariantKind(ref args) => {
                     trans_enum_variant(ccx,
@@ -259,7 +259,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
         ast_map::NodeStructCtor(struct_def) => {
             let d = mk_lldecl(abi::Rust);
-            set_inline_hint(d);
+            attributes::inline(d, attributes::InlineHint);
             base::trans_tuple_struct(ccx,
                                      &struct_def.fields,
                                      struct_def.ctor_id.expect("ast-mapped tuple struct \