summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
blob: 403152c80660925b5560754b37464df60d7b7f21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//=- WebAssemblyInstrFormats.td - WebAssembly Instr. Formats -*- tablegen -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// WebAssembly instruction format definitions.
///
//===----------------------------------------------------------------------===//

// WebAssembly Instruction Format.
// We instantiate 2 of these for every actual instruction (register based
// and stack based), see below.
class WebAssemblyInst<bits<32> inst, string asmstr, bit stack> : Instruction {
  field bits<32> Inst = inst; // Instruction encoding.
  field bit StackBased = stack;
  let Namespace   = "WebAssembly";
  let Pattern     = [];
  let AsmString   = asmstr;
}

// Normal instructions. Default instantiation of a WebAssemblyInst.
class NI<dag oops, dag iops, list<dag> pattern, bit stack, string asmstr = "",
         bits<32> inst = -1>
    : WebAssemblyInst<inst, asmstr, stack> {
  dag OutOperandList = oops;
  dag InOperandList  = iops;
  let Pattern        = pattern;
}

// Generates both register and stack based versions of one actual instruction.
// We have 2 sets of operands (oops & iops) for the register and stack
// based version of this instruction, as well as the corresponding asmstr.
// The register versions have virtual-register operands which correspond to wasm
// locals or stack locations. Each use and def of the register corresponds to an
// implicit get_local / set_local or access of stack operands in wasm. These
// instructions are used for ISel and all MI passes. The stack versions of the
// instructions do not have register operands (they implicitly operate on the
// stack), and get_locals and set_locals are explicit. The register instructions
// are converted to their corresponding stack instructions before lowering to
// MC.
// Every instruction should want to be based on this multi-class to guarantee
// there is always an equivalent pair of instructions.
multiclass I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
             list<dag> pattern_r, string asmstr_r = "", string asmstr_s = "",
             bits<32> inst = -1> {
  def "" : NI<oops_r, iops_r, pattern_r, 0, asmstr_r, inst>;
  def _S : NI<oops_s, iops_s, [], 1, asmstr_s, inst>;
}

// For instructions that have no register ops, so both sets are the same.
multiclass NRI<dag oops, dag iops, list<dag> pattern, string asmstr = "",
               bits<32> inst = -1> {
  defm "": I<oops, iops, oops, iops, pattern, asmstr, asmstr, inst>;
}

multiclass SIMD_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
                  list<dag> pattern_r, string asmstr_r = "",
                  string asmstr_s = "", bits<32> inst = -1> {
  defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s,
              inst>,
            Requires<[HasSIMD128]>;
}

multiclass ATOMIC_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
                    list<dag> pattern_r, string asmstr_r = "",
                    string asmstr_s = "", bits<32> inst = -1> {
  defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s,
              inst>,
            Requires<[HasAtomics]>;
}

// Unary and binary instructions, for the local types that WebAssembly supports.
multiclass UnaryInt<SDNode node, string name, bits<32> i32Inst,
                    bits<32> i64Inst> {
  defm _I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins),
                [(set I32:$dst, (node I32:$src))],
                !strconcat("i32.", !strconcat(name, "\t$dst, $src")),
                !strconcat("i32.", name), i32Inst>;
  defm _I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins),
                [(set I64:$dst, (node I64:$src))],
                !strconcat("i64.", !strconcat(name, "\t$dst, $src")),
                !strconcat("i64.", name), i64Inst>;
}
multiclass BinaryInt<SDNode node, string name, bits<32> i32Inst,
                     bits<32> i64Inst> {
  defm _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), (outs), (ins),
                [(set I32:$dst, (node I32:$lhs, I32:$rhs))],
                !strconcat("i32.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("i32.", name), i32Inst>;
  defm _I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs), (outs), (ins),
                [(set I64:$dst, (node I64:$lhs, I64:$rhs))],
                !strconcat("i64.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("i64.", name), i64Inst>;
}
multiclass UnaryFP<SDNode node, string name, bits<32> f32Inst,
                   bits<32> f64Inst> {
  defm _F32 : I<(outs F32:$dst), (ins F32:$src), (outs), (ins),
                [(set F32:$dst, (node F32:$src))],
                !strconcat("f32.", !strconcat(name, "\t$dst, $src")),
                !strconcat("f32.", name), f32Inst>;
  defm _F64 : I<(outs F64:$dst), (ins F64:$src), (outs), (ins),
                [(set F64:$dst, (node F64:$src))],
                !strconcat("f64.", !strconcat(name, "\t$dst, $src")),
                !strconcat("f64.", name), f64Inst>;
}
multiclass BinaryFP<SDNode node, string name, bits<32> f32Inst,
                    bits<32> f64Inst> {
  defm _F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs), (outs), (ins),
                [(set F32:$dst, (node F32:$lhs, F32:$rhs))],
                !strconcat("f32.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("f32.", name), f32Inst>;
  defm _F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs), (outs), (ins),
                [(set F64:$dst, (node F64:$lhs, F64:$rhs))],
                !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("f64.", name), f64Inst>;
}
multiclass SIMDBinary<SDNode node, SDNode fnode, string name> {
  defm _I8x16 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs),
                       (outs), (ins),
                       [(set (v16i8 V128:$dst), (node V128:$lhs, V128:$rhs))],
                       !strconcat("i8x16.",
                         !strconcat(name, "\t$dst, $lhs, $rhs")),
                       !strconcat("i8x16.", name)>;
  defm _I16x8 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs),
                       (outs), (ins),
                       [(set (v8i16 V128:$dst), (node V128:$lhs, V128:$rhs))],
                       !strconcat("i16x8.",
                         !strconcat(name, "\t$dst, $lhs, $rhs")),
                       !strconcat("i16x8.", name)>;
  defm _I32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs),
                       (outs), (ins),
                       [(set (v4i32 V128:$dst), (node V128:$lhs, V128:$rhs))],
                       !strconcat("i32x4.",
                         !strconcat(name, "\t$dst, $lhs, $rhs")),
                       !strconcat("i32x4.", name)>;
  defm _F32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs),
                       (outs), (ins),
                       [(set (v4f32 V128:$dst), (fnode V128:$lhs, V128:$rhs))],
                       !strconcat("f32x4.",
                         !strconcat(name, "\t$dst, $lhs, $rhs")),
                       !strconcat("f32x4.", name)>;
}
multiclass ComparisonInt<CondCode cond, string name, bits<32> i32Inst, bits<32> i64Inst> {
  defm _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), (outs), (ins),
                [(set I32:$dst, (setcc I32:$lhs, I32:$rhs, cond))],
                !strconcat("i32.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("i32.", name), i32Inst>;
  defm _I64 : I<(outs I32:$dst), (ins I64:$lhs, I64:$rhs), (outs), (ins),
                [(set I32:$dst, (setcc I64:$lhs, I64:$rhs, cond))],
                !strconcat("i64.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("i64.", name), i64Inst>;
}
multiclass ComparisonFP<CondCode cond, string name, bits<32> f32Inst, bits<32> f64Inst> {
  defm _F32 : I<(outs I32:$dst), (ins F32:$lhs, F32:$rhs), (outs), (ins),
                [(set I32:$dst, (setcc F32:$lhs, F32:$rhs, cond))],
                !strconcat("f32.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("f32.", name), f32Inst>;
  defm  _F64 : I<(outs I32:$dst), (ins F64:$lhs, F64:$rhs), (outs), (ins),
                [(set I32:$dst, (setcc F64:$lhs, F64:$rhs, cond))],
                !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")),
                !strconcat("f64.", name), f64Inst>;
}
OpenPOWER on IntegriCloud