130 Commits

Author SHA1 Message Date
Kazu Hirata
8b8778bae5
[WebAssembly] Use heterogenous lookups with std::set (NFC) (#114930) 2024-11-05 09:38:53 -08:00
Kazu Hirata
8e010ac5a1
[WebAssembly] Avoid repeated hash lookups (NFC) (#112124) 2024-10-13 07:36:49 -07:00
Rahul Joshi
fa789dffb1
[NFC] Rename Intrinsic::getDeclaration to getOrInsertDeclaration (#111752)
Rename the function to reflect its correct behavior and to be consistent
with `Module::getOrInsertFunction`. This is also in preparation of
adding a new `Intrinsic::getDeclaration` that will have behavior similar
to `Module::getFunction` (i.e, just lookup, no creation).
2024-10-11 05:26:03 -07:00
Jay Foad
e03f427196
[LLVM] Use {} instead of std::nullopt to initialize empty ArrayRef (#109133)
It is almost always simpler to use {} instead of std::nullopt to
initialize an empty ArrayRef. This patch changes all occurrences I could
find in LLVM itself. In future the ArrayRef(std::nullopt_t) constructor
could be deprecated or removed.
2024-09-19 16:16:38 +01:00
Heejin Ahn
0af7542135 Reapply "[WebAssembly] Fix phi handling for Wasm SjLj (#99730)"
This reapplies #99730. #99730 contained a nondeterministic iteration
which failed the reverse-iteration bot
(https://lab.llvm.org/buildbot/#/builders/110/builds/474) and reverted
in
f3f0d9928f.

The fix is make the order of iteration of new predecessors
determintistic by using `SmallSetVector`.
```diff
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -1689,7 +1689,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj(
     }
   }

-  SmallDenseMap<BasicBlock *, SmallPtrSet<BasicBlock *, 4>, 4>
+  SmallDenseMap<BasicBlock *, SmallSetVector<BasicBlock *, 4>, 4>
       UnwindDestToNewPreds;
   for (auto *CI : LongjmpableCalls) {
     // Even if the callee function has attribute 'nounwind', which is true for
```
2024-07-25 00:00:59 +00:00
Heejin Ahn
f3f0d9928f Revert "[WebAssembly] Fix phi handling for Wasm SjLj (#99730)"
This reverts commit 2bf71b8bc851b49745b795f228037db159005570.
This broke the builbot at
https://lab.llvm.org/buildbot/#/builders/110/builds/474.
2024-07-24 00:14:58 +00:00
Heejin Ahn
2bf71b8bc8
[WebAssembly] Fix phi handling for Wasm SjLj (#99730)
In Wasm SjLj, longjmpable `call`s that in functions that call `setjmp`
are converted into `invoke`s. Those `invoke`s are meant to unwind to
`catch.dispatch.longjmp` to figure out which `setjmp` those `longjmp`
buffers belong to:

fada922732/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp (L250-L260)

But in case a longjmpable call is within another `catchpad` or
`cleanuppad` scope, to maintain the nested scope structure, we should
make them unwind to the scope's next unwind destination and not directly
to `catch.dispatch.longjmp`:

fada922732/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp (L1698-L1727)
In this case the longjmps will eventually unwind to
`catch.dispatch.longjmp` and be handled there.

In this case, it is possible that the unwind destination (which is an
existing `catchpad` or `cleanuppad`) may already have `phi`s. And
because the unwind destinations get new predecessors because of the
newly created `invoke`s, those `phi`s need to have new entries for those
new predecessors.

This adds new preds as new incoming blocks to those `phi`s, and we use a
separate `SSAUpdater` to calculate the correct incoming values to those
blocks.

I have assumed `SSAUpdaterBulk` used in `rebuildSSA` would take care of
these things, but apparently it doesn't. It takes available defs and
adds `phi`s in the defs' dominance frontiers, i.e., where each def's
dominance ends, and rewrites other uses based on the newly added `phi`s.
But it doesn't add entries to existing `phi`s, and the case in this bug
may not even involve dominance frontiers; this bug is simply about
existing `phis`s that have gained new preds need new entries for them.
It is kind of surprising that this bug was only reported recently, given
that this pass has not been changed much in years.

Fixes #97496 and fixes
https://github.com/emscripten-core/emscripten/issues/22170.
2024-07-23 16:06:00 -07:00
Nikita Popov
74deadf196
[IRBuilder] Don't include Module.h (NFC) (#97159)
This used to be necessary to fetch the DataLayout, but isn't anymore.
2024-06-29 15:05:04 +02:00
Stephen Tozer
d75f9dd1d2 Revert "[IR][NFC] Update IRBuilder to use InsertPosition (#96497)"
Reverts the above commit, as it updates a common header function and
did not update all callsites:

  https://lab.llvm.org/buildbot/#/builders/29/builds/382

This reverts commit 6481dc57612671ebe77fe9c34214fba94e1b3b27.
2024-06-24 18:00:22 +01:00
Stephen Tozer
6481dc5761
[IR][NFC] Update IRBuilder to use InsertPosition (#96497)
Uses the new InsertPosition class (added in #94226) to simplify some of
the IRBuilder interface, and removes the need to pass a BasicBlock
alongside a BasicBlock::iterator, using the fact that we can now get the
parent basic block from the iterator even if it points to the sentinel.
This patch removes the BasicBlock argument from each constructor or call
to setInsertPoint.

This has no functional effect, but later on as we look to remove the
`Instruction *InsertBefore` argument from instruction-creation
(discussed
[here](https://discourse.llvm.org/t/psa-instruction-constructors-changing-to-iterator-only-insertion/77845)),
this will simplify the process by allowing us to deprecate the
InsertPosition constructor directly and catch all the cases where we use
instructions rather than iterators.
2024-06-24 17:27:43 +01:00
Heejin Ahn
6b7ecc7979 Revert "[WebAssembly] Remove threwValue comparison after __wasm_setjmp_test (#86633)"
This reverts commit 52431fdb1ab8d29be078edd55250e06381e4b6b0.

The PR assumed `__threwValue` couldn't be 0, but it could be when the
thrown thing is not a longjmp but an exception, so that `if` check was
actually necessary.
2024-03-28 04:41:29 +00:00
Heejin Ahn
52431fdb1a
[WebAssembly] Remove threwValue comparison after __wasm_setjmp_test (#86633)
Currently the code thinks a `longjmp` occurred if both `__THREW__` and
`__threwValue` are nonzero. But `__threwValue` can be 0, and the
`longjmp` library function should change it to 1 in case it is 0:
https://en.cppreference.com/w/c/program/longjmp

Emscripten libraries were not consistent about that, but after
https://github.com/emscripten-core/emscripten/pull/21493 and
https://github.com/emscripten-core/emscripten/pull/21502, we correctly
pass 1 in case the input is 0. So there will be no case `__threwValue`
is 0. And regardless of what `longjmp` library function does, treating
`longjmp`'s 0 input to its second argument as "not longjmping" doesn't
seem right.

I'm not sure where that `__threwValue` checking came from, but probably
I was porting then fastcomp's implementation and moved this part just
verbatim:
9bdc7bb4fc/lib/Target/JSBackend/CallHandlers.h (L274-L278)

Just for the context, how this was discovered:
https://github.com/emscripten-core/emscripten/pull/21502#pullrequestreview-1942160300
2024-03-27 11:11:16 -07:00
YAMAMOTO Takashi
6420f37926
[WebAssembly] Implement an alternative translation for -wasm-enable-sjlj (#84137)
Instead of maintaining per-function-invocation malloc()'ed tables to track which functions each label belongs to, store the equivalent info in jump buffers (jmp_buf) themselves.

Also, use a less emscripten-looking ABI symbols:
```
    saveSetjmp     -> __wasm_setjmp
    testSetjmp      -> __wasm_setjmp_test
    getTempRet0    -> (removed)
    __wasm_longjmp  -> (no change)
```

While I want to use this for WASI, it should work for emscripten as well.

An example runtime and a few tests:
https://github.com/yamt/garbage/tree/wasm-sjlj-alt2/wasm/longjmp

wasi-libc version of the runtime:
https://github.com/WebAssembly/wasi-libc/pull/483

emscripten version of the runtime:
https://github.com/emscripten-core/emscripten/pull/21502

Discussion:
https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
2024-03-25 18:11:56 -07:00
Jeremy Morse
b9d83eff25
[NFC][RemoveDIs] Use iterators for insertion at various call-sites (#84736)
These are the last remaining "trivial" changes to passes that use
Instruction pointers for insertion. All of this should be NFC, it's just
changing the spelling of how we identify a position.

In one or two locations, I'm also switching uses of getNextNode etc to
using std::next with iterators. This too should be NFC.

---------

Merged by: Stephen Tozer <stephen.tozer@sony.com>
2024-03-19 16:36:29 +00:00
Kazu Hirata
586ecdf205
[llvm] Use StringRef::{starts,ends}_with (NFC) (#74956)
This patch replaces uses of StringRef::{starts,ends}with with
StringRef::{starts,ends}_with for consistency with
std::{string,string_view}::{starts,ends}_with in C++20.

I'm planning to deprecate and eventually remove
StringRef::{starts,ends}with.
2023-12-11 21:01:36 -08:00
Konrad Kleine
5bd1b93cb2 Move CallInst::CreateFree to IRBuilderBase
Similarly to D158861 I'm moving the `CreateFree` method from `CallInst` to `IRBuilderBase`.

Differential Revision: https://reviews.llvm.org/D159418
2023-09-19 12:04:17 +02:00
Konrad Kleine
45bb45f2ae [llvm] Move CallInst::CreateMalloc to IRBuilderBase::CreateMalloc
This removes `CreateMalloc` from `CallInst` and adds it to the `IRBuilderBase`
class.

We no longer needed the `Instruction *InsertBefore` and
`BasicBlock *InsertAtEnd` arguments of the `createMalloc` helper
function because we're using `IRBuilder` now. That's why I we also don't
need 4 `CreateMalloc` functions, but only two.

Differential Revision: https://reviews.llvm.org/D158861
2023-09-19 09:05:48 +02:00
Jeremy Morse
e54277fa10 [NFC][RemoveDIs] Use iterators over inst-pointers when using IRBuilder
This patch adds a two-argument SetInsertPoint method to IRBuilder that
takes a block/iterator instead of an instruction, and updates many call
sites to use it. The motivating reason for doing this is given here [0],
we'd like to pass around more information about the position of debug-info
in the iterator object. That necessitates passing iterators around most of
the time.

[0] https://discourse.llvm.org/t/rfc-instruction-api-changes-needed-to-eliminate-debug-intrinsics-from-ir/68939

Differential Revision: https://reviews.llvm.org/D152468
2023-09-11 20:01:19 +01:00
Elliot Goodrich
4d0f1e3282 [llvm] Remove SmallSet from MachineInstr.h
`MachineInstr.h` is a commonly included file and this includes
`llvm/ADT/SmallSet.h` for one function `getUsedDebugRegs()`, which is
used only in one place.

According to `ClangBuildAnalyzer` (run solely on building LLVM, no other
projects) the second most expensive template to instantiate is the
`SmallSet::insert` method used in the `inline` implementation in
`getUsedDebugRegs()`:

```
**** Templates that took longest to instantiate:
554239 ms: std::unordered_map<int, int> (2826 times, avg 196 ms)
521187 ms: llvm::SmallSet<llvm::Register, 4>::insert (930 times, avg 560
       ms)
...
```

By removing this method and putting its implementation in the one call
site we greatly reduce the template instantiation time and reduce the
number of includes.

When copying the implementation, I removed a check on `MO.getReg()` as
this is checked within `MO.isVirtual()`.

Differential Revision: https://reviews.llvm.org/D157720
2023-08-12 18:15:27 +01:00
Bjorn Pettersson
fd05c34b18 Stop using legacy helpers indicating typed pointer types. NFC
Since we no longer support typed LLVM IR pointer types, the code can
be simplified into for example using PointerType::get directly instead
of using Type::getInt8PtrTy and Type::getInt32PtrTy etc.

Differential Revision: https://reviews.llvm.org/D156733
2023-08-02 12:08:37 +02:00
Youngsuk Kim
243f0566dc [llvm] Replace uses of Type::getPointerTo (NFC)
Partial progress towards removing in-tree uses of `Type::getPointerTo`,
before we can deprecate the API.

If the API is used solely to support an unnecessary bitcast, get rid of
the bitcast as well.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D153933
2023-06-28 09:21:34 -04:00
Heejin Ahn
4e844a1498 [WebAssembly] Replace Bugzilla links with Github issues
Reviewed By: dschuff, asb

Differential Revision: https://reviews.llvm.org/D145966
2023-03-17 20:13:00 -07:00
Kazu Hirata
7ada7bbee1 [Target] Use *{Set,Map}::contains (NFC) 2023-03-14 18:06:55 -07:00
Craig Topper
fffbfe7c0c [WebAssembly] Split WebAssemblyUtils to fix library layering for MC tools.
WebAssemblyUtils depends on CodeGen which depends on all middle end
optimization libraries.

This component is used by WebAssembly's AsmParser, Disassembler, and
MCTargetDesc libraries. Because of this, any MC layer tool built with
WebAssembly support includes a larger portion of LLVM than it should.

To fix this I've created an MC only version of WebAssemblyTypeUtilities.cpp
in MCTargetDesc to be used by the MC components.

This shrinks llvm-objdump and llvm-mc on my local release+asserts
build by 5-6 MB.

Reviewed By: MaskRay, aheejin

Differential Revision: https://reviews.llvm.org/D144354
2023-02-23 23:25:23 -08:00
Fangrui Song
21c4dc7997 std::optional::value => operator*/operator->
value() has undesired exception checking semantics and calls
__throw_bad_optional_access in libc++. Moreover, the API is unavailable without
_LIBCPP_NO_EXCEPTIONS on older Mach-O platforms (see
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS).

This fixes clang.
2022-12-17 00:42:05 +00:00
Vasileios Porpodas
18a4da8cbe [NFC] Cleanup: Remove uses of BasicBlock::getInstList().
This is part of a series of patches that aim at making Function::getInstList() private.

Differential Revision: https://reviews.llvm.org/D139971
2022-12-13 14:38:39 -08:00
Kazu Hirata
20cde15415 [Target] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-02 20:36:06 -08:00
Nikita Popov
ac47db6aca [Attributes] Return Optional from getAllocSizeArgs() (NFC)
As suggested on D135572, return Optional<> from getAllocSizeArgs()
rather than the peculiar pair(0, 0) sentinel.

The method on Attribute itself does not return Optional, because
the attribute must exist in that case.
2022-10-11 11:05:21 +02:00
Sam Clegg
fa306f1396 [WebAssembly] WebAssemblyLowerEmscriptenEHSjLj: Fix signature of malloc in wasm64 mode
Differential Revision: https://reviews.llvm.org/D132091
2022-08-17 18:16:34 -07:00
Nuno Lopes
fffabd5348 [NFC] Switch a few uses of undef to poison as placeholders for unreachable code 2022-07-30 13:55:56 +01:00
Kazu Hirata
611ffcf4e4 [llvm] Use value instead of getValue (NFC) 2022-07-13 23:11:56 -07:00
Kazu Hirata
a7938c74f1 [llvm] Don't use Optional::hasValue (NFC)
This patch replaces Optional::hasValue with the implicit cast to bool
in conditionals only.
2022-06-25 21:42:52 -07:00
Kazu Hirata
3b7c3a654c Revert "Don't use Optional::hasValue (NFC)"
This reverts commit aa8feeefd3ac6c78ee8f67bf033976fc7d68bc6d.
2022-06-25 11:56:50 -07:00
Kazu Hirata
aa8feeefd3 Don't use Optional::hasValue (NFC) 2022-06-25 11:55:57 -07:00
Heejin Ahn
0ca2132067 [WebAssembly] Improve EH/SjLj error messages
This includes a function name and a relevant instruction in error
messages when possible, making them more helpful.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D120678
2022-03-16 20:50:34 -07:00
Heejin Ahn
4f9b839772 [WebAssembly] Make EH/SjLj vars unconditionally thread local
This makes three thread local variables (`__THREW__`, `__threwValue`,
and `__wasm_lpad_context`) unconditionally thread local. If the target
doesn't support TLS, they will be downgraded to normal variables in
`stripThreadLocals`. This makes the object not linkable with other
objects using shared memory, which is what we intend here; these
variables should be thread local when used with shared memory. This is
what we initially tried in D88262.

But D88323 changed this: It only created these variables when threads
were supported, because `__THREW__` and `__threwValue` were always
generated even if Emscripten EH/SjLj was not used, making all objects
built without threads not linkable with shared memory, which was too
restrictive. But sometimes this is not safe. If we build an object using
variables such as `__THREW__` without threads, it can be linked to other
objects using shared memory, because the original object's `__THREW__`
was not created thread local to begin with.

So this CL basically reverts D88323 with some additional improvements:
- This checks each of the functions and global variables created within
  `LowerEmscriptenEHSjLj` pass and removes it if it's not used at the
  end of the pass. So only modules using those variables will be
  affected.
- Moves `CoalesceFeaturesAndStripAtomics` and `AtomicExpand` passes
  after all other IR pasess that can create thread local variables. It
  is not sufficient to move them to the end of `addIRPasses`, because
  `__wasm_lpad_context` is created in `WasmEHPrepare`, which runs inside
  `addPassesToHandleExceptions`, which runs before `addISelPrepare`. So
  we override `addISelPrepare` and move atomic/TLS stripping and
  expanding passes there.

This also removes merges `TLS` and `NO-TLS` FileCheck lines into one
`CHECK` line, because in the bitcode level we always create them as
thread local. Also some function declarations are deleted `CHECK` lines
because they are unused.

Reviewed By: tlively, sbc100

Differential Revision: https://reviews.llvm.org/D120013
2022-02-17 16:04:18 -08:00
Sam Clegg
37f422f4ac [WebAssembly] Use GeneralDynamic TLS for exception handling builtins.
These global TLS symbols are shared across all shared libraries and
therefor should not be assumed to be local to the current module.

Also add new error in the linker when TLS relocations are used against
undefined symbols.  TLS relocations are offsets into the current modules
tls data segment, and don't make sense for undefined symbols which are
modeled as global imports.

Fixes: https://github.com/emscripten-core/emscripten/issues/13398

Differential Revision: https://reviews.llvm.org/D119630
2022-02-14 14:08:32 -08:00
Simon Pilgrim
3a1fd17027 [WebAssembly] Use cast<> instead of dyn_cast<> to avoid dereference of nullptr
The pointers are dereferenced immediately, so assert the cast is correct instead of returning nullptr
2022-01-29 16:08:06 +00:00
Heejin Ahn
4f1244d7cc [WebAssembly] Nullify unnecessary setjmp invokes
This is similar to D116619, but now it handles `invoke`s. The reason we
didn't handle `invoke`s back then was we didn't support Wasm EH + Wasm
SjLj together, and the only case SjLj transformation will see `invoke`s
is when we are using Wasm EH. (In Emscripten EH, they would have been
transformed to `call`s to invoke wrappers.)

But after D117610 we support Wasm EH + Wasm SjLj together and we can
nullify `invoke`s to `setjmp` when there is no other longjmpable calls
within the function. Actually this is very unlikely to happen in
practice, because we treat destructors as longjmpable and also treat
`__cxa_end_catch` as longjmpable even if it is not.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D118408
2022-01-27 21:11:10 -08:00
Heejin Ahn
20c1d9ce5e [WebAssembly] Handle cleanuppad with no parent in Wasm SjLj
Wasm SjLj converts longjmpable calls into `invoke`s that unwind to
`%catch.longjmp.dispatch` BB, from where we check if the thrown
exception is a `longjmp`. But in case a call already has a `funclet`
attribute, i.e., it is within a catch scope, we have to unwind to its
unwind destination first to preserve the scoping structure. That will
eventually unwind to `%catch.longjmp.dispatch`, because all
`catchswitch` and `cleanupret` that unwind to caller are redirected to
`%catch.dispatch.longjmp` during Wasm SjLj transformation.

But the prevous code assumed `cleanuppad`'s parent pad was always an
instruction, and didn't handle when a `cleanuppad`'s parent is `none`.
This CL handles this case, and makes the `while` loop more intuitive by
removing `FromPad` condition and explicitly inserting `break`s.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D118407
2022-01-27 21:10:23 -08:00
Heejin Ahn
26d587cf0f [WebAssembly] Error out for setjmp within catch clause for Wasm SjLj
Wasm EH, used with either of Emscripten SjLj or Wasm SjLj, does not
allow `setjmp` calls to be placed within a `catch` clause, because we
don't support jumping into a `catch` block. Emscripten EH does not have
this restriction. But I think this restriction wouldn't prevent most of
use cases. This CL errors out with a clear messsage for this case.

Reviewed By: dschuff, kripken

Differential Revision: https://reviews.llvm.org/D118286
2022-01-27 21:05:43 -08:00
Heejin Ahn
786da40667 [WebAssembly] Don't copy noreturn attr to invokes
When we create an invoke wrapper call, if the original call instruction
has a `noreturn` attribute, we shouldn't copy it, because we expect
invoke wrapper calls to return. This generated incorrect `free` call
before an invoke wrapper call that calls `__cxa_throw`, because
`__cxa_throw` has `noreturn` attribute.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D118274
2022-01-27 21:04:43 -08:00
Heejin Ahn
d9517efbb3 [WebAssembly] Treat __cxa_end_catch not longjmpable in Emscripten SjLj
In D117610 we treated `__cxa_end_catch` longjmpable even though it was
not to make unwind destination relationships correct. But we only need
to do this in Wasm SjLj, and doing this in Emscripten SjLj does not make
the code incorrect but add unnecessary invokes. This CL treats
`__cxa_end_catch` longjmpable only in Wasm SjLj.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D117943
2022-01-27 21:03:23 -08:00
Heejin Ahn
eb675e972d [WebAssembly] Support Wasm EH + Wasm SjLj
D108960 added support for SjLj using Wasm EH instructions, which we call
Wasm SjLj going forward. (We call the old SjLj Emscripten SjLj) But it
did not support using Wasm EH and Wasm SjLj together. So far users of
Wasm EH had to use Wasm EH with Emscripten SjLj, which had a certain
limitation and it suffered from bigger code size increases as well.

This enables using Wasm EH and Wasm SjLj together.
1. This redirects `catchswitch` and `cleanupret` that unwind to caller
   to `catch.dispatch.longjmp` BB, which is a `catchswitch` BB that
   handles longjmps.
2. D108960 converted all longjmpable `call`s to `invokes` that unwind to
   `catch.dispatch.longjmp`. This CL checks if the `call` is embedded
   within another `catchpad`, and if so, makes it unwind to its nearest
   parent's unwind destination, rather than `catch.dispatch.longjmp`.
   This is necessary to preserve the scoping structure.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D117610
2022-01-19 20:13:54 -08:00
Serge Guelton
d2cc6c2d0c Use a sorted array instead of a map to store AttrBuilder string attributes
Using and std::map<SmallString, SmallString> for target dependent attributes is
inefficient: it makes its constructor slightly heavier, and involves extra
allocation for each new string attribute. Storing the attribute key/value as
strings implies extra allocation/copy step.

Use a sorted vector instead. Given the low number of attributes generally
involved, this is cheaper, as showcased by

https://llvm-compile-time-tracker.com/compare.php?from=5de322295f4ade692dc4f1823ae4450ad3c48af2&to=05bc480bf641a9e3b466619af43a2d123ee3f71d&stat=instructions

Differential Revision: https://reviews.llvm.org/D116599
2022-01-10 14:49:53 +01:00
Heejin Ahn
f2a43f06dd [WebAssembly] Use llvm utility functions in EH/SjLj
This uses `changeToCall` and `changeToInvokeAndSplitBasicBlock` from
`lib/Transforms/Utils`, replacing the custom logic. One difference of
those functions from our previous logic is they delete the original
`CallInst`/`InvokeInst`, which makes them tricky to use while iterating
through instructions/BBs. So this CL gathers the candidate calls first
and run them through `changeToInvokeAndSplitBasicBlock` later.

Also this renames some variables.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D116620
2022-01-04 17:47:20 -08:00
Heejin Ahn
f178f61e1d [WebAssembly] Nullify unnecessary setjmp calls
D107530 did a small optimization that, if a function contains `setjmp`
calls but not other calls that can `longjmp`, we don't do SjLj
transformation on those `setjmp` calls, because they don't have
possibilities of returning from `longjmp`.

But we should remove those `setjmp` calls even in that case, because
Emscripten doesn't provide that function, assuming it is lowered away by
SjLj transformation. `setjmp` always returns 0 when called directly, so
this CL replaces them with `i32 0`.

Fixes https://github.com/emscripten-core/emscripten/issues/15679.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D116619
2022-01-04 17:44:32 -08:00
Heejin Ahn
4625b84879 [WebAssembly] Support clang -fwasm-exceptions for bitcode
This supports bitcode compilation using `clang -fwasm-exceptions`.

---

The current situation:

Currently the backend requires two options for Wasm EH:
`-wasm-enable-eh` and `-exception-model=wasm`. Wasm SjLj requires two
options as well: `-wasm-enable-sjlj` and `-exception-model=wasm`. When
using Wasm EH via Emscripten, you only need to pass `-fwasm-exceptions`,
and these options will be added within the clang driver. This
description will focus on the case of Wasm EH going forward, but Wasm
SjLj's case is similar.

When you pass `-fwasm-exceptions` to emcc and clang driver, the clang
driver adds these options to the command line that calls the clang
frontend (`clang -cc1`): `-mllvm -wasm-enable-eh` and
`-exception-model=wasm`. `-wasm-enable-eh` is prefixed with `-mllvm`, so
it is passed as is to the backend. But `-exception-model` is parsed and
processed within the clang frontend and stored in `LangOptions` class.
This info is later transferred to `TargetOptions` class, and then
eventually passed to `MCAsmInfo` class. All LLVM code queries this
`MCAsmInfo` to get the exception model.

---

Problem:

The problem is the whole `LangOptions` processing is bypassed when
compiling bitcode, so the information transfer of `LangOptions` ->
`TargetOptions` -> `MCAsmInfo` does not happen. They are all set to
`ExceptionHandling::None`, which is the default value.

---

What other targets do, and why we can't do the same:

Other targets support bitcode compilation by the clang driver, but they
can do that by using different triples. For example, X86 target supports
multiple triples, each of which has its own subclass of `MCAsmInfo`, so
it can hardcode the appropriate exception model within those subclasses'
constructors. But we don't have separate triples for each exception
mode: none, emscripten, and wasm.

---

What this CL does:

If we can figure out whether `-wasm-enable-eh` is passed to the backend,
we can programatically set the exception model from the backend, rather
than requiring it to be passed.

So we check `WasmEnableEH` and `WasmEnableSjLj` variables, which are
`cl::opt` for `-wasm-enable-eh` and `-wasm-enable-sjlj`, in
`WebAssemblyMCAsmInfo` constructor, and if either of them is set, we set
`MCAsmInfo.ExceptionType` to Wasm. `TargetOptions` cannot be updated
there, so we make sure they are the same later.

Fixes https://github.com/emscripten-core/emscripten/issues/15712.

Reviewed By: dschuff

Differential Revision: https://reviews.llvm.org/D115893
2021-12-16 16:49:24 -08:00
Kazu Hirata
c1e32b3fc0 [Target] Migrate from getNumArgOperands to arg_size (NFC)
Note that getNumArgOperands is considered a legacy name.  See
llvm/include/llvm/IR/InstrTypes.h for details.
2021-10-02 12:06:29 -07:00
Heejin Ahn
468c4409f6 Revert "[WebAssembly] Rethrow longjmp in EH handling if EmSjLj is enabled"
This reverts commit b7b4ebbcfa463a7fae61dca7cec30c5b747bdec8.

Reason: This breaks several code-size tests in Emscripten test suite
because this exports `emscripten_longjmp` for programs that didn't do it
before.
2021-09-14 12:59:42 -07:00