self.debugging_opts.dump_dep_graph ||
self.debugging_opts.query_dep_graph
}
+
+ pub fn single_codegen_unit(&self) -> bool {
+ self.incremental.is_none() ||
+ self.cg.codegen_units == 1
+ }
}
// The type of entry function, so
"panic strategy to compile crate with"),
}
-
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
build_debugging_options, "Z", "debugging",
DB_OPTIONS, db_type_desc, dbsetters,
pub is_like_android: bool,
/// Whether the linker support GNU-like arguments such as -O. Defaults to false.
pub linker_is_gnu: bool,
+ /// The MinGW toolchain has a known issue that prevents it from correctly
+ /// handling COFF object files with more than 2^15 sections. Since each weak
+ /// symbol needs its own COMDAT section, weak linkage implies a large
+ /// number sections that easily exceeds the given limit for larger
+ /// codebases. Consequently we want a way to disallow weak linkage on some
+ /// platforms.
+ pub allows_weak_linkage: bool,
/// Whether the linker support rpaths or not. Defaults to false.
pub has_rpath: bool,
/// Whether to disable linking to compiler-rt. Defaults to false, as LLVM
is_like_android: false,
is_like_msvc: false,
linker_is_gnu: false,
+ allows_weak_linkage: true,
has_rpath: false,
no_compiler_rt: false,
no_default_libraries: true,
key!(is_like_msvc, bool);
key!(is_like_android, bool);
key!(linker_is_gnu, bool);
+ key!(allows_weak_linkage, bool);
key!(has_rpath, bool);
key!(no_compiler_rt, bool);
key!(no_default_libraries, bool);
target_option_val!(is_like_msvc);
target_option_val!(is_like_android);
target_option_val!(linker_is_gnu);
+ target_option_val!(allows_weak_linkage);
target_option_val!(has_rpath);
target_option_val!(no_compiler_rt);
target_option_val!(no_default_libraries);
staticlib_suffix: ".lib".to_string(),
no_default_libraries: true,
is_like_windows: true,
+ allows_weak_linkage: false,
pre_link_args: vec!(
// And here, we see obscure linker flags #45. On windows, it has been
// found to be necessary to have this flag to compile liblibc.
llfn
}
+fn translating_closure_body_via_mir_will_fail(ccx: &CrateContext,
+ closure_def_id: DefId)
+ -> bool {
+ let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
+ let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
+ let use_mir = default_to_mir ^ ccx.tcx().has_attr(closure_def_id, invert);
+
+ !use_mir
+}
+
+pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+ closure_def_id: DefId,
+ closure_substs: ty::ClosureSubsts<'tcx>) {
+ use syntax::ast::DUMMY_NODE_ID;
+ use syntax_pos::DUMMY_SP;
+ use syntax::ptr::P;
+
+ trans_closure_expr(Dest::Ignore(ccx),
+ &hir::FnDecl {
+ inputs: P::new(),
+ output: hir::NoReturn(DUMMY_SP),
+ variadic: false
+ },
+ &hir::Block {
+ stmts: P::new(),
+ expr: None,
+ id: DUMMY_NODE_ID,
+ rules: hir::DefaultBlock,
+ span: DUMMY_SP
+ },
+ DUMMY_NODE_ID,
+ closure_def_id,
+ closure_substs);
+}
+
pub enum Dest<'a, 'tcx: 'a> {
SaveIn(Block<'a, 'tcx>, ValueRef),
Ignore(&'a CrateContext<'a, 'tcx>)
// If we have not done so yet, translate this closure's body
if !ccx.instances().borrow().contains_key(&instance) {
let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
- llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
- llvm::SetUniqueComdat(ccx.llmod(), llfn);
+
+ if ccx.sess().target.target.options.allows_weak_linkage {
+ llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
+ llvm::SetUniqueComdat(ccx.llmod(), llfn);
+ } else {
+ llvm::SetLinkage(llfn, llvm::InternalLinkage);
+ }
// set an inline hint for all closures
attributes::inline(llfn, attributes::InlineAttr::Hint);
// If this is a closure, redirect to it.
let llfn = get_or_create_closure_declaration(ccx, closure_def_id, substs);
+ // If weak linkage is not allowed, we have to make sure that a local,
+ // private copy of the closure is available in this codegen unit
+ if !ccx.sess().target.target.options.allows_weak_linkage &&
+ !ccx.sess().opts.single_codegen_unit() {
+
+ if let Some(node_id) = ccx.tcx().map.as_local_node_id(closure_def_id) {
+ // If the closure is defined in the local crate, we can always just
+ // translate it.
+ let (decl, body) = match ccx.tcx().map.expect_expr(node_id).node {
+ hir::ExprClosure(_, ref decl, ref body, _) => (decl, body),
+ _ => { unreachable!() }
+ };
+
+ trans_closure_expr(Dest::Ignore(ccx),
+ decl,
+ body,
+ node_id,
+ closure_def_id,
+ substs);
+ } else {
+ // If the closure is defined in an upstream crate, we can only
+ // translate it if MIR-trans is active.
+
+ if translating_closure_body_via_mir_will_fail(ccx, closure_def_id) {
+ ccx.sess().fatal("You have run into a known limitation of the \
+ MingW toolchain. Either compile with -Zorbit or \
+ with -Ccodegen-units=1 to work around it.");
+ }
+
+ trans_closure_body_via_mir(ccx, closure_def_id, substs);
+ }
+ }
+
// If the closure is a Fn closure, but a FnOnce is needed (etc),
// then adapt the self type
let llfn_closure_kind = ccx.tcx().closure_kind(closure_def_id);
// FIXME Shouldn't need to manually trigger closure instantiations.
if let mir::AggregateKind::Closure(def_id, substs) = *kind {
- use rustc::hir;
- use syntax::ast::DUMMY_NODE_ID;
- use syntax::ptr::P;
use closure;
-
- closure::trans_closure_expr(closure::Dest::Ignore(self.ccx),
- &hir::FnDecl {
- inputs: P::new(),
- output: hir::NoReturn(DUMMY_SP),
- variadic: false
- },
- &hir::Block {
- stmts: P::new(),
- expr: None,
- id: DUMMY_NODE_ID,
- rules: hir::DefaultBlock,
- span: DUMMY_SP
- },
- DUMMY_NODE_ID, def_id,
- self.monomorphize(&substs));
+ closure::trans_closure_body_via_mir(self.ccx,
+ def_id,
+ self.monomorphize(&substs));
}
let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind {
_ => {
// FIXME Shouldn't need to manually trigger closure instantiations.
if let mir::AggregateKind::Closure(def_id, substs) = *kind {
- use rustc::hir;
- use syntax::ast::DUMMY_NODE_ID;
- use syntax::ptr::P;
- use syntax_pos::DUMMY_SP;
use closure;
- closure::trans_closure_expr(closure::Dest::Ignore(bcx.ccx()),
- &hir::FnDecl {
- inputs: P::new(),
- output: hir::NoReturn(DUMMY_SP),
- variadic: false
- },
- &hir::Block {
- stmts: P::new(),
- expr: None,
- id: DUMMY_NODE_ID,
- rules: hir::DefaultBlock,
- span: DUMMY_SP
- },
- DUMMY_NODE_ID, def_id,
- bcx.monomorphize(&substs));
+ closure::trans_closure_body_via_mir(bcx.ccx(),
+ def_id,
+ bcx.monomorphize(&substs));
}
for (i, operand) in operands.iter().enumerate() {