1
Fork 0

Add TargetOptions::min_global_align, with s390x at 16-bit

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.
This commit is contained in:
Josh Stone 2017-09-08 14:49:51 -07:00
parent dead08cb33
commit 95a5a0ed16
3 changed files with 29 additions and 2 deletions

View 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 @@ impl Default for TargetOptions {
crt_static_default: false,
crt_static_respected: false,
stack_probes: false,
min_global_align: None,
}
}
}
@ -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()) {
@ -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()

View 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(),

View file

@ -26,6 +26,7 @@ use rustc::ty;
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