From 30daedf60355d105d92ad011b9e115b01350593e Mon Sep 17 00:00:00 2001 From: Robin Kruppe Date: Wed, 16 Nov 2016 23:36:08 +0100 Subject: [PATCH] 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. --- src/Cargo.lock | 2 +- src/librustc_llvm/Cargo.toml | 3 - src/librustc_llvm/ffi.rs | 101 +++++++++--------------- src/librustc_llvm/lib.rs | 64 ++-------------- src/librustc_trans/Cargo.toml | 1 + src/librustc_trans/abi.rs | 123 +++++++++++++++++++++++++----- src/librustc_trans/attributes.rs | 7 +- src/librustc_trans/cabi_asmjs.rs | 6 +- src/librustc_trans/cabi_x86.rs | 4 +- src/librustc_trans/cabi_x86_64.rs | 8 +- src/librustc_trans/lib.rs | 4 + src/rustllvm/RustWrapper.cpp | 115 +++++++++++++++++----------- src/rustllvm/rustllvm.h | 22 ++++++ 13 files changed, 261 insertions(+), 199 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index ee38a043b12..4e5f0b2a3ec 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -409,7 +409,6 @@ version = "0.0.0" dependencies = [ "build_helper 0.1.0", "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_bitflags 0.0.0", ] [[package]] @@ -520,6 +519,7 @@ dependencies = [ "log 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", + "rustc_bitflags 0.0.0", "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index f97daa22ff6..88f8c0553ad 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -12,9 +12,6 @@ crate-type = ["dylib"] [features] static-libstdcpp = [] -[dependencies] -rustc_bitflags = { path = "../librustc_bitflags" } - [build-dependencies] build_helper = { path = "../build_helper" } gcc = "0.3.27" diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 78a9d67ed77..f64bd6626b7 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -82,59 +82,31 @@ pub enum DLLStorageClass { DllExport = 2, // Function to be accessible from DLL. } -bitflags! { - #[derive(Default, Debug)] - flags Attribute : u64 { - const ZExt = 1 << 0, - const SExt = 1 << 1, - const NoReturn = 1 << 2, - const InReg = 1 << 3, - const StructRet = 1 << 4, - const NoUnwind = 1 << 5, - const NoAlias = 1 << 6, - const ByVal = 1 << 7, - const Nest = 1 << 8, - const ReadNone = 1 << 9, - const ReadOnly = 1 << 10, - const NoInline = 1 << 11, - const AlwaysInline = 1 << 12, - const OptimizeForSize = 1 << 13, - const StackProtect = 1 << 14, - const StackProtectReq = 1 << 15, - const NoCapture = 1 << 21, - const NoRedZone = 1 << 22, - const NoImplicitFloat = 1 << 23, - const Naked = 1 << 24, - const InlineHint = 1 << 25, - const ReturnsTwice = 1 << 29, - 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, - } +/// Matches LLVMRustAttribute in rustllvm.h +/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, +/// though it is not ABI compatible (since it's a C++ enum) +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub enum Attribute { + 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, } /// LLVMIntPredicate @@ -422,6 +394,9 @@ pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque; #[allow(missing_copy_implementations)] pub enum 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 InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint); @@ -521,6 +496,9 @@ extern "C" { /// See llvm::LLVMType::getContext. pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef; + /// See llvm::Value::getContext + pub fn LLVMRustGetValueContext(V: ValueRef) -> ContextRef; + // Operations on integer types pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; @@ -783,6 +761,8 @@ extern "C" { Name: *const c_char) -> ValueRef; + pub fn LLVMRustCreateAttribute(C: ContextRef, kind: Attribute, val: u64) -> AttributeRef; + // Operations on functions pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> 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 LLVMSetGC(Fn: ValueRef, Name: *const c_char); pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: u64); - pub fn LLVMRustAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char); + pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: AttributeRef); pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint, Name: *const c_char, Value: *const c_char); - pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: u64); - 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); + pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: AttributeRef); // Operations on parameters pub fn LLVMCountParams(Fn: ValueRef) -> c_uint; @@ -821,9 +797,8 @@ extern "C" { pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef; pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef; pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef; - pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint); - pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint); - pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint; + pub fn LLVMAddAttribute(Arg: ValueRef, attr: AttributeRef); + pub fn LLVMRemoveAttribute(Arg: ValueRef, attr: AttributeRef); pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint); // Operations on basic blocks @@ -867,7 +842,7 @@ extern "C" { pub fn LLVMAddInstrAttribute(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 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); // Operations on call instructions (only) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 07b87072c43..32d9d9a3efc 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -29,12 +29,8 @@ #![feature(staged_api)] #![feature(linked_from)] #![feature(concat_idents)] -#![cfg_attr(not(stage0), feature(rustc_private))] extern crate libc; -#[macro_use] -#[no_link] -extern crate rustc_bitflags; pub use self::IntPredicate::*; 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, idx: AttributePlace, attr: &'static str, @@ -140,7 +88,7 @@ impl AttributePlace { AttributePlace::Argument(0) } - fn as_uint(self) -> c_uint { + pub fn as_uint(self) -> c_uint { match self { AttributePlace::Function => !0, AttributePlace::Argument(i) => i, @@ -228,16 +176,20 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) { } impl Attribute { + fn as_object(&self, value: ValueRef) -> AttributeRef { + unsafe { LLVMRustCreateAttribute(LLVMRustGetValueContext(value), *self, 0) } + } + 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) { - 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) { - 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) { diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 38f9e7ab0c5..796a80d0809 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_bitflags = { path = "../librustc_bitflags" } rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 0a5b013c79a..16d3fc1b904 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // 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 build::AllocaFcx; use common::{type_is_fat_ptr, BlockAndBuilder, C_uint}; @@ -49,6 +49,93 @@ enum ArgKind { 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(&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 /// 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 pub pad: Option, /// LLVM attributes of argument - pub attrs: llvm::Attributes + pub attrs: ArgAttributes } impl ArgType { @@ -92,7 +179,7 @@ impl ArgType { signedness: None, cast: None, pad: None, - attrs: llvm::Attributes::default() + attrs: ArgAttributes::default() } } @@ -100,15 +187,15 @@ impl ArgType { assert_eq!(self.kind, ArgKind::Direct); // 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); // For non-immediate arguments the callee gets its own copy of // the value on the stack, so there are no aliases. It's also // program-invisible so can't possibly capture - self.attrs.set(llvm::Attribute::NoAlias) - .set(llvm::Attribute::NoCapture) + self.attrs.set(ArgAttribute::NoAlias) + .set(ArgAttribute::NoCapture) .set_dereferenceable(llarg_sz); self.kind = ArgKind::Indirect; @@ -124,9 +211,9 @@ impl ArgType { if let Some(signed) = self.signedness { if self.ty.int_width() < bits { self.attrs.set(if signed { - llvm::Attribute::SExt + ArgAttribute::SExt } else { - llvm::Attribute::ZExt + ArgAttribute::ZExt }); } } @@ -314,7 +401,7 @@ impl FnType { if ty.is_bool() { let llty = Type::i1(ccx); let mut arg = ArgType::new(llty, llty); - arg.attrs.set(llvm::Attribute::ZExt); + arg.attrs.set(ArgAttribute::ZExt); arg } else { let mut arg = ArgType::new(type_of::type_of(ccx, ty), @@ -349,7 +436,7 @@ impl FnType { if let ty::TyBox(_) = ret_ty.sty { // `Box` pointer return values never alias because ownership // 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 @@ -371,7 +458,7 @@ impl FnType { let rust_ptr_attrs = |ty: Ty<'tcx>, arg: &mut ArgType| match ty.sty { // `Box` pointer parameters never alias because ownership is transferred ty::TyBox(inner) => { - arg.attrs.set(llvm::Attribute::NoAlias); + arg.attrs.set(ArgAttribute::NoAlias); Some(inner) } @@ -386,18 +473,18 @@ impl FnType { let interior_unsafe = mt.ty.type_contents(ccx.tcx()).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 { - arg.attrs.set(llvm::Attribute::ReadOnly); + arg.attrs.set(ArgAttribute::ReadOnly); } // When a reference in an argument has no named lifetime, it's // impossible for that reference to escape this function // (returned or stored beyond the call by a closure). if let ReLateBound(_, BrAnon(_)) = *b { - arg.attrs.set(llvm::Attribute::NoCapture); + arg.attrs.set(ArgAttribute::NoCapture); } Some(mt.ty) @@ -417,9 +504,9 @@ impl FnType { let mut info = ArgType::new(original_tys[1], sizing_tys[1]); 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() { - info.attrs.set(llvm::Attribute::NonNull); + info.attrs.set(ArgAttribute::NonNull); } } args.push(data); @@ -490,7 +577,7 @@ impl FnType { fixup(arg); } if self.ret.is_indirect() { - self.ret.attrs.set(llvm::Attribute::StructRet); + self.ret.attrs.set(ArgAttribute::StructRet); } return; } @@ -524,7 +611,7 @@ impl FnType { } if self.ret.is_indirect() { - self.ret.attrs.set(llvm::Attribute::StructRet); + self.ret.attrs.set(ArgAttribute::StructRet); } } diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index 62eac35e0ab..f1e90419a49 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -24,10 +24,9 @@ pub fn inline(val: ValueRef, inline: InlineAttr) { Always => Attribute::AlwaysInline.apply_llfn(Function, val), Never => Attribute::NoInline.apply_llfn(Function, val), None => { - let attr = Attribute::InlineHint | - Attribute::AlwaysInline | - Attribute::NoInline; - attr.unapply_llfn(Function, val) + Attribute::InlineHint.unapply_llfn(Function, val); + Attribute::AlwaysInline.unapply_llfn(Function, val); + Attribute::NoInline.unapply_llfn(Function, val); }, }; } diff --git a/src/librustc_trans/cabi_asmjs.rs b/src/librustc_trans/cabi_asmjs.rs index 3cbc378ab02..f410627400c 100644 --- a/src/librustc_trans/cabi_asmjs.rs +++ b/src/librustc_trans/cabi_asmjs.rs @@ -10,8 +10,8 @@ #![allow(non_upper_case_globals)] -use llvm::{Struct, Array, Attribute}; -use abi::{FnType, ArgType}; +use llvm::{Struct, Array}; +use abi::{FnType, ArgType, ArgAttribute}; use context::CrateContext; // 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) { if arg.ty.is_aggregate() { arg.make_indirect(ccx); - arg.attrs.set(Attribute::ByVal); + arg.attrs.set(ArgAttribute::ByVal); } } diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_trans/cabi_x86.rs index b52231fa6b4..5377b49a2b4 100644 --- a/src/librustc_trans/cabi_x86.rs +++ b/src/librustc_trans/cabi_x86.rs @@ -9,7 +9,7 @@ // except according to those terms. use llvm::*; -use abi::FnType; +use abi::{ArgAttribute, FnType}; use type_::Type; use super::common::*; use super::machine::*; @@ -45,7 +45,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { if arg.is_ignore() { continue; } if arg.ty.kind() == Struct { arg.make_indirect(ccx); - arg.attrs.set(Attribute::ByVal); + arg.attrs.set(ArgAttribute::ByVal); } else { arg.extend_integer_width_to(32); } diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index 33990148c8b..7f2fdbf000b 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -15,8 +15,8 @@ use self::RegClass::*; use llvm::{Integer, Pointer, Float, Double}; -use llvm::{Struct, Array, Attribute, Vector}; -use abi::{self, ArgType, FnType}; +use llvm::{Struct, Array, Vector}; +use abi::{self, ArgType, ArgAttribute, FnType}; use context::CrateContext; use type_::Type; @@ -334,7 +334,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { fn x86_64_ty(ccx: &CrateContext, arg: &mut ArgType, is_mem_cls: F, - ind_attr: Option) + ind_attr: Option) where F: FnOnce(&[RegClass]) -> bool { if !arg.ty.is_reg_ty() { @@ -384,7 +384,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { sse_regs -= needed_sse; } in_mem - }, Some(Attribute::ByVal)); + }, Some(ArgAttribute::ByVal)); // An integer, pointer, double or float parameter // thus the above closure passed to `x86_64_ty` won't diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 0757343a8af..f2c828c2f1f 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -23,6 +23,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![cfg_attr(not(stage0), deny(warnings))] +#![feature(associated_consts)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(cell_extras)] @@ -55,6 +56,9 @@ extern crate rustc_platform_intrinsics as intrinsics; extern crate serialize; extern crate rustc_const_math; extern crate rustc_const_eval; +#[macro_use] +#[no_link] +extern crate rustc_bitflags; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 369388caa04..7f0c7e2e5c9 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -109,37 +109,84 @@ extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef 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(Instr)); - AttrBuilder B; - B.addRawValue(Val); + AttrBuilder B(unwrap(attr)); Call.setAttributes( Call.getAttributes().addAttributes(Call->getContext(), index, AttributeSet::get(Call->getContext(), index, B))); } - extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, - unsigned idx, - uint64_t b) + unsigned index, + uint64_t bytes) { CallSite Call = CallSite(unwrap(Instr)); AttrBuilder B; - B.addDereferenceableAttr(b); + B.addDereferenceableAttr(bytes); Call.setAttributes( - Call.getAttributes().addAttributes(Call->getContext(), idx, + Call.getAttributes().addAttributes(Call->getContext(), index, AttributeSet::get(Call->getContext(), - idx, B))); + index, B))); } extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned index, - uint64_t Val) + LLVMAttributeRef attr) { Function *A = unwrap(Fn); - AttrBuilder B; - B.addRawValue(Val); + AttrBuilder B(unwrap(attr)); 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)); } -extern "C" void LLVMRustAddFunctionAttrString(LLVMValueRef Fn, - unsigned index, - const char *Name) -{ - Function *F = unwrap(Fn); - AttrBuilder B; - B.addAttribute(Name); - F->addAttributes(index, AttributeSet::get(F->getContext(), index, B)); -} - extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index, const char *Name, @@ -175,31 +212,15 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, unsigned index, - uint64_t Val) + LLVMAttributeRef attr) { - Function *A = unwrap(Fn); - const AttributeSet PAL = A->getAttributes(); - AttrBuilder B(Val); + Function *F = unwrap(Fn); + const AttributeSet PAL = F->getAttributes(); + AttrBuilder B(unwrap(attr)); const AttributeSet PALnew = - PAL.removeAttributes(A->getContext(), index, - AttributeSet::get(A->getContext(), index, B)); - A->setAttributes(PALnew); -} - -extern "C" void LLVMRustRemoveFunctionAttrString(LLVMValueRef fn, - unsigned index, - const char *Name) -{ - Function *f = unwrap(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)); + PAL.removeAttributes(F->getContext(), index, + AttributeSet::get(F->getContext(), index, B)); + F->setAttributes(PALnew); } // enable fpmath flag UnsafeAlgebra @@ -1293,3 +1314,7 @@ extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) { extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) { LLVMSetLinkage(V, from_rust(RustLinkage)); } + +extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) { + return wrap(&unwrap(V)->getContext()); +} diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index ffe94d1e22f..346153d578c 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -72,6 +72,28 @@ enum class LLVMRustResult { 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 LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;