Skip to content

Commit f1dabed

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 caea044 commit f1dabed

15 files changed

+430
-284
lines changed

src/librustc_trans/trans/base.rs

+80-200
Large diffs are not rendered by default.

src/librustc_trans/trans/callee.rs

+4-7
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;
@@ -326,13 +327,9 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
326327
debug!("tuple_fn_ty: {}", tuple_fn_ty.repr(tcx));
327328

328329
//
329-
let function_name =
330-
link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
331-
"fn_pointer_shim");
332-
let llfn =
333-
decl_internal_rust_fn(ccx,
334-
tuple_fn_ty,
335-
&function_name[..]);
330+
let function_name = link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
331+
"fn_pointer_shim");
332+
let llfn = declare::declare_internal_rust_fn(ccx, &function_name[..], tuple_fn_ty);
336333

337334
//
338335
let empty_substs = tcx.mk_substs(Substs::trans_empty());

src/librustc_trans/trans/cleanup.rs

+3-4
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

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use trans::cleanup::{CleanupMethods, CustomScope, ScopeId};
2121
use trans::common::*;
2222
use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue};
2323
use trans::debuginfo::{self, DebugLoc};
24+
use trans::declare;
2425
use trans::expr;
2526
use trans::monomorphize::{self, MonoId};
2627
use trans::type_of::*;
@@ -162,7 +163,11 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
162163
mangle_internal_name_by_path_and_seq(path, "closure")
163164
});
164165

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

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

src/librustc_trans/trans/common.rs

+5-3
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;
@@ -872,9 +873,10 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
872873
!null_terminated as Bool);
873874

874875
let gsym = token::gensym("str");
875-
let buf = CString::new(format!("str{}", gsym.usize()));
876-
let buf = buf.unwrap();
877-
let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
876+
let sym = format!("str{}", gsym.usize());
877+
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
878+
cx.sess().bug(&format!("symbol `{}` is already defined", sym));
879+
});
878880
llvm::LLVMSetInitializer(g, sc);
879881
llvm::LLVMSetGlobalConstant(g, True);
880882
llvm::SetLinkage(g, llvm::InternalLinkage);

src/librustc_trans/trans/consts.rs

+19-14
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
2525
use trans::{adt, closure, debuginfo, expr, inline, machine};
2626
use trans::base::{self, push_ctxt};
2727
use trans::common::*;
28+
use trans::declare;
2829
use trans::monomorphize;
2930
use trans::type_::Type;
3031
use trans::type_of;
@@ -35,6 +36,7 @@ use util::ppaux::{Repr, ty_to_string};
3536
use std::iter::repeat;
3637
use libc::c_uint;
3738
use syntax::{ast, ast_util};
39+
use syntax::parse::token;
3840
use syntax::ptr::P;
3941

4042
pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
@@ -96,13 +98,16 @@ pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
9698

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

113118
pub fn addr_of(ccx: &CrateContext,
114119
cv: ValueRef,
115-
kind: &str,
116-
id: ast::NodeId)
120+
kind: &str)
117121
-> ValueRef {
118122
match ccx.const_globals().borrow().get(&cv) {
119123
Some(&gv) => return gv,
120124
None => {}
121125
}
122-
let gv = addr_of_mut(ccx, cv, kind, id);
126+
let gv = addr_of_mut(ccx, cv, kind);
123127
unsafe {
124128
llvm::LLVMSetGlobalConstant(gv, True);
125129
}
@@ -233,7 +237,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
233237
}
234238
};
235239

236-
let lvalue = addr_of(ccx, val, "const", expr.id);
240+
let lvalue = addr_of(ccx, val, "const");
237241
ccx.const_values().borrow_mut().insert(key, lvalue);
238242
lvalue
239243
}
@@ -284,7 +288,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
284288
if adj.autoderefs == 0 {
285289
// Don't copy data to do a deref+ref
286290
// (i.e., skip the last auto-deref).
287-
llconst = addr_of(cx, llconst, "autoref", e.id);
291+
llconst = addr_of(cx, llconst, "autoref");
288292
} else {
289293
// Seeing as we are deref'ing here and take a reference
290294
// again to make the pointer part of the far pointer below,
@@ -312,7 +316,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
312316
None => {}
313317
Some(box ty::AutoUnsafe(_, None)) |
314318
Some(box ty::AutoPtr(_, _, None)) => {
315-
llconst = addr_of(cx, llconst, "autoref", e.id);
319+
llconst = addr_of(cx, llconst, "autoref");
316320
}
317321
Some(box ty::AutoUnsize(ref k)) => {
318322
let info =
@@ -711,12 +715,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
711715
// If this isn't the address of a static, then keep going through
712716
// normal constant evaluation.
713717
let (v, _) = const_expr(cx, &**sub, param_substs);
714-
addr_of(cx, v, "ref", e.id)
718+
addr_of(cx, v, "ref")
715719
}
716720
}
717721
ast::ExprAddrOf(ast::MutMutable, ref sub) => {
718722
let (v, _) = const_expr(cx, &**sub, param_substs);
719-
addr_of_mut(cx, v, "ref_mut_slice", e.id)
723+
addr_of_mut(cx, v, "ref_mut_slice")
720724
}
721725
ast::ExprTup(ref es) => {
722726
let repr = adt::represent_type(cx, ety);
@@ -862,7 +866,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
862866
}
863867
}
864868

