From b6b4f5a0e7a98d918d7c5a56e291c0063f257f1e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 11 Aug 2015 11:48:43 -0700 Subject: [PATCH] trans: Re-enable unwinding on 64-bit MSVC This commit leverages the runtime support for DWARF exception info added in #27210 to enable unwinding by default on 64-bit MSVC. This also additionally adds a few minor fixes here and there in the test harness and such to get `make check` entirely passing on 64-bit MSVC: * The invocation of `maketest.py` now works with spaces/quotes in CC * debuginfo tests are disabled on MSVC * A link error for librustc was hacked around (see #27438) --- mk/tests.mk | 7 ++++++- src/etc/maketest.py | 16 +++++++------- src/librustc/lib.rs | 13 ++++++++++++ .../target/x86_64_pc_windows_msvc.rs | 1 + src/librustc_data_structures/lib.rs | 4 ++++ src/librustc_trans/trans/base.rs | 21 +++++++++++++------ src/librustc_trans/trans/common.rs | 4 ++-- src/librustc_trans/trans/intrinsic.rs | 2 +- src/libstd/rt/unwind/mod.rs | 10 ++++----- 9 files changed, 55 insertions(+), 23 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index 28837e05195..f91828838a8 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -597,6 +597,10 @@ CTEST_DISABLE_debuginfo-gdb = CTEST_DISABLE_debuginfo-lldb = "lldb tests are disabled on android" endif +ifeq ($(findstring msvc,$(CFG_TARGET)),msvc) +CTEST_DISABLE_debuginfo-gdb = "gdb tests are disabled on MSVC" +endif + # CTEST_DISABLE_NONSELFHOST_$(TEST_GROUP), if set, will cause that # test group to be disabled *unless* the target is able to build a # compiler (i.e. when the target triple is in the set of of host @@ -1050,7 +1054,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ $$(MAKE) \ $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ $(3)/test/run-make/$$* \ - "$$(CC_$(3)) $$(CFG_GCCISH_CFLAGS_$(3))" \ + $$(CC_$(3)) \ + "$$(CFG_GCCISH_CFLAGS_$(3))" \ $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ "$$(TESTNAME)" \ $$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3)) \ diff --git a/src/etc/maketest.py b/src/etc/maketest.py index f500de5e15d..04bf81a96aa 100644 --- a/src/etc/maketest.py +++ b/src/etc/maketest.py @@ -41,14 +41,14 @@ def convert_path_spec(name, value): make = sys.argv[2] putenv('RUSTC', os.path.abspath(sys.argv[3])) putenv('TMPDIR', os.path.abspath(sys.argv[4])) -putenv('CC', sys.argv[5]) -putenv('RUSTDOC', os.path.abspath(sys.argv[6])) -filt = sys.argv[7] -putenv('LD_LIB_PATH_ENVVAR', sys.argv[8]) -putenv('HOST_RPATH_DIR', os.path.abspath(sys.argv[9])) -putenv('TARGET_RPATH_DIR', os.path.abspath(sys.argv[10])) -putenv('RUST_BUILD_STAGE', sys.argv[11]) -putenv('S', os.path.abspath(sys.argv[12])) +putenv('CC', sys.argv[5] + ' ' + sys.argv[6]) +putenv('RUSTDOC', os.path.abspath(sys.argv[7])) +filt = sys.argv[8] +putenv('LD_LIB_PATH_ENVVAR', sys.argv[9]) +putenv('HOST_RPATH_DIR', os.path.abspath(sys.argv[10])) +putenv('TARGET_RPATH_DIR', os.path.abspath(sys.argv[11])) +putenv('RUST_BUILD_STAGE', sys.argv[12]) +putenv('S', os.path.abspath(sys.argv[13])) putenv('PYTHON', sys.executable) if filt not in sys.argv[1]: diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index bb44abc4f07..935f75040ef 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -179,5 +179,18 @@ mod rustc { pub use lint; } +// FIXME(#27438): right now the unit tests of librustc don't refer to any actual +// functions generated in librustc_data_structures (all +// references are through generic functions), but statics are +// referenced from time to time. Due to this bug we won't +// actually correctly link in the statics unless we also +// reference a function, so be sure to reference a dummy +// function. +#[test] +fn noop() { + rustc_data_structures::__noop_fix_for_27438(); +} + + // Build the diagnostics array at the end so that the metadata includes error use sites. __build_diagnostic_array! { librustc, DIAGNOSTICS } diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs index addaaeb1b63..85756db9606 100644 --- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs +++ b/src/librustc_back/target/x86_64_pc_windows_msvc.rs @@ -13,6 +13,7 @@ use target::Target; pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); base.cpu = "x86-64".to_string(); + base.custom_unwind_resume = true; Target { llvm_target: "x86_64-pc-windows-msvc".to_string(), diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 558d15610df..b056ec2cb05 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -38,3 +38,7 @@ pub mod graph; pub mod bitvec; pub mod ivar; pub mod unify; + +// See comments in src/librustc/lib.rs +#[doc(hidden)] +pub fn __noop_fix_for_27438() {} diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 716b1290817..947c902b2a9 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -745,13 +745,22 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Returns whether this session's target will use SEH-based unwinding. +/// +/// This is only true for MSVC targets, and even then the 64-bit MSVC target +/// currently uses SEH-ish unwinding with DWARF info tables to the side (same as +/// 64-bit MinGW) instead of "full SEH". +pub fn wants_msvc_seh(sess: &Session) -> bool { + sess.target.target.options.is_like_msvc && sess.target.target.arch == "x86" +} + pub fn need_invoke(bcx: Block) -> bool { - // FIXME(#25869) currently unwinding is not implemented for MSVC and our - // normal unwinding infrastructure ends up just causing linker - // errors with the current LLVM implementation, so landing - // pads are disabled entirely for MSVC targets - if bcx.sess().no_landing_pads() || - bcx.sess().target.target.options.is_like_msvc { + // FIXME(#25869) currently SEH-based unwinding is pretty buggy in LLVM and + // is being overhauled as this is being written. Until that + // time such that upstream LLVM's implementation is more solid + // and we start binding it we need to skip invokes for any + // target which wants SEH-based unwinding. + if bcx.sess().no_landing_pads() || wants_msvc_seh(bcx.sess()) { return false; } diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index f57612789b5..98301221f96 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -595,7 +595,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { // landing pads as "landing pads for SEH". let target = &self.ccx.sess().target.target; match self.ccx.tcx().lang_items.eh_personality() { - Some(def_id) if !target.options.is_like_msvc => { + Some(def_id) if !base::wants_msvc_seh(self.ccx.sess()) => { callee::trans_fn_ref(self.ccx, def_id, ExprId(0), self.param_substs).val } @@ -604,7 +604,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { match *personality { Some(llpersonality) => llpersonality, None => { - let name = if !target.options.is_like_msvc { + let name = if !base::wants_msvc_seh(self.ccx.sess()) { "rust_eh_personality" } else if target.arch == "x86" { "_except_handler3" diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 0400771dff1..293a0a6a4ca 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -1037,7 +1037,7 @@ fn try_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Call(bcx, func, &[data], None, dloc); Store(bcx, C_null(Type::i8p(bcx.ccx())), dest); bcx - } else if bcx.sess().target.target.options.is_like_msvc { + } else if wants_msvc_seh(bcx.sess()) { trans_msvc_try(bcx, func, data, dest, dloc) } else { trans_gnu_try(bcx, func, data, dest, dloc) diff --git a/src/libstd/rt/unwind/mod.rs b/src/libstd/rt/unwind/mod.rs index bb43eec8db1..4feb2d49a98 100644 --- a/src/libstd/rt/unwind/mod.rs +++ b/src/libstd/rt/unwind/mod.rs @@ -77,18 +77,18 @@ use sys_common::mutex::Mutex; // implementations. One goes through SEH on Windows and the other goes through // libgcc via the libunwind-like API. -// *-pc-windows-msvc -#[cfg(all(windows, target_env = "msvc"))] +// i686-pc-windows-msvc +#[cfg(all(windows, target_arch = "x86", target_env = "msvc"))] #[path = "seh.rs"] #[doc(hidden)] pub mod imp; -// x86_64-pc-windows-gnu -#[cfg(all(windows, target_arch="x86_64", target_env="gnu"))] +// x86_64-pc-windows-* +#[cfg(all(windows, target_arch = "x86_64"))] #[path = "seh64_gnu.rs"] #[doc(hidden)] pub mod imp; // i686-pc-windows-gnu and all others -#[cfg(any(unix, all(windows, target_arch="x86", target_env="gnu")))] +#[cfg(any(unix, all(windows, target_arch = "x86", target_env = "gnu")))] #[path = "gcc.rs"] #[doc(hidden)] pub mod imp;