Rollup merge of #37328 - michaelwoerister:stable-local-symbol-names, r=nagisa
trans: Make names of internal symbols independent of CGU translation order Every codegen unit gets its own local counter for generating new symbol names. This makes bitcode and object files reproducible at the binary level even when incremental compilation is used. The PR also solves a rare ICE resulting from a naming conflict between a user defined name and a generated one. E.g. try compiling the following program with 1.12.1 stable: ```rust pub fn str7233() -> &'static str { "foo" } ``` This results in: > error: internal compiler error: ../src/librustc_trans/common.rs:979: symbol `str7233` is already defined Running into this is not very likely but it's also easily avoidable.
This commit is contained in:
commit
e7da61975f
|
@ -799,9 +799,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
|
||||||
s.as_ptr() as *const c_char,
|
s.as_ptr() as *const c_char,
|
||||||
s.len() as c_uint,
|
s.len() as c_uint,
|
||||||
!null_terminated as Bool);
|
!null_terminated as Bool);
|
||||||
|
let sym = cx.generate_local_symbol_name("str");
|
||||||
let gsym = token::gensym("str");
|
|
||||||
let sym = format!("str{}", gsym.0);
|
|
||||||
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
|
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
|
||||||
bug!("symbol `{}` is already defined", sym);
|
bug!("symbol `{}` is already defined", sym);
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,6 @@ use rustc::hir;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::parse::token;
|
|
||||||
|
|
||||||
pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
|
pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -44,10 +43,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
|
||||||
kind: &str)
|
kind: &str)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
// FIXME: this totally needs a better name generation scheme, perhaps a simple global
|
let name = ccx.generate_local_symbol_name(kind);
|
||||||
// counter? Also most other uses of gensym in trans.
|
|
||||||
let gsym = token::gensym("_");
|
|
||||||
let name = format!("{}{}", kind, gsym.0);
|
|
||||||
let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
|
let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
|
||||||
bug!("symbol `{}` is already defined", name);
|
bug!("symbol `{}` is already defined", name);
|
||||||
});
|
});
|
||||||
|
|
|
@ -166,6 +166,9 @@ pub struct LocalCrateContext<'tcx> {
|
||||||
type_of_depth: Cell<usize>,
|
type_of_depth: Cell<usize>,
|
||||||
|
|
||||||
symbol_map: Rc<SymbolMap<'tcx>>,
|
symbol_map: Rc<SymbolMap<'tcx>>,
|
||||||
|
|
||||||
|
/// A counter that is used for generating local symbol names
|
||||||
|
local_gen_sym_counter: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement DepTrackingMapConfig for `trait_cache`
|
// Implement DepTrackingMapConfig for `trait_cache`
|
||||||
|
@ -688,6 +691,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
|
||||||
n_llvm_insns: Cell::new(0),
|
n_llvm_insns: Cell::new(0),
|
||||||
type_of_depth: Cell::new(0),
|
type_of_depth: Cell::new(0),
|
||||||
symbol_map: symbol_map,
|
symbol_map: symbol_map,
|
||||||
|
local_gen_sym_counter: Cell::new(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
|
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
|
||||||
|
@ -1021,6 +1025,16 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||||
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
|
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
|
||||||
self.shared().empty_substs_for_def_id(item_def_id)
|
self.shared().empty_substs_for_def_id(item_def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a new symbol name with the given prefix. This symbol name must
|
||||||
|
/// only be used for definitions with `internal` or `private` linkage.
|
||||||
|
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
|
||||||
|
let idx = self.local().local_gen_sym_counter.get();
|
||||||
|
self.local().local_gen_sym_counter.set(idx + 1);
|
||||||
|
// Include a '.' character, so there can be no accidental conflicts with
|
||||||
|
// user defined names
|
||||||
|
format!("{}.{}", prefix, idx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
|
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
|
||||||
|
|
|
@ -19,12 +19,12 @@
|
||||||
// CHECK: @STATIC = {{.*}}, align 4
|
// CHECK: @STATIC = {{.*}}, align 4
|
||||||
|
|
||||||
// This checks the constants from inline_enum_const
|
// This checks the constants from inline_enum_const
|
||||||
// CHECK: @ref{{[0-9]+}} = {{.*}}, align 2
|
// CHECK: @ref.{{[0-9]+}} = {{.*}}, align 2
|
||||||
|
|
||||||
// This checks the constants from {low,high}_align_const, they share the same
|
// 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
|
// constant, but the alignment differs, so the higher one should be used
|
||||||
// CHECK: [[LOW_HIGH:@ref[0-9]+]] = {{.*}}, align 4
|
// CHECK: [[LOW_HIGH:@ref.[0-9]+]] = {{.*}}, align 4
|
||||||
// CHECK: [[LOW_HIGH_REF:@const[0-9]+]] = {{.*}} [[LOW_HIGH]]
|
// CHECK: [[LOW_HIGH_REF:@const.[0-9]+]] = {{.*}} [[LOW_HIGH]]
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
# check that the compile generated symbols for strings, binaries,
|
# check that the compile generated symbols for strings, binaries,
|
||||||
# vtables, etc. have semisane names (e.g. `str1234`); it's relatively
|
# vtables, etc. have semisane names (e.g. `str.1234`); it's relatively
|
||||||
# easy to accidentally modify the compiler internals to make them
|
# easy to accidentally modify the compiler internals to make them
|
||||||
# become things like `str"str"(1234)`.
|
# become things like `str"str"(1234)`.
|
||||||
|
|
||||||
|
@ -10,6 +10,6 @@ OUT=$(TMPDIR)/lib.s
|
||||||
all:
|
all:
|
||||||
$(RUSTC) lib.rs --emit=asm --crate-type=staticlib
|
$(RUSTC) lib.rs --emit=asm --crate-type=staticlib
|
||||||
# just check for symbol declarations with the names we're expecting.
|
# just check for symbol declarations with the names we're expecting.
|
||||||
grep 'str[0-9][0-9]*:' $(OUT)
|
grep 'str.[0-9][0-9]*:' $(OUT)
|
||||||
grep 'byte_str[0-9][0-9]*:' $(OUT)
|
grep 'byte_str.[0-9][0-9]*:' $(OUT)
|
||||||
grep 'vtable[0-9][0-9]*' $(OUT)
|
grep 'vtable.[0-9][0-9]*' $(OUT)
|
||||||
|
|
Loading…
Reference in New Issue