865-
pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
869+
pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) -> ValueRef {
866870
unsafe {
867871
let _icx = push_ctxt("trans_static");
868872
let g = base::get_item_val(ccx, id);
@@ -888,6 +892,7 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
888892
}
889893
}
890894
debuginfo::create_global_var_metadata(ccx, id, g);
895+
g
891896
}
892897
}
893898

src/librustc_trans/trans/context.rs

+8-14
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,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;
@@ -133,7 +134,6 @@ pub struct LocalCrateContext<'tcx> {
133134
llsizingtypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
134135
adt_reprs: RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>>,
135136
type_hashcodes: RefCell<FnvHashMap<Ty<'tcx>, String>>,
136-
all_llvm_symbols: RefCell<FnvHashSet<String>>,
137137
int_type: Type,
138138
opaque_vec_type: Type,
139139
builder: BuilderRef_res,
@@ -413,7 +413,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
413413
llsizingtypes: RefCell::new(FnvHashMap()),
414414
adt_reprs: RefCell::new(FnvHashMap()),
415415
type_hashcodes: RefCell::new(FnvHashMap()),
416-
all_llvm_symbols: RefCell::new(FnvHashSet()),
417416
int_type: Type::from_ref(ptr::null_mut()),
418417
opaque_vec_type: Type::from_ref(ptr::null_mut()),
419418
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
@@ -653,10 +652,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
653652
&self.local.type_hashcodes
654653
}
655654

656-
pub fn all_llvm_symbols<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
657-
&self.local.all_llvm_symbols
658-
}
659-
660655
pub fn stats<'a>(&'a self) -> &'a Stats {
661656
&self.shared.stats
662657
}
@@ -743,17 +738,16 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
743738
macro_rules! ifn {
744739
($name:expr, fn() -> $ret:expr) => (
745740
if *key == $name {
746-
let f = base::decl_cdecl_fn(
747-
ccx, $name, Type::func(&[], &$ret),
748-
ty::mk_nil(ccx.tcx()));
741+
let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret),
742+
ty::mk_nil(ccx.tcx()));
749743
ccx.intrinsics().borrow_mut().insert($name, f.clone());
750744
return Some(f);
751745
}
752746
);
753747
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
754748
if *key == $name {
755-
let f = base::decl_cdecl_fn(ccx, $name,
756-
Type::func(&[$($arg),*], &$ret), ty::mk_nil(ccx.tcx()));
749+
let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret),
750+
ty::mk_nil(ccx.tcx()));
757751
ccx.intrinsics().borrow_mut().insert($name, f.clone());
758752
return Some(f);
759753
}
@@ -888,9 +882,9 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
888882
// The `if key == $name` is already in ifn!
889883
ifn!($name, fn($($arg),*) -> $ret);
890884
} else if *key == $name {
891-
let f = base::decl_cdecl_fn(ccx, stringify!($cname),
892-
Type::func(&[$($arg),*], &$ret),
893-
ty::mk_nil(ccx.tcx()));
885+
let f = declare::declare_cfn(ccx, stringify!($cname),
886+
Type::func(&[$($arg),*], &$ret),
887+
ty::mk_nil(ccx.tcx()));
894888
ccx.intrinsics().borrow_mut().insert($name, f.clone());
895889
return Some(f);
896890
}

src/librustc_trans/trans/controlflow.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
417417
let filename = C_str_slice(ccx, filename);
418418
let line = C_u32(ccx, loc.line as u32);
419419
let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false);
420-
let expr_file_line = consts::addr_of(ccx, expr_file_line_const,
421-
"panic_loc", call_info.id);
420+
let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc");
422421
let args = vec!(expr_file_line);
423422
let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem);
424423
let bcx = callee::trans_lang_call(bcx,
@@ -450,8 +449,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
450449
let filename = C_str_slice(ccx, filename);
451450
let line = C_u32(ccx, loc.line as u32);
452451
let file_line_const = C_struct(ccx, &[filename, line], false);
453-
let file_line = consts::addr_of(ccx, file_line_const,
454-
"panic_bounds_check_loc", call_info.id);
452+
let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc");
455453
let args = vec!(file_line, index, len);
456454
let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem);
457455
let bcx = callee::trans_lang_call(bcx,

src/librustc_trans/trans/debuginfo.rs

+9-7
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)