Use llvm::Attribute API instead of "raw value" APIs, which will be removed in LLVM 4.0.

The librustc_llvm API remains mostly unchanged, except that llvm::Attribute is no longer a bitflag but represents only a *single* attribute.
The ability to store many attributes in a small number of bits and modify them without interacting with LLVM is only used in rustc_trans::abi and closely related modules, and only attributes for function arguments are considered there.
Thus rustc_trans::abi now has its own bit-packed representation of argument attributes, which are translated to rustc_llvm::Attribute when applying the attributes.
This commit is contained in:
Robin Kruppe 2016-11-16 23:36:08 +01:00
parent 5887ee5018
commit 30daedf603
13 changed files with 261 additions and 199 deletions

2
src/Cargo.lock generated
View File

@ -409,7 +409,6 @@ version = "0.0.0"
dependencies = [ dependencies = [
"build_helper 0.1.0", "build_helper 0.1.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_bitflags 0.0.0",
] ]
[[package]] [[package]]
@ -520,6 +519,7 @@ dependencies = [
"log 0.0.0", "log 0.0.0",
"rustc 0.0.0", "rustc 0.0.0",
"rustc_back 0.0.0", "rustc_back 0.0.0",
"rustc_bitflags 0.0.0",
"rustc_const_eval 0.0.0", "rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0", "rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0", "rustc_data_structures 0.0.0",

View File

@ -12,9 +12,6 @@ crate-type = ["dylib"]
[features] [features]
static-libstdcpp = [] static-libstdcpp = []
[dependencies]
rustc_bitflags = { path = "../librustc_bitflags" }
[build-dependencies] [build-dependencies]
build_helper = { path = "../build_helper" } build_helper = { path = "../build_helper" }
gcc = "0.3.27" gcc = "0.3.27"

View File

@ -82,59 +82,31 @@ pub enum DLLStorageClass {
DllExport = 2, // Function to be accessible from DLL. DllExport = 2, // Function to be accessible from DLL.
} }
bitflags! { /// Matches LLVMRustAttribute in rustllvm.h
#[derive(Default, Debug)] /// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
flags Attribute : u64 { /// though it is not ABI compatible (since it's a C++ enum)
const ZExt = 1 << 0, #[repr(C)]
const SExt = 1 << 1, #[derive(Copy, Clone, Debug)]
const NoReturn = 1 << 2, pub enum Attribute {
const InReg = 1 << 3, AlwaysInline = 0,
const StructRet = 1 << 4, ByVal = 1,
const NoUnwind = 1 << 5, Cold = 2,
const NoAlias = 1 << 6, InlineHint = 3,
const ByVal = 1 << 7, MinSize = 4,
const Nest = 1 << 8, Naked = 5,
const ReadNone = 1 << 9, NoAlias = 6,
const ReadOnly = 1 << 10, NoCapture = 7,
const NoInline = 1 << 11, NoInline = 8,
const AlwaysInline = 1 << 12, NonNull = 9,
const OptimizeForSize = 1 << 13, NoRedZone = 10,
const StackProtect = 1 << 14, NoReturn = 11,
const StackProtectReq = 1 << 15, NoUnwind = 12,
const NoCapture = 1 << 21, OptimizeForSize = 13,
const NoRedZone = 1 << 22, ReadOnly = 14,
const NoImplicitFloat = 1 << 23, SExt = 15,
const Naked = 1 << 24, StructRet = 16,
const InlineHint = 1 << 25, UWTable = 17,
const ReturnsTwice = 1 << 29, ZExt = 18,
const UWTable = 1 << 30,
const NonLazyBind = 1 << 31,
// Some of these are missing from the LLVM C API, the rest are
// present, but commented out, and preceded by the following warning:
// FIXME: These attributes are currently not included in the C API as
// a temporary measure until the API/ABI impact to the C API is understood
// and the path forward agreed upon.
const SanitizeAddress = 1 << 32,
const MinSize = 1 << 33,
const NoDuplicate = 1 << 34,
const StackProtectStrong = 1 << 35,
const SanitizeThread = 1 << 36,
const SanitizeMemory = 1 << 37,
const NoBuiltin = 1 << 38,
const Returned = 1 << 39,
const Cold = 1 << 40,
const Builtin = 1 << 41,
const OptimizeNone = 1 << 42,
const InAlloca = 1 << 43,
const NonNull = 1 << 44,
const JumpTable = 1 << 45,
const Convergent = 1 << 46,
const SafeStack = 1 << 47,
const NoRecurse = 1 << 48,
const InaccessibleMemOnly = 1 << 49,
const InaccessibleMemOrArgMemOnly = 1 << 50,
}
} }
/// LLVMIntPredicate /// LLVMIntPredicate
@ -422,6 +394,9 @@ pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
pub enum OperandBundleDef_opaque {} pub enum OperandBundleDef_opaque {}
pub type OperandBundleDefRef = *mut OperandBundleDef_opaque; pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;
#[allow(missing_copy_implementations)]
pub enum Attribute_opaque {}
pub type AttributeRef = *mut Attribute_opaque;
pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void); pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint); pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
@ -521,6 +496,9 @@ extern "C" {
/// See llvm::LLVMType::getContext. /// See llvm::LLVMType::getContext.
pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef; pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
/// See llvm::Value::getContext
pub fn LLVMRustGetValueContext(V: ValueRef) -> ContextRef;
// Operations on integer types // Operations on integer types
pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
@ -783,6 +761,8 @@ extern "C" {
Name: *const c_char) Name: *const c_char)
-> ValueRef; -> ValueRef;
pub fn LLVMRustCreateAttribute(C: ContextRef, kind: Attribute, val: u64) -> AttributeRef;
// Operations on functions // Operations on functions
pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef;
pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef; pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef;
@ -801,16 +781,12 @@ extern "C" {
pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char; pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char;
pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char); pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char);
pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64); pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64);
pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: u64); pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: AttributeRef);
pub fn LLVMRustAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef,
index: c_uint, index: c_uint,
Name: *const c_char, Name: *const c_char,
Value: *const c_char); Value: *const c_char);
pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: u64); pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: AttributeRef);
pub fn LLVMRustRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);
// Operations on parameters // Operations on parameters
pub fn LLVMCountParams(Fn: ValueRef) -> c_uint; pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
@ -821,9 +797,8 @@ extern "C" {
pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef; pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef; pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef; pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint); pub fn LLVMAddAttribute(Arg: ValueRef, attr: AttributeRef);
pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint); pub fn LLVMRemoveAttribute(Arg: ValueRef, attr: AttributeRef);
pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint); pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
// Operations on basic blocks // Operations on basic blocks
@ -867,7 +842,7 @@ extern "C" {
pub fn LLVMAddInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); pub fn LLVMAddInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint);
pub fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); pub fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint);
pub fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint, align: c_uint); pub fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint, align: c_uint);
pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, Val: u64); pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: AttributeRef);
pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64); pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64);
// Operations on call instructions (only) // Operations on call instructions (only)

