Skip to content

Commit d54cafb

Browse files
committed
Introduce trans::declare
We provide tools to tell what exact symbols to emit for any fn or static, but don’t quite check if that won’t cause any issues later on. Some of the issues include LLVM mangling our names again and our names pointing to wrong locations, us generating dumb foreign call wrappers, linker errors, extern functions resolving to different symbols altogether (extern {fn fail();} fail(); in some cases calling fail1()), etc. Before the commit we had a function called note_unique_llvm_symbol, so it is clear somebody was aware of the issue at some point, but the function was barely used, mostly in irrelevant locations. Along with working on it I took liberty to start refactoring trans/base into a few smaller modules. The refactoring is incomplete and I hope I will find some motivation to carry on with it. This is possibly a [breaking-change] because it makes dumbly written code properly invalid.
1 parent 2077901 commit d54cafb

File tree

15 files changed

+440
-298
lines changed

15 files changed

+440
-298
lines changed

src/librustc_trans/trans/base.rs

Lines changed: 80 additions & 200 deletions
Large diffs are not rendered by default.

src/librustc_trans/trans/callee.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use trans::common::{self, Block, Result, NodeIdAndSpan, ExprId, CrateContext,
4141
use trans::consts;
4242
use trans::datum::*;
4343
use trans::debuginfo::{DebugLoc, ToDebugLoc};
44+
use trans::declare;
4445
use trans::expr;
4546
use trans::glue;
4647
use trans::inline;
@@ -314,13 +315,9 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
314315
debug!("tuple_fn_ty: {}", tuple_fn_ty.repr(tcx));
315316

316317
//
317-
let function_name =
318-
link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
319-
"fn_pointer_shim");
320-
let llfn =
321-
decl_internal_rust_fn(ccx,
322-
tuple_fn_ty,
323-
&function_name[..]);
318+
let function_name = link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
319+
"fn_pointer_shim");
320+
let llfn = declare::declare_internal_rust_fn(ccx, &function_name[..], tuple_fn_ty);
324321

325322
//
326323
let empty_substs = tcx.mk_substs(Substs::trans_empty());

src/librustc_trans/trans/cleanup.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ use trans::callee;
126126
use trans::common;
127127
use trans::common::{Block, FunctionContext, ExprId, NodeIdAndSpan};
128128
use trans::debuginfo::{DebugLoc, ToDebugLoc};
129+
use trans::declare;
129130
use trans::glue;
130131
use middle::region;
131132
use trans::type_::Type;
@@ -844,10 +845,8 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
844845
Some(llpersonality) => llpersonality,
845846
None => {
846847
let fty = Type::variadic_func(&[], &Type::i32(self.ccx));
847-
let f = base::decl_cdecl_fn(self.ccx,
848-
"rust_eh_personality",
849-
fty,
850-
self.ccx.tcx().types.i32);
848+
let f = declare::declare_cfn(self.ccx, "rust_eh_personality", fty,
849+
self.ccx.tcx().types.i32);
851850
*personality = Some(f);
852851
f
853852
}

src/librustc_trans/trans/closure.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use trans::common::*;
2020
use trans::datum::{Datum, rvalue_scratch_datum};
2121
use trans::datum::{Rvalue, ByValue};
2222
use trans::debuginfo;
23+
use trans::declare;
2324
use trans::expr;
2425
use trans::monomorphize::{self, MonoId};
2526
use trans::type_of::*;
@@ -159,7 +160,11 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
159160
mangle_internal_name_by_path_and_seq(path, "closure")
160161
});
161162

162-
let llfn = decl_internal_rust_fn(ccx, function_type, &symbol[..]);
163+
// Currently there’s only a single user of get_or_create_declaration_if_closure and it
164+
// unconditionally defines the function, therefore we use define_* here.
165+
let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type).unwrap_or_else(||{
166+
ccx.sess().bug(&format!("symbol `{}` already defined", symbol));
167+
});
163168

