[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / WebAssembly / WebAssemblyInstrInfo.td
blob92e39cd019bc3b369bdb4aeab918866f5ded181d
1 // WebAssemblyInstrInfo.td-Describe the WebAssembly Instructions-*- tablegen -*-
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// WebAssembly Instruction definitions.
11 ///
12 //===----------------------------------------------------------------------===//
14 //===----------------------------------------------------------------------===//
15 // WebAssembly Instruction Predicate Definitions.
16 //===----------------------------------------------------------------------===//
18 def IsPIC     : Predicate<"TM.isPositionIndependent()">;
19 def IsNotPIC  : Predicate<"!TM.isPositionIndependent()">;
21 def HasAddr32 : Predicate<"!Subtarget->hasAddr64()">;
23 def HasAddr64 : Predicate<"Subtarget->hasAddr64()">;
25 def HasSIMD128 :
26     Predicate<"Subtarget->hasSIMD128()">,
27     AssemblerPredicate<(all_of FeatureSIMD128), "simd128">;
29 def HasAtomics :
30     Predicate<"Subtarget->hasAtomics()">,
31     AssemblerPredicate<(all_of FeatureAtomics), "atomics">;
33 def HasMultivalue :
34     Predicate<"Subtarget->hasMultivalue()">,
35     AssemblerPredicate<(all_of FeatureMultivalue), "multivalue">;
37 def HasNontrappingFPToInt :
38     Predicate<"Subtarget->hasNontrappingFPToInt()">,
39     AssemblerPredicate<(all_of FeatureNontrappingFPToInt), "nontrapping-fptoint">;
41 def NotHasNontrappingFPToInt :
42     Predicate<"!Subtarget->hasNontrappingFPToInt()">,
43     AssemblerPredicate<(all_of (not FeatureNontrappingFPToInt)), "nontrapping-fptoint">;
45 def HasSignExt :
46     Predicate<"Subtarget->hasSignExt()">,
47     AssemblerPredicate<(all_of FeatureSignExt), "sign-ext">;
49 def HasTailCall :
50     Predicate<"Subtarget->hasTailCall()">,
51     AssemblerPredicate<(all_of FeatureTailCall), "tail-call">;
53 def HasExceptionHandling :
54     Predicate<"Subtarget->hasExceptionHandling()">,
55     AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">;
57 def HasBulkMemory :
58     Predicate<"Subtarget->hasBulkMemory()">,
59     AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">;
61 def HasReferenceTypes :
62     Predicate<"Subtarget->hasReferenceTypes()">,
63     AssemblerPredicate<(all_of FeatureReferenceTypes), "reference-types">;
65 //===----------------------------------------------------------------------===//
66 // WebAssembly-specific DAG Node Types.
67 //===----------------------------------------------------------------------===//
69 def SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
70                                                   SDTCisVT<1, iPTR>]>;
71 def SDT_WebAssemblyCallSeqEnd :
72     SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
73 def SDT_WebAssemblyBrTable    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
74 def SDT_WebAssemblyArgument   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
75 def SDT_WebAssemblyLocalGet   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
76 def SDT_WebAssemblyLocalSet   : SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>;
77 def SDT_WebAssemblyReturn     : SDTypeProfile<0, -1, []>;
78 def SDT_WebAssemblyWrapper    : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
79                                                      SDTCisPtrTy<0>]>;
80 def SDT_WebAssemblyWrapperPIC : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
81                                                      SDTCisPtrTy<0>]>;
82 def SDT_WebAssemblyGlobalGet  : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
83 def SDT_WebAssemblyGlobalSet  : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>;
85 //===----------------------------------------------------------------------===//
86 // WebAssembly-specific DAG Nodes.
87 //===----------------------------------------------------------------------===//
89 def WebAssemblycallseq_start :
90     SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
91            [SDNPHasChain, SDNPOutGlue]>;
92 def WebAssemblycallseq_end :
93     SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
94            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
95 def WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
96                                  SDT_WebAssemblyBrTable,
97                                  [SDNPHasChain, SDNPVariadic]>;
98 def WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
99                                  SDT_WebAssemblyArgument>;
100 def WebAssemblyreturn   : SDNode<"WebAssemblyISD::RETURN",
101                                  SDT_WebAssemblyReturn,
102                                  [SDNPHasChain, SDNPVariadic]>;
103 def WebAssemblywrapper  : SDNode<"WebAssemblyISD::Wrapper",
104                                  SDT_WebAssemblyWrapper>;
105 def WebAssemblywrapperPIC  : SDNode<"WebAssemblyISD::WrapperPIC",
106                                      SDT_WebAssemblyWrapperPIC>;
107 def WebAssemblyglobal_get :
108     SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet,
109            [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
110 def WebAssemblyglobal_set :
111     SDNode<"WebAssemblyISD::GLOBAL_SET", SDT_WebAssemblyGlobalSet,
112            [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
113 def WebAssemblylocal_get :
114     SDNode<"WebAssemblyISD::LOCAL_GET", SDT_WebAssemblyLocalGet,
115            [SDNPHasChain, SDNPMayLoad]>;
116 def WebAssemblylocal_set :
117     SDNode<"WebAssemblyISD::LOCAL_SET", SDT_WebAssemblyLocalSet,
118            [SDNPHasChain, SDNPMayStore]>;
120 //===----------------------------------------------------------------------===//
121 // WebAssembly-specific Operands.
122 //===----------------------------------------------------------------------===//
124 // Default Operand has AsmOperandClass "Imm" which is for integers (and
125 // symbols), so specialize one for floats:
126 class FPImmAsmOperand<ValueType ty> : AsmOperandClass {
127   let Name = "FPImm" # ty;
128   let PredicateMethod = "isFPImm";
131 class FPOperand<ValueType ty> : Operand<ty> {
132   AsmOperandClass ParserMatchClass = FPImmAsmOperand<ty>;
135 let OperandNamespace = "WebAssembly" in {
137 let OperandType = "OPERAND_BASIC_BLOCK" in
138 def bb_op : Operand<OtherVT>;
140 let OperandType = "OPERAND_LOCAL" in
141 def local_op : Operand<i32>;
143 let OperandType = "OPERAND_GLOBAL" in {
144   // The operand to global instructions is always a 32-bit index.
145   def global_op32 : Operand<i32>;
146   // In PIC mode however, we temporarily represent this index as an external
147   // symbol, which to LLVM is a pointer, so in wasm64 mode it is easiest to
148   // pretend we use a 64-bit index for it.
149   def global_op64 : Operand<i64>;
152 let OperandType = "OPERAND_I32IMM" in
153 def i32imm_op : Operand<i32>;
155 let OperandType = "OPERAND_I64IMM" in
156 def i64imm_op : Operand<i64>;
158 let OperandType = "OPERAND_F32IMM" in
159 def f32imm_op : FPOperand<f32>;
161 let OperandType = "OPERAND_F64IMM" in
162 def f64imm_op : FPOperand<f64>;
164 let OperandType = "OPERAND_VEC_I8IMM" in
165 def vec_i8imm_op : Operand<i32>;
167 let OperandType = "OPERAND_VEC_I16IMM" in
168 def vec_i16imm_op : Operand<i32>;
170 let OperandType = "OPERAND_VEC_I32IMM" in
171 def vec_i32imm_op : Operand<i32>;
173 let OperandType = "OPERAND_VEC_I64IMM" in
174 def vec_i64imm_op : Operand<i64>;
176 let OperandType = "OPERAND_FUNCTION32" in
177 def function32_op : Operand<i32>;
179 let OperandType = "OPERAND_TABLE" in
180 def table32_op : Operand<i32>;
182 let OperandType = "OPERAND_OFFSET32" in
183 def offset32_op : Operand<i32>;
185 let OperandType = "OPERAND_OFFSET64" in
186 def offset64_op : Operand<i64>;
188 let OperandType = "OPERAND_P2ALIGN" in {
189 def P2Align : Operand<i32> {
190   let PrintMethod = "printWebAssemblyP2AlignOperand";
193 let OperandType = "OPERAND_TAG" in
194 def tag_op : Operand<i32>;
196 } // OperandType = "OPERAND_P2ALIGN"
198 let OperandType = "OPERAND_SIGNATURE" in
199 def Signature : Operand<i32> {
200   let PrintMethod = "printWebAssemblySignatureOperand";
203 let OperandType = "OPERAND_HEAPTYPE" in
204 def HeapType : Operand<i32> {
205   let PrintMethod = "printWebAssemblyHeapTypeOperand";
208 let OperandType = "OPERAND_TYPEINDEX" in
209 def TypeIndex : Operand<i32>;
211 } // OperandNamespace = "WebAssembly"
213 // TODO: Find more places to use this.
214 def bool_node : PatLeaf<(i32 I32:$cond), [{
215   return CurDAG->computeKnownBits(SDValue(N, 0)).countMinLeadingZeros() == 31;
216 }]>;
218 //===----------------------------------------------------------------------===//
219 // WebAssembly Register to Stack instruction mapping
220 //===----------------------------------------------------------------------===//
222 class StackRel;
223 def getStackOpcode : InstrMapping {
224   let FilterClass = "StackRel";
225   let RowFields = ["BaseName"];
226   let ColFields = ["StackBased"];
227   let KeyCol = ["false"];
228   let ValueCols = [["true"]];
231 //===----------------------------------------------------------------------===//
232 // WebAssembly Stack to Register instruction mapping
233 //===----------------------------------------------------------------------===//
235 class RegisterRel;
236 def getRegisterOpcode : InstrMapping {
237   let FilterClass = "RegisterRel";
238   let RowFields = ["BaseName"];
239   let ColFields = ["StackBased"];
240   let KeyCol = ["true"];
241   let ValueCols = [["false"]];
244 //===----------------------------------------------------------------------===//
245 // WebAssembly 32 to 64-bit instruction mapping
246 //===----------------------------------------------------------------------===//
248 class Wasm64Rel;
249 def getWasm64Opcode : InstrMapping {
250   let FilterClass = "Wasm64Rel";
251   let RowFields = ["Wasm32Name"];
252   let ColFields = ["IsWasm64"];
253   let KeyCol = ["false"];
254   let ValueCols = [["true"]];
257 //===----------------------------------------------------------------------===//
258 // WebAssembly Instruction Format Definitions.
259 //===----------------------------------------------------------------------===//
261 include "WebAssemblyInstrFormats.td"
263 //===----------------------------------------------------------------------===//
264 // Additional instructions.
265 //===----------------------------------------------------------------------===//
267 multiclass ARGUMENT<WebAssemblyRegClass rc, ValueType vt> {
268   let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>,
269       Uses = [ARGUMENTS] in
270   defm ARGUMENT_#vt :
271     I<(outs rc:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
272       [(set (vt rc:$res), (WebAssemblyargument timm:$argno))]>;
274 defm "": ARGUMENT<I32, i32>;
275 defm "": ARGUMENT<I64, i64>;
276 defm "": ARGUMENT<F32, f32>;
277 defm "": ARGUMENT<F64, f64>;
278 defm "": ARGUMENT<FUNCREF, funcref>;
279 defm "": ARGUMENT<EXTERNREF, externref>;
281 // local.get and local.set are not generated by instruction selection; they
282 // are implied by virtual register uses and defs.
283 multiclass LOCAL<WebAssemblyRegClass rc, Operand global_op> {
284   let hasSideEffects = 0 in {
285   // COPY is not an actual instruction in wasm, but since we allow local.get and
286   // local.set to be implicit during most of codegen, we can have a COPY which
287   // is actually a no-op because all the work is done in the implied local.get
288   // and local.set. COPYs are eliminated (and replaced with
289   // local.get/local.set) in the ExplicitLocals pass.
290   let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
291   defm COPY_#rc : I<(outs rc:$res), (ins rc:$src), (outs), (ins), [],
292                     "local.copy\t$res, $src", "local.copy">;
294   // TEE is similar to COPY, but writes two copies of its result. Typically
295   // this would be used to stackify one result and write the other result to a
296   // local.
297   let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
298   defm TEE_#rc : I<(outs rc:$res, rc:$also), (ins rc:$src), (outs), (ins), [],
299                    "local.tee\t$res, $also, $src", "local.tee">;
301   // This is the actual local.get instruction in wasm. These are made explicit
302   // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
303   // local, which is a side effect not otherwise modeled in LLVM.
304   let mayLoad = 1, isAsCheapAsAMove = 1 in
305   defm LOCAL_GET_#rc : I<(outs rc:$res), (ins local_op:$local),
306                          (outs), (ins local_op:$local), [],
307                          "local.get\t$res, $local", "local.get\t$local", 0x20>;
309   // This is the actual local.set instruction in wasm. These are made explicit
310   // by the ExplicitLocals pass. It has mayStore because it writes to a wasm
311   // local, which is a side effect not otherwise modeled in LLVM.
312   let mayStore = 1, isAsCheapAsAMove = 1 in
313   defm LOCAL_SET_#rc : I<(outs), (ins local_op:$local, rc:$src),
314                          (outs), (ins local_op:$local), [],
315                          "local.set\t$local, $src", "local.set\t$local", 0x21>;
317   // This is the actual local.tee instruction in wasm. TEEs are turned into
318   // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
319   // as LOCAL_SET.
320   let mayStore = 1, isAsCheapAsAMove = 1 in
321   defm LOCAL_TEE_#rc : I<(outs rc:$res), (ins local_op:$local, rc:$src),
322                          (outs), (ins local_op:$local), [],
323                          "local.tee\t$res, $local, $src", "local.tee\t$local",
324                          0x22>;
326   // Unused values must be dropped in some contexts.
327   defm DROP_#rc : I<(outs), (ins rc:$src), (outs), (ins), [],
328                     "drop\t$src", "drop", 0x1a>;
330   let mayLoad = 1 in
331   defm GLOBAL_GET_#rc : I<(outs rc:$res), (ins global_op:$addr),
332                           (outs), (ins global_op:$addr), [],
333                            "global.get\t$res, $addr", "global.get\t$addr",
334                           0x23>;
336   let mayStore = 1 in
337   defm GLOBAL_SET_#rc : I<(outs), (ins global_op:$addr, rc:$src),
338                           (outs), (ins global_op:$addr), [],
339                           "global.set\t$addr, $src", "global.set\t$addr",
340                           0x24>;
342   } // hasSideEffects = 0
343   foreach vt = rc.RegTypes in {
344     def : Pat<(vt (WebAssemblyglobal_get
345                    (WebAssemblywrapper tglobaladdr:$addr))),
346               (!cast<NI>("GLOBAL_GET_" # rc) tglobaladdr:$addr)>;
347     def : Pat<(WebAssemblyglobal_set
348                vt:$src, (WebAssemblywrapper tglobaladdr:$addr)),
349               (!cast<NI>("GLOBAL_SET_" # rc) tglobaladdr:$addr, vt:$src)>;
350     def : Pat<(vt (WebAssemblylocal_get (i32 timm:$local))),
351               (!cast<NI>("LOCAL_GET_" # rc) timm:$local)>;
352     def : Pat<(WebAssemblylocal_set timm:$local, vt:$src),
353               (!cast<NI>("LOCAL_SET_" # rc) timm:$local, vt:$src)>;
354   }
356 defm "" : LOCAL<I32, global_op32>;
357 defm "" : LOCAL<I64, global_op64>;  // 64-bit only needed for pointers.
358 defm "" : LOCAL<F32, global_op32>;
359 defm "" : LOCAL<F64, global_op32>;
360 defm "" : LOCAL<V128, global_op32>, Requires<[HasSIMD128]>;
361 defm "" : LOCAL<FUNCREF, global_op32>, Requires<[HasReferenceTypes]>;
362 defm "" : LOCAL<EXTERNREF, global_op32>, Requires<[HasReferenceTypes]>;
364 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
365 defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
366                    (outs), (ins i32imm_op:$imm),
367                    [(set I32:$res, imm:$imm)],
368                    "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>;
369 defm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm),
370                    (outs), (ins i64imm_op:$imm),
371                    [(set I64:$res, imm:$imm)],
372                    "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>;
373 defm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
374                    (outs), (ins f32imm_op:$imm),
375                    [(set F32:$res, fpimm:$imm)],
376                    "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>;
377 defm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
378                    (outs), (ins f64imm_op:$imm),
379                    [(set F64:$res, fpimm:$imm)],
380                    "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>;
381 } // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
383 def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
384           (CONST_I32 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr32]>;
385 def : Pat<(i64 (WebAssemblywrapper tglobaladdr:$addr)),
386           (CONST_I64 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr64]>;
388 def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
389           (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>;
390 def : Pat<(i64 (WebAssemblywrapper tglobaladdr:$addr)),
391           (GLOBAL_GET_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>;
393 def : Pat<(i32 (WebAssemblywrapperPIC tglobaladdr:$addr)),
394           (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>;
395 def : Pat<(i64 (WebAssemblywrapperPIC tglobaladdr:$addr)),
396           (CONST_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>;
398 def : Pat<(i32 (WebAssemblywrapper tglobaltlsaddr:$addr)),
399           (CONST_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>;
400 def : Pat<(i64 (WebAssemblywrapper tglobaltlsaddr:$addr)),
401           (CONST_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>;
403 def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
404           (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>;
405 def : Pat<(i64 (WebAssemblywrapper texternalsym:$addr)),
406           (GLOBAL_GET_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>;
408 def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
409           (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr32]>;
410 def : Pat<(i64 (WebAssemblywrapper texternalsym:$addr)),
411           (CONST_I64 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr64]>;
413 def : Pat<(i32 (WebAssemblywrapper mcsym:$sym)), (CONST_I32 mcsym:$sym)>;
414 def : Pat<(i64 (WebAssemblywrapper mcsym:$sym)), (CONST_I64 mcsym:$sym)>;
416 //===----------------------------------------------------------------------===//
417 // Additional sets of instructions.
418 //===----------------------------------------------------------------------===//
420 include "WebAssemblyInstrMemory.td"
421 include "WebAssemblyInstrCall.td"
422 include "WebAssemblyInstrControl.td"
423 include "WebAssemblyInstrInteger.td"
424 include "WebAssemblyInstrConv.td"
425 include "WebAssemblyInstrFloat.td"
426 include "WebAssemblyInstrAtomics.td"
427 include "WebAssemblyInstrSIMD.td"
428 include "WebAssemblyInstrRef.td"
429 include "WebAssemblyInstrBulkMemory.td"
430 include "WebAssemblyInstrTable.td"