1285163Sdim// WebAssemblyInstrInfo.td-Describe the WebAssembly Instructions-*- tablegen -*-
2285163Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6285163Sdim//
7285163Sdim//===----------------------------------------------------------------------===//
8286684Sdim///
9286684Sdim/// \file
10341825Sdim/// WebAssembly Instruction definitions.
11286684Sdim///
12285163Sdim//===----------------------------------------------------------------------===//
13285163Sdim
14285163Sdim//===----------------------------------------------------------------------===//
15285163Sdim// WebAssembly Instruction Predicate Definitions.
16285163Sdim//===----------------------------------------------------------------------===//
17285163Sdim
18353358Sdimdef IsPIC     : Predicate<"TM.isPositionIndependent()">;
19353358Sdimdef IsNotPIC  : Predicate<"!TM.isPositionIndependent()">;
20353358Sdim
21285163Sdimdef HasAddr32 : Predicate<"!Subtarget->hasAddr64()">;
22353358Sdim
23285163Sdimdef HasAddr64 : Predicate<"Subtarget->hasAddr64()">;
24353358Sdim
25353358Sdimdef HasSIMD128 :
26353358Sdim    Predicate<"Subtarget->hasSIMD128()">,
27353358Sdim    AssemblerPredicate<"FeatureSIMD128", "simd128">;
28353358Sdim
29344779Sdimdef HasUnimplementedSIMD128 :
30344779Sdim    Predicate<"Subtarget->hasUnimplementedSIMD128()">,
31344779Sdim    AssemblerPredicate<"FeatureUnimplementedSIMD128", "unimplemented-simd128">;
32353358Sdim
33353358Sdimdef HasAtomics :
34353358Sdim    Predicate<"Subtarget->hasAtomics()">,
35353358Sdim    AssemblerPredicate<"FeatureAtomics", "atomics">;
36353358Sdim
37353358Sdimdef HasMultivalue :
38353358Sdim    Predicate<"Subtarget->hasMultivalue()">,
39353358Sdim    AssemblerPredicate<"FeatureMultivalue", "multivalue">;
40353358Sdim
41327952Sdimdef HasNontrappingFPToInt :
42327952Sdim    Predicate<"Subtarget->hasNontrappingFPToInt()">,
43353358Sdim    AssemblerPredicate<"FeatureNontrappingFPToInt", "nontrapping-fptoint">;
44353358Sdim
45327952Sdimdef NotHasNontrappingFPToInt :
46327952Sdim    Predicate<"!Subtarget->hasNontrappingFPToInt()">,
47353358Sdim    AssemblerPredicate<"!FeatureNontrappingFPToInt", "nontrapping-fptoint">;
48353358Sdim
49341825Sdimdef HasSignExt :
50341825Sdim    Predicate<"Subtarget->hasSignExt()">,
51353358Sdim    AssemblerPredicate<"FeatureSignExt", "sign-ext">;
52285163Sdim
53353358Sdimdef HasTailCall :
54353358Sdim    Predicate<"Subtarget->hasTailCall()">,
55353358Sdim    AssemblerPredicate<"FeatureTailCall", "tail-call">;
56353358Sdim
57341825Sdimdef HasExceptionHandling :
58341825Sdim    Predicate<"Subtarget->hasExceptionHandling()">,
59353358Sdim    AssemblerPredicate<"FeatureExceptionHandling", "exception-handling">;
60341825Sdim
61353358Sdimdef HasBulkMemory :
62353358Sdim    Predicate<"Subtarget->hasBulkMemory()">,
63353358Sdim    AssemblerPredicate<"FeatureBulkMemory", "bulk-memory">;
64341825Sdim
65285163Sdim//===----------------------------------------------------------------------===//
66285163Sdim// WebAssembly-specific DAG Node Types.
67285163Sdim//===----------------------------------------------------------------------===//
68285163Sdim
69321369Sdimdef SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
70321369Sdim                                                  SDTCisVT<1, iPTR>]>;
71296417Sdimdef SDT_WebAssemblyCallSeqEnd :
72296417Sdim    SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
73353358Sdimdef SDT_WebAssemblyCall0      : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
74353358Sdimdef SDT_WebAssemblyCall1      : SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>;
75353358Sdimdef SDT_WebAssemblyBrTable    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
76353358Sdimdef SDT_WebAssemblyArgument   : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
77353358Sdimdef SDT_WebAssemblyReturn     : SDTypeProfile<0, -1, []>;
78353358Sdimdef SDT_WebAssemblyWrapper    : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
79353358Sdim                                                     SDTCisPtrTy<0>]>;
80353358Sdimdef SDT_WebAssemblyWrapperPIC : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
81353358Sdim                                                     SDTCisPtrTy<0>]>;
82353358Sdimdef SDT_WebAssemblyThrow      : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
83296417Sdim
84285163Sdim//===----------------------------------------------------------------------===//
85285163Sdim// WebAssembly-specific DAG Nodes.
86285163Sdim//===----------------------------------------------------------------------===//
87285163Sdim
88296417Sdimdef WebAssemblycallseq_start :
89296417Sdim    SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
90296417Sdim           [SDNPHasChain, SDNPOutGlue]>;
91296417Sdimdef WebAssemblycallseq_end :
92296417Sdim    SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
93296417Sdim           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
94296417Sdimdef WebAssemblycall0 : SDNode<"WebAssemblyISD::CALL0",
95296417Sdim                              SDT_WebAssemblyCall0,
96296417Sdim                              [SDNPHasChain, SDNPVariadic]>;
97296417Sdimdef WebAssemblycall1 : SDNode<"WebAssemblyISD::CALL1",
98296417Sdim                              SDT_WebAssemblyCall1,
99296417Sdim                              [SDNPHasChain, SDNPVariadic]>;
100353358Sdimdef WebAssemblyretcall : SDNode<"WebAssemblyISD::RET_CALL",
101353358Sdim                                SDT_WebAssemblyCall0,
102353358Sdim                                [SDNPHasChain, SDNPVariadic]>;
103309124Sdimdef WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
104309124Sdim                                 SDT_WebAssemblyBrTable,
105309124Sdim                                 [SDNPHasChain, SDNPVariadic]>;
106296417Sdimdef WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
107296417Sdim                                 SDT_WebAssemblyArgument>;
108296417Sdimdef WebAssemblyreturn   : SDNode<"WebAssemblyISD::RETURN",
109360784Sdim                                 SDT_WebAssemblyReturn,
110360784Sdim                                 [SDNPHasChain, SDNPVariadic]>;
111296417Sdimdef WebAssemblywrapper  : SDNode<"WebAssemblyISD::Wrapper",
112296417Sdim                                 SDT_WebAssemblyWrapper>;
113353358Sdimdef WebAssemblywrapperPIC  : SDNode<"WebAssemblyISD::WrapperPIC",
114353358Sdim                                     SDT_WebAssemblyWrapperPIC>;
115344779Sdimdef WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
116353358Sdim                              [SDNPHasChain, SDNPVariadic]>;
117296417Sdim
118285163Sdim//===----------------------------------------------------------------------===//
119285163Sdim// WebAssembly-specific Operands.
120285163Sdim//===----------------------------------------------------------------------===//
121285163Sdim
122353358Sdim// Default Operand has AsmOperandClass "Imm" which is for integers (and
123353358Sdim// symbols), so specialize one for floats:
124353358Sdimdef FPImmAsmOperand : AsmOperandClass {
125353358Sdim  let Name = "FPImm";
126353358Sdim  let PredicateMethod = "isFPImm";
127353358Sdim}
128353358Sdim
129353358Sdimclass FPOperand<ValueType ty> : Operand<ty> {
130353358Sdim  AsmOperandClass ParserMatchClass = FPImmAsmOperand;
131353358Sdim}
132353358Sdim
133296417Sdimlet OperandNamespace = "WebAssembly" in {
134286684Sdim
135296417Sdimlet OperandType = "OPERAND_BASIC_BLOCK" in
136296417Sdimdef bb_op : Operand<OtherVT>;
137296417Sdim
138314564Sdimlet OperandType = "OPERAND_LOCAL" in
139314564Sdimdef local_op : Operand<i32>;
140314564Sdim
141321369Sdimlet OperandType = "OPERAND_GLOBAL" in
142321369Sdimdef global_op : Operand<i32>;
143321369Sdim
144314564Sdimlet OperandType = "OPERAND_I32IMM" in
145314564Sdimdef i32imm_op : Operand<i32>;
146314564Sdim
147314564Sdimlet OperandType = "OPERAND_I64IMM" in
148314564Sdimdef i64imm_op : Operand<i64>;
149314564Sdim
150314564Sdimlet OperandType = "OPERAND_F32IMM" in
151353358Sdimdef f32imm_op : FPOperand<f32>;
152309124Sdim
153314564Sdimlet OperandType = "OPERAND_F64IMM" in
154353358Sdimdef f64imm_op : FPOperand<f64>;
155296417Sdim
156344779Sdimlet OperandType = "OPERAND_VEC_I8IMM" in
157344779Sdimdef vec_i8imm_op : Operand<i32>;
158344779Sdim
159344779Sdimlet OperandType = "OPERAND_VEC_I16IMM" in
160344779Sdimdef vec_i16imm_op : Operand<i32>;
161344779Sdim
162344779Sdimlet OperandType = "OPERAND_VEC_I32IMM" in
163344779Sdimdef vec_i32imm_op : Operand<i32>;
164344779Sdim
165344779Sdimlet OperandType = "OPERAND_VEC_I64IMM" in
166344779Sdimdef vec_i64imm_op : Operand<i64>;
167344779Sdim
168314564Sdimlet OperandType = "OPERAND_FUNCTION32" in
169314564Sdimdef function32_op : Operand<i32>;
170314564Sdim
171314564Sdimlet OperandType = "OPERAND_OFFSET32" in
172314564Sdimdef offset32_op : Operand<i32>;
173314564Sdim
174309124Sdimlet OperandType = "OPERAND_P2ALIGN" in {
175309124Sdimdef P2Align : Operand<i32> {
176309124Sdim  let PrintMethod = "printWebAssemblyP2AlignOperand";
177309124Sdim}
178344779Sdim
179344779Sdimlet OperandType = "OPERAND_EVENT" in
180344779Sdimdef event_op : Operand<i32>;
181344779Sdim
182309124Sdim} // OperandType = "OPERAND_P2ALIGN"
183309124Sdim
184353358Sdimlet OperandType = "OPERAND_SIGNATURE" in
185314564Sdimdef Signature : Operand<i32> {
186314564Sdim  let PrintMethod = "printWebAssemblySignatureOperand";
187314564Sdim}
188314564Sdim
189321369Sdimlet OperandType = "OPERAND_TYPEINDEX" in
190321369Sdimdef TypeIndex : Operand<i32>;
191321369Sdim
192296417Sdim} // OperandNamespace = "WebAssembly"
193296417Sdim
194285163Sdim//===----------------------------------------------------------------------===//
195344779Sdim// WebAssembly Register to Stack instruction mapping
196344779Sdim//===----------------------------------------------------------------------===//
197344779Sdim
198344779Sdimclass StackRel;
199344779Sdimdef getStackOpcode : InstrMapping {
200344779Sdim  let FilterClass = "StackRel";
201344779Sdim  let RowFields = ["BaseName"];
202344779Sdim  let ColFields = ["StackBased"];
203344779Sdim  let KeyCol = ["false"];
204344779Sdim  let ValueCols = [["true"]];
205344779Sdim}
206344779Sdim
207344779Sdim//===----------------------------------------------------------------------===//
208285163Sdim// WebAssembly Instruction Format Definitions.
209285163Sdim//===----------------------------------------------------------------------===//
210285163Sdim
211285163Sdiminclude "WebAssemblyInstrFormats.td"
212285163Sdim
213285163Sdim//===----------------------------------------------------------------------===//
214296417Sdim// Additional instructions.
215296417Sdim//===----------------------------------------------------------------------===//
216296417Sdim
217344779Sdimmulticlass ARGUMENT<WebAssemblyRegClass reg, ValueType vt> {
218353358Sdim  let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>,
219353358Sdim      Uses = [ARGUMENTS] in
220344779Sdim  defm ARGUMENT_#vt :
221344779Sdim    I<(outs reg:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
222344779Sdim      [(set (vt reg:$res), (WebAssemblyargument timm:$argno))]>;
223296417Sdim}
224344779Sdimdefm "": ARGUMENT<I32, i32>;
225344779Sdimdefm "": ARGUMENT<I64, i64>;
226344779Sdimdefm "": ARGUMENT<F32, f32>;
227344779Sdimdefm "": ARGUMENT<F64, f64>;
228353358Sdimdefm "": ARGUMENT<EXNREF, exnref>;
229296417Sdim
230344779Sdim// local.get and local.set are not generated by instruction selection; they
231309124Sdim// are implied by virtual register uses and defs.
232296417Sdimmulticlass LOCAL<WebAssemblyRegClass vt> {
233353358Sdim  let hasSideEffects = 0 in {
234344779Sdim  // COPY is not an actual instruction in wasm, but since we allow local.get and
235344779Sdim  // local.set to be implicit during most of codegen, we can have a COPY which
236344779Sdim  // is actually a no-op because all the work is done in the implied local.get
237344779Sdim  // and local.set. COPYs are eliminated (and replaced with
238344779Sdim  // local.get/local.set) in the ExplicitLocals pass.
239314564Sdim  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
240341825Sdim  defm COPY_#vt : I<(outs vt:$res), (ins vt:$src), (outs), (ins), [],
241344779Sdim                    "local.copy\t$res, $src", "local.copy">;
242309124Sdim
243314564Sdim  // TEE is similar to COPY, but writes two copies of its result. Typically
244314564Sdim  // this would be used to stackify one result and write the other result to a
245314564Sdim  // local.
246314564Sdim  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
247341825Sdim  defm TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), (outs), (ins), [],
248344779Sdim                   "local.tee\t$res, $also, $src", "local.tee">;
249314564Sdim
250344779Sdim  // This is the actual local.get instruction in wasm. These are made explicit
251314564Sdim  // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
252314564Sdim  // local, which is a side effect not otherwise modeled in LLVM.
253314564Sdim  let mayLoad = 1, isAsCheapAsAMove = 1 in
254344779Sdim  defm LOCAL_GET_#vt : I<(outs vt:$res), (ins local_op:$local),
255341825Sdim                         (outs), (ins local_op:$local), [],
256344779Sdim                         "local.get\t$res, $local", "local.get\t$local", 0x20>;
257314564Sdim
258344779Sdim  // This is the actual local.set instruction in wasm. These are made explicit
259314564Sdim  // by the ExplicitLocals pass. It has mayStore because it writes to a wasm
260314564Sdim  // local, which is a side effect not otherwise modeled in LLVM.
261314564Sdim  let mayStore = 1, isAsCheapAsAMove = 1 in
262344779Sdim  defm LOCAL_SET_#vt : I<(outs), (ins local_op:$local, vt:$src),
263341825Sdim                         (outs), (ins local_op:$local), [],
264344779Sdim                         "local.set\t$local, $src", "local.set\t$local", 0x21>;
265314564Sdim
266344779Sdim  // This is the actual local.tee instruction in wasm. TEEs are turned into
267344779Sdim  // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
268344779Sdim  // as LOCAL_SET.
269314564Sdim  let mayStore = 1, isAsCheapAsAMove = 1 in
270344779Sdim  defm LOCAL_TEE_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src),
271341825Sdim                         (outs), (ins local_op:$local), [],
272344779Sdim                         "local.tee\t$res, $local, $src", "local.tee\t$local",
273341825Sdim                         0x22>;
274314564Sdim
275321369Sdim  // Unused values must be dropped in some contexts.
276341825Sdim  defm DROP_#vt : I<(outs), (ins vt:$src), (outs), (ins), [],
277341825Sdim                    "drop\t$src", "drop", 0x1a>;
278321369Sdim
279321369Sdim  let mayLoad = 1 in
280344779Sdim  defm GLOBAL_GET_#vt : I<(outs vt:$res), (ins global_op:$local),
281341825Sdim                          (outs), (ins global_op:$local), [],
282344779Sdim                          "global.get\t$res, $local", "global.get\t$local",
283341825Sdim                          0x23>;
284321369Sdim
285321369Sdim  let mayStore = 1 in
286344779Sdim  defm GLOBAL_SET_#vt : I<(outs), (ins global_op:$local, vt:$src),
287341825Sdim                          (outs), (ins global_op:$local), [],
288344779Sdim                          "global.set\t$local, $src", "global.set\t$local",
289341825Sdim                          0x24>;
290321369Sdim
291309124Sdim} // hasSideEffects = 0
292296417Sdim}
293341825Sdimdefm "" : LOCAL<I32>;
294341825Sdimdefm "" : LOCAL<I64>;
295341825Sdimdefm "" : LOCAL<F32>;
296341825Sdimdefm "" : LOCAL<F64>;
297341825Sdimdefm "" : LOCAL<V128>, Requires<[HasSIMD128]>;
298353358Sdimdefm "" : LOCAL<EXNREF>, Requires<[HasExceptionHandling]>;
299296417Sdim
300309124Sdimlet isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
301341825Sdimdefm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
302341825Sdim                   (outs), (ins i32imm_op:$imm),
303341825Sdim                   [(set I32:$res, imm:$imm)],
304341825Sdim                   "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>;
305341825Sdimdefm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm),
306341825Sdim                   (outs), (ins i64imm_op:$imm),
307341825Sdim                   [(set I64:$res, imm:$imm)],
308341825Sdim                   "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>;
309341825Sdimdefm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
310341825Sdim                   (outs), (ins f32imm_op:$imm),
311341825Sdim                   [(set F32:$res, fpimm:$imm)],
312341825Sdim                   "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>;
313341825Sdimdefm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
314341825Sdim                   (outs), (ins f64imm_op:$imm),
315341825Sdim                   [(set F64:$res, fpimm:$imm)],
316341825Sdim                   "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>;
317309124Sdim} // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
318296417Sdim
319296417Sdimdef : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
320353358Sdim          (CONST_I32 tglobaladdr:$addr)>, Requires<[IsNotPIC]>;
321353358Sdim
322353358Sdimdef : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
323353358Sdim          (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC]>;
324353358Sdim
325353358Sdimdef : Pat<(i32 (WebAssemblywrapperPIC tglobaladdr:$addr)),
326353358Sdim          (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC]>;
327353358Sdim
328296417Sdimdef : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
329353358Sdim          (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC]>;
330353358Sdim
331353358Sdimdef : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
332353358Sdim          (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC]>;
333353358Sdim
334344779Sdimdef : Pat<(i32 (WebAssemblywrapper mcsym:$sym)), (CONST_I32 mcsym:$sym)>;
335344779Sdimdef : Pat<(i64 (WebAssemblywrapper mcsym:$sym)), (CONST_I64 mcsym:$sym)>;
336296417Sdim
337296417Sdim//===----------------------------------------------------------------------===//
338285163Sdim// Additional sets of instructions.
339285163Sdim//===----------------------------------------------------------------------===//
340285163Sdim
341286684Sdiminclude "WebAssemblyInstrMemory.td"
342286684Sdiminclude "WebAssemblyInstrCall.td"
343296417Sdiminclude "WebAssemblyInstrControl.td"
344286684Sdiminclude "WebAssemblyInstrInteger.td"
345296417Sdiminclude "WebAssemblyInstrConv.td"
346286684Sdiminclude "WebAssemblyInstrFloat.td"
347285163Sdiminclude "WebAssemblyInstrAtomics.td"
348285163Sdiminclude "WebAssemblyInstrSIMD.td"
349353358Sdiminclude "WebAssemblyInstrRef.td"
350353358Sdiminclude "WebAssemblyInstrBulkMemory.td"
351