Skip to content

Commit

Permalink
Fixed rust-lang#97
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDan64 committed Jul 28, 2019
1 parent f203922 commit f13d42f
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 110 deletions.
25 changes: 25 additions & 0 deletions src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,28 @@ impl Attribute {
}
}
}

/// An `AttributeLoc` determines where on a function an attribute is assigned to.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum AttributeLoc {
/// Assign to the `FunctionValue`'s return type.
Return,
/// Assign to one of the `FunctionValue`'s params (0-indexed).
Param(u32),
/// Assign to the `FunctionValue` itself.
Function,
}

impl AttributeLoc {
pub(crate) fn get_index(&self) -> u32 {
match self {
AttributeLoc::Return => 0,
AttributeLoc::Param(index) => {
assert!(*index <= u32::max_value() - 2, "Param index must be <= u32::max_value() - 2");

index + 1
},
AttributeLoc::Function => u32::max_value(),
}
}
}
78 changes: 43 additions & 35 deletions src/values/call_site_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use llvm_sys::core::{LLVMIsTailCall, LLVMSetTailCall, LLVMGetTypeKind, LLVMTypeO
use llvm_sys::prelude::LLVMValueRef;

#[llvm_versions(3.9..=latest)]
use crate::attributes::Attribute;
use crate::attributes::{Attribute, AttributeLoc};
use crate::support::LLVMString;
use crate::values::{AsValueRef, BasicValueEnum, InstructionValue, Value};
#[llvm_versions(3.9..=latest)]
Expand Down Expand Up @@ -112,6 +112,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -128,15 +129,15 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.add_attribute(0, string_attribute);
/// call_site_value.add_attribute(0, enum_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
/// ```
#[llvm_versions(3.9..=latest)]
pub fn add_attribute(&self, index: u32, attribute: Attribute) {
pub fn add_attribute(&self, loc: AttributeLoc, attribute: Attribute) {
use llvm_sys::core::LLVMAddCallSiteAttribute;

unsafe {
LLVMAddCallSiteAttribute(self.as_value_ref(), index, attribute.attribute)
LLVMAddCallSiteAttribute(self.as_value_ref(), loc.get_index(), attribute.attribute)
}
}

Expand Down Expand Up @@ -179,6 +180,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -195,17 +197,17 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.add_attribute(0, string_attribute);
/// call_site_value.add_attribute(0, enum_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
///
/// assert_eq!(call_site_value.count_attributes(0), 2);
/// assert_eq!(call_site_value.count_attributes(AttributeLoc::Return), 2);
/// ```
#[llvm_versions(3.9..=latest)]
pub fn count_attributes(&self, index: u32) -> u32 {
pub fn count_attributes(&self, loc: AttributeLoc) -> u32 {
use llvm_sys::core::LLVMGetCallSiteAttributeCount;

unsafe {
LLVMGetCallSiteAttributeCount(self.as_value_ref(), index)
LLVMGetCallSiteAttributeCount(self.as_value_ref(), loc.get_index())
}
}

Expand All @@ -214,6 +216,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -230,18 +233,18 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.add_attribute(0, string_attribute);
/// call_site_value.add_attribute(0, enum_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
///
/// assert_eq!(call_site_value.get_enum_attribute(0, 1).unwrap(), enum_attribute);
/// assert_eq!(call_site_value.get_enum_attribute(AttributeLoc::Return, 1).unwrap(), enum_attribute);
/// ```
// SubTypes: -> Attribute<Enum>
#[llvm_versions(3.9..=latest)]
pub fn get_enum_attribute(&self, index: u32, kind_id: u32) -> Option<Attribute> {
pub fn get_enum_attribute(&self, loc: AttributeLoc, kind_id: u32) -> Option<Attribute> {
use llvm_sys::core::LLVMGetCallSiteEnumAttribute;

let ptr = unsafe {
LLVMGetCallSiteEnumAttribute(self.as_value_ref(), index, kind_id)
LLVMGetCallSiteEnumAttribute(self.as_value_ref(), loc.get_index(), kind_id)
};

if ptr.is_null() {
Expand All @@ -256,6 +259,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -272,18 +276,18 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.add_attribute(0, string_attribute);
/// call_site_value.add_attribute(0, enum_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
///
/// assert_eq!(call_site_value.get_string_attribute(0, "my_key").unwrap(), string_attribute);
/// assert_eq!(call_site_value.get_string_attribute(AttributeLoc::Return, "my_key").unwrap(), string_attribute);
/// ```
// SubTypes: -> Attribute<String>
#[llvm_versions(3.9..=latest)]
pub fn get_string_attribute(&self, index: u32, key: &str) -> Option<Attribute> {
pub fn get_string_attribute(&self, loc: AttributeLoc, key: &str) -> Option<Attribute> {
use llvm_sys::core::LLVMGetCallSiteStringAttribute;

let ptr = unsafe {
LLVMGetCallSiteStringAttribute(self.as_value_ref(), index, key.as_ptr() as *const i8, key.len() as u32)
LLVMGetCallSiteStringAttribute(self.as_value_ref(), loc.get_index(), key.as_ptr() as *const i8, key.len() as u32)
};

if ptr.is_null() {
Expand All @@ -298,6 +302,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -314,18 +319,18 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.add_attribute(0, string_attribute);
/// call_site_value.add_attribute(0, enum_attribute);
/// call_site_value.remove_enum_attribute(0, 1);
/// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
/// call_site_value.remove_enum_attribute(AttributeLoc::Return, 1);
///
/// assert_eq!(call_site_value.get_enum_attribute(0, 1), None);
/// assert_eq!(call_site_value.get_enum_attribute(AttributeLoc::Return, 1), None);
/// ```
#[llvm_versions(3.9..=latest)]
pub fn remove_enum_attribute(&self, index: u32, kind_id: u32) {
pub fn remove_enum_attribute(&self, loc: AttributeLoc, kind_id: u32) {
use llvm_sys::core::LLVMRemoveCallSiteEnumAttribute;

unsafe {
LLVMRemoveCallSiteEnumAttribute(self.as_value_ref(), index, kind_id)
LLVMRemoveCallSiteEnumAttribute(self.as_value_ref(), loc.get_index(), kind_id)
}
}

Expand All @@ -334,6 +339,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -350,18 +356,18 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.add_attribute(0, string_attribute);
/// call_site_value.add_attribute(0, enum_attribute);
/// call_site_value.remove_string_attribute(0, "my_key");
/// call_site_value.add_attribute(AttributeLoc::Return, string_attribute);
/// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute);
/// call_site_value.remove_string_attribute(AttributeLoc::Return, "my_key");
///
/// assert_eq!(call_site_value.get_string_attribute(0, "my_key"), None);
/// assert_eq!(call_site_value.get_string_attribute(AttributeLoc::Return, "my_key"), None);
/// ```
#[llvm_versions(3.9..=latest)]
pub fn remove_string_attribute(&self, index: u32, key: &str) {
pub fn remove_string_attribute(&self, loc: AttributeLoc, key: &str) {
use llvm_sys::core::LLVMRemoveCallSiteStringAttribute;

unsafe {
LLVMRemoveCallSiteStringAttribute(self.as_value_ref(), index, key.as_ptr() as *const i8, key.len() as u32)
LLVMRemoveCallSiteStringAttribute(self.as_value_ref(), loc.get_index(), key.as_ptr() as *const i8, key.len() as u32)
}
}

Expand All @@ -370,6 +376,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand Down Expand Up @@ -462,6 +469,7 @@ impl CallSiteValue {
/// # Example
///
/// ```no_run
/// use inkwell::attributes::AttributeLoc;
/// use inkwell::context::Context;
///
/// let context = Context::create();
Expand All @@ -476,13 +484,13 @@ impl CallSiteValue {
///
/// let call_site_value = builder.build_call(fn_value, &[], "my_fn");
///
/// call_site_value.set_param_alignment_attribute(0, 2);
/// call_site_value.set_alignment_attribute(AttributeLoc::Param(0), 2);
/// ```
pub fn set_param_alignment_attribute(&self, index: u32, alignment: u32) {
pub fn set_alignment_attribute(&self, loc: AttributeLoc, alignment: u32) {
assert_eq!(alignment.count_ones(), 1, "Alignment must be a power of two.");

unsafe {
LLVMSetInstrParamAlignment(self.as_value_ref(), index, alignment)
LLVMSetInstrParamAlignment(self.as_value_ref(), loc.get_index(), alignment)
}
}

Expand Down
Loading

0 comments on commit f13d42f

Please sign in to comment.