View File

@ -29,12 +29,8 @@
#![feature(staged_api)] #![feature(staged_api)]
#![feature(linked_from)] #![feature(linked_from)]
#![feature(concat_idents)] #![feature(concat_idents)]
#![cfg_attr(not(stage0), feature(rustc_private))]
extern crate libc; extern crate libc;
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
pub use self::IntPredicate::*; pub use self::IntPredicate::*;
pub use self::RealPredicate::*; pub use self::RealPredicate::*;
@ -68,54 +64,6 @@ impl LLVMRustResult {
} }
} }
#[derive(Copy, Clone, Default, Debug)]
pub struct Attributes {
regular: Attribute,
dereferenceable_bytes: u64,
}
impl Attributes {
pub fn set(&mut self, attr: Attribute) -> &mut Self {
self.regular = self.regular | attr;
self
}
pub fn unset(&mut self, attr: Attribute) -> &mut Self {
self.regular = self.regular - attr;
self
}
pub fn set_dereferenceable(&mut self, bytes: u64) -> &mut Self {
self.dereferenceable_bytes = bytes;
self
}
pub fn unset_dereferenceable(&mut self) -> &mut Self {
self.dereferenceable_bytes = 0;
self
}
pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe {
self.regular.apply_llfn(idx, llfn);
if self.dereferenceable_bytes != 0 {
LLVMRustAddDereferenceableAttr(llfn, idx.as_uint(), self.dereferenceable_bytes);
}
}
}
pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
unsafe {
self.regular.apply_callsite(idx, callsite);
if self.dereferenceable_bytes != 0 {
LLVMRustAddDereferenceableCallSiteAttr(callsite,
idx.as_uint(),
self.dereferenceable_bytes);
}
}
}
}
pub fn AddFunctionAttrStringValue(llfn: ValueRef, pub fn AddFunctionAttrStringValue(llfn: ValueRef,
idx: AttributePlace, idx: AttributePlace,
attr: &'static str, attr: &'static str,
@ -140,7 +88,7 @@ impl AttributePlace {
AttributePlace::Argument(0) AttributePlace::Argument(0)
} }
fn as_uint(self) -> c_uint { pub fn as_uint(self) -> c_uint {
match self { match self {
AttributePlace::Function => !0, AttributePlace::Function => !0,
AttributePlace::Argument(i) => i, AttributePlace::Argument(i) => i,
@ -228,16 +176,20 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
} }
impl Attribute { impl Attribute {
fn as_object(&self, value: ValueRef) -> AttributeRef {
unsafe { LLVMRustCreateAttribute(LLVMRustGetValueContext(value), *self, 0) }
}
pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), self.bits()) } unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), self.as_object(llfn)) }
} }
pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), self.bits()) } unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), self.as_object(callsite)) }
} }
pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), self.bits()) } unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), self.as_object(llfn)) }
} }
pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) { pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {

View File

@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" }
log = { path = "../liblog" } log = { path = "../liblog" }
rustc = { path = "../librustc" } rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" } rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" }
rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" } rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" } rustc_data_structures = { path = "../librustc_data_structures" }

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use llvm::{self, ValueRef, Integer, Pointer, Float, Double, Struct, Array, Vector}; use llvm::{self, ValueRef, Integer, Pointer, Float, Double, Struct, Array, Vector, AttributePlace};
use base; use base;
use build::AllocaFcx; use build::AllocaFcx;
use common::{type_is_fat_ptr, BlockAndBuilder, C_uint}; use common::{type_is_fat_ptr, BlockAndBuilder, C_uint};
@ -49,6 +49,93 @@ enum ArgKind {
Ignore, Ignore,
} }
// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
// of this module
pub use self::attr_impl::ArgAttribute;
#[allow(non_upper_case_globals)]
mod attr_impl {
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
bitflags! {
#[derive(Default, Debug)]
flags ArgAttribute : u8 {
const ByVal = 1 << 0,
const NoAlias = 1 << 1,
const NoCapture = 1 << 2,
const NonNull = 1 << 3,
const ReadOnly = 1 << 4,
const SExt = 1 << 5,
const StructRet = 1 << 6,
const ZExt = 1 << 7,
}
}
}
macro_rules! for_each_kind {
($flags: ident, $f: ident, $($kind: ident),+) => ({
$(if $flags.contains(ArgAttribute::$kind) { $f(llvm::Attribute::$kind) })+
})
}
impl ArgAttribute {
fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
for_each_kind!(self, f,
ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt)
}
}
/// A compact representation of LLVM attributes (at least those relevant for this module)
/// that can be manipulated without interacting with LLVM's Attribute machinery.
#[derive(Copy, Clone, Debug, Default)]
pub struct ArgAttributes {
regular: ArgAttribute,
dereferenceable_bytes: u64,
}
impl ArgAttributes {
pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
self.regular = self.regular | attr;
self
}
pub fn unset(&mut self, attr: ArgAttribute) -> &mut Self {
self.regular = self.regular - attr;
self
}
pub fn set_dereferenceable(&mut self, bytes: u64) -> &mut Self {
self.dereferenceable_bytes = bytes;
self
}
pub fn unset_dereferenceable(&mut self) -> &mut Self {
self.dereferenceable_bytes = 0;
self
}
pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe {
self.regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
if self.dereferenceable_bytes != 0 {
llvm::LLVMRustAddDereferenceableAttr(llfn,
idx.as_uint(),
self.dereferenceable_bytes);
}
}
}
pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
unsafe {
self.regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
if self.dereferenceable_bytes != 0 {
llvm::LLVMRustAddDereferenceableCallSiteAttr(callsite,
idx.as_uint(),
self.dereferenceable_bytes);
}
}
}
}
/// Information about how a specific C type /// Information about how a specific C type
/// should be passed to or returned from a function /// should be passed to or returned from a function
/// ///
@ -80,7 +167,7 @@ pub struct ArgType {
/// Dummy argument, which is emitted before the real argument /// Dummy argument, which is emitted before the real argument
pub pad: Option<Type>, pub pad: Option<Type>,
/// LLVM attributes of argument /// LLVM attributes of argument
pub attrs: llvm::Attributes pub attrs: ArgAttributes
} }
impl ArgType { impl ArgType {
@ -92,7 +179,7 @@ impl ArgType {
signedness: None, signedness: None,
cast: None, cast: None,
pad: None, pad: None,
attrs: llvm::Attributes::default() attrs: ArgAttributes::default()
} }
} }
@ -100,15 +187,15 @@ impl ArgType {
assert_eq!(self.kind, ArgKind::Direct); assert_eq!(self.kind, ArgKind::Direct);
// Wipe old attributes, likely not valid through indirection. // Wipe old attributes, likely not valid through indirection.
self.attrs = llvm::Attributes::default(); self.attrs = ArgAttributes::default();
let llarg_sz = llsize_of_alloc(ccx, self.ty); let llarg_sz = llsize_of_alloc(ccx, self.ty);
// For non-immediate arguments the callee gets its own copy of // For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also // the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture // program-invisible so can't possibly capture
self.attrs.set(llvm::Attribute::NoAlias) self.attrs.set(ArgAttribute::NoAlias)
.set(llvm::Attribute::NoCapture) .set(ArgAttribute::NoCapture)
.set_dereferenceable(llarg_sz); .set_dereferenceable(llarg_sz);
self.kind = ArgKind::Indirect; self.kind = ArgKind::Indirect;
@ -124,9 +211,9 @@ impl ArgType {
if let Some(signed) = self.signedness { if let Some(signed) = self.signedness {
if self.ty.int_width() < bits { if self.ty.int_width() < bits {
self.attrs.set(if signed { self.attrs.set(if signed {
llvm::Attribute::SExt ArgAttribute::SExt
} else { } else {
llvm::Attribute::ZExt ArgAttribute::ZExt
}); });
} }
} }
@ -314,7 +401,7 @@ impl FnType {
if ty.is_bool() { if ty.is_bool() {
let llty = Type::i1(ccx); let llty = Type::i1(ccx);
let mut arg = ArgType::new(llty, llty); let mut arg = ArgType::new(llty, llty);
arg.attrs.set(llvm::Attribute::ZExt); arg.attrs.set(ArgAttribute::ZExt);
arg arg
} else { } else {
let mut arg = ArgType::new(type_of::type_of(ccx, ty), let mut arg = ArgType::new(type_of::type_of(ccx, ty),
@ -349,7 +436,7 @@ impl FnType {
if let ty::TyBox(_) = ret_ty.sty { if let ty::TyBox(_) = ret_ty.sty {
// `Box` pointer return values never alias because ownership // `Box` pointer return values never alias because ownership
// is transferred // is transferred
ret.attrs.set(llvm::Attribute::NoAlias); ret.attrs.set(ArgAttribute::NoAlias);
} }
// We can also mark the return value as `dereferenceable` in certain cases // We can also mark the return value as `dereferenceable` in certain cases
@ -371,7 +458,7 @@ impl FnType {
let rust_ptr_attrs = |ty: Ty<'tcx>, arg: &mut ArgType| match ty.sty { let rust_ptr_attrs = |ty: Ty<'tcx>, arg: &mut ArgType| match ty.sty {
// `Box` pointer parameters never alias because ownership is transferred // `Box` pointer parameters never alias because ownership is transferred
ty::TyBox(inner) => { ty::TyBox(inner) => {
arg.attrs.set(llvm::Attribute::NoAlias); arg.attrs.set(ArgAttribute::NoAlias);
Some(inner) Some(inner)
} }
@ -386,18 +473,18 @@ impl FnType {
let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe(); let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
if mt.mutbl != hir::MutMutable && !interior_unsafe { if mt.mutbl != hir::MutMutable && !interior_unsafe {
arg.attrs.set(llvm::Attribute::NoAlias); arg.attrs.set(ArgAttribute::NoAlias);
} }
if mt.mutbl == hir::MutImmutable && !interior_unsafe { if mt.mutbl == hir::MutImmutable && !interior_unsafe {
arg.attrs.set(llvm::Attribute::ReadOnly); arg.attrs.set(ArgAttribute::ReadOnly);
} }
// When a reference in an argument has no named lifetime, it's // When a reference in an argument has no named lifetime, it's
// impossible for that reference to escape this function // impossible for that reference to escape this function
// (returned or stored beyond the call by a closure). // (returned or stored beyond the call by a closure).
if let ReLateBound(_, BrAnon(_)) = *b { if let ReLateBound(_, BrAnon(_)) = *b {
arg.attrs.set(llvm::Attribute::NoCapture); arg.attrs.set(ArgAttribute::NoCapture);
} }
Some(mt.ty) Some(mt.ty)
@ -417,9 +504,9 @@ impl FnType {
let mut info = ArgType::new(original_tys[1], sizing_tys[1]); let mut info = ArgType::new(original_tys[1], sizing_tys[1]);
if let Some(inner) = rust_ptr_attrs(ty, &mut data) { if let Some(inner) = rust_ptr_attrs(ty, &mut data) {
data.attrs.set(llvm::Attribute::NonNull); data.attrs.set(ArgAttribute::NonNull);
if ccx.tcx().struct_tail(inner).is_trait() { if ccx.tcx().struct_tail(inner).is_trait() {
info.attrs.set(llvm::Attribute::NonNull); info.attrs.set(ArgAttribute::NonNull);
} }
} }
args.push(data); args.push(data);
@ -490,7 +577,7 @@ impl FnType {
fixup(arg); fixup(arg);
} }
if self.ret.is_indirect() { if self.ret.is_indirect() {
self.ret.attrs.set(llvm::Attribute::StructRet); self.ret.attrs.set(ArgAttribute::StructRet);
} }
return; return;
} }
@ -524,7 +611,7 @@ impl FnType {
} }
if self.ret.is_indirect() { if self.ret.is_indirect() {
self.ret.attrs.set(llvm::Attribute::StructRet); self.ret.attrs.set(ArgAttribute::StructRet);
} }
} }

View File

@ -24,10 +24,9 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
Always => Attribute::AlwaysInline.apply_llfn(Function, val), Always => Attribute::AlwaysInline.apply_llfn(Function, val),
Never => Attribute::NoInline.apply_llfn(Function, val), Never => Attribute::NoInline.apply_llfn(Function, val),
None => { None => {
let attr = Attribute::InlineHint | Attribute::InlineHint.unapply_llfn(Function, val);
Attribute::AlwaysInline | Attribute::AlwaysInline.unapply_llfn(Function, val);
Attribute::NoInline; Attribute::NoInline.unapply_llfn(Function, val);
attr.unapply_llfn(Function, val)
}, },
}; };
} }

View File

@ -10,8 +10,8 @@
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
use llvm::{Struct, Array, Attribute}; use llvm::{Struct, Array};
use abi::{FnType, ArgType}; use abi::{FnType, ArgType, ArgAttribute};
use context::CrateContext; use context::CrateContext;
// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128 // Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
@ -39,7 +39,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
if arg.ty.is_aggregate() { if arg.ty.is_aggregate() {
arg.make_indirect(ccx); arg.make_indirect(ccx);
arg.attrs.set(Attribute::ByVal); arg.attrs.set(ArgAttribute::ByVal);
} }
} }

