@@ -54,6 +54,35 @@ static cl::opt<bool> WasmDisableFixIrreducibleControlFlowPass(
54
54
" irreducible control flow optimization pass" ),
55
55
cl::init(false ));
56
56
57
+ // Exception handling & setjmp-longjmp handling related options.
58
+
59
+ // Emscripten's asm.js-style exception handling
60
+ cl::opt<bool > WebAssembly::WasmEnableEmEH (
61
+ " enable-emscripten-cxx-exceptions" ,
62
+ cl::desc (" WebAssembly Emscripten-style exception handling" ),
63
+ cl::init(false ));
64
+ // Emscripten's asm.js-style setjmp/longjmp handling
65
+ cl::opt<bool > WebAssembly::WasmEnableEmSjLj (
66
+ " enable-emscripten-sjlj" ,
67
+ cl::desc (" WebAssembly Emscripten-style setjmp/longjmp handling" ),
68
+ cl::init(false ));
69
+ // Exception handling using wasm EH instructions
70
+ cl::opt<bool >
71
+ WebAssembly::WasmEnableEH (" wasm-enable-eh" ,
72
+ cl::desc (" WebAssembly exception handling" ));
73
+ // setjmp/longjmp handling using wasm EH instrutions
74
+ cl::opt<bool > WebAssembly::WasmEnableSjLj (
75
+ " wasm-enable-sjlj" , cl::desc(" WebAssembly setjmp/longjmp handling" ));
76
+ // If true, use the legacy Wasm EH proposal:
77
+ // https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
78
+ // And if false, use the standardized Wasm EH proposal:
79
+ // https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
80
+ // Currently set to true by default because not all major web browsers turn on
81
+ // the new standard proposal by default, but will later change to false.
82
+ cl::opt<bool > WebAssembly::WasmUseLegacyEH (
83
+ " wasm-use-legacy-eh" , cl::desc(" WebAssembly exception handling (legacy)" ),
84
+ cl::init(true ));
85
+
57
86
extern " C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
58
87
LLVMInitializeWebAssemblyTarget () {
59
88
// Register the target.
@@ -111,6 +140,57 @@ static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM,
111
140
return *RM;
112
141
}
113
142
143
+ using WebAssembly::WasmEnableEH;
144
+ using WebAssembly::WasmEnableEmEH;
145
+ using WebAssembly::WasmEnableEmSjLj;
146
+ using WebAssembly::WasmEnableSjLj;
147
+
148
+ static void basicCheckForEHAndSjLj (TargetMachine *TM) {
149
+
150
+ // You can't enable two modes of EH at the same time
151
+ if (WasmEnableEmEH && WasmEnableEH)
152
+ report_fatal_error (
153
+ " -enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh" );
154
+ // You can't enable two modes of SjLj at the same time
155
+ if (WasmEnableEmSjLj && WasmEnableSjLj)
156
+ report_fatal_error (
157
+ " -enable-emscripten-sjlj not allowed with -wasm-enable-sjlj" );
158
+ // You can't mix Emscripten EH with Wasm SjLj.
159
+ if (WasmEnableEmEH && WasmEnableSjLj)
160
+ report_fatal_error (
161
+ " -enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj" );
162
+
163
+ if (TM->Options .ExceptionModel == ExceptionHandling::None) {
164
+ // FIXME: These flags should be removed in favor of directly using the
165
+ // generically configured ExceptionsType
166
+ if (WebAssembly::WasmEnableEH || WebAssembly::WasmEnableSjLj)
167
+ TM->Options .ExceptionModel = ExceptionHandling::Wasm;
168
+ }
169
+
170
+ // Basic Correctness checking related to -exception-model
171
+ if (TM->Options .ExceptionModel != ExceptionHandling::None &&
172
+ TM->Options .ExceptionModel != ExceptionHandling::Wasm)
173
+ report_fatal_error (" -exception-model should be either 'none' or 'wasm'" );
174
+ if (WasmEnableEmEH && TM->Options .ExceptionModel == ExceptionHandling::Wasm)
175
+ report_fatal_error (" -exception-model=wasm not allowed with "
176
+ " -enable-emscripten-cxx-exceptions" );
177
+ if (WasmEnableEH && TM->Options .ExceptionModel != ExceptionHandling::Wasm)
178
+ report_fatal_error (
179
+ " -wasm-enable-eh only allowed with -exception-model=wasm" );
180
+ if (WasmEnableSjLj && TM->Options .ExceptionModel != ExceptionHandling::Wasm)
181
+ report_fatal_error (
182
+ " -wasm-enable-sjlj only allowed with -exception-model=wasm" );
183
+ if ((!WasmEnableEH && !WasmEnableSjLj) &&
184
+ TM->Options .ExceptionModel == ExceptionHandling::Wasm)
185
+ report_fatal_error (
186
+ " -exception-model=wasm only allowed with at least one of "
187
+ " -wasm-enable-eh or -wasm-enable-sjlj" );
188
+
189
+ // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim
190
+ // measure, but some code will error out at compile time in this combination.
191
+ // See WebAssemblyLowerEmscriptenEHSjLj pass for details.
192
+ }
193
+
114
194
// / Create an WebAssembly architecture model.
115
195
// /
116
196
WebAssemblyTargetMachine::WebAssemblyTargetMachine (
@@ -149,7 +229,7 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
149
229
this ->Options .UniqueSectionNames = true ;
150
230
151
231
initAsmInfo ();
152
-
232
+ basicCheckForEHAndSjLj ( this );
153
233
// Note that we don't use setRequiresStructuredCFG(true). It disables
154
234
// optimizations than we're ok with, and want, such as critical edge
155
235
// splitting and tail merging.
@@ -400,61 +480,6 @@ FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
400
480
return nullptr ; // No reg alloc
401
481
}
402
482
403
- using WebAssembly::WasmEnableEH;
404
- using WebAssembly::WasmEnableEmEH;
405
- using WebAssembly::WasmEnableEmSjLj;
406
- using WebAssembly::WasmEnableSjLj;
407
-
408
- static void basicCheckForEHAndSjLj (TargetMachine *TM) {
409
-
410
- // You can't enable two modes of EH at the same time
411
- if (WasmEnableEmEH && WasmEnableEH)
412
- report_fatal_error (
413
- " -enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh" );
414
- // You can't enable two modes of SjLj at the same time
415
- if (WasmEnableEmSjLj && WasmEnableSjLj)
416
- report_fatal_error (
417
- " -enable-emscripten-sjlj not allowed with -wasm-enable-sjlj" );
418
- // You can't mix Emscripten EH with Wasm SjLj.
419
- if (WasmEnableEmEH && WasmEnableSjLj)
420
- report_fatal_error (
421
- " -enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj" );
422
-
423
- // Here we make sure TargetOptions.ExceptionModel is the same as
424
- // MCAsmInfo.ExceptionsType. Normally these have to be the same, because clang
425
- // stores the exception model info in LangOptions, which is later transferred
426
- // to TargetOptions and MCAsmInfo. But when clang compiles bitcode directly,
427
- // clang's LangOptions is not used and thus the exception model info is not
428
- // correctly transferred to TargetOptions and MCAsmInfo, so we make sure we
429
- // have the correct exception model in WebAssemblyMCAsmInfo constructor. But
430
- // in this case TargetOptions is still not updated, so we make sure they are
431
- // the same.
432
- TM->Options .ExceptionModel = TM->getMCAsmInfo ()->getExceptionHandlingType ();
433
-
434
- // Basic Correctness checking related to -exception-model
435
- if (TM->Options .ExceptionModel != ExceptionHandling::None &&
436
- TM->Options .ExceptionModel != ExceptionHandling::Wasm)
437
- report_fatal_error (" -exception-model should be either 'none' or 'wasm'" );
438
- if (WasmEnableEmEH && TM->Options .ExceptionModel == ExceptionHandling::Wasm)
439
- report_fatal_error (" -exception-model=wasm not allowed with "
440
- " -enable-emscripten-cxx-exceptions" );
441
- if (WasmEnableEH && TM->Options .ExceptionModel != ExceptionHandling::Wasm)
442
- report_fatal_error (
443
- " -wasm-enable-eh only allowed with -exception-model=wasm" );
444
- if (WasmEnableSjLj && TM->Options .ExceptionModel != ExceptionHandling::Wasm)
445
- report_fatal_error (
446
- " -wasm-enable-sjlj only allowed with -exception-model=wasm" );
447
- if ((!WasmEnableEH && !WasmEnableSjLj) &&
448
- TM->Options .ExceptionModel == ExceptionHandling::Wasm)
449
- report_fatal_error (
450
- " -exception-model=wasm only allowed with at least one of "
451
- " -wasm-enable-eh or -wasm-enable-sjlj" );
452
-
453
- // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim
454
- // measure, but some code will error out at compile time in this combination.
455
- // See WebAssemblyLowerEmscriptenEHSjLj pass for details.
456
- }
457
-
458
483
// ===----------------------------------------------------------------------===//
459
484
// The following functions are called from lib/CodeGen/Passes.cpp to modify
460
485
// the CodeGen pass sequence.
@@ -475,8 +500,6 @@ void WebAssemblyPassConfig::addIRPasses() {
475
500
if (getOptLevel () != CodeGenOptLevel::None)
476
501
addPass (createWebAssemblyOptimizeReturned ());
477
502
478
- basicCheckForEHAndSjLj (TM);
479
-
480
503
// If exception handling is not enabled and setjmp/longjmp handling is
481
504
// enabled, we lower invokes into calls and delete unreachable landingpad
482
505
// blocks. Lowering invokes when there is no EH support is done in
0 commit comments