Skip to content

Commit

Permalink
Introduce trans::declare
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nagisa committed Apr 3, 2015
1 parent caea044 commit f1dabed
Show file tree
Hide file tree
Showing 15 changed files with 430 additions and 284 deletions.
280 changes: 80 additions & 200 deletions src/librustc_trans/trans/base.rs

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions src/librustc_trans/trans/callee.rs
Expand Up @@ -41,6 +41,7 @@ use trans::common::{self, Block, Result, NodeIdAndSpan, ExprId, CrateContext,
use trans::consts;
use trans::datum::*;
use trans::debuginfo::{DebugLoc, ToDebugLoc};
use trans::declare;
use trans::expr;
use trans::glue;
use trans::inline;
Expand Down Expand Up @@ -326,13 +327,9 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
debug!("tuple_fn_ty: {}", tuple_fn_ty.repr(tcx));

//
let function_name =
link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
"fn_pointer_shim");
let llfn =
decl_internal_rust_fn(ccx,
tuple_fn_ty,
&function_name[..]);
let function_name = link::mangle_internal_name_by_type_and_seq(ccx, bare_fn_ty,
"fn_pointer_shim");
let llfn = declare::declare_internal_rust_fn(ccx, &function_name[..], tuple_fn_ty);

//
let empty_substs = tcx.mk_substs(Substs::trans_empty());
Expand Down
7 changes: 3 additions & 4 deletions src/librustc_trans/trans/cleanup.rs
Expand Up @@ -126,6 +126,7 @@ use trans::callee;
use trans::common;
use trans::common::{Block, FunctionContext, ExprId, NodeIdAndSpan};
use trans::debuginfo::{DebugLoc, ToDebugLoc};
use trans::declare;
use trans::glue;
use middle::region;
use trans::type_::Type;
Expand Down Expand Up @@ -844,10 +845,8 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
Some(llpersonality) => llpersonality,
None => {
let fty = Type::variadic_func(&[], &Type::i32(self.ccx));
let f = base::decl_cdecl_fn(self.ccx,
"rust_eh_personality",
fty,
self.ccx.tcx().types.i32);
let f = declare::declare_cfn(self.ccx, "rust_eh_personality", fty,
self.ccx.tcx().types.i32);
*personality = Some(f);
f
}
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_trans/trans/closure.rs
Expand Up @@ -21,6 +21,7 @@ use trans::cleanup::{CleanupMethods, CustomScope, ScopeId};
use trans::common::*;
use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue};
use trans::debuginfo::{self, DebugLoc};
use trans::declare;
use trans::expr;
use trans::monomorphize::{self, MonoId};
use trans::type_of::*;
Expand Down Expand Up @@ -162,7 +163,11 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
mangle_internal_name_by_path_and_seq(path, "closure")
});

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

// set an inline hint for all closures
attributes::inline(llfn, attributes::InlineAttr::Hint);
Expand Down
8 changes: 5 additions & 3 deletions src/librustc_trans/trans/common.rs
Expand Up @@ -31,6 +31,7 @@ use trans::cleanup;
use trans::consts;
use trans::datum;
use trans::debuginfo::{self, DebugLoc};
use trans::declare;
use trans::machine;
use trans::monomorphize;
use trans::type_::Type;
Expand Down Expand Up @@ -872,9 +873,10 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
!null_terminated as Bool);

let gsym = token::gensym("str");
let buf = CString::new(format!("str{}", gsym.usize()));
let buf = buf.unwrap();
let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
let sym = format!("str{}", gsym.usize());
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
cx.sess().bug(&format!("symbol `{}` is already defined", sym));
});
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True);
llvm::SetLinkage(g, llvm::InternalLinkage);
Expand Down
33 changes: 19 additions & 14 deletions src/librustc_trans/trans/consts.rs
Expand Up @@ -25,6 +25,7 @@ use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
use trans::{adt, closure, debuginfo, expr, inline, machine};
use trans::base::{self, push_ctxt};
use trans::common::*;
use trans::declare;
use trans::monomorphize;
use trans::type_::Type;
use trans::type_of;
Expand All @@ -35,6 +36,7 @@ use util::ppaux::{Repr, ty_to_string};
use std::iter::repeat;
use libc::c_uint;
use syntax::{ast, ast_util};
use syntax::parse::token;
use syntax::ptr::P;

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

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