View File

@ -9,7 +9,7 @@
// except according to those terms. // except according to those terms.
use llvm::*; use llvm::*;
use abi::FnType; use abi::{ArgAttribute, FnType};
use type_::Type; use type_::Type;
use super::common::*; use super::common::*;
use super::machine::*; use super::machine::*;
@ -45,7 +45,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
if arg.is_ignore() { continue; } if arg.is_ignore() { continue; }
if arg.ty.kind() == Struct { if arg.ty.kind() == Struct {
arg.make_indirect(ccx); arg.make_indirect(ccx);
arg.attrs.set(Attribute::ByVal); arg.attrs.set(ArgAttribute::ByVal);
} else { } else {
arg.extend_integer_width_to(32); arg.extend_integer_width_to(32);
} }

View File

@ -15,8 +15,8 @@
use self::RegClass::*; use self::RegClass::*;
use llvm::{Integer, Pointer, Float, Double}; use llvm::{Integer, Pointer, Float, Double};
use llvm::{Struct, Array, Attribute, Vector}; use llvm::{Struct, Array, Vector};
use abi::{self, ArgType, FnType}; use abi::{self, ArgType, ArgAttribute, FnType};
use context::CrateContext; use context::CrateContext;
use type_::Type; use type_::Type;
@ -334,7 +334,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
fn x86_64_ty<F>(ccx: &CrateContext, fn x86_64_ty<F>(ccx: &CrateContext,
arg: &mut ArgType, arg: &mut ArgType,
is_mem_cls: F, is_mem_cls: F,
ind_attr: Option<Attribute>) ind_attr: Option<ArgAttribute>)
where F: FnOnce(&[RegClass]) -> bool where F: FnOnce(&[RegClass]) -> bool
{ {
if !arg.ty.is_reg_ty() { if !arg.ty.is_reg_ty() {
@ -384,7 +384,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
sse_regs -= needed_sse; sse_regs -= needed_sse;
} }
in_mem in_mem
}, Some(Attribute::ByVal)); }, Some(ArgAttribute::ByVal));
// An integer, pointer, double or float parameter // An integer, pointer, double or float parameter
// thus the above closure passed to `x86_64_ty` won't // thus the above closure passed to `x86_64_ty` won't

