Skip to content

Set proper alignment on constants #28920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions src/librustc_trans/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}
}
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_trans/trans/controlflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_trans/trans/debuginfo/gdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
/// section.
pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
-> llvm::ValueRef {
let section_var_name = "__rustc_debug_gdb_scripts_section__";
let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
let section_var_name = &c_section_var_name[..c_section_var_name.len()-1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, you might want to use c_section_var_name.as_ptr() as *const _ below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For correctness even. Not sure where I lost that change (and even more confusing that it passed the test without it). Thanks!


let section_var = unsafe {
llvm::LLVMGetNamedGlobal(ccx.llmod(),
section_var_name.as_ptr() as *const _)
c_section_var_name.as_ptr() as *const _)
};

if section_var == ptr::null_mut() {
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_trans/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 66 additions & 0 deletions src/test/codegen/consts.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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, B> {
A(A),
B(B),
}

#[no_mangle]
pub static STATIC: E<i16, i32> = E::A(0);

// CHECK-LABEL: @static_enum_const
#[no_mangle]
pub fn static_enum_const() -> E<i16, i32> {
STATIC
}

// CHECK-LABEL: @inline_enum_const
#[no_mangle]
pub fn inline_enum_const() -> E<i8, i16> {
E::A(0)
}

// CHECK-LABEL: @low_align_const
#[no_mangle]
pub fn low_align_const() -> E<i16, [i16; 3]> {
// 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<i16, i32> {
// 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)
}