xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 HasAtomics :
260b57cec5SDimitry Andric    Predicate<"Subtarget->hasAtomics()">,
275ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureAtomics), "atomics">;
280b57cec5SDimitry Andric
290b57cec5SDimitry Andricdef HasBulkMemory :
300b57cec5SDimitry Andric    Predicate<"Subtarget->hasBulkMemory()">,
315ffd83dbSDimitry Andric    AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">;
325ffd83dbSDimitry Andric
33*0fca6ea1SDimitry Andricdef HasExceptionHandling :
34*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasExceptionHandling()">,
35*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">;
360b57cec5SDimitry Andric
3781ad6265SDimitry Andricdef HasExtendedConst :
3881ad6265SDimitry Andric    Predicate<"Subtarget->hasExtendedConst()">,
3981ad6265SDimitry Andric    AssemblerPredicate<(all_of FeatureExtendedConst), "extended-const">;
4081ad6265SDimitry Andric
41*0fca6ea1SDimitry Andricdef HasHalfPrecision :
42*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasHalfPrecision()">,
43*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureHalfPrecision), "half-precision">;
44*0fca6ea1SDimitry Andric
455f757f3fSDimitry Andricdef HasMultiMemory :
465f757f3fSDimitry Andric    Predicate<"Subtarget->hasMultiMemory()">,
475f757f3fSDimitry Andric    AssemblerPredicate<(all_of FeatureMultiMemory), "multimemory">;
485f757f3fSDimitry Andric
49*0fca6ea1SDimitry Andricdef HasMultivalue :
50*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasMultivalue()">,
51*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureMultivalue), "multivalue">;
52*0fca6ea1SDimitry Andric
53*0fca6ea1SDimitry Andricdef HasMutableGlobals:
54*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasMutableGlobals()">,
55*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureMutableGlobals), "mutable-globals">;
56*0fca6ea1SDimitry Andric
57*0fca6ea1SDimitry Andricdef HasNontrappingFPToInt :
58*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasNontrappingFPToInt()">,
59*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureNontrappingFPToInt),
60*0fca6ea1SDimitry Andric                       "nontrapping-fptoint">;
61*0fca6ea1SDimitry Andric
62*0fca6ea1SDimitry Andricdef NotHasNontrappingFPToInt :
63*0fca6ea1SDimitry Andric    Predicate<"!Subtarget->hasNontrappingFPToInt()">,
64*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of (not FeatureNontrappingFPToInt)),
65*0fca6ea1SDimitry Andric                       "nontrapping-fptoint">;
66*0fca6ea1SDimitry Andric
67*0fca6ea1SDimitry Andricdef HasReferenceTypes :
68*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasReferenceTypes()">,
69*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureReferenceTypes), "reference-types">;
70*0fca6ea1SDimitry Andric
71*0fca6ea1SDimitry Andricdef HasRelaxedSIMD :
72*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasRelaxedSIMD()">,
73*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureRelaxedSIMD), "relaxed-simd">;
74*0fca6ea1SDimitry Andric
75*0fca6ea1SDimitry Andricdef HasSignExt :
76*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasSignExt()">,
77*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureSignExt), "sign-ext">;
78*0fca6ea1SDimitry Andric
79*0fca6ea1SDimitry Andricdef HasSIMD128 :
80*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasSIMD128()">,
81*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureSIMD128), "simd128">;
82*0fca6ea1SDimitry Andric
83*0fca6ea1SDimitry Andricdef HasTailCall :
84*0fca6ea1SDimitry Andric    Predicate<"Subtarget->hasTailCall()">,
85*0fca6ea1SDimitry Andric    AssemblerPredicate<(all_of FeatureTailCall), "tail-call">;
86*0fca6ea1SDimitry Andric
870b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
880b57cec5SDimitry Andric// WebAssembly-specific DAG Node Types.
890b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
900b57cec5SDimitry Andric
910b57cec5SDimitry Andricdef SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
920b57cec5SDimitry Andric                                                  SDTCisVT<1, iPTR>]>;
930b57cec5SDimitry Andricdef SDT_WebAssemblyCallSeqEnd :
940b57cec5SDimitry Andric    SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
950b57cec5SDimitry Andricdef SDT_WebAssemblyBrTable    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
960b57cec5SDimitry Andricdef SDT_WebAssemblyArgument   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
97fe6060f1SDimitry Andricdef SDT_WebAssemblyLocalGet   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
98fe6060f1SDimitry Andricdef SDT_WebAssemblyLocalSet   : SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>;
990b57cec5SDimitry Andricdef SDT_WebAssemblyReturn     : SDTypeProfile<0, -1, []>;
1000b57cec5SDimitry Andricdef SDT_WebAssemblyWrapper    : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
1010b57cec5SDimitry Andric                                                     SDTCisPtrTy<0>]>;
102fe6060f1SDimitry Andricdef SDT_WebAssemblyGlobalGet  : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
103fe6060f1SDimitry Andricdef SDT_WebAssemblyGlobalSet  : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>;
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1060b57cec5SDimitry Andric// WebAssembly-specific DAG Nodes.
1070b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andricdef WebAssemblycallseq_start :
1100b57cec5SDimitry Andric    SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
1110b57cec5SDimitry Andric           [SDNPHasChain, SDNPOutGlue]>;
1120b57cec5SDimitry Andricdef WebAssemblycallseq_end :
1130b57cec5SDimitry Andric    SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
1140b57cec5SDimitry Andric           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
1150b57cec5SDimitry Andricdef WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
1160b57cec5SDimitry Andric                                 SDT_WebAssemblyBrTable,
1170b57cec5SDimitry Andric                                 [SDNPHasChain, SDNPVariadic]>;
1180b57cec5SDimitry Andricdef WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
1190b57cec5SDimitry Andric                                 SDT_WebAssemblyArgument>;
1200b57cec5SDimitry Andricdef WebAssemblyreturn   : SDNode<"WebAssemblyISD::RETURN",
1218bcb0991SDimitry Andric                                 SDT_WebAssemblyReturn,
1228bcb0991SDimitry Andric                                 [SDNPHasChain, SDNPVariadic]>;
123349cc55cSDimitry Andricdef WebAssemblyWrapper  : SDNode<"WebAssemblyISD::Wrapper",
1240b57cec5SDimitry Andric                                 SDT_WebAssemblyWrapper>;
125349cc55cSDimitry Andricdef WebAssemblyWrapperREL  : SDNode<"WebAssemblyISD::WrapperREL",
126349cc55cSDimitry Andric                                     SDT_WebAssemblyWrapper>;
127fe6060f1SDimitry Andricdef WebAssemblyglobal_get :
128fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet,
129fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
130fe6060f1SDimitry Andricdef WebAssemblyglobal_set :
131fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::GLOBAL_SET", SDT_WebAssemblyGlobalSet,
132fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
133fe6060f1SDimitry Andricdef WebAssemblylocal_get :
134fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::LOCAL_GET", SDT_WebAssemblyLocalGet,
135fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayLoad]>;
136fe6060f1SDimitry Andricdef WebAssemblylocal_set :
137fe6060f1SDimitry Andric    SDNode<"WebAssemblyISD::LOCAL_SET", SDT_WebAssemblyLocalSet,
138fe6060f1SDimitry Andric           [SDNPHasChain, SDNPMayStore]>;
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1410b57cec5SDimitry Andric// WebAssembly-specific Operands.
1420b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric// Default Operand has AsmOperandClass "Imm" which is for integers (and
1450b57cec5SDimitry Andric// symbols), so specialize one for floats:
146fe6060f1SDimitry Andricclass FPImmAsmOperand<ValueType ty> : AsmOperandClass {
147fe6060f1SDimitry Andric  let Name = "FPImm" # ty;
1480b57cec5SDimitry Andric  let PredicateMethod = "isFPImm";
1490b57cec5SDimitry Andric}
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andricclass FPOperand<ValueType ty> : Operand<ty> {
152fe6060f1SDimitry Andric  AsmOperandClass ParserMatchClass = FPImmAsmOperand<ty>;
1530b57cec5SDimitry Andric}
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andriclet OperandNamespace = "WebAssembly" in {
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andriclet OperandType = "OPERAND_BASIC_BLOCK" in
1580b57cec5SDimitry Andricdef bb_op : Operand<OtherVT>;
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andriclet OperandType = "OPERAND_LOCAL" in
1610b57cec5SDimitry Andricdef local_op : Operand<i32>;
1620b57cec5SDimitry Andric
163fe6060f1SDimitry Andriclet OperandType = "OPERAND_GLOBAL" in {
164fe6060f1SDimitry Andric  // The operand to global instructions is always a 32-bit index.
165fe6060f1SDimitry Andric  def global_op32 : Operand<i32>;
166fe6060f1SDimitry Andric  // In PIC mode however, we temporarily represent this index as an external
167fe6060f1SDimitry Andric  // symbol, which to LLVM is a pointer, so in wasm64 mode it is easiest to
168fe6060f1SDimitry Andric  // pretend we use a 64-bit index for it.
169fe6060f1SDimitry Andric  def global_op64 : Operand<i64>;
170fe6060f1SDimitry Andric}
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andriclet OperandType = "OPERAND_I32IMM" in
1730b57cec5SDimitry Andricdef i32imm_op : Operand<i32>;
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andriclet OperandType = "OPERAND_I64IMM" in
1760b57cec5SDimitry Andricdef i64imm_op : Operand<i64>;
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andriclet OperandType = "OPERAND_F32IMM" in
1790b57cec5SDimitry Andricdef f32imm_op : FPOperand<f32>;
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andriclet OperandType = "OPERAND_F64IMM" in
1820b57cec5SDimitry Andricdef f64imm_op : FPOperand<f64>;
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I8IMM" in
1850b57cec5SDimitry Andricdef vec_i8imm_op : Operand<i32>;
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I16IMM" in
1880b57cec5SDimitry Andricdef vec_i16imm_op : Operand<i32>;
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I32IMM" in
1910b57cec5SDimitry Andricdef vec_i32imm_op : Operand<i32>;
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I64IMM" in
1940b57cec5SDimitry Andricdef vec_i64imm_op : Operand<i64>;
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andriclet OperandType = "OPERAND_FUNCTION32" in
1970b57cec5SDimitry Andricdef function32_op : Operand<i32>;
1980b57cec5SDimitry Andric
199e8d8bef9SDimitry Andriclet OperandType = "OPERAND_TABLE" in
200e8d8bef9SDimitry Andricdef table32_op : Operand<i32>;
201e8d8bef9SDimitry Andric
2020b57cec5SDimitry Andriclet OperandType = "OPERAND_OFFSET32" in
2030b57cec5SDimitry Andricdef offset32_op : Operand<i32>;
2040b57cec5SDimitry Andric
2055ffd83dbSDimitry Andriclet OperandType = "OPERAND_OFFSET64" in
2065ffd83dbSDimitry Andricdef offset64_op : Operand<i64>;
2075ffd83dbSDimitry Andric
2080b57cec5SDimitry Andriclet OperandType = "OPERAND_P2ALIGN" in {
2090b57cec5SDimitry Andricdef P2Align : Operand<i32> {
2100b57cec5SDimitry Andric  let PrintMethod = "printWebAssemblyP2AlignOperand";
2110b57cec5SDimitry Andric}
2120b57cec5SDimitry Andric
213fe6060f1SDimitry Andriclet OperandType = "OPERAND_TAG" in
214fe6060f1SDimitry Andricdef tag_op : Operand<i32>;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric} // OperandType = "OPERAND_P2ALIGN"
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andriclet OperandType = "OPERAND_SIGNATURE" in
2190b57cec5SDimitry Andricdef Signature : Operand<i32> {
2200b57cec5SDimitry Andric  let PrintMethod = "printWebAssemblySignatureOperand";
2210b57cec5SDimitry Andric}
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andriclet OperandType = "OPERAND_TYPEINDEX" in
2240b57cec5SDimitry Andricdef TypeIndex : Operand<i32>;
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric} // OperandNamespace = "WebAssembly"
2270b57cec5SDimitry Andric
228fe6060f1SDimitry Andric// TODO: Find more places to use this.
229fe6060f1SDimitry Andricdef bool_node : PatLeaf<(i32 I32:$cond), [{
230fe6060f1SDimitry Andric  return CurDAG->computeKnownBits(SDValue(N, 0)).countMinLeadingZeros() == 31;
231fe6060f1SDimitry Andric}]>;
232fe6060f1SDimitry Andric
2330b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2340b57cec5SDimitry Andric// WebAssembly Register to Stack instruction mapping
2350b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andricclass StackRel;
2380b57cec5SDimitry Andricdef getStackOpcode : InstrMapping {
2390b57cec5SDimitry Andric  let FilterClass = "StackRel";
2400b57cec5SDimitry Andric  let RowFields = ["BaseName"];
2410b57cec5SDimitry Andric  let ColFields = ["StackBased"];
24281ad6265SDimitry Andric  let KeyCol = ["0"];
24381ad6265SDimitry Andric  let ValueCols = [["1"]];
2440b57cec5SDimitry Andric}
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
247fe6060f1SDimitry Andric// WebAssembly Stack to Register instruction mapping
248fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
249fe6060f1SDimitry Andric
250fe6060f1SDimitry Andricclass RegisterRel;
251fe6060f1SDimitry Andricdef getRegisterOpcode : InstrMapping {
252fe6060f1SDimitry Andric  let FilterClass = "RegisterRel";
253fe6060f1SDimitry Andric  let RowFields = ["BaseName"];
254fe6060f1SDimitry Andric  let ColFields = ["StackBased"];
25581ad6265SDimitry Andric  let KeyCol = ["1"];
25681ad6265SDimitry Andric  let ValueCols = [["0"]];
257fe6060f1SDimitry Andric}
258fe6060f1SDimitry Andric
259fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
2605ffd83dbSDimitry Andric// WebAssembly 32 to 64-bit instruction mapping
2615ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
2625ffd83dbSDimitry Andric
2635ffd83dbSDimitry Andricclass Wasm64Rel;
2645ffd83dbSDimitry Andricdef getWasm64Opcode : InstrMapping {
2655ffd83dbSDimitry Andric  let FilterClass = "Wasm64Rel";
2665ffd83dbSDimitry Andric  let RowFields = ["Wasm32Name"];
2675ffd83dbSDimitry Andric  let ColFields = ["IsWasm64"];
26881ad6265SDimitry Andric  let KeyCol = ["0"];
26981ad6265SDimitry Andric  let ValueCols = [["1"]];
2705ffd83dbSDimitry Andric}
2715ffd83dbSDimitry Andric
2725ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
2730b57cec5SDimitry Andric// WebAssembly Instruction Format Definitions.
2740b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2750b57cec5SDimitry Andric
2760b57cec5SDimitry Andricinclude "WebAssemblyInstrFormats.td"
2770b57cec5SDimitry Andric
2780b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2790b57cec5SDimitry Andric// Additional instructions.
2800b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2810b57cec5SDimitry Andric
282fe6060f1SDimitry Andricmulticlass ARGUMENT<WebAssemblyRegClass rc, ValueType vt> {
2830b57cec5SDimitry Andric  let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>,
2840b57cec5SDimitry Andric      Uses = [ARGUMENTS] in
2850b57cec5SDimitry Andric  defm ARGUMENT_#vt :
286fe6060f1SDimitry Andric    I<(outs rc:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
287fe6060f1SDimitry Andric      [(set (vt rc:$res), (WebAssemblyargument timm:$argno))]>;
2880b57cec5SDimitry Andric}
2890b57cec5SDimitry Andricdefm "": ARGUMENT<I32, i32>;
2900b57cec5SDimitry Andricdefm "": ARGUMENT<I64, i64>;
2910b57cec5SDimitry Andricdefm "": ARGUMENT<F32, f32>;
2920b57cec5SDimitry Andricdefm "": ARGUMENT<F64, f64>;
293e8d8bef9SDimitry Andricdefm "": ARGUMENT<FUNCREF, funcref>;
294e8d8bef9SDimitry Andricdefm "": ARGUMENT<EXTERNREF, externref>;
295*0fca6ea1SDimitry Andricdefm "": ARGUMENT<EXNREF, exnref>;
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric// local.get and local.set are not generated by instruction selection; they
2980b57cec5SDimitry Andric// are implied by virtual register uses and defs.
299fe6060f1SDimitry Andricmulticlass LOCAL<WebAssemblyRegClass rc, Operand global_op> {
3000b57cec5SDimitry Andric  let hasSideEffects = 0 in {
3010b57cec5SDimitry Andric  // COPY is not an actual instruction in wasm, but since we allow local.get and
3020b57cec5SDimitry Andric  // local.set to be implicit during most of codegen, we can have a COPY which
3030b57cec5SDimitry Andric  // is actually a no-op because all the work is done in the implied local.get
3040b57cec5SDimitry Andric  // and local.set. COPYs are eliminated (and replaced with
3050b57cec5SDimitry Andric  // local.get/local.set) in the ExplicitLocals pass.
3060b57cec5SDimitry Andric  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
307fe6060f1SDimitry Andric  defm COPY_#rc : I<(outs rc:$res), (ins rc:$src), (outs), (ins), [],
3080b57cec5SDimitry Andric                    "local.copy\t$res, $src", "local.copy">;
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric  // TEE is similar to COPY, but writes two copies of its result. Typically
3110b57cec5SDimitry Andric  // this would be used to stackify one result and write the other result to a
3120b57cec5SDimitry Andric  // local.
3130b57cec5SDimitry Andric  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
314fe6060f1SDimitry Andric  defm TEE_#rc : I<(outs rc:$res, rc:$also), (ins rc:$src), (outs), (ins), [],
3150b57cec5SDimitry Andric                   "local.tee\t$res, $also, $src", "local.tee">;
3160b57cec5SDimitry Andric
3170b57cec5SDimitry Andric  // This is the actual local.get instruction in wasm. These are made explicit
3180b57cec5SDimitry Andric  // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
3190b57cec5SDimitry Andric  // local, which is a side effect not otherwise modeled in LLVM.
3200b57cec5SDimitry Andric  let mayLoad = 1, isAsCheapAsAMove = 1 in
321fe6060f1SDimitry Andric  defm LOCAL_GET_#rc : I<(outs rc:$res), (ins local_op:$local),
3220b57cec5SDimitry Andric                         (outs), (ins local_op:$local), [],
3230b57cec5SDimitry Andric                         "local.get\t$res, $local", "local.get\t$local", 0x20>;
3240b57cec5SDimitry Andric
3250b57cec5SDimitry Andric  // This is the actual local.set instruction in wasm. These are made explicit
3260b57cec5SDimitry Andric  // by the ExplicitLocals pass. It has mayStore because it writes to a wasm
3270b57cec5SDimitry Andric  // local, which is a side effect not otherwise modeled in LLVM.
3280b57cec5SDimitry Andric  let mayStore = 1, isAsCheapAsAMove = 1 in
329fe6060f1SDimitry Andric  defm LOCAL_SET_#rc : I<(outs), (ins local_op:$local, rc:$src),
3300b57cec5SDimitry Andric                         (outs), (ins local_op:$local), [],
3310b57cec5SDimitry Andric                         "local.set\t$local, $src", "local.set\t$local", 0x21>;
3320b57cec5SDimitry Andric
3330b57cec5SDimitry Andric  // This is the actual local.tee instruction in wasm. TEEs are turned into
3340b57cec5SDimitry Andric  // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
3350b57cec5SDimitry Andric  // as LOCAL_SET.
3360b57cec5SDimitry Andric  let mayStore = 1, isAsCheapAsAMove = 1 in
337fe6060f1SDimitry Andric  defm LOCAL_TEE_#rc : I<(outs rc:$res), (ins local_op:$local, rc:$src),
3380b57cec5SDimitry Andric                         (outs), (ins local_op:$local), [],
3390b57cec5SDimitry Andric                         "local.tee\t$res, $local, $src", "local.tee\t$local",
3400b57cec5SDimitry Andric                         0x22>;
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric  // Unused values must be dropped in some contexts.
343fe6060f1SDimitry Andric  defm DROP_#rc : I<(outs), (ins rc:$src), (outs), (ins), [],
3440b57cec5SDimitry Andric                    "drop\t$src", "drop", 0x1a>;
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andric  let mayLoad = 1 in
347fe6060f1SDimitry Andric  defm GLOBAL_GET_#rc : I<(outs rc:$res), (ins global_op:$addr),
348fe6060f1SDimitry Andric                          (outs), (ins global_op:$addr), [],
349fe6060f1SDimitry Andric                           "global.get\t$res, $addr", "global.get\t$addr",
3500b57cec5SDimitry Andric                          0x23>;
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric  let mayStore = 1 in
353fe6060f1SDimitry Andric  defm GLOBAL_SET_#rc : I<(outs), (ins global_op:$addr, rc:$src),
354fe6060f1SDimitry Andric                          (outs), (ins global_op:$addr), [],
355fe6060f1SDimitry Andric                          "global.set\t$addr, $src", "global.set\t$addr",
3560b57cec5SDimitry Andric                          0x24>;
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric  } // hasSideEffects = 0
359fe6060f1SDimitry Andric  foreach vt = rc.RegTypes in {
360fe6060f1SDimitry Andric    def : Pat<(vt (WebAssemblyglobal_get
361349cc55cSDimitry Andric                   (WebAssemblyWrapper tglobaladdr:$addr))),
362fe6060f1SDimitry Andric              (!cast<NI>("GLOBAL_GET_" # rc) tglobaladdr:$addr)>;
363fe6060f1SDimitry Andric    def : Pat<(WebAssemblyglobal_set
364349cc55cSDimitry Andric               vt:$src, (WebAssemblyWrapper tglobaladdr:$addr)),
365fe6060f1SDimitry Andric              (!cast<NI>("GLOBAL_SET_" # rc) tglobaladdr:$addr, vt:$src)>;
366fe6060f1SDimitry Andric    def : Pat<(vt (WebAssemblylocal_get (i32 timm:$local))),
367fe6060f1SDimitry Andric              (!cast<NI>("LOCAL_GET_" # rc) timm:$local)>;
368fe6060f1SDimitry Andric    def : Pat<(WebAssemblylocal_set timm:$local, vt:$src),
369fe6060f1SDimitry Andric              (!cast<NI>("LOCAL_SET_" # rc) timm:$local, vt:$src)>;
3700b57cec5SDimitry Andric  }
371fe6060f1SDimitry Andric}
372fe6060f1SDimitry Andricdefm "" : LOCAL<I32, global_op32>;
373fe6060f1SDimitry Andricdefm "" : LOCAL<I64, global_op64>;  // 64-bit only needed for pointers.
374fe6060f1SDimitry Andricdefm "" : LOCAL<F32, global_op32>;
375fe6060f1SDimitry Andricdefm "" : LOCAL<F64, global_op32>;
376fe6060f1SDimitry Andricdefm "" : LOCAL<V128, global_op32>, Requires<[HasSIMD128]>;
377fe6060f1SDimitry Andricdefm "" : LOCAL<FUNCREF, global_op32>, Requires<[HasReferenceTypes]>;
378fe6060f1SDimitry Andricdefm "" : LOCAL<EXTERNREF, global_op32>, Requires<[HasReferenceTypes]>;
379*0fca6ea1SDimitry Andricdefm "" : LOCAL<EXNREF, global_op32>,
380*0fca6ea1SDimitry Andric          Requires<[HasReferenceTypes, HasExceptionHandling]>;
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andriclet isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
3830b57cec5SDimitry Andricdefm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
3840b57cec5SDimitry Andric                   (outs), (ins i32imm_op:$imm),
3850b57cec5SDimitry Andric                   [(set I32:$res, imm:$imm)],
3860b57cec5SDimitry Andric                   "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>;
3870b57cec5SDimitry Andricdefm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm),
3880b57cec5SDimitry Andric                   (outs), (ins i64imm_op:$imm),
3890b57cec5SDimitry Andric                   [(set I64:$res, imm:$imm)],
3900b57cec5SDimitry Andric                   "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>;
3910b57cec5SDimitry Andricdefm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
3920b57cec5SDimitry Andric                   (outs), (ins f32imm_op:$imm),
3930b57cec5SDimitry Andric                   [(set F32:$res, fpimm:$imm)],
3940b57cec5SDimitry Andric                   "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>;
3950b57cec5SDimitry Andricdefm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
3960b57cec5SDimitry Andric                   (outs), (ins f64imm_op:$imm),
3970b57cec5SDimitry Andric                   [(set F64:$res, fpimm:$imm)],
3980b57cec5SDimitry Andric                   "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>;
3990b57cec5SDimitry Andric} // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
4000b57cec5SDimitry Andric
401349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaladdr:$addr)),
402eaeb601bSDimitry Andric          (CONST_I32 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr32]>;
403349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaladdr:$addr)),
404eaeb601bSDimitry Andric          (CONST_I64 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr64]>;
4050b57cec5SDimitry Andric
406349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaladdr:$addr)),
407e8d8bef9SDimitry Andric          (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>;
408349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaladdr:$addr)),
409fe6060f1SDimitry Andric          (GLOBAL_GET_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>;
4100b57cec5SDimitry Andric
411349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL tglobaladdr:$addr)),
412e8d8bef9SDimitry Andric          (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>;
413349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL tglobaladdr:$addr)),
414e8d8bef9SDimitry Andric          (CONST_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>;
415e8d8bef9SDimitry Andric
416349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL tglobaltlsaddr:$addr)),
417e8d8bef9SDimitry Andric          (CONST_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>;
418349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL tglobaltlsaddr:$addr)),
419e8d8bef9SDimitry Andric          (CONST_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>;
4200b57cec5SDimitry Andric
421349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaltlsaddr:$addr)),
422349cc55cSDimitry Andric          (GLOBAL_GET_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>;
423349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaltlsaddr:$addr)),
424349cc55cSDimitry Andric          (GLOBAL_GET_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>;
425349cc55cSDimitry Andric
426349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper texternalsym:$addr)),
427e8d8bef9SDimitry Andric          (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>;
428349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper texternalsym:$addr)),
429fe6060f1SDimitry Andric          (GLOBAL_GET_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>;
4300b57cec5SDimitry Andric
431349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper texternalsym:$addr)),
432e8d8bef9SDimitry Andric          (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr32]>;
433349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper texternalsym:$addr)),
434e8d8bef9SDimitry Andric          (CONST_I64 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr64]>;
4350b57cec5SDimitry Andric
436349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL texternalsym:$addr)),
437349cc55cSDimitry Andric          (CONST_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>;
438349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL texternalsym:$addr)),
439349cc55cSDimitry Andric          (CONST_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>;
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4420b57cec5SDimitry Andric// Additional sets of instructions.
4430b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andricinclude "WebAssemblyInstrMemory.td"
4460b57cec5SDimitry Andricinclude "WebAssemblyInstrCall.td"
4470b57cec5SDimitry Andricinclude "WebAssemblyInstrControl.td"
4480b57cec5SDimitry Andricinclude "WebAssemblyInstrInteger.td"
4490b57cec5SDimitry Andricinclude "WebAssemblyInstrConv.td"
4500b57cec5SDimitry Andricinclude "WebAssemblyInstrFloat.td"
4510b57cec5SDimitry Andricinclude "WebAssemblyInstrAtomics.td"
4520b57cec5SDimitry Andricinclude "WebAssemblyInstrSIMD.td"
4530b57cec5SDimitry Andricinclude "WebAssemblyInstrRef.td"
4540b57cec5SDimitry Andricinclude "WebAssemblyInstrBulkMemory.td"
455e8d8bef9SDimitry Andricinclude "WebAssemblyInstrTable.td"
456