xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric// WebAssemblyInstrInfo.td-Describe the WebAssembly Instructions-*- tablegen -*-
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric///
90b57cec5SDimitry Andric/// \file
100b57cec5SDimitry Andric/// WebAssembly Instruction definitions.
110b57cec5SDimitry Andric///
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// WebAssembly Instruction Predicate Definitions.
160b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricdef IsPIC     : Predicate<"TM.isPositionIndependent()">;
190b57cec5SDimitry Andricdef IsNotPIC  : Predicate<"!TM.isPositionIndependent()">;
200b57cec5SDimitry Andric
210b57cec5SDimitry Andricdef HasAddr32 : Predicate<"!Subtarget->hasAddr64()">;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andricdef HasAddr64 : Predicate<"Subtarget->hasAddr64()">;
240b57cec5SDimitry Andric
250b57cec5SDimitry Andricdef HasSIMD128 :
260b57cec5SDimitry Andric    Predicate<"Subtarget->hasSIMD128()">,
275ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureSIMD128), "simd128">;
280b57cec5SDimitry Andric
29349cc55cSDimitry Andricdef HasRelaxedSIMD :
30349cc55cSDimitry Andric    Predicate<"Subtarget->hasRelaxedSIMD()">,
31349cc55cSDimitry Andric    AssemblerPredicate<(all_of FeatureRelaxedSIMD), "relaxed-simd">;
32349cc55cSDimitry Andric
330b57cec5SDimitry Andricdef HasAtomics :
340b57cec5SDimitry Andric    Predicate<"Subtarget->hasAtomics()">,
355ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureAtomics), "atomics">;
360b57cec5SDimitry Andric
370b57cec5SDimitry Andricdef HasMultivalue :
380b57cec5SDimitry Andric    Predicate<"Subtarget->hasMultivalue()">,
395ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureMultivalue), "multivalue">;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andricdef HasNontrappingFPToInt :
420b57cec5SDimitry Andric    Predicate<"Subtarget->hasNontrappingFPToInt()">,
435ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureNontrappingFPToInt), "nontrapping-fptoint">;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andricdef NotHasNontrappingFPToInt :
460b57cec5SDimitry Andric    Predicate<"!Subtarget->hasNontrappingFPToInt()">,
475ffd83dbSDimitry Andric    AssemblerPredicate<(all_of (not FeatureNontrappingFPToInt)), "nontrapping-fptoint">;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andricdef HasSignExt :
500b57cec5SDimitry Andric    Predicate<"Subtarget->hasSignExt()">,
515ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureSignExt), "sign-ext">;
520b57cec5SDimitry Andric
530b57cec5SDimitry Andricdef HasTailCall :
540b57cec5SDimitry Andric    Predicate<"Subtarget->hasTailCall()">,
555ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureTailCall), "tail-call">;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andricdef HasExceptionHandling :
580b57cec5SDimitry Andric    Predicate<"Subtarget->hasExceptionHandling()">,
595ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">;
600b57cec5SDimitry Andric
610b57cec5SDimitry Andricdef HasBulkMemory :
620b57cec5SDimitry Andric    Predicate<"Subtarget->hasBulkMemory()">,
635ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">;
645ffd83dbSDimitry Andric
655ffd83dbSDimitry Andricdef HasReferenceTypes :
665ffd83dbSDimitry Andric    Predicate<"Subtarget->hasReferenceTypes()">,
675ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureReferenceTypes), "reference-types">;
680b57cec5SDimitry Andric
6981ad6265SDimitry Andricdef HasExtendedConst :
7081ad6265SDimitry Andric    Predicate<"Subtarget->hasExtendedConst()">,
7181ad6265SDimitry Andric    AssemblerPredicate<(all_of FeatureExtendedConst), "extended-const">;
7281ad6265SDimitry Andric
73*5f757f3fSDimitry Andricdef HasMultiMemory :
74*5f757f3fSDimitry Andric    Predicate<"Subtarget->hasMultiMemory()">,
75*5f757f3fSDimitry Andric    AssemblerPredicate<(all_of FeatureMultiMemory), "multimemory">;
76*5f757f3fSDimitry Andric
770b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
780b57cec5SDimitry Andric// WebAssembly-specific DAG Node Types.
790b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
800b57cec5SDimitry Andric
810b57cec5SDimitry Andricdef SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
820b57cec5SDimitry Andric                                                  SDTCisVT<1, iPTR>]>;
830b57cec5SDimitry Andricdef SDT_WebAssemblyCallSeqEnd :
840b57cec5SDimitry Andric    SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
850b57cec5SDimitry Andricdef SDT_WebAssemblyBrTable    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
860b57cec5SDimitry Andricdef SDT_WebAssemblyArgument   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
87fe6060f1SDimitry Andricdef SDT_WebAssemblyLocalGet   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
88fe6060f1SDimitry Andricdef SDT_WebAssemblyLocalSet   : SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>;
890b57cec5SDimitry Andricdef SDT_WebAssemblyReturn     : SDTypeProfile<0, -1, []>;
900b57cec5SDimitry Andricdef SDT_WebAssemblyWrapper    : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
910b57cec5SDimitry Andric                                                     SDTCisPtrTy<0>]>;
92fe6060f1SDimitry Andricdef SDT_WebAssemblyGlobalGet  : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
93fe6060f1SDimitry Andricdef SDT_WebAssemblyGlobalSet  : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
960b57cec5SDimitry Andric// WebAssembly-specific DAG Nodes.
970b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
980b57cec5SDimitry Andric
990b57cec5SDimitry Andricdef WebAssemblycallseq_start :
1000b57cec5SDimitry Andric    SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
1010b57cec5SDimitry Andric           [SDNPHasChain, SDNPOutGlue]>;
1020b57cec5SDimitry Andricdef WebAssemblycallseq_end :
1030b57cec5SDimitry Andric    SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
1040b57cec5SDimitry Andric           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
1050b57cec5SDimitry Andricdef WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
1060b57cec5SDimitry Andric                                 SDT_WebAssemblyBrTable,
1070b57cec5SDimitry Andric                                 [SDNPHasChain, SDNPVariadic]>;
1080b57cec5SDimitry Andricdef WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
1090b57cec5SDimitry Andric                                 SDT_WebAssemblyArgument>;
1100b57cec5SDimitry Andricdef WebAssemblyreturn   : SDNode<"WebAssemblyISD::RETURN",
1118bcb0991SDimitry Andric                                 SDT_WebAssemblyReturn,
1128bcb0991SDimitry Andric                                 [SDNPHasChain, SDNPVariadic]>;
113349cc55cSDimitry Andricdef WebAssemblyWrapper  : SDNode<"WebAssemblyISD::Wrapper",
1140b57cec5SDimitry Andric                                 SDT_WebAssemblyWrapper>;
115349cc55cSDimitry Andricdef WebAssemblyWrapperREL  : SDNode<"WebAssemblyISD::WrapperREL",
116349cc55cSDimitry Andric                                     SDT_WebAssemblyWrapper>;
117fe6060f1SDimitry Andricdef WebAssemblyglobal_get :
118fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet,
119fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
120fe6060f1SDimitry Andricdef WebAssemblyglobal_set :
121fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::GLOBAL_SET", SDT_WebAssemblyGlobalSet,
122fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
123fe6060f1SDimitry Andricdef WebAssemblylocal_get :
124fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::LOCAL_GET", SDT_WebAssemblyLocalGet,
125fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayLoad]>;
126fe6060f1SDimitry Andricdef WebAssemblylocal_set :
127fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::LOCAL_SET", SDT_WebAssemblyLocalSet,
128fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayStore]>;
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1310b57cec5SDimitry Andric// WebAssembly-specific Operands.
1320b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric// Default Operand has AsmOperandClass "Imm" which is for integers (and
1350b57cec5SDimitry Andric// symbols), so specialize one for floats:
136fe6060f1SDimitry Andricclass FPImmAsmOperand<ValueType ty> : AsmOperandClass {
137fe6060f1SDimitry Andric  let Name = "FPImm" # ty;
1380b57cec5SDimitry Andric  let PredicateMethod = "isFPImm";
1390b57cec5SDimitry Andric}
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andricclass FPOperand<ValueType ty> : Operand<ty> {
142fe6060f1SDimitry Andric  AsmOperandClass ParserMatchClass = FPImmAsmOperand<ty>;
1430b57cec5SDimitry Andric}
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andriclet OperandNamespace = "WebAssembly" in {
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andriclet OperandType = "OPERAND_BASIC_BLOCK" in
1480b57cec5SDimitry Andricdef bb_op : Operand<OtherVT>;
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andriclet OperandType = "OPERAND_LOCAL" in
1510b57cec5SDimitry Andricdef local_op : Operand<i32>;
1520b57cec5SDimitry Andric
153fe6060f1SDimitry Andriclet OperandType = "OPERAND_GLOBAL" in {
154fe6060f1SDimitry Andric  // The operand to global instructions is always a 32-bit index.
155fe6060f1SDimitry Andric  def global_op32 : Operand<i32>;
156fe6060f1SDimitry Andric  // In PIC mode however, we temporarily represent this index as an external
157fe6060f1SDimitry Andric  // symbol, which to LLVM is a pointer, so in wasm64 mode it is easiest to
158fe6060f1SDimitry Andric  // pretend we use a 64-bit index for it.
159fe6060f1SDimitry Andric  def global_op64 : Operand<i64>;
160fe6060f1SDimitry Andric}
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andriclet OperandType = "OPERAND_I32IMM" in
1630b57cec5SDimitry Andricdef i32imm_op : Operand<i32>;
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andriclet OperandType = "OPERAND_I64IMM" in
1660b57cec5SDimitry Andricdef i64imm_op : Operand<i64>;
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andriclet OperandType = "OPERAND_F32IMM" in
1690b57cec5SDimitry Andricdef f32imm_op : FPOperand<f32>;
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andriclet OperandType = "OPERAND_F64IMM" in
1720b57cec5SDimitry Andricdef f64imm_op : FPOperand<f64>;
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I8IMM" in
1750b57cec5SDimitry Andricdef vec_i8imm_op : Operand<i32>;
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I16IMM" in
1780b57cec5SDimitry Andricdef vec_i16imm_op : Operand<i32>;
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I32IMM" in
1810b57cec5SDimitry Andricdef vec_i32imm_op : Operand<i32>;
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I64IMM" in
1840b57cec5SDimitry Andricdef vec_i64imm_op : Operand<i64>;
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andriclet OperandType = "OPERAND_FUNCTION32" in
1870b57cec5SDimitry Andricdef function32_op : Operand<i32>;
1880b57cec5SDimitry Andric
189e8d8bef9SDimitry Andriclet OperandType = "OPERAND_TABLE" in
190e8d8bef9SDimitry Andricdef table32_op : Operand<i32>;
191e8d8bef9SDimitry Andric
1920b57cec5SDimitry Andriclet OperandType = "OPERAND_OFFSET32" in
1930b57cec5SDimitry Andricdef offset32_op : Operand<i32>;
1940b57cec5SDimitry Andric
1955ffd83dbSDimitry Andriclet OperandType = "OPERAND_OFFSET64" in
1965ffd83dbSDimitry Andricdef offset64_op : Operand<i64>;
1975ffd83dbSDimitry Andric
1980b57cec5SDimitry Andriclet OperandType = "OPERAND_P2ALIGN" in {
1990b57cec5SDimitry Andricdef P2Align : Operand<i32> {
2000b57cec5SDimitry Andric  let PrintMethod = "printWebAssemblyP2AlignOperand";
2010b57cec5SDimitry Andric}
2020b57cec5SDimitry Andric
203fe6060f1SDimitry Andriclet OperandType = "OPERAND_TAG" in
204fe6060f1SDimitry Andricdef tag_op : Operand<i32>;
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric} // OperandType = "OPERAND_P2ALIGN"
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andriclet OperandType = "OPERAND_SIGNATURE" in
2090b57cec5SDimitry Andricdef Signature : Operand<i32> {
2100b57cec5SDimitry Andric  let PrintMethod = "printWebAssemblySignatureOperand";
2110b57cec5SDimitry Andric}
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andriclet OperandType = "OPERAND_TYPEINDEX" in
2140b57cec5SDimitry Andricdef TypeIndex : Operand<i32>;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric} // OperandNamespace = "WebAssembly"
2170b57cec5SDimitry Andric
218fe6060f1SDimitry Andric// TODO: Find more places to use this.
219fe6060f1SDimitry Andricdef bool_node : PatLeaf<(i32 I32:$cond), [{
220fe6060f1SDimitry Andric  return CurDAG->computeKnownBits(SDValue(N, 0)).countMinLeadingZeros() == 31;
221fe6060f1SDimitry Andric}]>;
222fe6060f1SDimitry Andric
2230b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2240b57cec5SDimitry Andric// WebAssembly Register to Stack instruction mapping
2250b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andricclass StackRel;
2280b57cec5SDimitry Andricdef getStackOpcode : InstrMapping {
2290b57cec5SDimitry Andric  let FilterClass = "StackRel";
2300b57cec5SDimitry Andric  let RowFields = ["BaseName"];
2310b57cec5SDimitry Andric  let ColFields = ["StackBased"];
23281ad6265SDimitry Andric  let KeyCol = ["0"];
23381ad6265SDimitry Andric  let ValueCols = [["1"]];
2340b57cec5SDimitry Andric}
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
237fe6060f1SDimitry Andric// WebAssembly Stack to Register instruction mapping
238fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
239fe6060f1SDimitry Andric
240fe6060f1SDimitry Andricclass RegisterRel;
241fe6060f1SDimitry Andricdef getRegisterOpcode : InstrMapping {
242fe6060f1SDimitry Andric  let FilterClass = "RegisterRel";
243fe6060f1SDimitry Andric  let RowFields = ["BaseName"];
244fe6060f1SDimitry Andric  let ColFields = ["StackBased"];
24581ad6265SDimitry Andric  let KeyCol = ["1"];
24681ad6265SDimitry Andric  let ValueCols = [["0"]];
247fe6060f1SDimitry Andric}
248fe6060f1SDimitry Andric
249fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
2505ffd83dbSDimitry Andric// WebAssembly 32 to 64-bit instruction mapping
2515ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
2525ffd83dbSDimitry Andric
2535ffd83dbSDimitry Andricclass Wasm64Rel;
2545ffd83dbSDimitry Andricdef getWasm64Opcode : InstrMapping {
2555ffd83dbSDimitry Andric  let FilterClass = "Wasm64Rel";
2565ffd83dbSDimitry Andric  let RowFields = ["Wasm32Name"];
2575ffd83dbSDimitry Andric  let ColFields = ["IsWasm64"];
25881ad6265SDimitry Andric  let KeyCol = ["0"];
25981ad6265SDimitry Andric  let ValueCols = [["1"]];
2605ffd83dbSDimitry Andric}
2615ffd83dbSDimitry Andric
2625ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
2630b57cec5SDimitry Andric// WebAssembly Instruction Format Definitions.
2640b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andricinclude "WebAssemblyInstrFormats.td"
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2690b57cec5SDimitry Andric// Additional instructions.
2700b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2710b57cec5SDimitry Andric
272fe6060f1SDimitry Andricmulticlass ARGUMENT<WebAssemblyRegClass rc, ValueType vt> {
2730b57cec5SDimitry Andric  let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>,
2740b57cec5SDimitry Andric      Uses = [ARGUMENTS] in
2750b57cec5SDimitry Andric  defm ARGUMENT_#vt :
276fe6060f1SDimitry Andric    I<(outs rc:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
277fe6060f1SDimitry Andric      [(set (vt rc:$res), (WebAssemblyargument timm:$argno))]>;
2780b57cec5SDimitry Andric}
2790b57cec5SDimitry Andricdefm "": ARGUMENT<I32, i32>;
2800b57cec5SDimitry Andricdefm "": ARGUMENT<I64, i64>;
2810b57cec5SDimitry Andricdefm "": ARGUMENT<F32, f32>;
2820b57cec5SDimitry Andricdefm "": ARGUMENT<F64, f64>;
283e8d8bef9SDimitry Andricdefm "": ARGUMENT<FUNCREF, funcref>;
284e8d8bef9SDimitry Andricdefm "": ARGUMENT<EXTERNREF, externref>;
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric// local.get and local.set are not generated by instruction selection; they
2870b57cec5SDimitry Andric// are implied by virtual register uses and defs.
288fe6060f1SDimitry Andricmulticlass LOCAL<WebAssemblyRegClass rc, Operand global_op> {
2890b57cec5SDimitry Andric  let hasSideEffects = 0 in {
2900b57cec5SDimitry Andric  // COPY is not an actual instruction in wasm, but since we allow local.get and
2910b57cec5SDimitry Andric  // local.set to be implicit during most of codegen, we can have a COPY which
2920b57cec5SDimitry Andric  // is actually a no-op because all the work is done in the implied local.get
2930b57cec5SDimitry Andric  // and local.set. COPYs are eliminated (and replaced with
2940b57cec5SDimitry Andric  // local.get/local.set) in the ExplicitLocals pass.
2950b57cec5SDimitry Andric  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
296fe6060f1SDimitry Andric  defm COPY_#rc : I<(outs rc:$res), (ins rc:$src), (outs), (ins), [],
2970b57cec5SDimitry Andric                    "local.copy\t$res, $src", "local.copy">;
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andric  // TEE is similar to COPY, but writes two copies of its result. Typically
3000b57cec5SDimitry Andric  // this would be used to stackify one result and write the other result to a
3010b57cec5SDimitry Andric  // local.
3020b57cec5SDimitry Andric  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
303fe6060f1SDimitry Andric  defm TEE_#rc : I<(outs rc:$res, rc:$also), (ins rc:$src), (outs), (ins), [],
3040b57cec5SDimitry Andric                   "local.tee\t$res, $also, $src", "local.tee">;
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric  // This is the actual local.get instruction in wasm. These are made explicit
3070b57cec5SDimitry Andric  // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
3080b57cec5SDimitry Andric  // local, which is a side effect not otherwise modeled in LLVM.
3090b57cec5SDimitry Andric  let mayLoad = 1, isAsCheapAsAMove = 1 in
310fe6060f1SDimitry Andric  defm LOCAL_GET_#rc : I<(outs rc:$res), (ins local_op:$local),
3110b57cec5SDimitry Andric                         (outs), (ins local_op:$local), [],
3120b57cec5SDimitry Andric                         "local.get\t$res, $local", "local.get\t$local", 0x20>;
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andric  // This is the actual local.set instruction in wasm. These are made explicit
3150b57cec5SDimitry Andric  // by the ExplicitLocals pass. It has mayStore because it writes to a wasm
3160b57cec5SDimitry Andric  // local, which is a side effect not otherwise modeled in LLVM.
3170b57cec5SDimitry Andric  let mayStore = 1, isAsCheapAsAMove = 1 in
318fe6060f1SDimitry Andric  defm LOCAL_SET_#rc : I<(outs), (ins local_op:$local, rc:$src),
3190b57cec5SDimitry Andric                         (outs), (ins local_op:$local), [],
3200b57cec5SDimitry Andric                         "local.set\t$local, $src", "local.set\t$local", 0x21>;
3210b57cec5SDimitry Andric
3220b57cec5SDimitry Andric  // This is the actual local.tee instruction in wasm. TEEs are turned into
3230b57cec5SDimitry Andric  // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
3240b57cec5SDimitry Andric  // as LOCAL_SET.
3250b57cec5SDimitry Andric  let mayStore = 1, isAsCheapAsAMove = 1 in
326fe6060f1SDimitry Andric  defm LOCAL_TEE_#rc : I<(outs rc:$res), (ins local_op:$local, rc:$src),
3270b57cec5SDimitry Andric                         (outs), (ins local_op:$local), [],
3280b57cec5SDimitry Andric                         "local.tee\t$res, $local, $src", "local.tee\t$local",
3290b57cec5SDimitry Andric                         0x22>;
3300b57cec5SDimitry Andric
3310b57cec5SDimitry Andric  // Unused values must be dropped in some contexts.
332fe6060f1SDimitry Andric  defm DROP_#rc : I<(outs), (ins rc:$src), (outs), (ins), [],
3330b57cec5SDimitry Andric                    "drop\t$src", "drop", 0x1a>;
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric  let mayLoad = 1 in
336fe6060f1SDimitry Andric  defm GLOBAL_GET_#rc : I<(outs rc:$res), (ins global_op:$addr),
337fe6060f1SDimitry Andric                          (outs), (ins global_op:$addr), [],
338fe6060f1SDimitry Andric                           "global.get\t$res, $addr", "global.get\t$addr",
3390b57cec5SDimitry Andric                          0x23>;
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric  let mayStore = 1 in
342fe6060f1SDimitry Andric  defm GLOBAL_SET_#rc : I<(outs), (ins global_op:$addr, rc:$src),
343fe6060f1SDimitry Andric                          (outs), (ins global_op:$addr), [],
344fe6060f1SDimitry Andric                          "global.set\t$addr, $src", "global.set\t$addr",
3450b57cec5SDimitry Andric                          0x24>;
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric  } // hasSideEffects = 0
348fe6060f1SDimitry Andric  foreach vt = rc.RegTypes in {
349fe6060f1SDimitry Andric    def : Pat<(vt (WebAssemblyglobal_get
350349cc55cSDimitry Andric                   (WebAssemblyWrapper tglobaladdr:$addr))),
351fe6060f1SDimitry Andric              (!cast<NI>("GLOBAL_GET_" # rc) tglobaladdr:$addr)>;
352fe6060f1SDimitry Andric    def : Pat<(WebAssemblyglobal_set
353349cc55cSDimitry Andric               vt:$src, (WebAssemblyWrapper tglobaladdr:$addr)),
354fe6060f1SDimitry Andric              (!cast<NI>("GLOBAL_SET_" # rc) tglobaladdr:$addr, vt:$src)>;
355fe6060f1SDimitry Andric    def : Pat<(vt (WebAssemblylocal_get (i32 timm:$local))),
356fe6060f1SDimitry Andric              (!cast<NI>("LOCAL_GET_" # rc) timm:$local)>;
357fe6060f1SDimitry Andric    def : Pat<(WebAssemblylocal_set timm:$local, vt:$src),
358fe6060f1SDimitry Andric              (!cast<NI>("LOCAL_SET_" # rc) timm:$local, vt:$src)>;
3590b57cec5SDimitry Andric  }
360fe6060f1SDimitry Andric}
361fe6060f1SDimitry Andricdefm "" : LOCAL<I32, global_op32>;
362fe6060f1SDimitry Andricdefm "" : LOCAL<I64, global_op64>;  // 64-bit only needed for pointers.
363fe6060f1SDimitry Andricdefm "" : LOCAL<F32, global_op32>;
364fe6060f1SDimitry Andricdefm "" : LOCAL<F64, global_op32>;
365fe6060f1SDimitry Andricdefm "" : LOCAL<V128, global_op32>, Requires<[HasSIMD128]>;
366fe6060f1SDimitry Andricdefm "" : LOCAL<FUNCREF, global_op32>, Requires<[HasReferenceTypes]>;
367fe6060f1SDimitry Andricdefm "" : LOCAL<EXTERNREF, global_op32>, Requires<[HasReferenceTypes]>;
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andriclet isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
3700b57cec5SDimitry Andricdefm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
3710b57cec5SDimitry Andric                   (outs), (ins i32imm_op:$imm),
3720b57cec5SDimitry Andric                   [(set I32:$res, imm:$imm)],
3730b57cec5SDimitry Andric                   "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>;
3740b57cec5SDimitry Andricdefm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm),
3750b57cec5SDimitry Andric                   (outs), (ins i64imm_op:$imm),
3760b57cec5SDimitry Andric                   [(set I64:$res, imm:$imm)],
3770b57cec5SDimitry Andric                   "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>;
3780b57cec5SDimitry Andricdefm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
3790b57cec5SDimitry Andric                   (outs), (ins f32imm_op:$imm),
3800b57cec5SDimitry Andric                   [(set F32:$res, fpimm:$imm)],
3810b57cec5SDimitry Andric                   "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>;
3820b57cec5SDimitry Andricdefm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
3830b57cec5SDimitry Andric                   (outs), (ins f64imm_op:$imm),
3840b57cec5SDimitry Andric                   [(set F64:$res, fpimm:$imm)],
3850b57cec5SDimitry Andric                   "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>;
3860b57cec5SDimitry Andric} // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
3870b57cec5SDimitry Andric
388349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaladdr:$addr)),
389eaeb601bSDimitry Andric          (CONST_I32 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr32]>;
390349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaladdr:$addr)),
391eaeb601bSDimitry Andric          (CONST_I64 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr64]>;
3920b57cec5SDimitry Andric
393349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaladdr:$addr)),
394e8d8bef9SDimitry Andric          (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>;
395349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaladdr:$addr)),
396fe6060f1SDimitry Andric          (GLOBAL_GET_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>;
3970b57cec5SDimitry Andric
398349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL tglobaladdr:$addr)),
399e8d8bef9SDimitry Andric          (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>;
400349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL tglobaladdr:$addr)),
401e8d8bef9SDimitry Andric          (CONST_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>;
402e8d8bef9SDimitry Andric
403349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL tglobaltlsaddr:$addr)),
404e8d8bef9SDimitry Andric          (CONST_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>;
405349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL tglobaltlsaddr:$addr)),
406e8d8bef9SDimitry Andric          (CONST_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>;
4070b57cec5SDimitry Andric
408349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaltlsaddr:$addr)),
409349cc55cSDimitry Andric          (GLOBAL_GET_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>;
410349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaltlsaddr:$addr)),
411349cc55cSDimitry Andric          (GLOBAL_GET_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>;
412349cc55cSDimitry Andric
413349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper texternalsym:$addr)),
414e8d8bef9SDimitry Andric          (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>;
415349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper texternalsym:$addr)),
416fe6060f1SDimitry Andric          (GLOBAL_GET_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>;
4170b57cec5SDimitry Andric
418349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper texternalsym:$addr)),
419e8d8bef9SDimitry Andric          (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr32]>;
420349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper texternalsym:$addr)),
421e8d8bef9SDimitry Andric          (CONST_I64 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr64]>;
4220b57cec5SDimitry Andric
423349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL texternalsym:$addr)),
424349cc55cSDimitry Andric          (CONST_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>;
425349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL texternalsym:$addr)),
426349cc55cSDimitry Andric          (CONST_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>;
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4290b57cec5SDimitry Andric// Additional sets of instructions.
4300b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andricinclude "WebAssemblyInstrMemory.td"
4330b57cec5SDimitry Andricinclude "WebAssemblyInstrCall.td"
4340b57cec5SDimitry Andricinclude "WebAssemblyInstrControl.td"
4350b57cec5SDimitry Andricinclude "WebAssemblyInstrInteger.td"
4360b57cec5SDimitry Andricinclude "WebAssemblyInstrConv.td"
4370b57cec5SDimitry Andricinclude "WebAssemblyInstrFloat.td"
4380b57cec5SDimitry Andricinclude "WebAssemblyInstrAtomics.td"
4390b57cec5SDimitry Andricinclude "WebAssemblyInstrSIMD.td"
4400b57cec5SDimitry Andricinclude "WebAssemblyInstrRef.td"
4410b57cec5SDimitry Andricinclude "WebAssemblyInstrBulkMemory.td"
442e8d8bef9SDimitry Andricinclude "WebAssemblyInstrTable.td"
443