Skip to content

Commit e7da619

Browse files
author
Jonathan Turner
authored
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.
2 parents 050499c + 992203b commit e7da619

File tree

5 files changed

+23
-15
lines changed

5 files changed

+23
-15
lines changed

src/librustc_trans/common.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -799,9 +799,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
799799
s.as_ptr() as *const c_char,
800800
s.len() as c_uint,
801801
!null_terminated as Bool);
802-
803-
let gsym = token::gensym("str");
804-
let sym = format!("str{}", gsym.0);
802+
let sym = cx.generate_local_symbol_name("str");
805803
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
806804
bug!("symbol `{}` is already defined", sym);
807805
});

src/librustc_trans/consts.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use rustc::hir;
3030
use std::ffi::{CStr, CString};
3131
use syntax::ast;
3232
use syntax::attr;
33-
use syntax::parse::token;
3433

3534
pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
3635
unsafe {
@@ -44,10 +43,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
4443
kind: &str)
4544
-> ValueRef {
4645
unsafe {
47-
// FIXME: this totally needs a better name generation scheme, perhaps a simple global
48-
// counter? Also most other uses of gensym in trans.
49-
let gsym = token::gensym("_");
50-
let name = format!("{}{}", kind, gsym.0);
46+
let name = ccx.generate_local_symbol_name(kind);
5147
let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
5248
bug!("symbol `{}` is already defined", name);
5349
});

src/librustc_trans/context.rs

+14
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ pub struct LocalCrateContext<'tcx> {
166166
type_of_depth: Cell<usize>,
167167

168168
symbol_map: Rc<SymbolMap<'tcx>>,
169+
170+
/// A counter that is used for generating local symbol names
171+
local_gen_sym_counter: Cell<usize>,
169172
}
170173

171174
// Implement DepTrackingMapConfig for `trait_cache`
@@ -688,6 +691,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
688691
n_llvm_insns: Cell::new(0),
689692
type_of_depth: Cell::new(0),
690693
symbol_map: symbol_map,
694+
local_gen_sym_counter: Cell::new(0),
691695
};
692696

693697
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
@@ -1021,6 +1025,16 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
10211025
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
10221026
self.shared().empty_substs_for_def_id(item_def_id)
10231027
}
1028+
1029+
/// Generate a new symbol name with the given prefix. This symbol name must
1030+
/// only be used for definitions with `internal` or `private` linkage.
1031+
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
1032+
let idx = self.local().local_gen_sym_counter.get();
1033+
self.local().local_gen_sym_counter.set(idx + 1);
1034+
// Include a '.' character, so there can be no accidental conflicts with
1035+
// user defined names
1036+
format!("{}.{}", prefix, idx)
1037+
}
10241038
}
10251039

10261040
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);

src/test/codegen/consts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
// CHECK: @STATIC = {{.*}}, align 4
2020

2121
// This checks the constants from inline_enum_const
22-
// CHECK: @ref{{[0-9]+}} = {{.*}}, align 2
22+
// CHECK: @ref.{{[0-9]+}} = {{.*}}, align 2
2323

2424
// This checks the constants from {low,high}_align_const, they share the same
2525
// constant, but the alignment differs, so the higher one should be used
26-
// CHECK: [[LOW_HIGH:@ref[0-9]+]] = {{.*}}, align 4
27-
// CHECK: [[LOW_HIGH_REF:@const[0-9]+]] = {{.*}} [[LOW_HIGH]]
26+
// CHECK: [[LOW_HIGH:@ref.[0-9]+]] = {{.*}}, align 4
27+
// CHECK: [[LOW_HIGH_REF:@const.[0-9]+]] = {{.*}} [[LOW_HIGH]]
2828

2929
#[derive(Copy, Clone)]
3030

Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-include ../tools.mk
22

33
# check that the compile generated symbols for strings, binaries,
4-
# vtables, etc. have semisane names (e.g. `str1234`); it's relatively
4+
# vtables, etc. have semisane names (e.g. `str.1234`); it's relatively
55
# easy to accidentally modify the compiler internals to make them
66
# become things like `str"str"(1234)`.
77

@@ -10,6 +10,6 @@ OUT=$(TMPDIR)/lib.s
1010
all:
1111
$(RUSTC) lib.rs --emit=asm --crate-type=staticlib
1212
# just check for symbol declarations with the names we're expecting.
13-
grep 'str[0-9][0-9]*:' $(OUT)
14-
grep 'byte_str[0-9][0-9]*:' $(OUT)
15-
grep 'vtable[0-9][0-9]*' $(OUT)
13+
grep 'str.[0-9][0-9]*:' $(OUT)
14+
grep 'byte_str.[0-9][0-9]*:' $(OUT)
15+
grep 'vtable.[0-9][0-9]*' $(OUT)

0 commit comments

Comments
 (0)