Skip to content

Commit 31a71a3

Browse files
committed
[WebAssembly] Make result of 'catch' inst variadic
`catch` instruction can have any number of result values depending on its tag, but so far we have only needed a single i32 return value for C++ exception so the instruction was specified that way. But using the instruction for SjLj handling requires multiple return values. This makes `catch` instruction's results variadic and moves selection of `throw` and `catch` instruction from ISelLowering to ISelDAGToDAG. Moving `catch` to ISelDAGToDAG is necessary because I am not aware of a good way to do instruction selection for variadic output instructions in TableGen. This also moves `throw` because 1. `throw` and `catch` share the same utility function and 2. there is really no reason we should do that in ISelLowering in the first place. What we do is mostly the same in both places, and moving them to ISelDAGToDAG allows us to remove unnecessary mid-level nodes for `throw` and `catch` in WebAssemblyISD.def and WebAssemblyInstrInfo.td. This also adds handling for new `catch` instruction to AsmTypeCheck. Reviewed By: dschuff, tlively Differential Revision: https://reviews.llvm.org/D107423
1 parent 9c19b36 commit 31a71a3

File tree

6 files changed

+71
-59
lines changed

6 files changed

+71
-59
lines changed

llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst) {
213213
if (popType(ErrorLoc, {}))
214214
return true;
215215
} else if (Name == "end_block" || Name == "end_loop" || Name == "end_if" ||
216-
Name == "else") {
216+
Name == "else" || Name == "end_try") {
217217
if (checkEnd(ErrorLoc))
218218
return true;
219219
} else if (Name == "call_indirect" || Name == "return_call_indirect") {
@@ -230,6 +230,18 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst) {
230230
return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() +
231231
" missing .functype");
232232
if (checkSig(ErrorLoc, *Sig)) return true;
233+
} else if (Name == "catch") {
234+
const MCSymbolRefExpr *SymRef;
235+
if (getSymRef(ErrorLoc, Inst, SymRef))
236+
return true;
237+
const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->getSymbol());
238+
const auto *Sig = WasmSym->getSignature();
239+
if (!Sig || WasmSym->getType() != wasm::WASM_SYMBOL_TYPE_TAG)
240+
return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() +
241+
" missing .tagtype");
242+
// catch instruction pushes values whose types are specified in the tag's
243+
// "params" part
244+
Stack.insert(Stack.end(), Sig->Params.begin(), Sig->Params.end());
233245
} else if (Name == "ref.null") {
234246
auto VT = static_cast<wasm::ValType>(Inst.getOperand(0).getImm());
235247
Stack.push_back(VT);

llvm/lib/Target/WebAssembly/WebAssemblyISD.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ HANDLE_NODETYPE(PROMOTE_LOW)
4141
HANDLE_NODETYPE(TRUNC_SAT_ZERO_S)
4242
HANDLE_NODETYPE(TRUNC_SAT_ZERO_U)
4343
HANDLE_NODETYPE(DEMOTE_ZERO)
44-
HANDLE_NODETYPE(THROW)
45-
HANDLE_NODETYPE(CATCH)
4644
HANDLE_NODETYPE(MEMORY_COPY)
4745
HANDLE_NODETYPE(MEMORY_FILL)
4846

llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "WebAssemblyTargetMachine.h"
1818
#include "llvm/CodeGen/MachineFrameInfo.h"
1919
#include "llvm/CodeGen/SelectionDAGISel.h"
20+
#include "llvm/CodeGen/WasmEHFuncInfo.h"
2021
#include "llvm/IR/DiagnosticInfo.h"
2122
#include "llvm/IR/Function.h" // To access function attributes.
2223
#include "llvm/IR/IntrinsicsWebAssembly.h"
@@ -87,6 +88,15 @@ void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
8788
SelectionDAGISel::PreprocessISelDAG();
8889
}
8990

