llvm.org GIT mirror llvm / b29d4ba
[WebAssembly] Rename except_ref type to exnref Summary: We agreed to rename `except_ref` to `exnref` for consistency with other reference types in https://github.com/WebAssembly/exception-handling/issues/79. This also renames WebAssemblyInstrExceptRef.td to WebAssemblyInstrRef.td in order to use the file for other reference types in future. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, jfb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64703 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366145 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn a month ago
27 changed file(s) with 139 addition(s) and 144 deletion(s). Raw diff Collapse all Expand all
223223 WASM_TYPE_F64 = 0x7C,
224224 WASM_TYPE_V128 = 0x7B,
225225 WASM_TYPE_FUNCREF = 0x70,
226 WASM_TYPE_EXCEPT_REF = 0x68,
226 WASM_TYPE_EXNREF = 0x68,
227227 WASM_TYPE_FUNC = 0x60,
228228 WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
229229 };
331331 F32 = WASM_TYPE_F32,
332332 F64 = WASM_TYPE_F64,
333333 V128 = WASM_TYPE_V128,
334 EXCEPT_REF = WASM_TYPE_EXCEPT_REF,
334 EXNREF = WASM_TYPE_EXNREF,
335335 };
336336
337337 struct WasmSignature {
159159 def FlagVT : ValueType<0 , 126>; // Pre-RA sched glue
160160 def isVoid : ValueType<0 , 127>; // Produces no value
161161 def untyped: ValueType<8 , 128>; // Produces an untyped value
162 def ExceptRef: ValueType<0, 129>; // WebAssembly's except_ref type
162 def exnref: ValueType<0, 129>; // WebAssembly's exnref type
163163 def token : ValueType<0 , 248>; // TokenTy
164164 def MetadataVT: ValueType<0, 249>; // Metadata
165165
205205 // unspecified type. The register class
206206 // will be determined by the opcode.
207207
208 ExceptRef = 129, // WebAssembly's except_ref type
208 exnref = 129, // WebAssembly's exnref type
209209
210210 FIRST_VALUETYPE = 1, // This is always the beginning of the list.
211211 LAST_VALUETYPE = 130, // This always remains at the end of the list.
810810 case v1024f32: return 32768;
811811 case v2048i32:
812812 case v2048f32: return 65536;
813 case ExceptRef: return 0; // opaque type
813 case exnref: return 0; // opaque type
814814 }
815815 }
816816
206206 case MVT::v8f64: return "v8f64";
207207 case MVT::Metadata:return "Metadata";
208208 case MVT::Untyped: return "Untyped";
209 case MVT::ExceptRef: return "ExceptRef";
209 case MVT::exnref : return "exnref";
210210 }
211211 }
212212
307307 Type == "i32x4" || Type == "i64x2" || Type == "f32x4" ||
308308 Type == "f64x2")
309309 return wasm::ValType::V128;
310 if (Type == "except_ref")
311 return wasm::ValType::EXCEPT_REF;
310 if (Type == "exnref")
311 return wasm::ValType::EXNREF;
312312 return Optional();
313313 }
314314
319319 .Case("f32", WebAssembly::ExprType::F32)
320320 .Case("f64", WebAssembly::ExprType::F64)
321321 .Case("v128", WebAssembly::ExprType::V128)
322 .Case("except_ref", WebAssembly::ExprType::ExceptRef)
322 .Case("exnref", WebAssembly::ExprType::Exnref)
323323 .Case("void", WebAssembly::ExprType::Void)
324324 .Default(WebAssembly::ExprType::Invalid);
325325 }
281281 return "funcref";
282282 case wasm::WASM_TYPE_FUNC:
283283 return "func";
284 case wasm::WASM_TYPE_EXCEPT_REF:
285 return "except_ref";
284 case wasm::WASM_TYPE_EXNREF:
285 return "exnref";
286286 case wasm::WASM_TYPE_NORESULT:
287287 return "void";
288288 default:
145145 case MVT::v4f32:
146146 case MVT::v2f64:
147147 return wasm::ValType::V128;
148 case MVT::ExceptRef:
149 return wasm::ValType::EXCEPT_REF;
148 case MVT::exnref:
149 return wasm::ValType::EXNREF;
150150 default:
151151 llvm_unreachable("unexpected type");
152152 }
129129 F32 = 0x7D,
130130 F64 = 0x7C,
131131 V128 = 0x7B,
132 ExceptRef = 0x68,
132 Exnref = 0x68,
133133 Invalid = 0x00
134134 };
135135
402402 case WebAssembly::COPY_F64_S:
403403 case WebAssembly::COPY_V128:
404404 case WebAssembly::COPY_V128_S:
405 case WebAssembly::COPY_EXCEPT_REF:
406 case WebAssembly::COPY_EXCEPT_REF_S:
405 case WebAssembly::COPY_EXNREF:
406 case WebAssembly::COPY_EXNREF_S:
407407 return true;
408408 default:
409409 return false;
452452 case WebAssembly::CALL_v4f32_S:
453453 case WebAssembly::CALL_v2f64:
454454 case WebAssembly::CALL_v2f64_S:
455 case WebAssembly::CALL_ExceptRef:
456 case WebAssembly::CALL_ExceptRef_S:
455 case WebAssembly::CALL_exnref:
456 case WebAssembly::CALL_exnref_S:
457457 case WebAssembly::RET_CALL:
458458 case WebAssembly::RET_CALL_S:
459459 return true;
486486 case WebAssembly::CALL_INDIRECT_v4f32_S:
487487 case WebAssembly::CALL_INDIRECT_v2f64:
488488 case WebAssembly::CALL_INDIRECT_v2f64_S:
489 case WebAssembly::CALL_INDIRECT_ExceptRef:
490 case WebAssembly::CALL_INDIRECT_ExceptRef_S:
489 case WebAssembly::CALL_INDIRECT_exnref:
490 case WebAssembly::CALL_INDIRECT_exnref_S:
491491 case WebAssembly::RET_CALL_INDIRECT:
492492 case WebAssembly::RET_CALL_INDIRECT_S:
493493 return true;
529529 case WebAssembly::CALL_v4f32_S:
530530 case WebAssembly::CALL_v2f64:
531531 case WebAssembly::CALL_v2f64_S:
532 case WebAssembly::CALL_ExceptRef:
533 case WebAssembly::CALL_ExceptRef_S:
532 case WebAssembly::CALL_exnref:
533 case WebAssembly::CALL_exnref_S:
534534 case WebAssembly::CALL_INDIRECT_i32:
535535 case WebAssembly::CALL_INDIRECT_i32_S:
536536 case WebAssembly::CALL_INDIRECT_i64:
551551 case WebAssembly::CALL_INDIRECT_v4f32_S:
552552 case WebAssembly::CALL_INDIRECT_v2f64:
553553 case WebAssembly::CALL_INDIRECT_v2f64_S:
554 case WebAssembly::CALL_INDIRECT_ExceptRef:
555 case WebAssembly::CALL_INDIRECT_ExceptRef_S:
554 case WebAssembly::CALL_INDIRECT_exnref:
555 case WebAssembly::CALL_INDIRECT_exnref_S:
556556 return 1;
557557 default:
558558 llvm_unreachable("Not a call instruction");
307307
308308 // Add the BLOCK.
309309
310 // 'br_on_exn' extracts except_ref object and pushes variable number of values
310 // 'br_on_exn' extracts exnref object and pushes variable number of values
311311 // depending on its tag. For C++ exception, its a single i32 value, and the
312312 // generated code will be in the form of:
313313 // block i32
765765 // Note that the new wrapping block/end_block will be generated later in
766766 // placeBlockMarker.
767767 //
768 // TODO Currently local.set and local.gets are generated to move except_ref
769 // value created by catches. That's because we don't support yielding values
770 // from a block in LLVM machine IR yet, even though it is supported by wasm.
771 // Delete unnecessary local.get/local.sets once yielding values from a block
772 // is supported. The full EH spec requires multi-value support to do this, but
768 // TODO Currently local.set and local.gets are generated to move exnref value
769 // created by catches. That's because we don't support yielding values from a
770 // block in LLVM machine IR yet, even though it is supported by wasm. Delete
771 // unnecessary local.get/local.sets once yielding values from a block is
772 // supported. The full EH spec requires multi-value support to do this, but
773773 // for C++ we don't yet need it because we only throw a single i32.
774774 //
775775 // ---
833833 DenseMap> UnwindDestToTryRanges;
834834 // In new CFG,
835835 DenseMap> BrDestToTryRanges;
836 // In new CFG, cept_ref>
836 // In new CFG, nref>
837837 DenseMap BrDestToExnReg;
838838
839839 // Gather possibly throwing calls (i.e., previously invokes) whose current
935935 // of the function with a local.get and a rethrow instruction.
936936 if (NeedAppendixBlock) {
937937 auto *AppendixBB = getAppendixBlock(MF);
938 unsigned ExnReg =
939 MRI.createVirtualRegister(&WebAssembly::EXCEPT_REFRegClass);
938 unsigned ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
940939 BuildMI(AppendixBB, DebugLoc(), TII.get(WebAssembly::RETHROW))
941940 .addReg(ExnReg);
942941 // These instruction ranges should branch to this appendix BB.
12241223 case MVT::v2f64:
12251224 RetType = WebAssembly::ExprType::V128;
12261225 break;
1227 case MVT::ExceptRef:
1228 RetType = WebAssembly::ExprType::ExceptRef;
1226 case MVT::exnref:
1227 RetType = WebAssembly::ExprType::Exnref;
12291228 break;
12301229 default:
12311230 llvm_unreachable("unexpected return type");
8484 return CALL_INDIRECT_v4f32;
8585 case PCALL_INDIRECT_v2f64:
8686 return CALL_INDIRECT_v2f64;
87 case PCALL_INDIRECT_ExceptRef:
88 return CALL_INDIRECT_ExceptRef;
87 case PCALL_INDIRECT_exnref:
88 return CALL_INDIRECT_exnref;
8989 case PRET_CALL_INDIRECT:
9090 return RET_CALL_INDIRECT;
9191 default:
8989 return WebAssembly::DROP_F64;
9090 if (RC == &WebAssembly::V128RegClass)
9191 return WebAssembly::DROP_V128;
92 if (RC == &WebAssembly::EXCEPT_REFRegClass)
93 return WebAssembly::DROP_EXCEPT_REF;
92 if (RC == &WebAssembly::EXNREFRegClass)
93 return WebAssembly::DROP_EXNREF;
9494 llvm_unreachable("Unexpected register class");
9595 }
9696
106106 return WebAssembly::LOCAL_GET_F64;
107107 if (RC == &WebAssembly::V128RegClass)
108108 return WebAssembly::LOCAL_GET_V128;
109 if (RC == &WebAssembly::EXCEPT_REFRegClass)
110 return WebAssembly::LOCAL_GET_EXCEPT_REF;
109 if (RC == &WebAssembly::EXNREFRegClass)
110 return WebAssembly::LOCAL_GET_EXNREF;
111111 llvm_unreachable("Unexpected register class");
112112 }
113113
123123 return WebAssembly::LOCAL_SET_F64;
124124 if (RC == &WebAssembly::V128RegClass)
125125 return WebAssembly::LOCAL_SET_V128;
126 if (RC == &WebAssembly::EXCEPT_REFRegClass)
127 return WebAssembly::LOCAL_SET_EXCEPT_REF;
126 if (RC == &WebAssembly::EXNREFRegClass)
127 return WebAssembly::LOCAL_SET_EXNREF;
128128 llvm_unreachable("Unexpected register class");
129129 }
130130
140140 return WebAssembly::LOCAL_TEE_F64;
141141 if (RC == &WebAssembly::V128RegClass)
142142 return WebAssembly::LOCAL_TEE_V128;
143 if (RC == &WebAssembly::EXCEPT_REFRegClass)
144 return WebAssembly::LOCAL_TEE_EXCEPT_REF;
143 if (RC == &WebAssembly::EXNREFRegClass)
144 return WebAssembly::LOCAL_TEE_EXNREF;
145145 llvm_unreachable("Unexpected register class");
146146 }
147147
157157 return MVT::f64;
158158 if (RC == &WebAssembly::V128RegClass)
159159 return MVT::v16i8;
160 if (RC == &WebAssembly::EXCEPT_REFRegClass)
161 return MVT::ExceptRef;
160 if (RC == &WebAssembly::EXNREFRegClass)
161 return MVT::exnref;
162162 llvm_unreachable("unrecognized register class");
163163 }
164164
128128 case MVT::i64:
129129 case MVT::f32:
130130 case MVT::f64:
131 case MVT::ExceptRef:
131 case MVT::exnref:
132132 return VT;
133133 case MVT::f16:
134134 return MVT::f32;
697697 Opc = WebAssembly::ARGUMENT_v2f64;
698698 RC = &WebAssembly::V128RegClass;
699699 break;
700 case MVT::ExceptRef:
701 Opc = WebAssembly::ARGUMENT_ExceptRef;
702 RC = &WebAssembly::EXCEPT_REFRegClass;
700 case MVT::exnref:
701 Opc = WebAssembly::ARGUMENT_exnref;
702 RC = &WebAssembly::EXNREFRegClass;
703703 break;
704704 default:
705705 return false;
814814 : WebAssembly::PCALL_INDIRECT_v2f64;
815815 ResultReg = createResultReg(&WebAssembly::V128RegClass);
816816 break;
817 case MVT::ExceptRef:
818 Opc = IsDirect ? WebAssembly::CALL_ExceptRef
819 : WebAssembly::PCALL_INDIRECT_ExceptRef;
820 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
817 case MVT::exnref:
818 Opc = IsDirect ? WebAssembly::CALL_exnref
819 : WebAssembly::PCALL_INDIRECT_exnref;
820 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
821821 break;
822822 default:
823823 return false;
920920 Opc = WebAssembly::SELECT_F64;
921921 RC = &WebAssembly::F64RegClass;
922922 break;
923 case MVT::ExceptRef:
924 Opc = WebAssembly::SELECT_EXCEPT_REF;
925 RC = &WebAssembly::EXCEPT_REFRegClass;
923 case MVT::exnref:
924 Opc = WebAssembly::SELECT_EXNREF;
925 RC = &WebAssembly::EXNREFRegClass;
926926 break;
927927 default:
928928 return false;
13401340 case MVT::v2f64:
13411341 Opc = WebAssembly::RETURN_v2f64;
13421342 break;
1343 case MVT::ExceptRef:
1344 Opc = WebAssembly::RETURN_EXCEPT_REF;
1343 case MVT::exnref:
1344 Opc = WebAssembly::RETURN_EXNREF;
13451345 break;
13461346 default:
13471347 return false;
5858 defm "" : CALL;
5959 defm "" : CALL;
6060 defm "" : CALL;
61 defm "" : CALL<ExceptRef, EXCEPT_REF, "except_ref.", [HasExceptionHandling]>;
61 defm "" : CALL<exnref, EXNREF, "exnref.", [HasExceptionHandling]>;
6262 defm "" : CALL;
6363 defm "" : CALL;
6464 defm "" : CALL;
138138 (CALL_v4f32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
139139 def : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
140140 (CALL_v2f64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>;
141 def : Pat<(ExceptRef
142 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
143 (CALL_ExceptRef tglobaladdr:$callee)>,
141 def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
142 (CALL_exnref tglobaladdr:$callee)>,
144143 Requires<[HasExceptionHandling]>;
145144 def : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)),
146145 (CALL_VOID tglobaladdr:$callee)>;
168167 (CALL_v4f32 texternalsym:$callee)>, Requires<[HasSIMD128]>;
169168 def : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
170169 (CALL_v2f64 texternalsym:$callee)>, Requires<[HasSIMD128]>;
171 def : Pat<(ExceptRef
172 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
173 (CALL_ExceptRef texternalsym:$callee)>,
170 def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
171 (CALL_exnref texternalsym:$callee)>,
174172 Requires<[HasExceptionHandling]>;
175173 def : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)),
176174 (CALL_VOID texternalsym:$callee)>;
113113 defm "": RETURN;
114114 defm "": RETURN;
115115 defm "": RETURN;
116 defm "": RETURNCEPT_REF>;
116 defm "": RETURNNREF>;
117117 defm "": SIMD_RETURN;
118118 defm "": SIMD_RETURN;
119119 defm "": SIMD_RETURN;
143143 (outs), (ins event_op:$tag),
144144 [(WebAssemblythrow (WebAssemblywrapper texternalsym:$tag))],
145145 "throw \t$tag", "throw \t$tag", 0x08>;
146 defm RETHROW : I<(outs), (ins EXCEPT_REF:$exn), (outs), (ins),
147 [], "rethrow \t$exn", "rethrow", 0x09>;
146 defm RETHROW : I<(outs), (ins EXNREF:$exn), (outs), (ins), [],
147 "rethrow \t$exn", "rethrow", 0x09>;
148148 // Pseudo instruction to be the lowering target of int_wasm_rethrow_in_catch
149149 // intrinsic. Will be converted to the real rethrow instruction later.
150150 let isPseudo = 1 in
160160
161161 // Catching an exception: catch / extract_exception
162162 let hasCtrlDep = 1, hasSideEffects = 1 in
163 defm CATCH : I<(outs EXCEPT_REF:$dst), (ins), (outs), (ins), [],
163 defm CATCH : I<(outs EXNREF:$dst), (ins), (outs), (ins), [],
164164 "catch \t$dst", "catch", 0x07>;
165165
166166 // Querying / extracing exception: br_on_exn
167 // br_on_exn queries an except_ref to see if it matches the corresponding
168 // exception tag index. If true it branches to the given label and pushes the
167 // br_on_exn queries an exnref to see if it matches the corresponding exception
168 // tag index. If true it branches to the given label and pushes the
169169 // corresponding argument values of the exception onto the stack.
170170 let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in
171 defm BR_ON_EXN : I<(outs), (ins bb_op:$dst, event_op:$tag, EXCEPT_REF:$exn),
171 defm BR_ON_EXN : I<(outs), (ins bb_op:$dst, event_op:$tag, EXNREF:$exn),
172172 (outs), (ins bb_op:$dst, event_op:$tag), [],
173173 "br_on_exn \t$dst, $tag, $exn", "br_on_exn \t$dst, $tag",
174174 0x0a>;
+0
-26
lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td less more
None // WebAssemblyInstrExceptRef.td-WebAssembly except_ref codegen --*- tablegen -*-
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 ///
8 /// \file
9 /// WebAssembly except_ref operand code-gen constructs.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 defm SELECT_EXCEPT_REF : I<(outs EXCEPT_REF:$dst),
14 (ins EXCEPT_REF:$lhs, EXCEPT_REF:$rhs, I32:$cond),
15 (outs), (ins),
16 [(set EXCEPT_REF:$dst,
17 (select I32:$cond, EXCEPT_REF:$lhs,
18 EXCEPT_REF:$rhs))],
19 "except_ref.select\t$dst, $lhs, $rhs, $cond",
20 "except_ref.select", 0x1b>;
21
22 def : Pat<(select (i32 (setne I32:$cond, 0)), EXCEPT_REF:$lhs, EXCEPT_REF:$rhs),
23 (SELECT_EXCEPT_REF EXCEPT_REF:$lhs, EXCEPT_REF:$rhs, I32:$cond)>;
24 def : Pat<(select (i32 (seteq I32:$cond, 0)), EXCEPT_REF:$lhs, EXCEPT_REF:$rhs),
25 (SELECT_EXCEPT_REF EXCEPT_REF:$rhs, EXCEPT_REF:$lhs, I32:$cond)>;
191191 MachineFunction &MF = *MBB.getParent();
192192 auto &MRI = MF.getRegInfo();
193193 bool IsBrOnExn = Cond[1].isReg() && MRI.getRegClass(Cond[1].getReg()) ==
194 &WebAssembly::EXCEPT_REFRegClass;
194 &WebAssembly::EXNREFRegClass;
195195
196196 if (Cond[0].getImm()) {
197197 if (IsBrOnExn) {
221221 MachineFunction &MF = *Cond[1].getParent()->getParent()->getParent();
222222 auto &MRI = MF.getRegInfo();
223223 if (Cond[1].isReg() &&
224 MRI.getRegClass(Cond[1].getReg()) == &WebAssembly::EXCEPT_REFRegClass)
224 MRI.getRegClass(Cond[1].getReg()) == &WebAssembly::EXNREFRegClass)
225225 return true;
226226
227227 Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
223223 defm "": ARGUMENT;
224224 defm "": ARGUMENT;
225225 defm "": ARGUMENT;
226 defm "": ARGUMENTCEPT_REF, ExceptRef>;
226 defm "": ARGUMENTNREF, exnref>;
227227
228228 // local.get and local.set are not generated by instruction selection; they
229229 // are implied by virtual register uses and defs.
293293 defm "" : LOCAL;
294294 defm "" : LOCAL;
295295 defm "" : LOCAL, Requires<[HasSIMD128]>;
296 defm "" : LOCALCEPT_REF>, Requires<[HasExceptionHandling]>;
296 defm "" : LOCALNREF>, Requires<[HasExceptionHandling]>;
297297
298298 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
299299 defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
344344 include "WebAssemblyInstrFloat.td"
345345 include "WebAssemblyInstrAtomics.td"
346346 include "WebAssemblyInstrSIMD.td"
347 include "WebAssemblyInstrExceptRef.td"
347 include "WebAssemblyInstrRef.td"
348348 include "WebAssemblyInstrBulkMemory.td"
0 // WebAssemblyInstrRef.td - WebAssembly reference type codegen --*- tablegen -*-
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 ///
8 /// \file
9 /// WebAssembly refence type operand codegen constructs.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 defm SELECT_EXNREF : I<(outs EXNREF:$dst),
14 (ins EXNREF:$lhs, EXNREF:$rhs, I32:$cond),
15 (outs), (ins),
16 [(set EXNREF:$dst,
17 (select I32:$cond, EXNREF:$lhs, EXNREF:$rhs))],
18 "exnref.select\t$dst, $lhs, $rhs, $cond",
19 "exnref.select", 0x1b>;
20
21 def : Pat<(select (i32 (setne I32:$cond, 0)), EXNREF:$lhs, EXNREF:$rhs),
22 (SELECT_EXNREF EXNREF:$lhs, EXNREF:$rhs, I32:$cond)>;
23 def : Pat<(select (i32 (seteq I32:$cond, 0)), EXNREF:$lhs, EXNREF:$rhs),
24 (SELECT_EXNREF EXNREF:$rhs, EXNREF:$lhs, I32:$cond)>;
130130 auto InsertPos = MBB.begin();
131131 if (InsertPos->isEHLabel()) // EH pad starts with an EH label
132132 ++InsertPos;
133 unsigned DstReg =
134 MRI.createVirtualRegister(&WebAssembly::EXCEPT_REFRegClass);
133 unsigned DstReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
135134 BuildMI(MBB, InsertPos, MBB.begin()->getDebugLoc(),
136135 TII.get(WebAssembly::CATCH), DstReg);
137136 }
208207 }
209208
210209 // Wasm uses 'br_on_exn' instruction to check the tag of an exception. It takes
211 // except_ref type object returned by 'catch', and branches to the destination
212 // if it matches a given tag. We currently use __cpp_exception symbol to
213 // represent the tag for all C++ exceptions.
210 // exnref type object returned by 'catch', and branches to the destination if it
211 // matches a given tag. We currently use __cpp_exception symbol to represent the
212 // tag for all C++ exceptions.
214213 //
215214 // block $l (result i32)
216215 // ...
217 // ;; except_ref $e is on the stack at this point
216 // ;; exnref $e is on the stack at this point
218217 // br_on_exn $l $e ;; branch to $l with $e's arguments
219218 // ...
220219 // end
221220 // ;; Here we expect the extracted values are on top of the wasm value stack
222221 // ... Handle exception using values ...
223222 //
224 // br_on_exn takes an except_ref object and branches if it matches the given
225 // tag. There can be multiple br_on_exn instructions if we want to match for
226 // another tag, but for now we only test for __cpp_exception tag, and if it does
227 // not match, i.e., it is a foreign exception, we rethrow it.
223 // br_on_exn takes an exnref object and branches if it matches the given tag.
224 // There can be multiple br_on_exn instructions if we want to match for another
225 // tag, but for now we only test for __cpp_exception tag, and if it does not
226 // match, i.e., it is a foreign exception, we rethrow it.
228227 //
229228 // In the destination BB that's the target of br_on_exn, extracted exception
230229 // values (in C++'s case a single i32, which represents an exception pointer)
278277
279278 // - Before:
280279 // ehpad:
281 // %exnref:except_ref = catch
280 // %exnref:exnref = catch
282281 // %exn:i32 = extract_exception
283282 // ... use exn ...
284283 //
285284 // - After:
286285 // ehpad:
287 // %exnref:except_ref = catch
286 // %exnref:exnref = catch
288287 // br_on_exn %thenbb, $__cpp_exception, %exnref
289288 // br %elsebb
290289 // elsebb:
316315 //
317316 // - Before:
318317 // ehpad:
319 // %exnref:except_ref = catch
318 // %exnref:exnref = catch
320319 // %exn:i32 = extract_exception
321320 // call @__clang_call_terminate(%exn)
322321 // unreachable
323322 //
324323 // - After:
325324 // ehpad:
326 // %exnref:except_ref = catch
325 // %exnref:exnref = catch
327326 // br_on_exn %thenbb, $__cpp_exception, %exnref
328327 // br %elsebb
329328 // elsebb:
833833 // entering blocks, which is a part of multi-value proposal.
834834 //
835835 // Once we support live-in values of wasm blocks, this can be:
836 // catch ; push except_ref value onto stack
837 // block except_ref -> i32
838 // br_on_exn $__cpp_exception ; pop the except_ref value
836 // catch ; push exnref value onto stack
837 // block exnref -> i32
838 // br_on_exn $__cpp_exception ; pop the exnref value
839839 // end_block
840840 //
841841 // But because we don't support it yet, the catch instruction's dst
4242
4343 def V128_0: WebAssemblyReg<"%v128">;
4444
45 def EXCEPT_REF_0 : WebAssemblyReg<"%except_ref.0">;
45 def EXNREF_0 : WebAssemblyReg<"%exnref.0">;
4646
4747 // The value stack "register". This is an opaque entity which serves to order
4848 // uses and defs that must remain in LIFO order.
6363 def F64 : WebAssemblyRegClass<[f64], 64, (add F64_0)>;
6464 def V128 : WebAssemblyRegClass<[v4f32, v2f64, v2i64, v4i32, v16i8, v8i16], 128,
6565 (add V128_0)>;
66 def EXCEPT_REF : WebAssemblyRegClass<[ExceptRef], 0, (add EXCEPT_REF_0)>;
66 def EXNREF : WebAssemblyRegClass<[exnref], 0, (add EXNREF_0)>;
3030 ; CHECK: global.get ${{.+}}=, __stack_pointer
3131 ; CHECK: try
3232 ; CHECK: call foo
33 ; CHECK: catch $[[EXCEPT_REF:[0-9]+]]=
33 ; CHECK: catch $[[EXNREF:[0-9]+]]=
3434 ; CHECK: global.set __stack_pointer
3535 ; CHECK: block i32
36 ; CHECK: br_on_exn 0, __cpp_exception, $[[EXCEPT_REF]]
37 ; CHECK: rethrow $[[EXCEPT_REF]]
36 ; CHECK: br_on_exn 0, __cpp_exception, $[[EXNREF]]
37 ; CHECK: rethrow $[[EXNREF]]
3838 ; CHECK: end_block
3939 ; CHECK: extract_exception $[[EXN:[0-9]+]]=
4040 ; CHECK-DAG: i32.store __wasm_lpad_context
4646 ; CHECK: call __cxa_end_catch
4747 ; CHECK: br 1
4848 ; CHECK: end_block
49 ; CHECK: rethrow $[[EXCEPT_REF]]
49 ; CHECK: rethrow $[[EXNREF]]
5050 ; CHECK: end_try
5151 define void @test_catch() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
5252 entry:
9191 ; CHECK-LABEL: test_cleanup:
9292 ; CHECK: try
9393 ; CHECK: call foo
94 ; CHECK: catch $[[EXCEPT_REF:[0-9]+]]=
94 ; CHECK: catch $[[EXNREF:[0-9]+]]=
9595 ; CHECK: global.set __stack_pointer
9696 ; CHECK: i32.call $drop=, _ZN4TempD2Ev
97 ; CHECK: rethrow $[[EXCEPT_REF]]
97 ; CHECK: rethrow $[[EXNREF]]
9898 ; CHECK: end_try
9999 define void @test_cleanup() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
100100 entry:
2222 0x11 0x80 0x01 0x00
2323
2424 # CHECK: call 0
25 # CHECK-NOT: except_ref.call 0
25 # CHECK-NOT: exnref.call 0
2626 0x10 0x00
2727
2828 # CHECK: local.get 128
6969 # TODO: enable once instruction has been added.
7070 #i32x4.trunc_sat_f32x4_s
7171 i32.trunc_f32_s
72 try except_ref
72 try exnref
7373 i32.atomic.load 0
7474 atomic.notify 0
7575 .LBB0_3:
171171 # CHECK-NEXT: end_if
172172 # CHECK-NEXT: f32x4.add
173173 # CHECK-NEXT: i32.trunc_f32_s
174 # CHECK-NEXT: try except_ref
174 # CHECK-NEXT: try exnref
175175 # CHECK-NEXT: i32.atomic.load 0
176176 # CHECK-NEXT: atomic.notify 0
177177 # CHECK-NEXT: .LBB0_3:
88
99 test1:
1010 .functype test1 (i32, i64) -> (i32)
11 .local i32, i64, except_ref
11 .local i32, i64, exnref
1212 local.get 3
1313 end_function
1414
2020 # CHECK-NEXT: 9: 20 02 local.get 2
2121 # CHECK-NEXT: b: 0b end
2222 # CHECK-LABEL: test1:
23 # CHECK-NEXT: .local i32, i64, except_ref
23 # CHECK-NEXT: .local i32, i64, exnref
2424 # CHECK-NEXT: 14: 20 03 local.get 3
2525 # CHECK-NEXT: 16: 0b end
9999 ; predecessors: %bb.0
100100 successors: %bb.3, %bb.9
101101 liveins: $value_stack
102 %0:except_ref = CATCH implicit-def $arguments
102 %0:exnref = CATCH implicit-def $arguments
103103 CLEANUPRET implicit-def dead $arguments
104104
105105 bb.3 (landing-pad):
106106 ; predecessors: %bb.2
107107 successors: %bb.4, %bb.6
108108 liveins: $value_stack
109 %1:except_ref = CATCH implicit-def $arguments
109 %1:exnref = CATCH implicit-def $arguments
110110 BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
111111 BR %bb.6, implicit-def $arguments
112112
137137 ; predecessors: %bb.4
138138 successors: %bb.9
139139 liveins: $value_stack
140 %2:except_ref = CATCH implicit-def $arguments
140 %2:exnref = CATCH implicit-def $arguments
141141 CLEANUPRET implicit-def dead $arguments
142142
143143 bb.9 (landing-pad):
144144 ; predecessors: %bb.2, %bb.6, %bb.8
145145 liveins: $value_stack
146 %3:except_ref = CATCH implicit-def $arguments
146 %3:exnref = CATCH implicit-def $arguments
147147 CLEANUPRET implicit-def dead $arguments
148148
149149 bb.10:
256256 ; predecessors: %bb.0
257257 successors: %bb.2, %bb.8
258258 liveins: $value_stack
259 %0:except_ref = CATCH implicit-def $arguments
259 %0:exnref = CATCH implicit-def $arguments
260260 BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
261261 BR %bb.8, implicit-def $arguments
262262
270270 ; predecessors: %bb.2
271271 successors: %bb.4, %bb.6
272272 liveins: $value_stack
273 %1:except_ref = CATCH implicit-def $arguments
273 %1:exnref = CATCH implicit-def $arguments
274274 BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
275275 BR %bb.6, implicit-def $arguments
276276
312312 ; predecessors: %bb.4
313313 successors: %bb.11
314314 liveins: $value_stack
315 %2:except_ref = CATCH implicit-def $arguments
315 %2:exnref = CATCH implicit-def $arguments
316316 CLEANUPRET implicit-def dead $arguments
317317
318318 bb.11 (landing-pad):
319319 ; predecessors: %bb.2, %bb.6, %bb.10
320320 liveins: $value_stack
321 %3:except_ref = CATCH implicit-def $arguments
321 %3:exnref = CATCH implicit-def $arguments
322322 CLEANUPRET implicit-def dead $arguments
323323
324324 bb.12:
190190 case MVT::iPTR: return "MVT::iPTR";
191191 case MVT::iPTRAny: return "MVT::iPTRAny";
192192 case MVT::Untyped: return "MVT::Untyped";
193 case MVT::ExceptRef: return "MVT::ExceptRef";
193 case MVT::exnref: return "MVT::exnref";
194194 default: llvm_unreachable("ILLEGAL VALUE TYPE!");
195195 }
196196 }