Skip to content

Commit 6a7bc3f

Browse files
authored
Unrolled build for rust-lang#131830
Rollup merge of rust-lang#131830 - hoodmane:emscripten-wasm-eh, r=workingjubilee Add support for wasm exception handling to Emscripten target This is a draft because we need some additional setting for the Emscripten target to select between the old exception handling and the new exception handling. I don't know how to add a setting like that, would appreciate advice from Rust folks. We could maybe choose to use the new exception handling if `Ctarget-feature=+exception-handling` is passed? I tried this but I get errors from llvm so I'm not doing it right.
2 parents 0f1e965 + 49c7423 commit 6a7bc3f

File tree

21 files changed

+131
-10
lines changed

21 files changed

+131
-10
lines changed

compiler/rustc_codegen_llvm/src/llvm_util.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,10 @@ unsafe fn configure_llvm(sess: &Session) {
109109
add("-wasm-enable-eh", false);
110110
}
111111

112-
if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind {
112+
if sess.target.os == "emscripten"
113+
&& !sess.opts.unstable_opts.emscripten_wasm_eh
114+
&& sess.panic_strategy() == PanicStrategy::Unwind
115+
{
113116
add("-enable-emscripten-cxx-exceptions", false);
114117
}
115118

compiler/rustc_codegen_ssa/src/back/link.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2451,10 +2451,12 @@ fn add_order_independent_options(
24512451
}
24522452

24532453
if sess.target.os == "emscripten" {
2454-
cmd.cc_arg("-s").cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
2455-
"DISABLE_EXCEPTION_CATCHING=1"
2454+
cmd.cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
2455+
"-sDISABLE_EXCEPTION_CATCHING=1"
2456+
} else if sess.opts.unstable_opts.emscripten_wasm_eh {
2457+
"-fwasm-exceptions"
24562458
} else {
2457-
"DISABLE_EXCEPTION_CATCHING=0"
2459+
"-sDISABLE_EXCEPTION_CATCHING=0"
24582460
});
24592461
}
24602462

compiler/rustc_codegen_ssa/src/base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
388388
// exceptions. This means that the VM does the unwinding for
389389
// us
390390
pub fn wants_wasm_eh(sess: &Session) -> bool {
391-
sess.target.is_like_wasm && sess.target.os != "emscripten"
391+
sess.target.is_like_wasm
392+
&& (sess.target.os != "emscripten" || sess.opts.unstable_opts.emscripten_wasm_eh)
392393
}
393394

394395
/// Returns `true` if this session's target will use SEH-based unwinding.

