Skip to content

Commit

Permalink
Add TargetOptions::min_global_align, with s390x at 16-bit
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cuviper committed Sep 8, 2017
1 parent dead08c commit 95a5a0e
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/librustc_back/target/mod.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -486,6 +489,7 @@ impl Default for TargetOptions {
crt_static_default: false,
crt_static_respected: false,
stack_probes: false,
min_global_align: None,
}
}
}
Expand Down Expand Up @@ -724,6 +728,7 @@ impl Target {
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()) {
Expand Down Expand Up @@ -914,6 +919,7 @@ impl ToJson for Target {
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()
Expand Down
1 change: 1 addition & 0 deletions src/librustc_back/target/s390x_unknown_linux_gnu.rs
Expand Up @@ -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(),
Expand Down
24 changes: 22 additions & 2 deletions src/librustc_trans/consts.rs
Expand Up @@ -26,6 +26,7 @@ use rustc::ty;

use rustc::hir;

use std::cmp;
use std::ffi::{CStr, CString};
use syntax::ast;
use syntax::attr;
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 95a5a0e

Please sign in to comment.