pub fn addr_of(ccx: &CrateContext,
cv: ValueRef,
kind: &str,
id: ast::NodeId)
kind: &str)
-> ValueRef {
match ccx.const_globals().borrow().get(&cv) {
Some(&gv) => return gv,
None => {}
}
let gv = addr_of_mut(ccx, cv, kind, id);
let gv = addr_of_mut(ccx, cv, kind);
unsafe {
llvm::LLVMSetGlobalConstant(gv, True);
}
Expand Down Expand Up @@ -233,7 +237,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
};

let lvalue = addr_of(ccx, val, "const", expr.id);
let lvalue = addr_of(ccx, val, "const");
ccx.const_values().borrow_mut().insert(key, lvalue);
lvalue
}
Expand Down Expand Up @@ -284,7 +288,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
if adj.autoderefs == 0 {
// Don't copy data to do a deref+ref
// (i.e., skip the last auto-deref).
llconst = addr_of(cx, llconst, "autoref", e.id);
llconst = addr_of(cx, llconst, "autoref");
} else {
// Seeing as we are deref'ing here and take a reference
// again to make the pointer part of the far pointer below,
Expand Down Expand Up @@ -312,7 +316,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
None => {}
Some(box ty::AutoUnsafe(_, None)) |
Some(box ty::AutoPtr(_, _, None)) => {
llconst = addr_of(cx, llconst, "autoref", e.id);
llconst = addr_of(cx, llconst, "autoref");
}
Some(box ty::AutoUnsize(ref k)) => {
let info =
Expand Down Expand Up @@ -711,12 +715,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// If this isn't the address of a static, then keep going through
// normal constant evaluation.
let (v, _) = const_expr(cx, &**sub, param_substs);
addr_of(cx, v, "ref", e.id)
addr_of(cx, v, "ref")
}
}
ast::ExprAddrOf(ast::MutMutable, ref sub) => {
let (v, _) = const_expr(cx, &**sub, param_substs);
addr_of_mut(cx, v, "ref_mut_slice", e.id)
addr_of_mut(cx, v, "ref_mut_slice")
}
ast::ExprTup(ref es) => {
let repr = adt::represent_type(cx, ety);
Expand Down Expand Up @@ -862,7 +866,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
}

pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) -> ValueRef {
unsafe {
let _icx = push_ctxt("trans_static");
let g = base::get_item_val(ccx, id);
Expand All @@ -888,6 +892,7 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
}
}
debuginfo::create_global_var_metadata(ccx, id, g);
g
}
}

Expand Down
22 changes: 8 additions & 14 deletions src/librustc_trans/trans/context.rs
Expand Up @@ -20,6 +20,7 @@ use trans::base;
use trans::builder::Builder;
use trans::common::{ExternMap,BuilderRef_res};
use trans::debuginfo;
use trans::declare;
use trans::monomorphize::MonoId;
use trans::type_::{Type, TypeNames};
use middle::subst::Substs;
Expand Down Expand Up @@ -133,7 +134,6 @@ pub struct LocalCrateContext<'tcx> {
llsizingtypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
adt_reprs: RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>>,
type_hashcodes: RefCell<FnvHashMap<Ty<'tcx>, String>>,
all_llvm_symbols: RefCell<FnvHashSet<String>>,
int_type: Type,
opaque_vec_type: Type,
builder: BuilderRef_res,
Expand Down Expand Up @@ -413,7 +413,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
llsizingtypes: RefCell::new(FnvHashMap()),
adt_reprs: RefCell::new(FnvHashMap()),
type_hashcodes: RefCell::new(FnvHashMap()),
all_llvm_symbols: RefCell::new(FnvHashSet()),
int_type: Type::from_ref(ptr::null_mut()),
opaque_vec_type: Type::from_ref(ptr::null_mut()),
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
Expand Down Expand Up @@ -653,10 +652,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local.type_hashcodes
}