164169
// set an inline hint for all closures
165170
attributes::inline(llfn, attributes::InlineAttr::Hint);

src/librustc_trans/trans/common.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use trans::cleanup;
3131
use trans::consts;
3232
use trans::datum;
3333
use trans::debuginfo::{self, DebugLoc};
34+
use trans::declare;
3435
use trans::machine;
3536
use trans::monomorphize;
3637
use trans::type_::Type;
@@ -880,9 +881,10 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
880881
!null_terminated as Bool);
881882

882883
let gsym = token::gensym("str");
883-
let buf = CString::new(format!("str{}", gsym.usize()));
884-
let buf = buf.unwrap();
885-
let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
884+
let sym = format!("str{}", gsym.usize());
885+
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
886+
cx.sess().bug(&format!("symbol `{}` is already defined", sym));
887+
});
886888
llvm::LLVMSetInitializer(g, sc);
887889
llvm::LLVMSetGlobalConstant(g, True);
888890
llvm::SetLinkage(g, llvm::InternalLinkage);

src/librustc_trans/trans/consts.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use middle::{check_const, const_eval, def};
1717
use trans::{adt, closure, debuginfo, expr, inline, machine};
1818
use trans::base::{self, push_ctxt};
1919
use trans::common::*;
20+
use trans::declare;
2021
use trans::monomorphize;
2122
use trans::type_::Type;
2223
use trans::type_of;
@@ -27,6 +28,7 @@ use util::ppaux::{Repr, ty_to_string};
2728
use std::iter::repeat;
2829
use libc::c_uint;
2930
use syntax::{ast, ast_util};
31+
use syntax::parse::token;
3032
use syntax::ptr::P;
3133

3234
pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
@@ -75,7 +77,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
7577
ast::LitBool(b) => C_bool(cx, b),
7678
ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
7779
ast::LitBinary(ref data) => {
78-
let g = addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id);
80+
let g = addr_of(cx, C_bytes(cx, &data[..]), "binary");
7981
let base = ptrcast(g, Type::i8p(cx));
8082
let prev_const = cx.const_unsized().borrow_mut()
8183
.insert(base, g);
@@ -95,13 +97,16 @@ pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
9597

9698
fn addr_of_mut(ccx: &CrateContext,
9799
cv: ValueRef,
98-
kind: &str,
99-
id: ast::NodeId)
100+
kind: &str)
100101
-> ValueRef {
101102
unsafe {
102-
let name = format!("{}{}\0", kind, id);
103-
let gv = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(cv).to_ref(),
104-
name.as_ptr() as *const _);
103+
// FIXME: this totally needs a better name generation scheme, perhaps a simple global
104+
// counter? Also most other uses of gensym in trans.
105+
let gsym = token::gensym("_");
106+
let name = format!("{}{}", kind, gsym.usize());
107+
let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
108+
ccx.sess().bug(&format!("symbol `{}` is already defined", name));
109+
});
105110
llvm::LLVMSetInitializer(gv, cv);
106111
SetLinkage(gv, InternalLinkage);
107112
SetUnnamedAddr(gv, true);
@@ -111,14 +116,13 @@ fn addr_of_mut(ccx: &CrateContext,
111116

112117
pub fn addr_of(ccx: &CrateContext,
113118
cv: ValueRef,
114-
kind: &str,
115-
id: ast::NodeId)
119+
kind: &str)
116120
-> ValueRef {
117121
match ccx.const_globals().borrow().get(&cv) {
118122
Some(&gv) => return gv,
119123
None => {}
120124
}
121-
let gv = addr_of_mut(ccx, cv, kind, id);
125+
let gv = addr_of_mut(ccx, cv, kind);
122126
unsafe {
123127
llvm::LLVMSetGlobalConstant(gv, True);
124128
}
@@ -232,7 +236,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
232236
}
233237
};
234238

