Auto merge of #37831 - rkruppe:llvm-attr-fwdcompat, r=eddyb
[LLVM 4.0] Use llvm::Attribute APIs instead of "raw value" APIs
The latter will be removed in LLVM 4.0 (see 4a6fc8bacf
).
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.
cc #37609
This commit is contained in:
commit
0bd2ce62b2
2
src/Cargo.lock
generated
2
src/Cargo.lock
generated
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -145,6 +145,9 @@ fn main() {
|
||||
cfg.flag("-DLLVM_RUSTLLVM");
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed=../rustllvm/PassWrapper.cpp");
|
||||
println!("cargo:rerun-if-changed=../rustllvm/RustWrapper.cpp");
|
||||
println!("cargo:rerun-if-changed=../rustllvm/ArchiveWrapper.cpp");
|
||||
cfg.file("../rustllvm/PassWrapper.cpp")
|
||||
.file("../rustllvm/RustWrapper.cpp")
|
||||
.file("../rustllvm/ArchiveWrapper.cpp")
|
||||
|
@ -83,59 +83,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
|
||||
@ -423,6 +395,9 @@ pub enum 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);
|
||||
@ -530,6 +505,9 @@ pub enum DIDescriptorFlags {
|
||||
/// 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;
|
||||
@ -792,6 +770,8 @@ pub fn LLVMAddAlias(M: ModuleRef,
|
||||
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;
|
||||
@ -810,16 +790,12 @@ pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
|
||||
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;
|
||||
@ -830,9 +806,8 @@ pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef,
|
||||
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
|
||||
@ -876,7 +851,7 @@ pub fn LLVMInsertBasicBlockInContext(C: ContextRef,
|
||||
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)
|
||||
|
@ -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 @@ pub fn into_result(self) -> Result<(), ()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 @@ pub fn ReturnValue() -> Self {
|
||||
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) {
|
||||
|
@ -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" }
|
||||
|
@ -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};
|
||||
@ -50,6 +50,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<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
|
||||
/// should be passed to or returned from a function
|
||||
///
|
||||
@ -81,7 +168,7 @@ pub struct ArgType {
|
||||
/// Dummy argument, which is emitted before the real argument
|
||||
pub pad: Option<Type>,
|
||||
/// LLVM attributes of argument
|
||||
pub attrs: llvm::Attributes
|
||||
pub attrs: ArgAttributes
|
||||
}
|
||||
|
||||
impl ArgType {
|
||||
@ -93,7 +180,7 @@ fn new(original_ty: Type, ty: Type) -> ArgType {
|
||||
signedness: None,
|
||||
cast: None,
|
||||
pad: None,
|
||||
attrs: llvm::Attributes::default()
|
||||
attrs: ArgAttributes::default()
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,15 +188,15 @@ pub fn make_indirect(&mut self, ccx: &CrateContext) {
|
||||
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;
|
||||
@ -125,9 +212,9 @@ pub fn extend_integer_width_to(&mut self, bits: u64) {
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -315,7 +402,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
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),
|
||||
@ -350,7 +437,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
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
|
||||
@ -372,7 +459,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
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)
|
||||
}
|
||||
|
||||
@ -387,18 +474,18 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
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)
|
||||
@ -418,9 +505,9 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
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);
|
||||
@ -491,7 +578,7 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
|
||||
fixup(arg);
|
||||
}
|
||||
if self.ret.is_indirect() {
|
||||
self.ret.attrs.set(llvm::Attribute::StructRet);
|
||||
self.ret.attrs.set(ArgAttribute::StructRet);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -526,7 +613,7 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
|
||||
}
|
||||
|
||||
if self.ret.is_indirect() {
|
||||
self.ret.attrs.set(llvm::Attribute::StructRet);
|
||||
self.ret.attrs.set(ArgAttribute::StructRet);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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<F>(ccx: &CrateContext,
|
||||
arg: &mut ArgType,
|
||||
is_mem_cls: F,
|
||||
ind_attr: Option<Attribute>)
|
||||
ind_attr: Option<ArgAttribute>)
|
||||
where F: FnOnce(&[RegClass]) -> bool
|
||||
{
|
||||
if !arg.ty.is_reg_ty() {
|
||||
@ -384,7 +384,7 @@ fn x86_64_ty<F>(ccx: &CrateContext,
|
||||
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
|
||||
|
@ -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 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;
|
||||
|
@ -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<Instruction>(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<Instruction>(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<Function>(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<Function>(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<Function>(Fn);
|
||||
const AttributeSet PAL = A->getAttributes();
|
||||
AttrBuilder B(Val);
|
||||
Function *F = unwrap<Function>(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<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));
|
||||
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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user