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:
parent
5887ee5018
commit
30daedf603
2
src/Cargo.lock
generated
2
src/Cargo.lock
generated
@ -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",
|
||||||
|
@ -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"
|
||||||
|
@ -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)
|
||||||
|
@ -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) {
|
||||||
|
@ -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" }
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user