235-
let lvalue = addr_of(ccx, val, "const", expr.id);
239+
let lvalue = addr_of(ccx, val, "const");
236240
ccx.const_values().borrow_mut().insert(key, lvalue);
237241
lvalue
238242
}
@@ -280,7 +284,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
280284
if adj.autoderefs == 0 {
281285
// Don't copy data to do a deref+ref
282286
// (i.e., skip the last auto-deref).
283-
llconst = addr_of(cx, llconst, "autoref", e.id);
287+
llconst = addr_of(cx, llconst, "autoref");
284288
} else {
285289
// Seeing as we are deref'ing here and take a reference
286290
// again to make the pointer part of the far pointer below,
@@ -308,7 +312,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
308312
None => {}
309313
Some(box ty::AutoUnsafe(_, None)) |
310314
Some(box ty::AutoPtr(_, _, None)) => {
311-
llconst = addr_of(cx, llconst, "autoref", e.id);
315+
llconst = addr_of(cx, llconst, "autoref");
312316
}
313317
Some(box ty::AutoUnsize(ref k)) => {
314318
let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
@@ -591,12 +595,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
591595
// If this isn't the address of a static, then keep going through
592596
// normal constant evaluation.
593597
let (v, _) = const_expr(cx, &**sub, param_substs);
594-
addr_of(cx, v, "ref", e.id)
598+
addr_of(cx, v, "ref")
595599
}
596600
}
597601
ast::ExprAddrOf(ast::MutMutable, ref sub) => {
598602
let (v, _) = const_expr(cx, &**sub, param_substs);
599-
addr_of_mut(cx, v, "ref_mut_slice", e.id)
603+
addr_of_mut(cx, v, "ref_mut_slice")
600604
}
601605
ast::ExprTup(ref es) => {
602606
let repr = adt::represent_type(cx, ety);
@@ -746,7 +750,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
746750
}
747751
}
748752

749-
pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
753+
pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) -> ValueRef {
750754
unsafe {
751755
let _icx = push_ctxt("trans_static");
752756
let g = base::get_item_val(ccx, id);
@@ -772,6 +776,7 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
772776
}
773777
}
774778
debuginfo::create_global_var_metadata(ccx, id, g);
779+
g
775780
}
776781
}
777782

src/librustc_trans/trans/context.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use trans::base;
2020
use trans::builder::Builder;
2121
use trans::common::{ExternMap,tydesc_info,BuilderRef_res};
2222
use trans::debuginfo;
23+
use trans::declare;
2324
use trans::monomorphize::MonoId;
2425
use trans::type_::{Type, TypeNames};
2526
use middle::subst::Substs;
@@ -137,7 +138,6 @@ pub struct LocalCrateContext<'tcx> {
137138
llsizingtypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
138139
adt_reprs: RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>>,
139140
type_hashcodes: RefCell<FnvHashMap<Ty<'tcx>, String>>,
140-
all_llvm_symbols: RefCell<FnvHashSet<String>>,
141141
int_type: Type,
142142
opaque_vec_type: Type,
143143
builder: BuilderRef_res,
@@ -418,7 +418,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
418418
llsizingtypes: RefCell::new(FnvHashMap()),
419419
adt_reprs: RefCell::new(FnvHashMap()),
420420
type_hashcodes: RefCell::new(FnvHashMap()),
421-
all_llvm_symbols: RefCell::new(FnvHashSet()),
422421
int_type: Type::from_ref(ptr::null_mut()),
423422
opaque_vec_type: Type::from_ref(ptr::null_mut()),
424423
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
@@ -673,10 +672,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
673672
&self.local.type_hashcodes
674673
}
675674

