]> git.lizzy.rs Git - rust.git/commitdiff
Add `TargetOptions::min_global_align`, with s390x at 16-bit
authorJosh Stone <jistone@redhat.com>
Fri, 8 Sep 2017 21:49:51 +0000 (14:49 -0700)
committerJosh Stone <jistone@redhat.com>
Fri, 8 Sep 2017 21:49:51 +0000 (14:49 -0700)
The SystemZ `LALR` instruction provides PC-relative addressing for
globals, but only to *even* addresses, so other compilers make sure that
such globals are always 2-byte aligned.  In Clang, this is modeled with
`TargetInfo::MinGlobalAlign`, and `TargetOptions::min_global_align` now
serves the same purpose for rustc.

In Clang, the only targets that set this are SystemZ, Lanai, and NVPTX,
and the latter two don't have targets in rust master.

src/librustc_back/target/mod.rs
src/librustc_back/target/s390x_unknown_linux_gnu.rs
src/librustc_trans/consts.rs

index 130e1b695dbd5b7bbcdab87d5bb3edc6fab29588..301cf3f8c8208d0019ba55fbd43477ad9f9e1c36 100644 (file)
@@ -425,6 +425,9 @@ pub struct TargetOptions {
 
     /// Whether or not stack probes (__rust_probestack) are enabled
     pub stack_probes: bool,
+
+    /// The minimum alignment for global symbols.
+    pub min_global_align: Option<u64>,
 }
 
 impl Default for TargetOptions {
@@ -486,6 +489,7 @@ fn default() -> TargetOptions {
             crt_static_default: false,
             crt_static_respected: false,
             stack_probes: false,
+            min_global_align: None,
         }
     }
 }
@@ -724,6 +728,7 @@ macro_rules! key {
         key!(crt_static_default, bool);
         key!(crt_static_respected, bool);
         key!(stack_probes, bool);
+        key!(min_global_align, Option<u64>);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -914,6 +919,7 @@ macro_rules! target_option_val {
         target_option_val!(crt_static_default);
         target_option_val!(crt_static_respected);
         target_option_val!(stack_probes);
+        target_option_val!(min_global_align);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
index 78a6bb7933d9539c6637b21a1fce2c8f828b2032..aad9effacd440460898b21f105a3818b2b314ef9 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> TargetResult {
     base.max_atomic_width = Some(64);
     // see #36994
     base.exe_allocation_crate = None;
+    base.min_global_align = Some(16);
 
     Ok(Target {
         llvm_target: "s390x-unknown-linux-gnu".to_string(),
index a30a15f75b3afc13e742806c13e4e42969947ce6..bad8a8655d0938cc5625bc9e0dfed2c1de2a362d 100644 (file)
@@ -26,6 +26,7 @@
 
 use rustc::hir;
 
+use std::cmp;
 use std::ffi::{CStr, CString};
 use syntax::ast;
 use syntax::attr;
@@ -42,6 +43,25 @@ pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef {
     }
 }
 
+fn set_global_alignment(ccx: &CrateContext,
+                        gv: ValueRef,
+                        mut align: machine::llalign) {
+    // The target may require greater alignment for globals than the type does.
+    // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
+    // which can force it to be smaller.  Rust doesn't support this yet.
+    if let Some(min) = ccx.sess().target.target.options.min_global_align {
+        match ty::layout::Align::from_bits(min, min) {
+            Ok(min) => align = cmp::max(align, min.abi() as machine::llalign),
+            Err(err) => {
+                ccx.sess().err(&format!("invalid minimum global alignment: {}", err));
+            }
+        }
+    }
+    unsafe {
+        llvm::LLVMSetAlignment(gv, align);
+    }
+}
+
 pub fn addr_of_mut(ccx: &CrateContext,
                    cv: ValueRef,
                    align: machine::llalign,
@@ -53,7 +73,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
             bug!("symbol `{}` is already defined", name);
         });
         llvm::LLVMSetInitializer(gv, cv);
-        llvm::LLVMSetAlignment(gv, align);
+        set_global_alignment(ccx, gv, align);
         llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage);
         SetUnnamedAddr(gv, true);
         gv
@@ -276,7 +296,7 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             ccx.statics_to_rauw().borrow_mut().push((g, new_g));
             new_g
         };
-        llvm::LLVMSetAlignment(g, ccx.align_of(ty));
+        set_global_alignment(ccx, g, ccx.align_of(ty));
         llvm::LLVMSetInitializer(g, v);
 
         // As an optimization, all shared statics which do not have interior