91+
static SDValue getTagSymNode(int Tag, SelectionDAG *DAG) {
92+
assert(Tag == WebAssembly::CPP_EXCEPTION);
93+
auto &MF = DAG->getMachineFunction();
94+
const auto &TLI = DAG->getTargetLoweringInfo();
95+
MVT PtrVT = TLI.getPointerTy(DAG->getDataLayout());
96+
const char *SymName = MF.createExternalSymbolName("__cpp_exception");
97+
return DAG->getTargetExternalSymbol(SymName, PtrVT);
98+
}
99+
90100
void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
91101
// If we have a custom node, we already have selected!
92102
if (Node->isMachineOpcode()) {
@@ -151,6 +161,7 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
151161
ReplaceNode(Node, TLSSize);
152162
return;
153163
}
164+
154165
case Intrinsic::wasm_tls_align: {
155166
MachineSDNode *TLSAlign = CurDAG->getMachineNode(
156167
GlobalGetIns, DL, PtrVT,
@@ -161,8 +172,11 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
161172
}
162173
break;
163174
}
175+
164176
case ISD::INTRINSIC_W_CHAIN: {
165177
unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
178+
const auto &TLI = CurDAG->getTargetLoweringInfo();
179+
MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
166180
switch (IntNo) {
167181
case Intrinsic::wasm_tls_base: {
168182
MachineSDNode *TLSBase = CurDAG->getMachineNode(
@@ -172,9 +186,48 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
172186
ReplaceNode(Node, TLSBase);
173187
return;
174188
}
189+
190+
case Intrinsic::wasm_catch_exn: {
191+
int Tag = Node->getConstantOperandVal(2);
192+
SDValue SymNode = getTagSymNode(Tag, CurDAG);
193+
MachineSDNode *Catch =
194+
CurDAG->getMachineNode(WebAssembly::CATCH, DL,
195+
{
196+
PtrVT, // exception pointer
197+
MVT::Other // outchain type
198+
},
199+
{
200+
SymNode, // exception symbol
201+
Node->getOperand(0) // inchain
202+
});
203+
ReplaceNode(Node, Catch);
204+
return;
205+
}
175206
}
176207
break;
177208
}
209+
210+
case ISD::INTRINSIC_VOID: {
211+
unsigned IntNo = Node->getConstantOperandVal(1);
212+
switch (IntNo) {
213+
case Intrinsic::wasm_throw: {
214+
int Tag = Node->getConstantOperandVal(2);
215+
SDValue SymNode = getTagSymNode(Tag, CurDAG);
216+
MachineSDNode *Throw =
217+
CurDAG->getMachineNode(WebAssembly::THROW, DL,
218+
MVT::Other, // outchain type
219+
{
220+
SymNode, // exception symbol
221+
Node->getOperand(3), // thrown value
222+
Node->getOperand(0) // inchain
223+
});
224+
ReplaceNode(Node, Throw);
225+
return;
226+
}
227+
}
228+
break;
229+
}
230+
178231
case WebAssemblyISD::CALL:
179232
case WebAssemblyISD::RET_CALL: {
180233
// CALL has both variable operands and variable results, but ISel only

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "llvm/CodeGen/MachineRegisterInfo.h"
2626
#include "llvm/CodeGen/SelectionDAG.h"
2727
#include "llvm/CodeGen/SelectionDAGNodes.h"
28-
#include "llvm/CodeGen/WasmEHFuncInfo.h"
2928
#include "llvm/IR/DiagnosticInfo.h"
3029
#include "llvm/IR/DiagnosticPrinter.h"
3130
#include "llvm/IR/Function.h"
@@ -1665,21 +1664,6 @@ SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
16651664
MachinePointerInfo(SV));
16661665
}
16671666

1668-
static SDValue getCppExceptionSymNode(SDValue Op, unsigned TagIndex,
1669-
SelectionDAG &DAG) {
1670-
// We only support C++ exceptions for now
1671-
int Tag =
1672-
cast<ConstantSDNode>(Op.getOperand(TagIndex).getNode())->getZExtValue();
1673-
if (Tag != WebAssembly::CPP_EXCEPTION)
1674-
llvm_unreachable("Invalid tag: We only support C++ exceptions for now");
1675-
auto &MF = DAG.getMachineFunction();
1676-
const auto &TLI = DAG.getTargetLoweringInfo();
1677-
MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
1678-
const char *SymName = MF.createExternalSymbolName("__cpp_exception");
1679-
return DAG.getNode(WebAssemblyISD::Wrapper, SDLoc(Op), PtrVT,
1680-
DAG.getTargetExternalSymbol(SymName, PtrVT));
1681-
}
1682-
16831667
SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
16841668
SelectionDAG &DAG) const {
16851669
MachineFunction &MF = DAG.getMachineFunction();
@@ -1712,30 +1696,6 @@ SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
17121696
DAG.getMCSymbol(S, PtrVT));
17131697
}
17141698

