diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index a7bb4043e7d..09bf1beb22b 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -98,7 +98,7 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit) ast::LitBool(b) => C_bool(cx, b), ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()), ast::LitByteStr(ref data) => { - addr_of(cx, C_bytes(cx, &data[..]), "byte_str") + addr_of(cx, C_bytes(cx, &data[..]), 1, "byte_str") } } } @@ -111,6 +111,7 @@ pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef { fn addr_of_mut(ccx: &CrateContext, cv: ValueRef, + align: machine::llalign, kind: &str) -> ValueRef { unsafe { @@ -122,6 +123,7 @@ fn addr_of_mut(ccx: &CrateContext, ccx.sess().bug(&format!("symbol `{}` is already defined", name)); }); llvm::LLVMSetInitializer(gv, cv); + llvm::LLVMSetAlignment(gv, align); SetLinkage(gv, InternalLinkage); SetUnnamedAddr(gv, true); gv @@ -130,13 +132,23 @@ fn addr_of_mut(ccx: &CrateContext, pub fn addr_of(ccx: &CrateContext, cv: ValueRef, + align: machine::llalign, kind: &str) -> ValueRef { match ccx.const_globals().borrow().get(&cv) { - Some(&gv) => return gv, + Some(&gv) => { + unsafe { + // Upgrade the alignment in cases where the same constant is used with different + // alignment requirements + if align > llvm::LLVMGetAlignment(gv) { + llvm::LLVMSetAlignment(gv, align); + } + } + return gv; + } None => {} } - let gv = addr_of_mut(ccx, cv, kind); + let gv = addr_of_mut(ccx, cv, align, kind); unsafe { llvm::LLVMSetGlobalConstant(gv, True); } @@ -254,11 +266,11 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, Some(&val) => return val, None => {} } + let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, + &ccx.tcx().expr_ty(expr)); let val = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) { // Avoid autorefs as they would create global instead of stack // references, even when only the latter are correct. - let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, - &ccx.tcx().expr_ty(expr)); const_expr_unadjusted(ccx, expr, ty, param_substs, None) } else { const_expr(ccx, expr, param_substs, None).0 @@ -274,7 +286,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } }; - let lvalue = addr_of(ccx, val, "const"); + let lvalue = addr_of(ccx, val, type_of::align_of(ccx, ty), "const"); ccx.const_values().borrow_mut().insert(key, lvalue); lvalue } @@ -314,7 +326,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if adj.autoderefs == 0 { // Don't copy data to do a deref+ref // (i.e., skip the last auto-deref). - llconst = addr_of(cx, llconst, "autoref"); + llconst = addr_of(cx, llconst, type_of::align_of(cx, ty), "autoref"); ty = cx.tcx().mk_imm_ref(cx.tcx().mk_region(ty::ReStatic), ty); } } else { @@ -720,13 +732,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } else { // If this isn't the address of a static, then keep going through // normal constant evaluation. - let (v, _) = const_expr(cx, &**sub, param_substs, fn_args); - addr_of(cx, v, "ref") + let (v, ty) = const_expr(cx, &**sub, param_substs, fn_args); + addr_of(cx, v, type_of::align_of(cx, ty), "ref") } }, hir::ExprAddrOf(hir::MutMutable, ref sub) => { - let (v, _) = const_expr(cx, &**sub, param_substs, fn_args); - addr_of_mut(cx, v, "ref_mut_slice") + let (v, ty) = const_expr(cx, &**sub, param_substs, fn_args); + addr_of_mut(cx, v, type_of::align_of(cx, ty), "ref_mut_slice") }, hir::ExprTup(ref es) => { let repr = adt::represent_type(cx, ety); @@ -934,6 +946,7 @@ pub fn trans_static(ccx: &CrateContext, ccx.statics_to_rauw().borrow_mut().push((g, new_g)); new_g }; + llvm::LLVMSetAlignment(g, type_of::align_of(ccx, ty)); llvm::LLVMSetInitializer(g, v); // As an optimization, all shared statics which do not have interior diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 875eb353cf7..5f83abc065f 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -22,6 +22,7 @@ use trans::consts; use trans::debuginfo; use trans::debuginfo::{DebugLoc, ToDebugLoc}; use trans::expr; +use trans::machine; use trans; use middle::ty; @@ -401,7 +402,8 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let filename = C_str_slice(ccx, filename); let line = C_u32(ccx, loc.line as u32); let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); - let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc"); + let align = machine::llalign_of_min(ccx, val_ty(expr_file_line_const)); + let expr_file_line = consts::addr_of(ccx, expr_file_line_const, align, "panic_loc"); let args = vec!(expr_file_line); let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem); let bcx = callee::trans_lang_call(bcx, @@ -433,7 +435,8 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let filename = C_str_slice(ccx, filename); let line = C_u32(ccx, loc.line as u32); let file_line_const = C_struct(ccx, &[filename, line], false); - let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc"); + let align = machine::llalign_of_min(ccx, val_ty(file_line_const)); + let file_line = consts::addr_of(ccx, file_line_const, align, "panic_bounds_check_loc"); let args = vec!(file_line, index, len); let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 614453830c6..9a119d0a0e4 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -651,7 +651,9 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, C_uint(ccx, align) ].into_iter().chain(methods).collect(); - let vtable = consts::addr_of(ccx, C_struct(ccx, &components, false), "vtable"); + let vtable_const = C_struct(ccx, &components, false); + let align = machine::llalign_of_pref(ccx, val_ty(vtable_const)); + let vtable = consts::addr_of(ccx, vtable_const, align, "vtable"); ccx.vtables().borrow_mut().insert(trait_ref, vtable); vtable diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs new file mode 100644 index 00000000000..6b4e626df92 --- /dev/null +++ b/src/test/codegen/consts.rs @@ -0,0 +1,66 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +// Below, these constants are defined as enum variants that by itself would +// have a lower alignment than the enum type. Ensure that we mark them +// correctly with the higher alignment of the enum. + +// CHECK: @STATIC = {{.*}}, align 4 + +// This checks the constants from inline_enum_const +// CHECK: @const{{[0-9]+}} = {{.*}}, align 2 + +// This checks the constants from {low,high}_align_const, they share the same +// constant, but the alignment differs, so the higher one should be used +// CHECK: @const{{[0-9]+}} = {{.*}}, align 4 + +#[derive(Copy, Clone)] + +// repr(i16) is required for the {low,high}_align_const test +#[repr(i16)] +pub enum E { + A(A), + B(B), +} + +#[no_mangle] +pub static STATIC: E = E::A(0); + +// CHECK-LABEL: @static_enum_const +#[no_mangle] +pub fn static_enum_const() -> E { + STATIC +} + +// CHECK-LABEL: @inline_enum_const +#[no_mangle] +pub fn inline_enum_const() -> E { + E::A(0) +} + +// CHECK-LABEL: @low_align_const +#[no_mangle] +pub fn low_align_const() -> E { +// Check that low_align_const and high_align_const use the same constant +// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{[0-9]+}}, i8* {{.*}} [[LOW_HIGH:@const[0-9]+]] + E::A(0) +} + +// CHECK-LABEL: @high_align_const +#[no_mangle] +pub fn high_align_const() -> E { +// Check that low_align_const and high_align_const use the same constant +// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{[0-9]}}, i8* {{.*}} [[LOW_HIGH]] + E::A(0) +}