2016-10-25 03:49:43 +08:00
|
|
|
//===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2016-10-25 03:49:43 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
2018-05-01 23:54:18 +08:00
|
|
|
/// This file implements several utility functions for WebAssembly.
|
2016-10-25 03:49:43 +08:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "WebAssemblyUtilities.h"
|
|
|
|
#include "WebAssemblyMachineFunctionInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
2017-02-28 06:38:58 +08:00
|
|
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
2016-10-25 03:49:43 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2018-06-19 08:32:03 +08:00
|
|
|
const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate";
|
|
|
|
const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
|
|
|
|
const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
|
|
|
|
const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
|
|
|
|
const char *const WebAssembly::PersonalityWrapperFn =
|
|
|
|
"_Unwind_Wasm_CallPersonality";
|
|
|
|
|
2016-10-25 03:49:43 +08:00
|
|
|
/// Test whether MI is a child of some other node in an expression tree.
|
|
|
|
bool WebAssembly::isChild(const MachineInstr &MI,
|
|
|
|
const WebAssemblyFunctionInfo &MFI) {
|
|
|
|
if (MI.getNumOperands() == 0)
|
|
|
|
return false;
|
|
|
|
const MachineOperand &MO = MI.getOperand(0);
|
|
|
|
if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
|
|
|
|
return false;
|
[webassembly] Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Reviewers: aheejin
Subscribers: jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision for whole review: https://reviews.llvm.org/D65962
llvm-svn: 368627
2019-08-13 06:40:45 +08:00
|
|
|
Register Reg = MO.getReg();
|
2019-08-02 07:27:28 +08:00
|
|
|
return Register::isVirtualRegister(Reg) && MFI.isVRegStackified(Reg);
|
2016-10-25 03:49:43 +08:00
|
|
|
}
|
2017-02-25 07:18:00 +08:00
|
|
|
|
2018-06-19 08:32:03 +08:00
|
|
|
bool WebAssembly::mayThrow(const MachineInstr &MI) {
|
|
|
|
switch (MI.getOpcode()) {
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
case WebAssembly::THROW:
|
|
|
|
case WebAssembly::THROW_S:
|
2018-06-19 08:32:03 +08:00
|
|
|
case WebAssembly::RETHROW:
|
2018-08-27 23:45:51 +08:00
|
|
|
case WebAssembly::RETHROW_S:
|
2018-06-19 08:32:03 +08:00
|
|
|
return true;
|
|
|
|
}
|
2019-07-13 06:08:25 +08:00
|
|
|
if (isCallIndirect(MI.getOpcode()))
|
2018-06-19 08:32:03 +08:00
|
|
|
return true;
|
|
|
|
if (!MI.isCall())
|
|
|
|
return false;
|
|
|
|
|
2020-02-06 10:17:11 +08:00
|
|
|
const MachineOperand &MO = getCalleeOp(MI);
|
[WebAssembly] Add memory intrinsics handling to mayThrow()
Summary:
Previously, `WebAssembly::mayThrow()` assumed all inputs are global
addresses. But when intrinsics, such as `memcpy`, `memmove`, or `memset`
are lowered to external symbols in instruction selection and later
emitted as library calls. And these functions don't throw.
This patch adds handling to those memory intrinsics to `mayThrow`
function. But while most of libcalls don't throw, we can't guarantee all
of them don't throw, so currently we conservatively return true for all
other external symbols.
I think a better way to solve this problem is to embed 'nounwind' info
in `TargetLowering::CallLoweringInfo`, so that we can access the info
from the backend. This will also enable transferring 'nounwind'
properties of LLVM IR instructions. Currently we don't transfer that
info and we can only access properties of callee functions, if the
callees are within the module. Other targets don't need this info in the
backend because they do all the processing before isel, but it will help
us because that info will reduce code size increase in fixing unwind
destination mismatches in CFGStackify.
But for now we return false for these memory intrinsics and true for all
other libcalls conservatively.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68553
llvm-svn: 373967
2019-10-08 05:14:45 +08:00
|
|
|
assert(MO.isGlobal() || MO.isSymbol());
|
|
|
|
|
|
|
|
if (MO.isSymbol()) {
|
|
|
|
// Some intrinsics are lowered to calls to external symbols, which are then
|
|
|
|
// lowered to calls to library functions. Most of libcalls don't throw, but
|
|
|
|
// we only list some of them here now.
|
|
|
|
// TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
|
|
|
|
// instead for more accurate info.
|
|
|
|
const char *Name = MO.getSymbolName();
|
|
|
|
if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
|
|
|
|
strcmp(Name, "memset") == 0)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-06-19 08:32:03 +08:00
|
|
|
const auto *F = dyn_cast<Function>(MO.getGlobal());
|
|
|
|
if (!F)
|
|
|
|
return true;
|
|
|
|
if (F->doesNotThrow())
|
|
|
|
return false;
|
|
|
|
// These functions never throw
|
|
|
|
if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
|
|
|
|
F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
|
|
|
|
return false;
|
2019-03-30 19:04:48 +08:00
|
|
|
|
|
|
|
// TODO Can we exclude call instructions that are marked as 'nounwind' in the
|
|
|
|
// original LLVm IR? (Even when the callee may throw)
|
2018-06-19 08:32:03 +08:00
|
|
|
return true;
|
|
|
|
}
|
2020-02-06 10:17:11 +08:00
|
|
|
|
2020-02-06 14:35:01 +08:00
|
|
|
const MachineOperand &WebAssembly::getCalleeOp(const MachineInstr &MI) {
|
2020-02-06 10:17:11 +08:00
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
case WebAssembly::CALL:
|
|
|
|
case WebAssembly::CALL_S:
|
[WebAssembly] Replace all calls with generalized multivalue calls
Summary:
Extends the multivalue call infrastructure to tail calls, removes all
legacy calls specialized for particular result types, and removes the
CallIndirectFixup pass, since all indirect call arguments are now
fixed up directly in the post-insertion hook.
In order to keep supporting pretty-printed defs and uses in test
expectations, MCInstLower now inserts an immediate containing the
number of defs for each call and call_indirect. The InstPrinter is
updated to query this immediate if it is present and determine which
MCOperands are defs and uses accordingly.
Depends on D72902.
Reviewers: aheejin
Subscribers: dschuff, mgorny, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74192
2020-02-07 08:29:59 +08:00
|
|
|
case WebAssembly::RET_CALL:
|
|
|
|
case WebAssembly::RET_CALL_S:
|
2020-02-06 14:35:01 +08:00
|
|
|
return MI.getOperand(MI.getNumExplicitDefs());
|
|
|
|
case WebAssembly::CALL_INDIRECT:
|
|
|
|
case WebAssembly::CALL_INDIRECT_S:
|
[WebAssembly] Replace all calls with generalized multivalue calls
Summary:
Extends the multivalue call infrastructure to tail calls, removes all
legacy calls specialized for particular result types, and removes the
CallIndirectFixup pass, since all indirect call arguments are now
fixed up directly in the post-insertion hook.
In order to keep supporting pretty-printed defs and uses in test
expectations, MCInstLower now inserts an immediate containing the
number of defs for each call and call_indirect. The InstPrinter is
updated to query this immediate if it is present and determine which
MCOperands are defs and uses accordingly.
Depends on D72902.
Reviewers: aheejin
Subscribers: dschuff, mgorny, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74192
2020-02-07 08:29:59 +08:00
|
|
|
case WebAssembly::RET_CALL_INDIRECT:
|
|
|
|
case WebAssembly::RET_CALL_INDIRECT_S:
|
2020-02-06 14:35:01 +08:00
|
|
|
return MI.getOperand(MI.getNumOperands() - 1);
|
2020-02-06 10:17:11 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Not a call instruction");
|
|
|
|
}
|
|
|
|
}
|