]> git.lizzy.rs Git - rust.git/commitdiff
Fix removal of function attributes on ARM
authorBjörn Steinbrink <bsteinbr@gmail.com>
Sat, 26 Mar 2016 11:27:33 +0000 (12:27 +0100)
committerBjörn Steinbrink <bsteinbr@gmail.com>
Sat, 26 Mar 2016 12:02:54 +0000 (13:02 +0100)
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

src/librustc_llvm/lib.rs
src/librustc_trans/trans/attributes.rs
src/rustllvm/RustWrapper.cpp

index c1b909bd877a85bd3d61bcf7601b494a25c454d1..ee57812fb9823017e35dfae40db51d330149b66c 100644 (file)
@@ -964,9 +964,10 @@ pub fn LLVMGetOrInsertFunction(M: ModuleRef,
     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;
@@ -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 {
index 4ea920c57aadb1782f4df7cca43614c9e8d2c27b..b771afea0f3bde1e04fe86927ab5f9a6174b4cd5 100644 (file)
@@ -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;
@@ -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)
         },
     };
 }
@@ -41,12 +39,7 @@ 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);
     }
 }
 
@@ -54,12 +47,7 @@ pub fn emit_uwtable(val: ValueRef, emit: bool) {
 #[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);
     }
@@ -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);
     }
 }
 
@@ -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);
     }
 }
 
index 33174c1e9dfe36abdb0c91aa82000320b8e7c6a6..6ff90a8f53a04098893948488993fece9a822ac1 100644 (file)
@@ -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();