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