use rustc::ty::{self, Ty, TyCtxt};
use session::config::NoDebugInfo;
use session::Session;
+use session::config;
use symbol_map::SymbolMap;
use util::sha2::Sha256;
- use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+ use util::nodemap::{NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
- /// Track mapping of external ids to local items imported for inlining
- external: RefCell<DefIdMap<Option<ast::NodeId>>>,
- /// Backwards version of the `external` map (inlined items to where they
- /// came from)
- external_srcs: RefCell<NodeMap<DefId>>,
/// Cache instances of monomorphic and polymorphic items
instances: RefCell<FnvHashMap<Instance<'tcx>, ValueRef>>,
monomorphizing: RefCell<DefIdMap<usize>>,
}
}
+pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
+ let reloc_model_arg = match sess.opts.cg.relocation_model {
+ Some(ref s) => &s[..],
+ None => &sess.target.target.options.relocation_model[..],
+ };
+
+ match reloc_model_arg {
+ "pic" => llvm::RelocPIC,
+ "static" => llvm::RelocStatic,
+ "default" => llvm::RelocDefault,
+ "dynamic-no-pic" => llvm::RelocDynamicNoPic,
+ _ => {
+ sess.err(&format!("{:?} is not a valid relocation mode",
+ sess.opts
+ .cg
+ .relocation_model));
+ sess.abort_if_errors();
+ bug!();
+ }
+ }
+}
+
+fn is_any_library(sess: &Session) -> bool {
+ sess.crate_types.borrow().iter().any(|ty| {
+ *ty != config::CrateTypeExecutable
+ })
+}
+
+pub fn is_pie_binary(sess: &Session) -> bool {
+ !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocPIC
+}
+
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
let mod_name = CString::new(mod_name).unwrap();
let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
.ok().expect("got a non-UTF8 data-layout from LLVM");
- if sess.target.target.data_layout != data_layout {
+ // Unfortunately LLVM target specs change over time, and right now we
+ // don't have proper support to work with any more than one
+ // `data_layout` than the one that is in the rust-lang/rust repo. If
+ // this compiler is configured against a custom LLVM, we may have a
+ // differing data layout, even though we should update our own to use
+ // that one.
+ //
+ // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
+ // disable this check entirely as we may be configured with something
+ // that has a different target layout.
+ //
+ // Unsure if this will actually cause breakage when rustc is configured
+ // as such.
+ //
+ // FIXME(#34960)
+ let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
+ let custom_llvm_used = cfg_llvm_root.trim() != "";
+
+ if !custom_llvm_used && sess.target.target.data_layout != data_layout {
bug!("data-layout for builtin `{}` target, `{}`, \
differs from LLVM default, `{}`",
sess.target.target.llvm_target,
let llvm_target = sess.target.target.llvm_target.as_bytes();
let llvm_target = CString::new(llvm_target).unwrap();
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
+
+ if is_pie_binary(sess) {
+ llvm::LLVMRustSetModulePIELevel(llmod);
+ }
+
(llcx, llmod)
}
&llmod_id[..]);
let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
- Some(debuginfo::CrateDebugContext::new(llmod))
+ let dctx = debuginfo::CrateDebugContext::new(llmod);
+ debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess);
+ Some(dctx)
} else {
None
};
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
fn_pointer_shims: RefCell::new(FnvHashMap()),
drop_glues: RefCell::new(FnvHashMap()),
- external: RefCell::new(DefIdMap()),
- external_srcs: RefCell::new(NodeMap()),
instances: RefCell::new(FnvHashMap()),
monomorphizing: RefCell::new(DefIdMap()),
vtables: RefCell::new(FnvHashMap()),
&self.local().drop_glues
}
- pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
- &self.local().external
+ pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option<ast::NodeId> {
+ self.sess().cstore.local_node_for_inlined_defid(def_id)
}
- pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<DefId>> {
- &self.local().external_srcs
+ pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> {
+ self.sess().cstore.defid_for_inlined_node(node_id)
}
pub fn instances<'a>(&'a self) -> &'a RefCell<FnvHashMap<Instance<'tcx>, ValueRef>> {
fn_should_be_ignored, is_node_local_to_unit};
use super::namespace::mangled_name_of_item;
use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
-use super::{declare_local, VariableKind, VariableAccess};
+use super::{declare_local, VariableKind, VariableAccess, CrateDebugContext};
+use context::SharedCrateContext;
+use session::Session;
use llvm::{self, ValueRef};
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
use syntax::parse::token;
use syntax_pos::{self, Span};
-
// From DWARF 5.
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
const DW_LANG_RUST: c_uint = 0x1c;
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
// ptr::null() doesn't work :(
-pub const NO_FILE_METADATA: DIFile = (0 as DIFile);
pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
const FLAGS_NONE: c_uint = 0;
// First, find out the 'real' def_id of the type. Items inlined from
// other crates have to be mapped back to their source.
let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
- match cx.external_srcs().borrow().get(&node_id).cloned() {
- Some(source_def_id) => {
- // The given def_id identifies the inlined copy of a
- // type definition, let's take the source of the copy.
- source_def_id
- }
- None => def_id
+ if cx.tcx().map.is_inlined(node_id) {
+ // The given def_id identifies the inlined copy of a
+ // type definition, let's take the source of the copy.
+ cx.defid_for_inlined_node(node_id).unwrap()
+ } else {
+ def_id
}
} else {
def_id
unsafe {
llvm::LLVMDIBuilderCreateSubroutineType(
DIB(cx),
- NO_FILE_METADATA,
+ unknown_file_metadata(cx),
create_DIArray(DIB(cx), &signature_metadata[..]))
},
false);
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
+ let file_metadata = unknown_file_metadata(cx);
composite_type_metadata(cx,
trait_llvm_type,
unique_type_id,
&[],
containing_scope,
- NO_FILE_METADATA,
+ file_metadata,
syntax_pos::DUMMY_SP)
}
return ptr_metadata;
}
-pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
- let work_dir = &cx.sess().working_dir;
- let compile_unit_name = match cx.sess().local_crate_source_file {
- None => fallback_path(cx),
+pub fn compile_unit_metadata(scc: &SharedCrateContext,
+ debug_context: &CrateDebugContext,
+ sess: &Session)
+ -> DIDescriptor {
+ let work_dir = &sess.working_dir;
+ let compile_unit_name = match sess.local_crate_source_file {
+ None => fallback_path(scc),
Some(ref abs_path) => {
if abs_path.is_relative() {
- cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
- fallback_path(cx)
+ sess.warn("debuginfo: Invalid path to crate's local root source file!");
+ fallback_path(scc)
} else {
match abs_path.strip_prefix(work_dir) {
Ok(ref p) if p.is_relative() => {
path2cstr(&Path::new(".").join(p))
}
}
- _ => fallback_path(cx)
+ _ => fallback_path(scc)
}
}
}
let split_name = "\0";
return unsafe {
llvm::LLVMDIBuilderCreateCompileUnit(
- debug_context(cx).builder,
+ debug_context.builder,
DW_LANG_RUST,
compile_unit_name,
work_dir.as_ptr(),
producer.as_ptr(),
- cx.sess().opts.optimize != config::OptLevel::No,
+ sess.opts.optimize != config::OptLevel::No,
flags.as_ptr() as *const _,
0,
split_name.as_ptr() as *const _)
};
- fn fallback_path(cx: &CrateContext) -> CString {
- CString::new(cx.link_meta().crate_name.clone()).unwrap()
+ fn fallback_path(scc: &SharedCrateContext) -> CString {
+ CString::new(scc.link_meta().crate_name.clone()).unwrap()
}
}
DIB(cx),
containing_scope,
name.as_ptr(),
- NO_FILE_METADATA,
+ file_metadata,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(discriminant_size),
bytes_to_bits(discriminant_align),
DIB(cx),
composite_type_metadata,
member_name.as_ptr(),
- NO_FILE_METADATA,
+ unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER,
bytes_to_bits(member_size),
bytes_to_bits(member_align),
DIB(cx),
containing_scope,
name.as_ptr(),
- NO_FILE_METADATA,
+ unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER,
bytes_to_bits(struct_size),
bytes_to_bits(struct_align),
// crate should already contain debuginfo for it. More importantly, the
// global might not even exist in un-inlined form anywhere which would lead
// to a linker errors.
- if cx.external_srcs().borrow().contains_key(&node_id) {
+ if cx.tcx().map.is_inlined(node_id) {
return;
}
let loc = span_start(cx, span);
(file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
- (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
+ (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
};
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
use self::namespace::mangled_name_of_item;
use self::type_names::compute_debuginfo_type_name;
use self::metadata::{type_metadata, diverging_type_metadata};
-use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
+use self::metadata::{file_metadata, scope_metadata, TypeMap};
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
use llvm;
mod utils;
mod namespace;
mod type_names;
-mod metadata;
+pub mod metadata;
mod create_scope_map;
mod source_loc;
}
debug!("finalize");
- let _ = compile_unit_metadata(cx);
if gdb::needs_gdb_debug_scripts_section(cx) {
// Add a .debug_gdb_scripts section to this compile-unit. This will
});
// Try to get some span information, if we have an inlined item.
- let definition_span = match cx.external().borrow().get(&instance.def) {
- Some(&Some(node_id)) => cx.tcx().map.span(node_id),
- _ => cx.tcx().map.def_id_span(instance.def, syntax_pos::DUMMY_SP)
- };
+ let definition_span = cx.tcx()
+ .map
+ .def_id_span(instance.def, syntax_pos::DUMMY_SP);
(containing_scope, definition_span)
}