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

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

2
src/Cargo.lock generated
View File

@ -409,7 +409,6 @@ version = "0.0.0"
dependencies = [
"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",

View File

@ -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"

View File

@ -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)

View File

@ -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) {

View File

@ -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" }

View File

@ -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<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
///
@ -80,7 +167,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 {
@ -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);
}
}

View File

@ -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);
},
};
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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 @@ 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

View File

@ -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;

View File

@ -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());
}

View File

@ -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;