WebAssemblyInstrInfo.td revision 344779
1// WebAssemblyInstrInfo.td-Describe the WebAssembly Instructions-*- tablegen -*-
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// WebAssembly Instruction definitions.
12///
13//===----------------------------------------------------------------------===//
14
15//===----------------------------------------------------------------------===//
16// WebAssembly Instruction Predicate Definitions.
17//===----------------------------------------------------------------------===//
18
19def HasAddr32 : Predicate<"!Subtarget->hasAddr64()">;
20def HasAddr64 : Predicate<"Subtarget->hasAddr64()">;
21def HasSIMD128 : Predicate<"Subtarget->hasSIMD128()">,
22                           AssemblerPredicate<"FeatureSIMD128", "simd128">;
23def HasUnimplementedSIMD128 :
24    Predicate<"Subtarget->hasUnimplementedSIMD128()">,
25    AssemblerPredicate<"FeatureUnimplementedSIMD128", "unimplemented-simd128">;
26def HasAtomics : Predicate<"Subtarget->hasAtomics()">,
27                           AssemblerPredicate<"FeatureAtomics", "atomics">;
28def HasNontrappingFPToInt :
29    Predicate<"Subtarget->hasNontrappingFPToInt()">,
30              AssemblerPredicate<"FeatureNontrappingFPToInt",
31                                 "nontrapping-fptoint">;
32def NotHasNontrappingFPToInt :
33    Predicate<"!Subtarget->hasNontrappingFPToInt()">,
34              AssemblerPredicate<"!FeatureNontrappingFPToInt",
35                                 "nontrapping-fptoint">;
36def HasSignExt :
37    Predicate<"Subtarget->hasSignExt()">,
38              AssemblerPredicate<"FeatureSignExt",
39                                 "sign-ext">;
40def NotHasSignExt :
41    Predicate<"!Subtarget->hasSignExt()">,
42              AssemblerPredicate<"!FeatureSignExt",
43                                 "sign-ext">;
44
45def HasExceptionHandling :
46    Predicate<"Subtarget->hasExceptionHandling()">,
47              AssemblerPredicate<"FeatureExceptionHandling",
48                                 "exception-handling">;
49
50def NotHasExceptionHandling :
51    Predicate<"!Subtarget->hasExceptionHandling()">,
52              AssemblerPredicate<"!FeatureExceptionHandling",
53                                 "exception-handling">;
54
55//===----------------------------------------------------------------------===//
56// WebAssembly-specific DAG Node Types.
57//===----------------------------------------------------------------------===//
58
59def SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
60                                                  SDTCisVT<1, iPTR>]>;
61def SDT_WebAssemblyCallSeqEnd :
62    SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
63def SDT_WebAssemblyCall0    : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
64def SDT_WebAssemblyCall1    : SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>;
65def SDT_WebAssemblyBrTable  : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
66def SDT_WebAssemblyArgument : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>;
67def SDT_WebAssemblyReturn   : SDTypeProfile<0, -1, []>;
68def SDT_WebAssemblyWrapper  : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
69                                                   SDTCisPtrTy<0>]>;
70def SDT_WebAssemblyThrow    : SDTypeProfile<0, 2, [SDTCisPtrTy<0>]>;
71
72//===----------------------------------------------------------------------===//
73// WebAssembly-specific DAG Nodes.
74//===----------------------------------------------------------------------===//
75
76def WebAssemblycallseq_start :
77    SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart,
78           [SDNPHasChain, SDNPOutGlue]>;
79def WebAssemblycallseq_end :
80    SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd,
81           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
82def WebAssemblycall0 : SDNode<"WebAssemblyISD::CALL0",
83                              SDT_WebAssemblyCall0,
84                              [SDNPHasChain, SDNPVariadic]>;
85def WebAssemblycall1 : SDNode<"WebAssemblyISD::CALL1",
86                              SDT_WebAssemblyCall1,
87                              [SDNPHasChain, SDNPVariadic]>;
88def WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE",
89                                 SDT_WebAssemblyBrTable,
90                                 [SDNPHasChain, SDNPVariadic]>;
91def WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT",
92                                 SDT_WebAssemblyArgument>;
93def WebAssemblyreturn   : SDNode<"WebAssemblyISD::RETURN",
94                                 SDT_WebAssemblyReturn, [SDNPHasChain]>;
95def WebAssemblywrapper  : SDNode<"WebAssemblyISD::Wrapper",
96                                 SDT_WebAssemblyWrapper>;
97def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
98                              [SDNPHasChain]>;
99
100//===----------------------------------------------------------------------===//
101// WebAssembly-specific Operands.
102//===----------------------------------------------------------------------===//
103
104let OperandNamespace = "WebAssembly" in {
105
106let OperandType = "OPERAND_BASIC_BLOCK" in
107def bb_op : Operand<OtherVT>;
108
109let OperandType = "OPERAND_LOCAL" in
110def local_op : Operand<i32>;
111
112let OperandType = "OPERAND_GLOBAL" in
113def global_op : Operand<i32>;
114
115let OperandType = "OPERAND_I32IMM" in
116def i32imm_op : Operand<i32>;
117
118let OperandType = "OPERAND_I64IMM" in
119def i64imm_op : Operand<i64>;
120
121let OperandType = "OPERAND_F32IMM" in
122def f32imm_op : Operand<f32>;
123
124let OperandType = "OPERAND_F64IMM" in
125def f64imm_op : Operand<f64>;
126
127let OperandType = "OPERAND_VEC_I8IMM" in
128def vec_i8imm_op : Operand<i32>;
129
130let OperandType = "OPERAND_VEC_I16IMM" in
131def vec_i16imm_op : Operand<i32>;
132
133let OperandType = "OPERAND_VEC_I32IMM" in
134def vec_i32imm_op : Operand<i32>;
135
136let OperandType = "OPERAND_VEC_I64IMM" in
137def vec_i64imm_op : Operand<i64>;
138
139let OperandType = "OPERAND_FUNCTION32" in
140def function32_op : Operand<i32>;
141
142let OperandType = "OPERAND_OFFSET32" in
143def offset32_op : Operand<i32>;
144
145let OperandType = "OPERAND_P2ALIGN" in {
146def P2Align : Operand<i32> {
147  let PrintMethod = "printWebAssemblyP2AlignOperand";
148}
149
150let OperandType = "OPERAND_EVENT" in
151def event_op : Operand<i32>;
152
153} // OperandType = "OPERAND_P2ALIGN"
154
155let OperandType = "OPERAND_SIGNATURE" in {
156def Signature : Operand<i32> {
157  let PrintMethod = "printWebAssemblySignatureOperand";
158}
159} // OperandType = "OPERAND_SIGNATURE"
160
161let OperandType = "OPERAND_TYPEINDEX" in
162def TypeIndex : Operand<i32>;
163
164} // OperandNamespace = "WebAssembly"
165
166//===----------------------------------------------------------------------===//
167// WebAssembly Register to Stack instruction mapping
168//===----------------------------------------------------------------------===//
169
170class StackRel;
171def getStackOpcode : InstrMapping {
172  let FilterClass = "StackRel";
173  let RowFields = ["BaseName"];
174  let ColFields = ["StackBased"];
175  let KeyCol = ["false"];
176  let ValueCols = [["true"]];
177}
178
179//===----------------------------------------------------------------------===//
180// WebAssembly Instruction Format Definitions.
181//===----------------------------------------------------------------------===//
182
183include "WebAssemblyInstrFormats.td"
184
185//===----------------------------------------------------------------------===//
186// Additional instructions.
187//===----------------------------------------------------------------------===//
188
189multiclass ARGUMENT<WebAssemblyRegClass reg, ValueType vt> {
190  let hasSideEffects = 1, isCodeGenOnly = 1,
191      Defs = []<Register>, Uses = [ARGUMENTS] in
192  defm ARGUMENT_#vt :
193    I<(outs reg:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno),
194      [(set (vt reg:$res), (WebAssemblyargument timm:$argno))]>;
195}
196defm "": ARGUMENT<I32, i32>;
197defm "": ARGUMENT<I64, i64>;
198defm "": ARGUMENT<F32, f32>;
199defm "": ARGUMENT<F64, f64>;
200defm "": ARGUMENT<EXCEPT_REF, ExceptRef>;
201
202// local.get and local.set are not generated by instruction selection; they
203// are implied by virtual register uses and defs.
204multiclass LOCAL<WebAssemblyRegClass vt> {
205let hasSideEffects = 0 in {
206  // COPY is not an actual instruction in wasm, but since we allow local.get and
207  // local.set to be implicit during most of codegen, we can have a COPY which
208  // is actually a no-op because all the work is done in the implied local.get
209  // and local.set. COPYs are eliminated (and replaced with
210  // local.get/local.set) in the ExplicitLocals pass.
211  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
212  defm COPY_#vt : I<(outs vt:$res), (ins vt:$src), (outs), (ins), [],
213                    "local.copy\t$res, $src", "local.copy">;
214
215  // TEE is similar to COPY, but writes two copies of its result. Typically
216  // this would be used to stackify one result and write the other result to a
217  // local.
218  let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in
219  defm TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), (outs), (ins), [],
220                   "local.tee\t$res, $also, $src", "local.tee">;
221
222  // This is the actual local.get instruction in wasm. These are made explicit
223  // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm
224  // local, which is a side effect not otherwise modeled in LLVM.
225  let mayLoad = 1, isAsCheapAsAMove = 1 in
226  defm LOCAL_GET_#vt : I<(outs vt:$res), (ins local_op:$local),
227                         (outs), (ins local_op:$local), [],
228                         "local.get\t$res, $local", "local.get\t$local", 0x20>;
229
230  // This is the actual local.set instruction in wasm. These are made explicit
231  // by the ExplicitLocals pass. It has mayStore because it writes to a wasm
232  // local, which is a side effect not otherwise modeled in LLVM.
233  let mayStore = 1, isAsCheapAsAMove = 1 in
234  defm LOCAL_SET_#vt : I<(outs), (ins local_op:$local, vt:$src),
235                         (outs), (ins local_op:$local), [],
236                         "local.set\t$local, $src", "local.set\t$local", 0x21>;
237
238  // This is the actual local.tee instruction in wasm. TEEs are turned into
239  // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason
240  // as LOCAL_SET.
241  let mayStore = 1, isAsCheapAsAMove = 1 in
242  defm LOCAL_TEE_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src),
243                         (outs), (ins local_op:$local), [],
244                         "local.tee\t$res, $local, $src", "local.tee\t$local",
245                         0x22>;
246
247  // Unused values must be dropped in some contexts.
248  defm DROP_#vt : I<(outs), (ins vt:$src), (outs), (ins), [],
249                    "drop\t$src", "drop", 0x1a>;
250
251  let mayLoad = 1 in
252  defm GLOBAL_GET_#vt : I<(outs vt:$res), (ins global_op:$local),
253                          (outs), (ins global_op:$local), [],
254                          "global.get\t$res, $local", "global.get\t$local",
255                          0x23>;
256
257  let mayStore = 1 in
258  defm GLOBAL_SET_#vt : I<(outs), (ins global_op:$local, vt:$src),
259                          (outs), (ins global_op:$local), [],
260                          "global.set\t$local, $src", "global.set\t$local",
261                          0x24>;
262
263} // hasSideEffects = 0
264}
265defm "" : LOCAL<I32>;
266defm "" : LOCAL<I64>;
267defm "" : LOCAL<F32>;
268defm "" : LOCAL<F64>;
269defm "" : LOCAL<V128>, Requires<[HasSIMD128]>;
270defm "" : LOCAL<EXCEPT_REF>, Requires<[HasExceptionHandling]>;
271
272let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
273defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
274                   (outs), (ins i32imm_op:$imm),
275                   [(set I32:$res, imm:$imm)],
276                   "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>;
277defm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm),
278                   (outs), (ins i64imm_op:$imm),
279                   [(set I64:$res, imm:$imm)],
280                   "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>;
281defm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm),
282                   (outs), (ins f32imm_op:$imm),
283                   [(set F32:$res, fpimm:$imm)],
284                   "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>;
285defm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm),
286                   (outs), (ins f64imm_op:$imm),
287                   [(set F64:$res, fpimm:$imm)],
288                   "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>;
289} // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1
290
291def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)),
292          (CONST_I32 tglobaladdr:$addr)>;
293def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
294          (CONST_I32 texternalsym:$addr)>;
295def : Pat<(i32 (WebAssemblywrapper mcsym:$sym)), (CONST_I32 mcsym:$sym)>;
296def : Pat<(i64 (WebAssemblywrapper mcsym:$sym)), (CONST_I64 mcsym:$sym)>;
297
298//===----------------------------------------------------------------------===//
299// Additional sets of instructions.
300//===----------------------------------------------------------------------===//
301
302include "WebAssemblyInstrMemory.td"
303include "WebAssemblyInstrCall.td"
304include "WebAssemblyInstrControl.td"
305include "WebAssemblyInstrInteger.td"
306include "WebAssemblyInstrConv.td"
307include "WebAssemblyInstrFloat.td"
308include "WebAssemblyInstrAtomics.td"
309include "WebAssemblyInstrSIMD.td"
310include "WebAssemblyInstrExceptRef.td"
311