xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric///
90b57cec5SDimitry Andric/// \file
100b57cec5SDimitry Andric/// WebAssembly Memory operand code-gen constructs.
110b57cec5SDimitry Andric///
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric// TODO:
150b57cec5SDimitry Andric//  - WebAssemblyTargetLowering having to do with atomics
160b57cec5SDimitry Andric//  - Each has optional alignment.
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16
190b57cec5SDimitry Andric// local types. These memory-only types instead zero- or sign-extend into local
200b57cec5SDimitry Andric// types when loading, and truncate when storing.
210b57cec5SDimitry Andric
22bdd1243dSDimitry Andric// Address Operands
230b57cec5SDimitry Andric
24bdd1243dSDimitry Andric// These patterns match the static (offset) and dynamic (address stack operand)
25bdd1243dSDimitry Andric// operands for loads and stores, based on a combination of target global
26bdd1243dSDimitry Andric// addresses and constants.
27bdd1243dSDimitry Andric// For example,
28bdd1243dSDimitry Andric// (load (add tga, x))   -> load offset=tga, addr=x
29bdd1243dSDimitry Andric// (store v, tga)        -> store v, offset=tga, addr=0
30bdd1243dSDimitry Andric// (load (add const, x)) -> load offset=const, addr=x
31bdd1243dSDimitry Andric// (store v, const)      -> store v, offset=const, addr=0
32bdd1243dSDimitry Andric// (load x)              -> load offset=0, addr=x
33bdd1243dSDimitry Andricdef AddrOps32 : ComplexPattern<i32, 2, "SelectAddrOperands32">;
34bdd1243dSDimitry Andricdef AddrOps64 : ComplexPattern<i64, 2, "SelectAddrOperands64">;
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric// Defines atomic and non-atomic loads, regular and extending.
375ffd83dbSDimitry Andricmulticlass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode,
385ffd83dbSDimitry Andric                           list<Predicate> reqs = []> {
395ffd83dbSDimitry Andric  let mayLoad = 1, UseNamedOperandTable = 1 in {
405ffd83dbSDimitry Andric  defm "_A32": I<(outs rc:$dst),
410b57cec5SDimitry Andric                 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
420b57cec5SDimitry Andric                 (outs), (ins P2Align:$p2align, offset32_op:$off),
430b57cec5SDimitry Andric                 [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
4481ad6265SDimitry Andric                 !strconcat(Name, "\t${off}${p2align}"), Opcode, false>,
455ffd83dbSDimitry Andric               Requires<reqs>;
465ffd83dbSDimitry Andric  defm "_A64": I<(outs rc:$dst),
475ffd83dbSDimitry Andric                 (ins P2Align:$p2align, offset64_op:$off, I64:$addr),
485ffd83dbSDimitry Andric                 (outs), (ins P2Align:$p2align, offset64_op:$off),
495ffd83dbSDimitry Andric                 [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
5081ad6265SDimitry Andric                 !strconcat(Name, "\t${off}${p2align}"), Opcode, true>,
515ffd83dbSDimitry Andric               Requires<reqs>;
525ffd83dbSDimitry Andric  }
530b57cec5SDimitry Andric}
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric// Basic load.
560b57cec5SDimitry Andric// FIXME: When we can break syntax compatibility, reorder the fields in the
570b57cec5SDimitry Andric// asmstrings to match the binary encoding.
585ffd83dbSDimitry Andricdefm LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28, []>;
595ffd83dbSDimitry Andricdefm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29, []>;
605ffd83dbSDimitry Andricdefm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a, []>;
615ffd83dbSDimitry Andricdefm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b, []>;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric// Extending load.
645ffd83dbSDimitry Andricdefm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c, []>;
655ffd83dbSDimitry Andricdefm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d, []>;
665ffd83dbSDimitry Andricdefm LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e, []>;
675ffd83dbSDimitry Andricdefm LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f, []>;
685ffd83dbSDimitry Andricdefm LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30, []>;
695ffd83dbSDimitry Andricdefm LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31, []>;
705ffd83dbSDimitry Andricdefm LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32, []>;
715ffd83dbSDimitry Andricdefm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33, []>;
725ffd83dbSDimitry Andricdefm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34, []>;
735ffd83dbSDimitry Andricdefm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35, []>;
740b57cec5SDimitry Andric
75*0fca6ea1SDimitry Andric// Half-precision load.
76*0fca6ea1SDimitry Andricdefm LOAD_F16_F32 :
77*0fca6ea1SDimitry Andric  WebAssemblyLoad<F32, "f32.load_f16", 0xfc30, [HasHalfPrecision]>;
78*0fca6ea1SDimitry Andric
79bdd1243dSDimitry Andric// Pattern matching
800b57cec5SDimitry Andric
81bdd1243dSDimitry Andricmulticlass LoadPat<ValueType ty, SDPatternOperator kind, string Name> {
82bdd1243dSDimitry Andric      def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr))),
83bdd1243dSDimitry Andric           (!cast<NI>(Name # "_A32") 0,
84bdd1243dSDimitry Andric                                     offset32_op:$offset,
85bdd1243dSDimitry Andric                                     I32:$addr)>,
86bdd1243dSDimitry Andric                                     Requires<[HasAddr32]>;
870b57cec5SDimitry Andric
88bdd1243dSDimitry Andric      def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr))),
89bdd1243dSDimitry Andric           (!cast<NI>(Name # "_A64") 0,
90bdd1243dSDimitry Andric                                     offset64_op:$offset,
91bdd1243dSDimitry Andric                                     I64:$addr)>,
92bdd1243dSDimitry Andric                                     Requires<[HasAddr64]>;
93bdd1243dSDimitry Andric}
940b57cec5SDimitry Andric
95bdd1243dSDimitry Andricdefm : LoadPat<i32, load, "LOAD_I32">;
96bdd1243dSDimitry Andricdefm : LoadPat<i64, load, "LOAD_I64">;
97bdd1243dSDimitry Andricdefm : LoadPat<f32, load, "LOAD_F32">;
98bdd1243dSDimitry Andricdefm : LoadPat<f64, load, "LOAD_F64">;
990b57cec5SDimitry Andric
100bdd1243dSDimitry Andricdefm : LoadPat<i32, sextloadi8, "LOAD8_S_I32">;
101bdd1243dSDimitry Andricdefm : LoadPat<i32, sextloadi16, "LOAD16_S_I32">;
102bdd1243dSDimitry Andricdefm : LoadPat<i64, sextloadi8, "LOAD8_S_I64">;
103bdd1243dSDimitry Andricdefm : LoadPat<i64, sextloadi16, "LOAD16_S_I64">;
104bdd1243dSDimitry Andricdefm : LoadPat<i64, sextloadi32, "LOAD32_S_I64">;
1050b57cec5SDimitry Andric
106bdd1243dSDimitry Andricdefm : LoadPat<i32, zextloadi8, "LOAD8_U_I32">;
107bdd1243dSDimitry Andricdefm : LoadPat<i32, zextloadi16, "LOAD16_U_I32">;
108bdd1243dSDimitry Andricdefm : LoadPat<i64, zextloadi8, "LOAD8_U_I64">;
109bdd1243dSDimitry Andricdefm : LoadPat<i64, zextloadi16, "LOAD16_U_I64">;
110bdd1243dSDimitry Andricdefm : LoadPat<i64, zextloadi32, "LOAD32_U_I64">;
1110b57cec5SDimitry Andric
112bdd1243dSDimitry Andricdefm : LoadPat<i32, extloadi8, "LOAD8_U_I32">;
113bdd1243dSDimitry Andricdefm : LoadPat<i32, extloadi16, "LOAD16_U_I32">;
114bdd1243dSDimitry Andricdefm : LoadPat<i64, extloadi8, "LOAD8_U_I64">;
115bdd1243dSDimitry Andricdefm : LoadPat<i64, extloadi16, "LOAD16_U_I64">;
116bdd1243dSDimitry Andricdefm : LoadPat<i64, extloadi32, "LOAD32_U_I64">;
1170b57cec5SDimitry Andric
118*0fca6ea1SDimitry Andricdefm : LoadPat<f32, int_wasm_loadf16_f32, "LOAD_F16_F32">;
119*0fca6ea1SDimitry Andric
1200b57cec5SDimitry Andric// Defines atomic and non-atomic stores, regular and truncating
1215ffd83dbSDimitry Andricmulticlass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode,
1225ffd83dbSDimitry Andric                            list<Predicate> reqs = []> {
1230b57cec5SDimitry Andric  let mayStore = 1, UseNamedOperandTable = 1 in
1245ffd83dbSDimitry Andric  defm "_A32" : I<(outs),
1250b57cec5SDimitry Andric                  (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
1260b57cec5SDimitry Andric                  (outs),
1270b57cec5SDimitry Andric                  (ins P2Align:$p2align, offset32_op:$off), [],
1280b57cec5SDimitry Andric                  !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
12981ad6265SDimitry Andric                  !strconcat(Name, "\t${off}${p2align}"), Opcode, false>,
1305ffd83dbSDimitry Andric                Requires<reqs>;
1315ffd83dbSDimitry Andric  let mayStore = 1, UseNamedOperandTable = 1 in
1325ffd83dbSDimitry Andric  defm "_A64" : I<(outs),
1335ffd83dbSDimitry Andric                  (ins P2Align:$p2align, offset64_op:$off, I64:$addr, rc:$val),
1345ffd83dbSDimitry Andric                  (outs),
1355ffd83dbSDimitry Andric                  (ins P2Align:$p2align, offset64_op:$off), [],
1365ffd83dbSDimitry Andric                  !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
13781ad6265SDimitry Andric                  !strconcat(Name, "\t${off}${p2align}"), Opcode, true>,
1385ffd83dbSDimitry Andric                Requires<reqs>;
1390b57cec5SDimitry Andric}
1405ffd83dbSDimitry Andric
1410b57cec5SDimitry Andric// Basic store.
1420b57cec5SDimitry Andric// Note: WebAssembly inverts SelectionDAG's usual operand order.
1430b57cec5SDimitry Andricdefm STORE_I32  : WebAssemblyStore<I32, "i32.store", 0x36>;
1440b57cec5SDimitry Andricdefm STORE_I64  : WebAssemblyStore<I64, "i64.store", 0x37>;
1450b57cec5SDimitry Andricdefm STORE_F32  : WebAssemblyStore<F32, "f32.store", 0x38>;
1460b57cec5SDimitry Andricdefm STORE_F64  : WebAssemblyStore<F64, "f64.store", 0x39>;
1470b57cec5SDimitry Andric
148bdd1243dSDimitry Andricmulticlass StorePat<ValueType ty, SDPatternOperator kind, string Name> {
149bdd1243dSDimitry Andric  def : Pat<(kind ty:$val, (AddrOps32 offset32_op:$offset, I32:$addr)),
150bdd1243dSDimitry Andric            (!cast<NI>(Name # "_A32") 0,
151bdd1243dSDimitry Andric                                      offset32_op:$offset,
152bdd1243dSDimitry Andric                                      I32:$addr,
1535ffd83dbSDimitry Andric                                      ty:$val)>,
154bdd1243dSDimitry Andric            Requires<[HasAddr32]>;
155bdd1243dSDimitry Andric  def : Pat<(kind ty:$val, (AddrOps64 offset64_op:$offset, I64:$addr)),
156bdd1243dSDimitry Andric            (!cast<NI>(Name # "_A64") 0,
157bdd1243dSDimitry Andric                                      offset64_op:$offset,
158bdd1243dSDimitry Andric                                      I64:$addr,
1595ffd83dbSDimitry Andric                                      ty:$val)>,
160bdd1243dSDimitry Andric            Requires<[HasAddr64]>;
1615ffd83dbSDimitry Andric}
162bdd1243dSDimitry Andric
163bdd1243dSDimitry Andricdefm : StorePat<i32, store, "STORE_I32">;
164bdd1243dSDimitry Andricdefm : StorePat<i64, store, "STORE_I64">;
165bdd1243dSDimitry Andricdefm : StorePat<f32, store, "STORE_F32">;
166bdd1243dSDimitry Andricdefm : StorePat<f64, store, "STORE_F64">;
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric// Truncating store.
1690b57cec5SDimitry Andricdefm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>;
1700b57cec5SDimitry Andricdefm STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>;
1710b57cec5SDimitry Andricdefm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>;
1720b57cec5SDimitry Andricdefm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>;
1730b57cec5SDimitry Andricdefm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>;
1740b57cec5SDimitry Andric
175*0fca6ea1SDimitry Andric// Half-precision store.
176*0fca6ea1SDimitry Andricdefm STORE_F16_F32 :
177*0fca6ea1SDimitry Andric  WebAssemblyStore<F32, "f32.store_f16", 0xfc31, [HasHalfPrecision]>;
178*0fca6ea1SDimitry Andric
179bdd1243dSDimitry Andricdefm : StorePat<i32, truncstorei8, "STORE8_I32">;
180bdd1243dSDimitry Andricdefm : StorePat<i32, truncstorei16, "STORE16_I32">;
181bdd1243dSDimitry Andricdefm : StorePat<i64, truncstorei8, "STORE8_I64">;
182bdd1243dSDimitry Andricdefm : StorePat<i64, truncstorei16, "STORE16_I64">;
183bdd1243dSDimitry Andricdefm : StorePat<i64, truncstorei32, "STORE32_I64">;
1840b57cec5SDimitry Andric
185*0fca6ea1SDimitry Andricdefm : StorePat<f32, int_wasm_storef16_f32, "STORE_F16_F32">;
186*0fca6ea1SDimitry Andric
1875ffd83dbSDimitry Andricmulticlass MemoryOps<WebAssemblyRegClass rc, string B> {
1880b57cec5SDimitry Andric// Current memory size.
1895ffd83dbSDimitry Andricdefm MEMORY_SIZE_A#B : I<(outs rc:$dst), (ins i32imm:$flags),
1900b57cec5SDimitry Andric                         (outs), (ins i32imm:$flags),
1915ffd83dbSDimitry Andric                         [(set rc:$dst,
1920b57cec5SDimitry Andric                           (int_wasm_memory_size (i32 imm:$flags)))],
1930b57cec5SDimitry Andric                         "memory.size\t$dst, $flags", "memory.size\t$flags",
1945ffd83dbSDimitry Andric                         0x3f>;
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric// Grow memory.
1975ffd83dbSDimitry Andricdefm MEMORY_GROW_A#B : I<(outs rc:$dst), (ins i32imm:$flags, rc:$delta),
1980b57cec5SDimitry Andric                         (outs), (ins i32imm:$flags),
1995ffd83dbSDimitry Andric                         [(set rc:$dst,
2000b57cec5SDimitry Andric                           (int_wasm_memory_grow (i32 imm:$flags),
2015ffd83dbSDimitry Andric                             rc:$delta))],
2020b57cec5SDimitry Andric                         "memory.grow\t$dst, $flags, $delta",
2035ffd83dbSDimitry Andric                         "memory.grow\t$flags", 0x40>;
2045ffd83dbSDimitry Andric}
2055ffd83dbSDimitry Andric
2065ffd83dbSDimitry Andricdefm : MemoryOps<I32, "32">;
2075ffd83dbSDimitry Andricdefm : MemoryOps<I64, "64">;
208