1715-
case Intrinsic::wasm_throw: {
1716-
SDValue SymNode = getCppExceptionSymNode(Op, 2, DAG);
1717-
return DAG.getNode(WebAssemblyISD::THROW, DL,
1718-
MVT::Other, // outchain type
1719-
{
1720-
Op.getOperand(0), // inchain
1721-
SymNode, // exception symbol
1722-
Op.getOperand(3) // thrown value
1723-
});
1724-
}
1725-
1726-
case Intrinsic::wasm_catch_exn: {
1727-
SDValue SymNode = getCppExceptionSymNode(Op, 2, DAG);
1728-
return DAG.getNode(WebAssemblyISD::CATCH, DL,
1729-
{
1730-
MVT::i32, // outchain type
1731-
MVT::Other // return value
1732-
},
1733-
{
1734-
Op.getOperand(0), // inchain
1735-
SymNode // exception symbol
1736-
});
1737-
}
1738-
17391699
case Intrinsic::wasm_shuffle: {
17401700
// Drop in-chain and replace undefs, but otherwise pass through unchanged
17411701
SDValue Ops[18];

llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ let Predicates = [HasExceptionHandling] in {
130130
// Throwing an exception: throw / rethrow
131131
let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
132132
defm THROW : I<(outs), (ins tag_op:$tag, variable_ops),
133-
(outs), (ins tag_op:$tag),
134-
[(WebAssemblythrow (WebAssemblywrapper texternalsym:$tag))],
133+
(outs), (ins tag_op:$tag), [],
135134
"throw \t$tag", "throw \t$tag", 0x08>;
136135
defm RETHROW : NRI<(outs), (ins i32imm:$depth), [], "rethrow \t$depth", 0x09>;
137136
} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
@@ -147,14 +146,10 @@ defm END_TRY : NRI<(outs), (ins), [], "end_try", 0x0b>;
147146

148147
// Catching an exception: catch / catch_all
149148
let hasCtrlDep = 1, hasSideEffects = 1 in {
150-
// Currently 'catch' can only extract an i32, which is sufficient for C++
151-
// support, but according to the spec 'catch' can extract any number of values
152-
// based on the tag type.
153-
defm CATCH : I<(outs I32:$dst), (ins tag_op:$tag),
154-
(outs), (ins tag_op:$tag),
155-
[(set I32:$dst,
156-
(WebAssemblycatch (WebAssemblywrapper texternalsym:$tag)))],
157-
"catch \t$dst, $tag", "catch \t$tag", 0x07>;
149+
let variadicOpsAreDefs = 1 in
150+
defm CATCH : I<(outs), (ins tag_op:$tag, variable_ops),
151+
(outs), (ins tag_op:$tag), [],
152+
"catch", "catch \t$tag", 0x07>;
158153
defm CATCH_ALL : NRI<(outs), (ins), [], "catch_all", 0x19>;
159154
}
160155

llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ def SDT_WebAssemblyWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
7979
SDTCisPtrTy<0>]>;
8080
def SDT_WebAssemblyWrapperPIC : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
8181
SDTCisPtrTy<0>]>;
82-
def SDT_WebAssemblyThrow : SDTypeProfile<0, -1, []>;
83-
def SDT_WebAssemblyCatch : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>;
8482
def SDT_WebAssemblyGlobalGet : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
8583
def SDT_WebAssemblyGlobalSet : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>;
8684

@@ -106,10 +104,6 @@ def WebAssemblywrapper : SDNode<"WebAssemblyISD::Wrapper",
106104
SDT_WebAssemblyWrapper>;
107105
def WebAssemblywrapperPIC : SDNode<"WebAssemblyISD::WrapperPIC",
108106
SDT_WebAssemblyWrapperPIC>;
109-
def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
110-
[SDNPHasChain, SDNPVariadic]>;
111-
def WebAssemblycatch : SDNode<"WebAssemblyISD::CATCH", SDT_WebAssemblyCatch,
112-
[SDNPHasChain, SDNPSideEffect]>;
113107
def WebAssemblyglobal_get :
114108
SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet,
115109
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;

0 commit comments

Comments
 (0)