提交 c71970ee 编写于 作者: S Simonas Kazlauskas

Extract attribute handling code into a module

This commit causes no change in trans semantics, it just moves some functions around and
deduplicates them.
上级 d36c4db9
......@@ -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;
......
// 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);
}
}
}
// 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");
......
......@@ -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 {})",
......
......@@ -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
}
......
......@@ -19,43 +19,44 @@
#[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 {
......
......@@ -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 \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册