Skip to content

Commit b7b5ea7

Browse files
committed
Generate unique symbol names if const pointers refer to promoted static
1 parent c280357 commit b7b5ea7

4 files changed

Lines changed: 71 additions & 3 deletions

File tree

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use gccjit::{LValue, RValue, ToRValue, Type};
1+
use gccjit::{GlobalKind, LValue, RValue, ToRValue, Type};
22
use rustc_abi::Primitive::Pointer;
33
use rustc_abi::{self as abi, HasDataLayout};
44
use rustc_codegen_ssa::traits::{
@@ -97,6 +97,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
9797
}
9898
};
9999

100+
if need_symbol_name {
101+
let name = self.generate_global_symbol_name();
102+
103+
let init = crate::consts::const_alloc_to_gcc_uncached(self, alloc);
104+
let alloc = alloc.inner();
105+
let typ = self.val_ty(init).get_aligned(alloc.align.bytes());
106+
107+
let global = self.declare_global_with_linkage(&name, typ, GlobalKind::Internal);
108+
109+
global.global_set_initializer_rvalue(init);
110+
return Ok((global.get_address(None), Some(SymbolName::new(self.tcx, &name))));
111+
}
112+
100113
let value = match alloc.inner().mutability {
101114
Mutability::Mut => {
102115
self.static_addr_of_mut(const_alloc_to_gcc(self, alloc), alloc.inner().align, None)

compiler/rustc_codegen_gcc/src/context.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ pub struct CodegenCx<'gcc, 'tcx> {
117117
/// A counter that is used for generating local symbol names
118118
local_gen_sym_counter: Cell<usize>,
119119

120+
/// A counter that is used for generating global symbol names
121+
global_gen_sym_counter: Cell<usize>,
122+
120123
eh_personality: Cell<Option<Function<'gcc>>>,
121124
#[cfg(feature = "master")]
122125
pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>,
@@ -296,6 +299,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
296299
tcx,
297300
struct_types: Default::default(),
298301
local_gen_sym_counter: Cell::new(0),
302+
global_gen_sym_counter: Cell::new(0),
299303
eh_personality: Cell::new(None),
300304
#[cfg(feature = "master")]
301305
rust_try_fn: Cell::new(None),
@@ -595,6 +599,24 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
595599
name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY));
596600
name
597601
}
602+
603+
/// Generates a new global symbol name with the given prefix. This symbol name must
604+
/// only be used for definitions with `internal` or `private` linkage.
605+
pub fn generate_global_symbol_name(&self) -> String {
606+
let idx = self.global_gen_sym_counter.get();
607+
self.global_gen_sym_counter.set(idx + 1);
608+
609+
let sym = self.codegen_unit.symbol_name();
610+
let prefix = sym.as_str();
611+
let mut name = String::with_capacity(prefix.len() + 6);
612+
name.push_str(prefix);
613+
name.push('.');
614+
// Offset the index by the base so that always at least two characters
615+
// are generated. This avoids cases where the suffix is interpreted as
616+
// size by the assembler (for m68k: .b, .w, .l).
617+
name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY));
618+
name
619+
}
598620
}
599621

600622
fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel {

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,25 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
181181
}
182182
};
183183

184-
assert!(!need_symbol_name);
185-
186184
let init = const_alloc_to_llvm(self, alloc.inner(), /*static*/ false);
187185
let alloc = alloc.inner();
186+
187+
if need_symbol_name {
188+
// If a symbol name is needed, use `static_addr_of_mut` so we can give it unique symbol names.
189+
let value = self.static_addr_of_mut(init, alloc.align, None);
190+
if alloc.mutability.is_not() {
191+
llvm::set_global_constant(value, true);
192+
}
193+
194+
// Even though we're generating with internal linkage, this symbol name still needs to
195+
// be globally unique. LTO can rename symbol names if there are duplicates, but the
196+
// names inserted into global asm as text cannot be updated.
197+
let name = self.generate_global_symbol_name();
198+
llvm::set_value_name(value, name.as_bytes());
199+
llvm::set_linkage(value, llvm::Linkage::InternalLinkage);
200+
return Ok(value);
201+
}
202+
188203
let value = match alloc.mutability {
189204
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
190205
_ => self.static_addr_of_impl(init, alloc.align, None),

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ pub(crate) struct FullCx<'ll, 'tcx> {
143143
/// A counter that is used for generating local symbol names
144144
local_gen_sym_counter: Cell<usize>,
145145

146+
/// A counter that is used for generating global symbol names
147+
global_gen_sym_counter: Cell<usize>,
148+
146149
/// `codegen_static` will sometimes create a second global variable with a
147150
/// different type and clear the symbol name of the original global.
148151
/// `global_asm!` needs to be able to find this new global so that it can
@@ -681,6 +684,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
681684
rust_try_fn: Cell::new(None),
682685
intrinsics: Default::default(),
683686
local_gen_sym_counter: Cell::new(0),
687+
global_gen_sym_counter: Cell::new(0),
684688
renamed_statics: Default::default(),
685689
objc_class_t: Cell::new(None),
686690
objc_classrefs: Default::default(),
@@ -1063,6 +1067,20 @@ impl CodegenCx<'_, '_> {
10631067
name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
10641068
name
10651069
}
1070+
1071+
/// Generates a new global symbol name with the given prefix.
1072+
pub(crate) fn generate_global_symbol_name(&self) -> String {
1073+
let idx = self.global_gen_sym_counter.get();
1074+
self.global_gen_sym_counter.set(idx + 1);
1075+
1076+
let sym = self.codegen_unit.symbol_name();
1077+
let prefix = sym.as_str();
1078+
let mut name = String::with_capacity(prefix.len() + 6);
1079+
name.push_str(prefix);
1080+
name.push('.');
1081+
name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
1082+
name
1083+
}
10661084
}
10671085

10681086
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {

0 commit comments

Comments
 (0)