rustc_llvm: An AttrBuilder that's not completely wasteful.

This commit is contained in:
Eduard Burtescu 2016-02-25 19:08:10 +02:00
parent 763b6cba37
commit c7172a9935
3 changed files with 114 additions and 103 deletions

View file

@ -33,8 +33,6 @@
extern crate libc;
#[macro_use] #[no_link] extern crate rustc_bitflags;
pub use self::OtherAttribute::*;
pub use self::SpecialAttribute::*;
pub use self::AttributeSet::*;
pub use self::IntPredicate::*;
pub use self::RealPredicate::*;
@ -133,7 +131,7 @@ pub enum DLLStorageClassTypes {
}
bitflags! {
#[derive(Debug)]
#[derive(Default, Debug)]
flags Attribute : u64 {
const ZExt = 1 << 0,
const SExt = 1 << 1,
@ -165,31 +163,74 @@ bitflags! {
// 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;
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,
}
}
#[derive(Copy, Clone)]
pub enum SpecialAttribute {
DereferenceableAttribute(u64)
#[derive(Copy, Clone, Default)]
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: c_uint, llfn: ValueRef) {
unsafe {
LLVMAddFunctionAttribute(llfn, idx, self.regular.bits());
if self.dereferenceable_bytes != 0 {
LLVMAddDereferenceableAttr(llfn, idx,
self.dereferenceable_bytes);
}
}
}
pub fn apply_callsite(&self, idx: c_uint, callsite: ValueRef) {
unsafe {
LLVMAddCallSiteAttribute(callsite, idx, self.regular.bits());
if self.dereferenceable_bytes != 0 {
LLVMAddDereferenceableCallSiteAttr(callsite, idx,
self.dereferenceable_bytes);
}
}
}
}
#[repr(C)]
@ -199,45 +240,8 @@ pub enum AttributeSet {
FunctionIndex = !0
}
pub trait AttrHelper {
fn apply_llfn(&self, idx: c_uint, llfn: ValueRef);
fn apply_callsite(&self, idx: c_uint, callsite: ValueRef);
}
impl AttrHelper for Attribute {
fn apply_llfn(&self, idx: c_uint, llfn: ValueRef) {
unsafe {
LLVMAddFunctionAttribute(llfn, idx, self.bits() as uint64_t);
}
}
fn apply_callsite(&self, idx: c_uint, callsite: ValueRef) {
unsafe {
LLVMAddCallSiteAttribute(callsite, idx, self.bits() as uint64_t);
}
}
}
impl AttrHelper for SpecialAttribute {
fn apply_llfn(&self, idx: c_uint, llfn: ValueRef) {
match *self {
DereferenceableAttribute(bytes) => unsafe {
LLVMAddDereferenceableAttr(llfn, idx, bytes as uint64_t);
}
}
}
fn apply_callsite(&self, idx: c_uint, callsite: ValueRef) {
match *self {
DereferenceableAttribute(bytes) => unsafe {
LLVMAddDereferenceableCallSiteAttr(callsite, idx, bytes as uint64_t);
}
}
}
}
pub struct AttrBuilder {
attrs: Vec<(usize, Box<AttrHelper+'static>)>
attrs: Vec<(usize, Attributes)>
}
impl AttrBuilder {
@ -247,14 +251,23 @@ impl AttrBuilder {
}
}
pub fn arg<T: AttrHelper + 'static>(&mut self, idx: usize, a: T) -> &mut AttrBuilder {
self.attrs.push((idx, box a as Box<AttrHelper+'static>));
self
pub fn arg(&mut self, idx: usize) -> &mut Attributes {
let mut found = None;
for (i, &(idx2, _)) in self.attrs.iter().enumerate() {
if idx == idx2 {
found = Some(i);
break;
}
}
let i = found.unwrap_or_else(|| {
self.attrs.push((idx, Attributes::default()));
self.attrs.len() - 1
});
&mut self.attrs[i].1
}
pub fn ret<T: AttrHelper + 'static>(&mut self, a: T) -> &mut AttrBuilder {
self.attrs.push((ReturnIndex as usize, box a as Box<AttrHelper+'static>));
self
pub fn ret(&mut self) -> &mut Attributes {
self.arg(ReturnIndex as usize)
}
pub fn apply_llfn(&self, llfn: ValueRef) {