676-
pub fn all_llvm_symbols<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
677-
&self.local.all_llvm_symbols
678-
}
679-
680675
pub fn stats<'a>(&'a self) -> &'a Stats {
681676
&self.shared.stats
682677
}
@@ -756,17 +751,16 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
756751
macro_rules! ifn {
757752
($name:expr, fn() -> $ret:expr) => (
758753
if *key == $name {
759-
let f = base::decl_cdecl_fn(
760-
ccx, $name, Type::func(&[], &$ret),
761-
ty::mk_nil(ccx.tcx()));
754+
let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret),
755+
ty::mk_nil(ccx.tcx()));
762756
ccx.intrinsics().borrow_mut().insert($name, f.clone());
763757
return Some(f);
764758
}
765759
);
766760
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
767761
if *key == $name {
768-
let f = base::decl_cdecl_fn(ccx, $name,
769-
Type::func(&[$($arg),*], &$ret), ty::mk_nil(ccx.tcx()));
762+
let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret),
763+
ty::mk_nil(ccx.tcx()));
770764
ccx.intrinsics().borrow_mut().insert($name, f.clone());
771765
return Some(f);
772766
}
@@ -901,9 +895,9 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
901895
// The `if key == $name` is already in ifn!
902896
ifn!($name, fn($($arg),*) -> $ret);
903897
} else if *key == $name {
904-
let f = base::decl_cdecl_fn(ccx, stringify!($cname),
905-
Type::func(&[$($arg),*], &$ret),
906-
ty::mk_nil(ccx.tcx()));
898+
let f = declare::declare_cfn(ccx, stringify!($cname),
899+
Type::func(&[$($arg),*], &$ret),
900+
ty::mk_nil(ccx.tcx()));
907901
ccx.intrinsics().borrow_mut().insert($name, f.clone());
908902
return Some(f);
909903
}

src/librustc_trans/trans/controlflow.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
378378
let filename = C_str_slice(ccx, filename);
379379
let line = C_u32(ccx, loc.line as u32);
380380
let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false);
381-
let expr_file_line = consts::addr_of(ccx, expr_file_line_const,
382-
"panic_loc", call_info.id);
381+
let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc");
383382
let args = vec!(expr_file_line);
384383
let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem);
385384
let bcx = callee::trans_lang_call(bcx,
@@ -407,8 +406,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
407406
let filename = C_str_slice(ccx, filename);
408407
let line = C_u32(ccx, loc.line as u32);
409408
let file_line_const = C_struct(ccx, &[filename, line], false);
410-
let file_line = consts::addr_of(ccx, file_line_const,
411-
"panic_bounds_check_loc", call_info.id);
409+
let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc");
412410
let args = vec!(file_line, index, len);
413411
let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem);
414412
let bcx = callee::trans_lang_call(bcx,

src/librustc_trans/trans/debuginfo.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,9 @@ use llvm::debuginfo::*;
196196
use metadata::csearch;
197197
use middle::subst::{self, Substs};
198198
use trans::{self, adt, machine, type_of};
199-
use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block,
200-
C_bytes, NormalizingClosureTyper};
199+
use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, C_bytes,
200+
NormalizingClosureTyper};
201+
use trans::declare;
201202
use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
202203
use trans::monomorphize;
203204
use trans::type_::Type;
@@ -4071,7 +4072,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
40714072
/// section.
40724073
fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
40734074
-> llvm::ValueRef {
4074-
let section_var_name = b"__rustc_debug_gdb_scripts_section__\0";
4075+
let section_var_name = "__rustc_debug_gdb_scripts_section__";
40754076

40764077
let section_var = unsafe {
40774078
llvm::LLVMGetNamedGlobal(ccx.llmod(),
@@ -4085,10 +4086,11 @@ fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
40854086
unsafe {
40864087
let llvm_type = Type::array(&Type::i8(ccx),
40874088
section_contents.len() as u64);
4088-
let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
4089-
llvm_type.to_ref(),
4090-
section_var_name.as_ptr()
4091-
as *const _);
4089+
4090+
let section_var = declare::define_global(ccx, section_var_name,
4091+
llvm_type).unwrap_or_else(||{
4092+
ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name))
4093+
});
40924094
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
40934095
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
40944096
llvm::LLVMSetGlobalConstant(section_var, llvm::True);

0 commit comments

Comments
 (0)