View File

@ -23,6 +23,7 @@
html_root_url = "https://doc.rust-lang.org/nightly/")] html_root_url = "https://doc.rust-lang.org/nightly/")]
#![cfg_attr(not(stage0), deny(warnings))] #![cfg_attr(not(stage0), deny(warnings))]
#![feature(associated_consts)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(cell_extras)] #![feature(cell_extras)]
@ -55,6 +56,9 @@ extern crate rustc_platform_intrinsics as intrinsics;
extern crate serialize; extern crate serialize;
extern crate rustc_const_math; extern crate rustc_const_math;
extern crate rustc_const_eval; extern crate rustc_const_eval;
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
#[macro_use] extern crate log; #[macro_use] extern crate log;
#[macro_use] extern crate syntax; #[macro_use] extern crate syntax;

View File

@ -109,37 +109,84 @@ extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
return wrap(Type::getMetadataTy(*unwrap(C))); return wrap(Type::getMetadataTy(*unwrap(C)));
} }
extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) { static Attribute::AttrKind
from_rust(LLVMRustAttribute kind) {
switch (kind) {
case AlwaysInline:
return Attribute::AlwaysInline;
case ByVal:
return Attribute::ByVal;
case Cold:
return Attribute::Cold;
case InlineHint:
return Attribute::InlineHint;
case MinSize:
return Attribute::MinSize;
case Naked:
return Attribute::Naked;
case NoAlias:
return Attribute::NoAlias;
case NoCapture:
return Attribute::NoCapture;
case NoInline:
return Attribute::NoInline;
case NonNull:
return Attribute::NonNull;
case NoRedZone:
return Attribute::NoRedZone;
case NoReturn:
return Attribute::NoReturn;
case NoUnwind:
return Attribute::NoUnwind;
case OptimizeForSize:
return Attribute::OptimizeForSize;
case ReadOnly:
return Attribute::ReadOnly;
case SExt:
return Attribute::SExt;
case StructRet:
return Attribute::StructRet;
case UWTable:
return Attribute::UWTable;
case ZExt:
return Attribute::ZExt;
default:
llvm_unreachable("bad AttributeKind");
}
}
extern "C" LLVMAttributeRef LLVMRustCreateAttribute(LLVMContextRef C, LLVMRustAttribute Kind, uint64_t Val) {
return wrap(Attribute::get(*unwrap(C), from_rust(Kind), Val));
}
extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, LLVMAttributeRef attr) {
CallSite Call = CallSite(unwrap<Instruction>(Instr)); CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B; AttrBuilder B(unwrap(attr));
B.addRawValue(Val);
Call.setAttributes( Call.setAttributes(
Call.getAttributes().addAttributes(Call->getContext(), index, Call.getAttributes().addAttributes(Call->getContext(), index,
AttributeSet::get(Call->getContext(), AttributeSet::get(Call->getContext(),
index, B))); index, B)));
} }
extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
unsigned idx, unsigned index,
uint64_t b) uint64_t bytes)
{ {
CallSite Call = CallSite(unwrap<Instruction>(Instr)); CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B; AttrBuilder B;
B.addDereferenceableAttr(b); B.addDereferenceableAttr(bytes);
Call.setAttributes( Call.setAttributes(
Call.getAttributes().addAttributes(Call->getContext(), idx, Call.getAttributes().addAttributes(Call->getContext(), index,
AttributeSet::get(Call->getContext(), AttributeSet::get(Call->getContext(),
idx, B))); index, B)));
} }
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn,
unsigned index, unsigned index,
uint64_t Val) LLVMAttributeRef attr)
{ {
Function *A = unwrap<Function>(Fn); Function *A = unwrap<Function>(Fn);
AttrBuilder B; AttrBuilder B(unwrap(attr));
B.addRawValue(Val);
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
} }
@ -153,16 +200,6 @@ extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn,
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
} }
extern "C" void LLVMRustAddFunctionAttrString(LLVMValueRef Fn,
unsigned index,
const char *Name)
{
Function *F = unwrap<Function>(Fn);
AttrBuilder B;
B.addAttribute(Name);
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
unsigned index, unsigned index,
const char *Name, const char *Name,
@ -175,31 +212,15 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
unsigned index, unsigned index,
uint64_t Val) LLVMAttributeRef attr)
{ {
Function *A = unwrap<Function>(Fn); Function *F = unwrap<Function>(Fn);
const AttributeSet PAL = A->getAttributes(); const AttributeSet PAL = F->getAttributes();
AttrBuilder B(Val); AttrBuilder B(unwrap(attr));
const AttributeSet PALnew = const AttributeSet PALnew =
PAL.removeAttributes(A->getContext(), index, PAL.removeAttributes(F->getContext(), index,
AttributeSet::get(A->getContext(), index, B)); AttributeSet::get(F->getContext(), index, B));
A->setAttributes(PALnew); F->setAttributes(PALnew);
}
extern "C" void LLVMRustRemoveFunctionAttrString(LLVMValueRef fn,
unsigned index,
const char *Name)
{
Function *f = unwrap<Function>(fn);
LLVMContext &C = f->getContext();
AttrBuilder B;
B.addAttribute(Name);
AttributeSet to_remove = AttributeSet::get(C, index, B);
AttributeSet attrs = f->getAttributes();
f->setAttributes(attrs.removeAttributes(f->getContext(),
index,
to_remove));
} }
// enable fpmath flag UnsafeAlgebra // enable fpmath flag UnsafeAlgebra
@ -1293,3 +1314,7 @@ extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) { extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) {
LLVMSetLinkage(V, from_rust(RustLinkage)); LLVMSetLinkage(V, from_rust(RustLinkage));
} }
extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
return wrap(&unwrap(V)->getContext());
}

View File

@ -72,6 +72,28 @@ enum class LLVMRustResult {
Failure Failure
}; };
enum LLVMRustAttribute {
AlwaysInline = 0,
ByVal = 1,
Cold = 2,
InlineHint = 3,
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
NoReturn = 11,
NoUnwind = 12,
OptimizeForSize = 13,
ReadOnly = 14,
SExt = 15,
StructRet = 16,
UWTable = 17,
ZExt = 18,
};
typedef struct OpaqueRustString *RustStringRef; typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef; typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;