]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
Merge ^/head r363583 through r364040.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / WebAssembly / WebAssemblyInstrInfo.td
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 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 // WebAssembly Instruction Predicate Definitions.
16 //===----------------------------------------------------------------------===//
17
18 def IsPIC     : Predicate<"TM.isPositionIndependent()">;
19 def IsNotPIC  : Predicate<"!TM.isPositionIndependent()">;
20
21 def HasAddr32 : Predicate<"!Subtarget->hasAddr64()">;
22
23 def HasAddr64 : Predicate<"Subtarget->hasAddr64()">;
24
25 def HasSIMD128 :
26     Predicate<"Subtarget->hasSIMD128()">,
27     AssemblerPredicate<(all_of FeatureSIMD128), "simd128">;
28
29 def HasUnimplementedSIMD128 :
30     Predicate<"Subtarget->hasUnimplementedSIMD128()">,
31     AssemblerPredicate<(all_of FeatureUnimplementedSIMD128), "unimplemented-simd128">;
32
33 def HasAtomics :
34     Predicate<"Subtarget->hasAtomics()">,
35     AssemblerPredicate<(all_of FeatureAtomics), "atomics">;
36
37 def HasMultivalue :
38     Predicate<"Subtarget->hasMultivalue()">,
39     AssemblerPredicate<(all_of FeatureMultivalue), "multivalue">;
40
41 def HasNontrappingFPToInt :
42     Predicate<"Subtarget->hasNontrappingFPToInt()">,
43     AssemblerPredicate<(all_of FeatureNontrappingFPToInt), "nontrapping-fptoint">;
44
45 def NotHasNontrappingFPToInt :
46     Predicate<"!Subtarget->hasNontrappingFPToInt()">,
47     AssemblerPredicate<(all_of (not FeatureNontrappingFPToInt)), "nontrapping-fptoint">;
48
49 def HasSignExt :
50     Predicate<"Subtarget->hasSignExt()">,
51     AssemblerPredicate<(all_of FeatureSignExt), "sign-ext">;
52
53 def HasTailCall :
54     Predicate<"Subtarget->hasTailCall()">,
55     AssemblerPredicate<(all_of FeatureTailCall), "tail-call">;
56
57 def HasExceptionHandling :
58     Predicate<"Subtarget->hasExceptionHandling()">,
59     AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">;
60
61 def HasBulkMemory :
62     Predicate<"Subtarget->hasBulkMemory()">,
63     AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">;
64
65 def HasReferenceTypes :
66     Predicate<"Subtarget->hasReferenceTypes()">,
67     AssemblerPredicate<(all_of FeatureReferenceTypes), "reference-types">;
68
69 //===----------------------------------------------------------------------===//
70 // WebAssembly-specific DAG Node Types.
71 //===----------------------------------------------------------------------===//
72
73 def SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
74                                                   SDTCisVT<1, iPTR>]>;
75 def SDT_WebAssemblyCallSeqEnd :
76     SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
77 def SDT_WebAssemblyCall0      : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
78 def SDT_WebAssemblyCall1      : SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>;
79 def SDT_WebAssemblyBrTable    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
80 def SDT_WebAssemblyArgument   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
81 def SDT_WebAssemblyReturn     : SDTypeProfile<0, -1, []>;
82 def SDT_WebAssemblyWrapper    : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
83                                                      SDTCisPtrTy<0>]>;
84 def SDT_WebAssemblyWrapperPIC : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
85                                                      SDTCisPtrTy<0>]>;
86 def SDT_WebAssemblyThrow      : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
87
88 //===----------------------------------------------------------------------===//
89 // WebAssembly-specific DAG Nodes.
90 //===----------------------------------------------------------------------===//
91
92 def WebAssemblycallseq_start :
93     SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
94            [SDNPHasChain, SDNPOutGlue]>;
95 def WebAssemblycallseq_end :
96     SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
97            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
98 def WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
99                                  SDT_WebAssemblyBrTable,
100                                  [SDNPHasChain, SDNPVariadic]>;
101 def WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
102                                  SDT_WebAssemblyArgument>;
103 def WebAssemblyreturn   : SDNode<"WebAssemblyISD::RETURN",
104                                  SDT_WebAssemblyReturn,
105                                  [SDNPHasChain, SDNPVariadic]>;
106 def WebAssemblywrapper  : SDNode<"WebAssemblyISD::Wrapper",
107                                  SDT_WebAssemblyWrapper>;
108 def WebAssemblywrapperPIC  : SDNode<"WebAssemblyISD::WrapperPIC",
109                                      SDT_WebAssemblyWrapperPIC>;
110 def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
111                               [SDNPHasChain, SDNPVariadic]>;
112
113 //===----------------------------------------------------------------------===//
114 // WebAssembly-specific Operands.
115 //===----------------------------------------------------------------------===//
116
117 // Default Operand has AsmOperandClass "Imm" which is for integers (and
118 // symbols), so specialize one for floats:
119 def FPImmAsmOperand : AsmOperandClass {
120   let Name = "FPImm";
121   let PredicateMethod = "isFPImm";
122 }
123
124 class FPOperand<ValueType ty> : Operand<ty> {
125   AsmOperandClass ParserMatchClass = FPImmAsmOperand;
126 }
127
128 let OperandNamespace = "WebAssembly" in {
129
130 let OperandType = "OPERAND_BASIC_BLOCK" in
131 def bb_op : Operand<OtherVT>;
132
133 let OperandType = "OPERAND_LOCAL" in
134 def local_op : Operand<i32>;
135
136 let OperandType = "OPERAND_GLOBAL" in
137 def global_op : Operand<i32>;
138
139 let OperandType = "OPERAND_I32IMM" in
140 def i32imm_op : Operand<i32>;
141
142 let OperandType = "OPERAND_I64IMM" in
143 def i64imm_op : Operand<i64>;
144
145 let OperandType = "OPERAND_F32IMM" in
146 def f32imm_op : FPOperand<f32>;
147
148 let OperandType = "OPERAND_F64IMM" in
149 def f64imm_op : FPOperand<f64>;
150
151 let OperandType = "OPERAND_VEC_I8IMM" in
152 def vec_i8imm_op : Operand<i32>;
153
154 let OperandType = "OPERAND_VEC_I16IMM" in
155 def vec_i16imm_op : Operand<i32>;
156
157 let OperandType = "OPERAND_VEC_I32IMM" in
158 def vec_i32imm_op : Operand<i32>;
159
160 let OperandType = "OPERAND_VEC_I64IMM" in
161 def vec_i64imm_op : Operand<i64>;
162
163 let OperandType = "OPERAND_FUNCTION32" in
164 def function32_op : Operand<i32>;
165
166 let OperandType = "OPERAND_OFFSET32" in
167 def offset32_op : Operand<i32>;
168
169 let OperandType = "OPERAND_OFFSET64" in
170 def offset64_op : Operand<i64>;
171
172 let OperandType = "OPERAND_P2ALIGN" in {
173 def P2Align : Operand<i32> {
174   let PrintMethod = "printWebAssemblyP2AlignOperand";
175 }
176
177 let OperandType = "OPERAND_EVENT" in
178 def event_op : Operand<i32>;
179
180 } // OperandType = "OPERAND_P2ALIGN"
181
182 let OperandType = "OPERAND_SIGNATURE" in
183 def Signature : Operand<i32> {
184   let PrintMethod = "printWebAssemblySignatureOperand";
185 }
186
187 let OperandType = "OPERAND_TYPEINDEX" in
188 def TypeIndex : Operand<i32>;
189
190 } // OperandNamespace = "WebAssembly"
191
192 //===----------------------------------------------------------------------===//
193 // WebAssembly Register to Stack instruction mapping
194 //===----------------------------------------------------------------------===//
195
196 class StackRel;
197 def getStackOpcode : InstrMapping {
198   let FilterClass = "StackRel";
199   let RowFields = ["BaseName"];
200   let ColFields = ["StackBased"];
201   let KeyCol = ["false"];
202   let ValueCols = [["true"]];
203 }
204
205 //===----------------------------------------------------------------------===//
206 // WebAssembly 32 to 64-bit instruction mapping
207 //===----------------------------------------------------------------------===//
208
209 class Wasm64Rel;
210 def getWasm64Opcode : InstrMapping {
211   let FilterClass = "Wasm64Rel";
212   let RowFields = ["Wasm32Name"];
213   let ColFields = ["IsWasm64"];
214   let KeyCol = ["false"];
215   let ValueCols = [["true"]];
216 }
217
218 //===----------------------------------------------------------------------===//
219 // WebAssembly Instruction Format Definitions.
220 //===----------------------------------------------------------------------===//
221
222 include "WebAssemblyInstrFormats.td"
223
224 //===----------------------------------------------------------------------===//
225 // Additional instructions.
226 //===----------------------------------------------------------------------===//
227
228 multiclass ARGUMENT<WebAssemblyRegClass reg, ValueType vt> {
229   let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>,
230       Uses = [ARGUMENTS] in
231   defm ARGUMENT_#vt :
232     I<(outs reg:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
233       [(set (vt reg:$res), (WebAssemblyargument timm:$argno))]>;
234 }
235 defm "": ARGUMENT<I32, i32>;
236 defm "": ARGUMENT<I64, i64>;
237 defm "": ARGUMENT<F32, f32>;
238 defm "": ARGUMENT<F64, f64>;
239 defm "": ARGUMENT<EXNREF, exnref>;
240
241 // local.get and local.set are not generated by instruction selection; they
242 // are implied by virtual register uses and defs.
243 multiclass LOCAL<WebAssemblyRegClass vt> {
244   let hasSideEffects = 0 in {
245   // COPY is not an actual instruction in wasm, but since we allow local.get and
246   // local.set to be implicit during most of codegen, we can have a COPY which
247   // is actually a no-op because all the work is done in the implied local.get
248   // and local.set. COPYs are eliminated (and replaced with
249   // local.get/local.set) in the ExplicitLocals pass.
250   let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
251   defm COPY_#vt : I<(outs vt:$res), (ins vt:$src), (outs), (ins), [],
252                     "local.copy\t$res, $src", "local.copy">;
253
254   // TEE is similar to COPY, but writes two copies of its result. Typically
255   // this would be used to stackify one result and write the other result to a
256   // local.
257   let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
258   defm TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), (outs), (ins), [],
259                    "local.tee\t$res, $also, $src", "local.tee">;
260
261   // This is the actual local.get instruction in wasm. These are made explicit
262   // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
263   // local, which is a side effect not otherwise modeled in LLVM.
264   let mayLoad = 1, isAsCheapAsAMove = 1 in
265   defm LOCAL_GET_#vt : I<(outs vt:$res), (ins local_op:$local),
266                          (outs), (ins local_op:$local), [],
267                          "local.get\t$res, $local", "local.get\t$local", 0x20>;
268
269   // This is the actual local.set instruction in wasm. These are made explicit
270   // by the ExplicitLocals pass. It has mayStore because it writes to a wasm
271   // local, which is a side effect not otherwise modeled in LLVM.
272   let mayStore = 1, isAsCheapAsAMove = 1 in
273   defm LOCAL_SET_#vt : I<(outs), (ins local_op:$local, vt:$src),
274                          (outs), (ins local_op:$local), [],
275                          "local.set\t$local, $src", "local.set\t$local", 0x21>;
276
277   // This is the actual local.tee instruction in wasm. TEEs are turned into
278   // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
279   // as LOCAL_SET.
280   let mayStore = 1, isAsCheapAsAMove = 1 in
281   defm LOCAL_TEE_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src),
282                          (outs), (ins local_op:$local), [],
283                          "local.tee\t$res, $local, $src", "local.tee\t$local",
284                          0x22>;
285
286   // Unused values must be dropped in some contexts.
287   defm DROP_#vt : I<(outs), (ins vt:$src), (outs), (ins), [],
288                     "drop\t$src", "drop", 0x1a>;
289
290   let mayLoad = 1 in
291   defm GLOBAL_GET_#vt : I<(outs vt:$res), (ins global_op:$local),
292                           (outs), (ins global_op:$local), [],
293                           "global.get\t$res, $local", "global.get\t$local",
294                           0x23>;
295
296   let mayStore = 1 in
297   defm GLOBAL_SET_#vt : I<(outs), (ins global_op:$local, vt:$src),
298                           (outs), (ins global_op:$local), [],
299                           "global.set\t$local, $src", "global.set\t$local",
300                           0x24>;
301
302 } // hasSideEffects = 0
303 }
304 defm "" : LOCAL<I32>;
305 defm "" : LOCAL<I64>;
306 defm "" : LOCAL<F32>;
307 defm "" : LOCAL<F64>;
308 defm "" : LOCAL<V128>, Requires<[HasSIMD128]>;
309 defm "" : LOCAL<EXNREF>, Requires<[HasExceptionHandling]>;
310
311 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
312 defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
313                    (outs), (ins i32imm_op:$imm),
314                    [(set I32:$res, imm:$imm)],
315                    "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>;
316 defm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm),
317                    (outs), (ins i64imm_op:$imm),
318                    [(set I64:$res, imm:$imm)],
319                    "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>;
320 defm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
321                    (outs), (ins f32imm_op:$imm),
322                    [(set F32:$res, fpimm:$imm)],
323                    "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>;
324 defm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
325                    (outs), (ins f64imm_op:$imm),
326                    [(set F64:$res, fpimm:$imm)],
327                    "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>;
328 } // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
329
330 def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
331           (CONST_I32 tglobaladdr:$addr)>, Requires<[IsNotPIC]>;
332
333 def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
334           (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC]>;
335
336 def : Pat<(i32 (WebAssemblywrapperPIC tglobaladdr:$addr)),
337           (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC]>;
338
339 def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
340           (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC]>;
341
342 def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
343           (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC]>;
344
345 def : Pat<(i32 (WebAssemblywrapper mcsym:$sym)), (CONST_I32 mcsym:$sym)>;
346 def : Pat<(i64 (WebAssemblywrapper mcsym:$sym)), (CONST_I64 mcsym:$sym)>;
347
348 //===----------------------------------------------------------------------===//
349 // Additional sets of instructions.
350 //===----------------------------------------------------------------------===//
351
352 include "WebAssemblyInstrMemory.td"
353 include "WebAssemblyInstrCall.td"
354 include "WebAssemblyInstrControl.td"
355 include "WebAssemblyInstrInteger.td"
356 include "WebAssemblyInstrConv.td"
357 include "WebAssemblyInstrFloat.td"
358 include "WebAssemblyInstrAtomics.td"
359 include "WebAssemblyInstrSIMD.td"
360 include "WebAssemblyInstrRef.td"
361 include "WebAssemblyInstrBulkMemory.td"