compiler/rustc_feature/src/builtin_attrs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const GATED_CFGS: &[GatedCfg] = &[
3737
(sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
3838
// this is consistent with naming of the compiler flag it's for
3939
(sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
40+
(sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
4041
];
4142

4243
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ declare_features! (
202202
(internal, allow_internal_unstable, "1.0.0", None),
203203
/// Allows using anonymous lifetimes in argument-position impl-trait.
204204
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
205+
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
206+
(internal, cfg_emscripten_wasm_eh, "CURRENT_RUSTC_VERSION", None),
205207
/// Allows identifying the `compiler_builtins` crate.
206208
(internal, compiler_builtins, "1.13.0", None),
207209
/// Allows writing custom MIR

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ fn test_unstable_options_tracking_hash() {
782782
tracked!(dwarf_version, Some(5));
783783
tracked!(embed_source, true);
784784
tracked!(emit_thin_lto, false);
785+
tracked!(emscripten_wasm_eh, true);
785786
tracked!(export_executable_symbols, true);
786787
tracked!(fewer_names, Some(true));
787788
tracked!(fixed_x18, true);

compiler/rustc_passes/src/weak_lang_items.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ pub(crate) fn check_crate(
2626
if items.eh_personality().is_none() {
2727
items.missing.push(LangItem::EhPersonality);
2828
}
29-
if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() {
29+
if tcx.sess.target.os == "emscripten"
30+
&& items.eh_catch_typeinfo().is_none()
31+
&& !tcx.sess.opts.unstable_opts.emscripten_wasm_eh
32+
{
3033
items.missing.push(LangItem::EhCatchTypeinfo);
3134
}
3235

compiler/rustc_session/src/config/cfg.rs

+5
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
143143
| (sym::target_has_atomic_load_store, Some(_))
144144
| (sym::target_thread_local, None) => disallow(cfg, "--target"),
145145
(sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
146+
(sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"),
146147
_ => {}
147148
}
148149
}
@@ -295,6 +296,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
295296
ins_none!(sym::ub_checks);
296297
}
297298

299+
// Nightly-only implementation detail for the `panic_unwind` and `unwind` crates.
300+
if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh {
301+
ins_none!(sym::emscripten_wasm_eh);
302+
}
298303
ret
299304
}
300305

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,8 @@ options! {
17711771
"emit a section containing stack size metadata (default: no)"),
17721772
emit_thin_lto: bool = (true, parse_bool, [TRACKED],
17731773
"emit the bc module with thin LTO info (default: yes)"),
1774+
emscripten_wasm_eh: bool = (false, parse_bool, [TRACKED],
1775+
"Use WebAssembly error handling for wasm32-unknown-emscripten"),
17741776
enforce_type_length_limit: bool = (false, parse_bool, [TRACKED],
17751777
"enforce the type length limit when monomorphizing instances in codegen"),
17761778
export_executable_symbols: bool = (false, parse_bool, [TRACKED],

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ symbols! {
570570
cfg_autodiff_fallback,
571571
cfg_boolean_literals,
572572
cfg_doctest,
573+
cfg_emscripten_wasm_eh,
573574
cfg_eval,
574575
cfg_fmt_debug,
575576
cfg_hide,
@@ -823,6 +824,7 @@ symbols! {
823824
emit_enum_variant_arg,
824825
emit_struct,
825826
emit_struct_field,
827+
emscripten_wasm_eh,
826828
enable,
827829
encode,
828830
end,

library/panic_unwind/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ libc = { version = "0.2", default-features = false }
2323

2424
[lints.rust.unexpected_cfgs]
2525
level = "warn"
26-
check-cfg = []
26+
check-cfg = ['cfg(emscripten_wasm_eh)']

library/panic_unwind/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
// `real_imp` is unused with Miri, so silence warnings.
2626
#![cfg_attr(miri, allow(dead_code))]
2727
#![allow(internal_features)]
28+
#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
2829

2930
use alloc::boxed::Box;
3031
use core::any::Any;
3132
use core::panic::PanicPayload;
3233

3334
cfg_if::cfg_if! {
34-
if #[cfg(target_os = "emscripten")] {
35+
if #[cfg(all(target_os = "emscripten", not(emscripten_wasm_eh)))] {
3536
#[path = "emcc.rs"]
3637
mod imp;
3738
} else if #[cfg(target_os = "hermit")] {

library/unwind/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ system-llvm-libunwind = []
3737

3838
[lints.rust.unexpected_cfgs]
3939
level = "warn"
40-
check-cfg = []
40+
check-cfg = ['cfg(emscripten_wasm_eh)']

library/unwind/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
#![feature(staged_api)]
55
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
66
#![cfg_attr(
7-
all(target_family = "wasm", not(target_os = "emscripten")),
7+
all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)),
88
feature(simd_wasm64, wasm_exception_handling_intrinsics)
99
)]
1010
#![allow(internal_features)]
11+
#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))]
1112

1213
// Force libc to be included even if unused. This is required by many platforms.
1314
#[cfg(not(all(windows, target_env = "msvc")))]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# `emscripten-wasm-eh`
2+
3+
Use the WebAssembly exception handling ABI to unwind for the
4+
`wasm32-unknown-emscripten`. If compiling with this setting, the `emcc` linker
5+
should be invoked with `-fwasm-exceptions`. If linking with C/C++ files, the
6+
C/C++ files should also be compiled with `-fwasm-exceptions`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//@ compile-flags: -O --target wasm32-unknown-emscripten -Z emscripten-wasm-eh
2+
//@ needs-llvm-components: webassembly
3+
4+
// Emscripten catch_unwind using wasm exceptions
5+
6+
#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
7+
#![crate_type = "lib"]
8+
#![no_std]
9+
#![no_core]
10+
11+
#[lang = "sized"]
12+
trait Sized {}
13+
#[lang = "freeze"]
14+
trait Freeze {}
15+
#[lang = "copy"]
16+
trait Copy {}
17+
18+
impl<T> Copy for *mut T {}
19+
20+
#[rustc_intrinsic]
21+
fn size_of<T>() -> usize {
22+
loop {}
23+
}
24+
25+
extern "rust-intrinsic" {
26+
fn catch_unwind(
27+
try_fn: fn(_: *mut u8),
28+
data: *mut u8,
29+
catch_fn: fn(_: *mut u8, _: *mut u8),
30+
) -> i32;
31+
}
32+
33+
// CHECK-LABEL: @ptr_size
34+
#[no_mangle]
35+
pub fn ptr_size() -> usize {
36+
// CHECK: ret [[PTR_SIZE:.*]]
37+
size_of::<*mut u8>()
38+
}
39+
40+
// CHECK-LABEL: @test_catch_unwind
41+
#[no_mangle]
42+
pub unsafe fn test_catch_unwind(
43+
try_fn: fn(_: *mut u8),
44+
data: *mut u8,
45+
catch_fn: fn(_: *mut u8, _: *mut u8),
46+
) -> i32 {
47+
// CHECK: start:
48+
// CHECK: invoke void %try_fn(ptr %data)
49+
// CHECK: to label %__rust_try.exit unwind label %catchswitch.i
50+
// CHECK: catchswitch.i: ; preds = %start
51+
// CHECK: %catchswitch1.i = catchswitch within none [label %catchpad.i] unwind to caller
52+
53+
// CHECK: catchpad.i: ; preds = %catchswitch.i
54+
// CHECK: %catchpad2.i = catchpad within %catchswitch1.i [ptr null]
55+
// CHECK: %0 = tail call ptr @llvm.wasm.get.exception(token %catchpad2.i)
56+
// CHECK: %1 = tail call i32 @llvm.wasm.get.ehselector(token %catchpad2.i)
57+
// CHECK: call void %catch_fn(ptr %data, ptr %0) [ "funclet"(token %catchpad2.i) ]
58+
// CHECK: catchret from %catchpad2.i to label %__rust_try.exit
59+
60+
// CHECK: __rust_try.exit: ; preds = %start, %catchpad.i
61+
// CHECK: %common.ret.op.i = phi i32 [ 0, %start ], [ 1, %catchpad.i ]
62+
// CHECK: ret i32 %common.ret.op.i
63+
64+
catch_unwind(try_fn, data, catch_fn)
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: unexpected `--cfg emscripten_wasm_eh` flag
2+
|
3+
= note: config `emscripten_wasm_eh` is only supposed to be controlled by `-Z emscripten_wasm_eh`
4+
= note: manually setting a built-in cfg can and does create incoherent behaviors
5+
= note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
6+
7+
error: aborting due to 1 previous error
8+

tests/ui/cfg/disallowed-cli-cfgs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_
88
//@ revisions: target_thread_local_ relocation_model_
99
//@ revisions: fmt_debug_
10+
//@ revisions: emscripten_wasm_eh_
1011

1112
//@ [overflow_checks_]compile-flags: --cfg overflow_checks
1213
//@ [debug_assertions_]compile-flags: --cfg debug_assertions
@@ -33,5 +34,6 @@
3334
//@ [target_thread_local_]compile-flags: --cfg target_thread_local
3435
//@ [relocation_model_]compile-flags: --cfg relocation_model="a"
3536
//@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow"
37+
//@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh
3638

3739
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//@ compile-flags: --check-cfg=cfg(emscripten_wasm_eh)
2+
#[cfg(not(emscripten_wasm_eh))]
3+
//~^ `cfg(emscripten_wasm_eh)` is experimental
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: `cfg(emscripten_wasm_eh)` is experimental and subject to change
2+
--> $DIR/feature-gate-cfg-emscripten-wasm-eh.rs:2:11
3+
|
4+
LL | #[cfg(not(emscripten_wasm_eh))]
5+
| ^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add `#![feature(cfg_emscripten_wasm_eh)]` to the crate attributes to enable
8+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)