Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix removal of function attributes on ARM
We use a 64bit integer to pass the set of attributes that is to be
removed, but the called C function expects a 32bit integer. On most
platforms this doesn't cause any problems other than being unable to
unset some attributes, but on  ARM even the lower 32bit aren't handled
correctly because the 64bit value is passed in different registers, so
the C function actually sees random garbage.

So we need to fix the relevant functions to use 32bit integers instead.
Additionally we need an implementation that actually accepts 64bit
integers because some attributes can only be unset that way.

Fixes #32360
  • Loading branch information
dotdash committed Mar 26, 2016
1 parent d322f99 commit 95697a8
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 27 deletions.
12 changes: 10 additions & 2 deletions src/librustc_llvm/lib.rs
Expand Up @@ -964,9 +964,10 @@ extern {
pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
Name: *const c_char,
Value: *const c_char);
pub fn LLVMRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: uint64_t);
pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);

/* Operations on parameters */
pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
Expand Down Expand Up @@ -2184,6 +2185,13 @@ pub fn SetFunctionAttribute(fn_: ValueRef, attr: Attribute) {
}
}

pub fn RemoveFunctionAttributes(fn_: ValueRef, attr: Attribute) {
unsafe {
LLVMRemoveFunctionAttributes(fn_, FunctionIndex as c_uint,
attr.bits() as uint64_t)
}
}

/* Memory-managed interface to target data. */

pub struct TargetData {
Expand Down
31 changes: 6 additions & 25 deletions src/librustc_trans/trans/attributes.rs
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.
//! Set and unset common attributes on LLVM values.

use libc::{c_uint, c_ulonglong};
use libc::c_uint;
use llvm::{self, ValueRef};
use session::config::NoDebugInfo;
pub use syntax::attr::InlineAttr;
Expand All @@ -28,9 +28,7 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
let attr = llvm::Attribute::InlineHint |
llvm::Attribute::AlwaysInline |
llvm::Attribute::NoInline;
unsafe {
llvm::LLVMRemoveFunctionAttr(val, attr.bits() as c_ulonglong)
}
llvm::RemoveFunctionAttributes(val, attr)
},
};
}
Expand All @@ -41,25 +39,15 @@ pub fn emit_uwtable(val: ValueRef, emit: bool) {
if emit {
llvm::SetFunctionAttribute(val, llvm::Attribute::UWTable);
} else {
unsafe {
llvm::LLVMRemoveFunctionAttr(
val,
llvm::Attribute::UWTable.bits() as c_ulonglong,
);
}
llvm::RemoveFunctionAttributes(val, llvm::Attribute::UWTable);
}
}

/// Tell LLVM whether the function can or cannot unwind.
#[inline]
pub fn unwind(val: ValueRef, can_unwind: bool) {
if can_unwind {
unsafe {
llvm::LLVMRemoveFunctionAttr(
val,
llvm::Attribute::NoUnwind.bits() as c_ulonglong,
);
}
llvm::RemoveFunctionAttributes(val, llvm::Attribute::NoUnwind);
} else {
llvm::SetFunctionAttribute(val, llvm::Attribute::NoUnwind);
}
Expand All @@ -72,12 +60,7 @@ pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
if optimize {
llvm::SetFunctionAttribute(val, llvm::Attribute::OptimizeForSize);
} else {
unsafe {
llvm::LLVMRemoveFunctionAttr(
val,
llvm::Attribute::OptimizeForSize.bits() as c_ulonglong,
);
}
llvm::RemoveFunctionAttributes(val, llvm::Attribute::OptimizeForSize);
}
}

Expand All @@ -87,9 +70,7 @@ pub fn naked(val: ValueRef, is_naked: bool) {
if is_naked {
llvm::SetFunctionAttribute(val, llvm::Attribute::Naked);
} else {
unsafe {
llvm::LLVMRemoveFunctionAttr(val, llvm::Attribute::Naked.bits() as c_ulonglong);
}
llvm::RemoveFunctionAttributes(val, llvm::Attribute::Naked);
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/rustllvm/RustWrapper.cpp
Expand Up @@ -151,6 +151,16 @@ extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}

extern "C" void LLVMRemoveFunctionAttributes(LLVMValueRef Fn, unsigned index, uint64_t Val) {
Function *A = unwrap<Function>(Fn);
const AttributeSet PAL = A->getAttributes();
AttrBuilder B(Val);
const AttributeSet PALnew =
PAL.removeAttributes(A->getContext(), index,
AttributeSet::get(A->getContext(), index, B));
A->setAttributes(PALnew);
}

extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
Function *f = unwrap<Function>(fn);
LLVMContext &C = f->getContext();
Expand Down

0 comments on commit 95697a8

Please sign in to comment.