pub fn all_llvm_symbols<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
&self.local.all_llvm_symbols
}

pub fn stats<'a>(&'a self) -> &'a Stats {
&self.shared.stats
}
Expand Down Expand Up @@ -743,17 +738,16 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
macro_rules! ifn {
($name:expr, fn() -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(
ccx, $name, Type::func(&[], &$ret),
ty::mk_nil(ccx.tcx()));
let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret),
ty::mk_nil(ccx.tcx()));
ccx.intrinsics().borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(ccx, $name,
Type::func(&[$($arg),*], &$ret), ty::mk_nil(ccx.tcx()));
let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret),
ty::mk_nil(ccx.tcx()));
ccx.intrinsics().borrow_mut().insert($name, f.clone());
return Some(f);
}
Expand Down Expand Up @@ -888,9 +882,9 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
// The `if key == $name` is already in ifn!
ifn!($name, fn($($arg),*) -> $ret);
} else if *key == $name {
let f = base::decl_cdecl_fn(ccx, stringify!($cname),
Type::func(&[$($arg),*], &$ret),
ty::mk_nil(ccx.tcx()));
let f = declare::declare_cfn(ccx, stringify!($cname),
Type::func(&[$($arg),*], &$ret),
ty::mk_nil(ccx.tcx()));
ccx.intrinsics().borrow_mut().insert($name, f.clone());
return Some(f);
}
Expand Down
6 changes: 2 additions & 4 deletions src/librustc_trans/trans/controlflow.rs
Expand Up @@ -417,8 +417,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let filename = C_str_slice(ccx, filename);
let line = C_u32(ccx, loc.line as u32);
let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false);
let expr_file_line = consts::addr_of(ccx, expr_file_line_const,
"panic_loc", call_info.id);
let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc");
let args = vec!(expr_file_line);
let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem);
let bcx = callee::trans_lang_call(bcx,
Expand Down Expand Up @@ -450,8 +449,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let filename = C_str_slice(ccx, filename);
let line = C_u32(ccx, loc.line as u32);
let file_line_const = C_struct(ccx, &[filename, line], false);
let file_line = consts::addr_of(ccx, file_line_const,
"panic_bounds_check_loc", call_info.id);
let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc");
let args = vec!(file_line, index, len);
let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem);
let bcx = callee::trans_lang_call(bcx,
Expand Down
16 changes: 9 additions & 7 deletions src/librustc_trans/trans/debuginfo.rs
Expand Up @@ -196,8 +196,9 @@ use llvm::debuginfo::*;
use metadata::csearch;
use middle::subst::{self, Substs};
use trans::{self, adt, machine, type_of};
use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block,
C_bytes, NormalizingClosureTyper};
use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, C_bytes,
NormalizingClosureTyper};
use trans::declare;
use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
use trans::monomorphize;
use trans::type_::Type;
Expand Down Expand Up @@ -4071,7 +4072,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
/// section.
fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
-> llvm::ValueRef {
let section_var_name = b"__rustc_debug_gdb_scripts_section__\0";
let section_var_name = "__rustc_debug_gdb_scripts_section__";

let section_var = unsafe {
llvm::LLVMGetNamedGlobal(ccx.llmod(),
Expand All @@ -4085,10 +4086,11 @@ fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
unsafe {
let llvm_type = Type::array(&Type::i8(ccx),
section_contents.len() as u64);
let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
llvm_type.to_ref(),
section_var_name.as_ptr()
as *const _);

let section_var = declare::define_global(ccx, section_var_name,
llvm_type).unwrap_or_else(||{
ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name))
});
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
Expand Down

0 comments on commit f1dabed

Please sign in to comment.