10b57cec5SDimitry Andric// WebAssemblyInstrInfo.td-Describe the WebAssembly Instructions-*- 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 Instruction definitions. 110b57cec5SDimitry Andric/// 120b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric// WebAssembly Instruction Predicate Definitions. 160b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 180b57cec5SDimitry Andricdef IsPIC : Predicate<"TM.isPositionIndependent()">; 190b57cec5SDimitry Andricdef IsNotPIC : Predicate<"!TM.isPositionIndependent()">; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andricdef HasAddr32 : Predicate<"!Subtarget->hasAddr64()">; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andricdef HasAddr64 : Predicate<"Subtarget->hasAddr64()">; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andricdef HasSIMD128 : 260b57cec5SDimitry Andric Predicate<"Subtarget->hasSIMD128()">, 275ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureSIMD128), "simd128">; 280b57cec5SDimitry Andric 29*349cc55cSDimitry Andricdef HasRelaxedSIMD : 30*349cc55cSDimitry Andric Predicate<"Subtarget->hasRelaxedSIMD()">, 31*349cc55cSDimitry Andric AssemblerPredicate<(all_of FeatureRelaxedSIMD), "relaxed-simd">; 32*349cc55cSDimitry Andric 330b57cec5SDimitry Andricdef HasAtomics : 340b57cec5SDimitry Andric Predicate<"Subtarget->hasAtomics()">, 355ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureAtomics), "atomics">; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andricdef HasMultivalue : 380b57cec5SDimitry Andric Predicate<"Subtarget->hasMultivalue()">, 395ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureMultivalue), "multivalue">; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andricdef HasNontrappingFPToInt : 420b57cec5SDimitry Andric Predicate<"Subtarget->hasNontrappingFPToInt()">, 435ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureNontrappingFPToInt), "nontrapping-fptoint">; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andricdef NotHasNontrappingFPToInt : 460b57cec5SDimitry Andric Predicate<"!Subtarget->hasNontrappingFPToInt()">, 475ffd83dbSDimitry Andric AssemblerPredicate<(all_of (not FeatureNontrappingFPToInt)), "nontrapping-fptoint">; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andricdef HasSignExt : 500b57cec5SDimitry Andric Predicate<"Subtarget->hasSignExt()">, 515ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureSignExt), "sign-ext">; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andricdef HasTailCall : 540b57cec5SDimitry Andric Predicate<"Subtarget->hasTailCall()">, 555ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureTailCall), "tail-call">; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andricdef HasExceptionHandling : 580b57cec5SDimitry Andric Predicate<"Subtarget->hasExceptionHandling()">, 595ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andricdef HasBulkMemory : 620b57cec5SDimitry Andric Predicate<"Subtarget->hasBulkMemory()">, 635ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">; 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andricdef HasReferenceTypes : 665ffd83dbSDimitry Andric Predicate<"Subtarget->hasReferenceTypes()">, 675ffd83dbSDimitry Andric AssemblerPredicate<(all_of FeatureReferenceTypes), "reference-types">; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 700b57cec5SDimitry Andric// WebAssembly-specific DAG Node Types. 710b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 720b57cec5SDimitry Andric 730b57cec5SDimitry Andricdef SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>, 740b57cec5SDimitry Andric SDTCisVT<1, iPTR>]>; 750b57cec5SDimitry Andricdef SDT_WebAssemblyCallSeqEnd : 760b57cec5SDimitry Andric SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; 770b57cec5SDimitry Andricdef SDT_WebAssemblyBrTable : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>; 780b57cec5SDimitry Andricdef SDT_WebAssemblyArgument : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>; 79fe6060f1SDimitry Andricdef SDT_WebAssemblyLocalGet : SDTypeProfile<1, 1, [SDTCisVT<1, i32>]>; 80fe6060f1SDimitry Andricdef SDT_WebAssemblyLocalSet : SDTypeProfile<0, 2, [SDTCisVT<0, i32>]>; 810b57cec5SDimitry Andricdef SDT_WebAssemblyReturn : SDTypeProfile<0, -1, []>; 820b57cec5SDimitry Andricdef SDT_WebAssemblyWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, 830b57cec5SDimitry Andric SDTCisPtrTy<0>]>; 84fe6060f1SDimitry Andricdef SDT_WebAssemblyGlobalGet : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>; 85fe6060f1SDimitry Andricdef SDT_WebAssemblyGlobalSet : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 880b57cec5SDimitry Andric// WebAssembly-specific DAG Nodes. 890b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 900b57cec5SDimitry Andric 910b57cec5SDimitry Andricdef WebAssemblycallseq_start : 920b57cec5SDimitry Andric SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart, 930b57cec5SDimitry Andric [SDNPHasChain, SDNPOutGlue]>; 940b57cec5SDimitry Andricdef WebAssemblycallseq_end : 950b57cec5SDimitry Andric SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd, 960b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 970b57cec5SDimitry Andricdef WebAssemblybr_table : SDNode<"WebAssemblyISD::BR_TABLE", 980b57cec5SDimitry Andric SDT_WebAssemblyBrTable, 990b57cec5SDimitry Andric [SDNPHasChain, SDNPVariadic]>; 1000b57cec5SDimitry Andricdef WebAssemblyargument : SDNode<"WebAssemblyISD::ARGUMENT", 1010b57cec5SDimitry Andric SDT_WebAssemblyArgument>; 1020b57cec5SDimitry Andricdef WebAssemblyreturn : SDNode<"WebAssemblyISD::RETURN", 1038bcb0991SDimitry Andric SDT_WebAssemblyReturn, 1048bcb0991SDimitry Andric [SDNPHasChain, SDNPVariadic]>; 105*349cc55cSDimitry Andricdef WebAssemblyWrapper : SDNode<"WebAssemblyISD::Wrapper", 1060b57cec5SDimitry Andric SDT_WebAssemblyWrapper>; 107*349cc55cSDimitry Andricdef WebAssemblyWrapperREL : SDNode<"WebAssemblyISD::WrapperREL", 108*349cc55cSDimitry Andric SDT_WebAssemblyWrapper>; 109fe6060f1SDimitry Andricdef WebAssemblyglobal_get : 110fe6060f1SDimitry Andric SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet, 111fe6060f1SDimitry Andric [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 112fe6060f1SDimitry Andricdef WebAssemblyglobal_set : 113fe6060f1SDimitry Andric SDNode<"WebAssemblyISD::GLOBAL_SET", SDT_WebAssemblyGlobalSet, 114fe6060f1SDimitry Andric [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 115fe6060f1SDimitry Andricdef WebAssemblylocal_get : 116fe6060f1SDimitry Andric SDNode<"WebAssemblyISD::LOCAL_GET", SDT_WebAssemblyLocalGet, 117fe6060f1SDimitry Andric [SDNPHasChain, SDNPMayLoad]>; 118fe6060f1SDimitry Andricdef WebAssemblylocal_set : 119fe6060f1SDimitry Andric SDNode<"WebAssemblyISD::LOCAL_SET", SDT_WebAssemblyLocalSet, 120fe6060f1SDimitry Andric [SDNPHasChain, SDNPMayStore]>; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1230b57cec5SDimitry Andric// WebAssembly-specific Operands. 1240b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric// Default Operand has AsmOperandClass "Imm" which is for integers (and 1270b57cec5SDimitry Andric// symbols), so specialize one for floats: 128fe6060f1SDimitry Andricclass FPImmAsmOperand<ValueType ty> : AsmOperandClass { 129fe6060f1SDimitry Andric let Name = "FPImm" # ty; 1300b57cec5SDimitry Andric let PredicateMethod = "isFPImm"; 1310b57cec5SDimitry Andric} 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andricclass FPOperand<ValueType ty> : Operand<ty> { 134fe6060f1SDimitry Andric AsmOperandClass ParserMatchClass = FPImmAsmOperand<ty>; 1350b57cec5SDimitry Andric} 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andriclet OperandNamespace = "WebAssembly" in { 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andriclet OperandType = "OPERAND_BASIC_BLOCK" in 1400b57cec5SDimitry Andricdef bb_op : Operand<OtherVT>; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andriclet OperandType = "OPERAND_LOCAL" in 1430b57cec5SDimitry Andricdef local_op : Operand<i32>; 1440b57cec5SDimitry Andric 145fe6060f1SDimitry Andriclet OperandType = "OPERAND_GLOBAL" in { 146fe6060f1SDimitry Andric // The operand to global instructions is always a 32-bit index. 147fe6060f1SDimitry Andric def global_op32 : Operand<i32>; 148fe6060f1SDimitry Andric // In PIC mode however, we temporarily represent this index as an external 149fe6060f1SDimitry Andric // symbol, which to LLVM is a pointer, so in wasm64 mode it is easiest to 150fe6060f1SDimitry Andric // pretend we use a 64-bit index for it. 151fe6060f1SDimitry Andric def global_op64 : Operand<i64>; 152fe6060f1SDimitry Andric} 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andriclet OperandType = "OPERAND_I32IMM" in 1550b57cec5SDimitry Andricdef i32imm_op : Operand<i32>; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andriclet OperandType = "OPERAND_I64IMM" in 1580b57cec5SDimitry Andricdef i64imm_op : Operand<i64>; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andriclet OperandType = "OPERAND_F32IMM" in 1610b57cec5SDimitry Andricdef f32imm_op : FPOperand<f32>; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andriclet OperandType = "OPERAND_F64IMM" in 1640b57cec5SDimitry Andricdef f64imm_op : FPOperand<f64>; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I8IMM" in 1670b57cec5SDimitry Andricdef vec_i8imm_op : Operand<i32>; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I16IMM" in 1700b57cec5SDimitry Andricdef vec_i16imm_op : Operand<i32>; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I32IMM" in 1730b57cec5SDimitry Andricdef vec_i32imm_op : Operand<i32>; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andriclet OperandType = "OPERAND_VEC_I64IMM" in 1760b57cec5SDimitry Andricdef vec_i64imm_op : Operand<i64>; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andriclet OperandType = "OPERAND_FUNCTION32" in 1790b57cec5SDimitry Andricdef function32_op : Operand<i32>; 1800b57cec5SDimitry Andric 181e8d8bef9SDimitry Andriclet OperandType = "OPERAND_TABLE" in 182e8d8bef9SDimitry Andricdef table32_op : Operand<i32>; 183e8d8bef9SDimitry Andric 1840b57cec5SDimitry Andriclet OperandType = "OPERAND_OFFSET32" in 1850b57cec5SDimitry Andricdef offset32_op : Operand<i32>; 1860b57cec5SDimitry Andric 1875ffd83dbSDimitry Andriclet OperandType = "OPERAND_OFFSET64" in 1885ffd83dbSDimitry Andricdef offset64_op : Operand<i64>; 1895ffd83dbSDimitry Andric 1900b57cec5SDimitry Andriclet OperandType = "OPERAND_P2ALIGN" in { 1910b57cec5SDimitry Andricdef P2Align : Operand<i32> { 1920b57cec5SDimitry Andric let PrintMethod = "printWebAssemblyP2AlignOperand"; 1930b57cec5SDimitry Andric} 1940b57cec5SDimitry Andric 195fe6060f1SDimitry Andriclet OperandType = "OPERAND_TAG" in 196fe6060f1SDimitry Andricdef tag_op : Operand<i32>; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric} // OperandType = "OPERAND_P2ALIGN" 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andriclet OperandType = "OPERAND_SIGNATURE" in 2010b57cec5SDimitry Andricdef Signature : Operand<i32> { 2020b57cec5SDimitry Andric let PrintMethod = "printWebAssemblySignatureOperand"; 2030b57cec5SDimitry Andric} 2040b57cec5SDimitry Andric 205e8d8bef9SDimitry Andriclet OperandType = "OPERAND_HEAPTYPE" in 206e8d8bef9SDimitry Andricdef HeapType : Operand<i32> { 207e8d8bef9SDimitry Andric let PrintMethod = "printWebAssemblyHeapTypeOperand"; 208e8d8bef9SDimitry Andric} 209e8d8bef9SDimitry Andric 2100b57cec5SDimitry Andriclet OperandType = "OPERAND_TYPEINDEX" in 2110b57cec5SDimitry Andricdef TypeIndex : Operand<i32>; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric} // OperandNamespace = "WebAssembly" 2140b57cec5SDimitry Andric 215fe6060f1SDimitry Andric// TODO: Find more places to use this. 216fe6060f1SDimitry Andricdef bool_node : PatLeaf<(i32 I32:$cond), [{ 217fe6060f1SDimitry Andric return CurDAG->computeKnownBits(SDValue(N, 0)).countMinLeadingZeros() == 31; 218fe6060f1SDimitry Andric}]>; 219fe6060f1SDimitry Andric 2200b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2210b57cec5SDimitry Andric// WebAssembly Register to Stack instruction mapping 2220b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andricclass StackRel; 2250b57cec5SDimitry Andricdef getStackOpcode : InstrMapping { 2260b57cec5SDimitry Andric let FilterClass = "StackRel"; 2270b57cec5SDimitry Andric let RowFields = ["BaseName"]; 2280b57cec5SDimitry Andric let ColFields = ["StackBased"]; 2290b57cec5SDimitry Andric let KeyCol = ["false"]; 2300b57cec5SDimitry Andric let ValueCols = [["true"]]; 2310b57cec5SDimitry Andric} 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 234fe6060f1SDimitry Andric// WebAssembly Stack to Register instruction mapping 235fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andricclass RegisterRel; 238fe6060f1SDimitry Andricdef getRegisterOpcode : InstrMapping { 239fe6060f1SDimitry Andric let FilterClass = "RegisterRel"; 240fe6060f1SDimitry Andric let RowFields = ["BaseName"]; 241fe6060f1SDimitry Andric let ColFields = ["StackBased"]; 242fe6060f1SDimitry Andric let KeyCol = ["true"]; 243fe6060f1SDimitry Andric let ValueCols = [["false"]]; 244fe6060f1SDimitry Andric} 245fe6060f1SDimitry Andric 246fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 2475ffd83dbSDimitry Andric// WebAssembly 32 to 64-bit instruction mapping 2485ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 2495ffd83dbSDimitry Andric 2505ffd83dbSDimitry Andricclass Wasm64Rel; 2515ffd83dbSDimitry Andricdef getWasm64Opcode : InstrMapping { 2525ffd83dbSDimitry Andric let FilterClass = "Wasm64Rel"; 2535ffd83dbSDimitry Andric let RowFields = ["Wasm32Name"]; 2545ffd83dbSDimitry Andric let ColFields = ["IsWasm64"]; 2555ffd83dbSDimitry Andric let KeyCol = ["false"]; 2565ffd83dbSDimitry Andric let ValueCols = [["true"]]; 2575ffd83dbSDimitry Andric} 2585ffd83dbSDimitry Andric 2595ffd83dbSDimitry Andric//===----------------------------------------------------------------------===// 2600b57cec5SDimitry Andric// WebAssembly Instruction Format Definitions. 2610b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andricinclude "WebAssemblyInstrFormats.td" 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2660b57cec5SDimitry Andric// Additional instructions. 2670b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2680b57cec5SDimitry Andric 269fe6060f1SDimitry Andricmulticlass ARGUMENT<WebAssemblyRegClass rc, ValueType vt> { 2700b57cec5SDimitry Andric let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>, 2710b57cec5SDimitry Andric Uses = [ARGUMENTS] in 2720b57cec5SDimitry Andric defm ARGUMENT_#vt : 273fe6060f1SDimitry Andric I<(outs rc:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno), 274fe6060f1SDimitry Andric [(set (vt rc:$res), (WebAssemblyargument timm:$argno))]>; 2750b57cec5SDimitry Andric} 2760b57cec5SDimitry Andricdefm "": ARGUMENT<I32, i32>; 2770b57cec5SDimitry Andricdefm "": ARGUMENT<I64, i64>; 2780b57cec5SDimitry Andricdefm "": ARGUMENT<F32, f32>; 2790b57cec5SDimitry Andricdefm "": ARGUMENT<F64, f64>; 280e8d8bef9SDimitry Andricdefm "": ARGUMENT<FUNCREF, funcref>; 281e8d8bef9SDimitry Andricdefm "": ARGUMENT<EXTERNREF, externref>; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric// local.get and local.set are not generated by instruction selection; they 2840b57cec5SDimitry Andric// are implied by virtual register uses and defs. 285fe6060f1SDimitry Andricmulticlass LOCAL<WebAssemblyRegClass rc, Operand global_op> { 2860b57cec5SDimitry Andric let hasSideEffects = 0 in { 2870b57cec5SDimitry Andric // COPY is not an actual instruction in wasm, but since we allow local.get and 2880b57cec5SDimitry Andric // local.set to be implicit during most of codegen, we can have a COPY which 2890b57cec5SDimitry Andric // is actually a no-op because all the work is done in the implied local.get 2900b57cec5SDimitry Andric // and local.set. COPYs are eliminated (and replaced with 2910b57cec5SDimitry Andric // local.get/local.set) in the ExplicitLocals pass. 2920b57cec5SDimitry Andric let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in 293fe6060f1SDimitry Andric defm COPY_#rc : I<(outs rc:$res), (ins rc:$src), (outs), (ins), [], 2940b57cec5SDimitry Andric "local.copy\t$res, $src", "local.copy">; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric // TEE is similar to COPY, but writes two copies of its result. Typically 2970b57cec5SDimitry Andric // this would be used to stackify one result and write the other result to a 2980b57cec5SDimitry Andric // local. 2990b57cec5SDimitry Andric let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in 300fe6060f1SDimitry Andric defm TEE_#rc : I<(outs rc:$res, rc:$also), (ins rc:$src), (outs), (ins), [], 3010b57cec5SDimitry Andric "local.tee\t$res, $also, $src", "local.tee">; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // This is the actual local.get instruction in wasm. These are made explicit 3040b57cec5SDimitry Andric // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm 3050b57cec5SDimitry Andric // local, which is a side effect not otherwise modeled in LLVM. 3060b57cec5SDimitry Andric let mayLoad = 1, isAsCheapAsAMove = 1 in 307fe6060f1SDimitry Andric defm LOCAL_GET_#rc : I<(outs rc:$res), (ins local_op:$local), 3080b57cec5SDimitry Andric (outs), (ins local_op:$local), [], 3090b57cec5SDimitry Andric "local.get\t$res, $local", "local.get\t$local", 0x20>; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric // This is the actual local.set instruction in wasm. These are made explicit 3120b57cec5SDimitry Andric // by the ExplicitLocals pass. It has mayStore because it writes to a wasm 3130b57cec5SDimitry Andric // local, which is a side effect not otherwise modeled in LLVM. 3140b57cec5SDimitry Andric let mayStore = 1, isAsCheapAsAMove = 1 in 315fe6060f1SDimitry Andric defm LOCAL_SET_#rc : I<(outs), (ins local_op:$local, rc:$src), 3160b57cec5SDimitry Andric (outs), (ins local_op:$local), [], 3170b57cec5SDimitry Andric "local.set\t$local, $src", "local.set\t$local", 0x21>; 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric // This is the actual local.tee instruction in wasm. TEEs are turned into 3200b57cec5SDimitry Andric // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason 3210b57cec5SDimitry Andric // as LOCAL_SET. 3220b57cec5SDimitry Andric let mayStore = 1, isAsCheapAsAMove = 1 in 323fe6060f1SDimitry Andric defm LOCAL_TEE_#rc : I<(outs rc:$res), (ins local_op:$local, rc:$src), 3240b57cec5SDimitry Andric (outs), (ins local_op:$local), [], 3250b57cec5SDimitry Andric "local.tee\t$res, $local, $src", "local.tee\t$local", 3260b57cec5SDimitry Andric 0x22>; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric // Unused values must be dropped in some contexts. 329fe6060f1SDimitry Andric defm DROP_#rc : I<(outs), (ins rc:$src), (outs), (ins), [], 3300b57cec5SDimitry Andric "drop\t$src", "drop", 0x1a>; 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric let mayLoad = 1 in 333fe6060f1SDimitry Andric defm GLOBAL_GET_#rc : I<(outs rc:$res), (ins global_op:$addr), 334fe6060f1SDimitry Andric (outs), (ins global_op:$addr), [], 335fe6060f1SDimitry Andric "global.get\t$res, $addr", "global.get\t$addr", 3360b57cec5SDimitry Andric 0x23>; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric let mayStore = 1 in 339fe6060f1SDimitry Andric defm GLOBAL_SET_#rc : I<(outs), (ins global_op:$addr, rc:$src), 340fe6060f1SDimitry Andric (outs), (ins global_op:$addr), [], 341fe6060f1SDimitry Andric "global.set\t$addr, $src", "global.set\t$addr", 3420b57cec5SDimitry Andric 0x24>; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric } // hasSideEffects = 0 345fe6060f1SDimitry Andric foreach vt = rc.RegTypes in { 346fe6060f1SDimitry Andric def : Pat<(vt (WebAssemblyglobal_get 347*349cc55cSDimitry Andric (WebAssemblyWrapper tglobaladdr:$addr))), 348fe6060f1SDimitry Andric (!cast<NI>("GLOBAL_GET_" # rc) tglobaladdr:$addr)>; 349fe6060f1SDimitry Andric def : Pat<(WebAssemblyglobal_set 350*349cc55cSDimitry Andric vt:$src, (WebAssemblyWrapper tglobaladdr:$addr)), 351fe6060f1SDimitry Andric (!cast<NI>("GLOBAL_SET_" # rc) tglobaladdr:$addr, vt:$src)>; 352fe6060f1SDimitry Andric def : Pat<(vt (WebAssemblylocal_get (i32 timm:$local))), 353fe6060f1SDimitry Andric (!cast<NI>("LOCAL_GET_" # rc) timm:$local)>; 354fe6060f1SDimitry Andric def : Pat<(WebAssemblylocal_set timm:$local, vt:$src), 355fe6060f1SDimitry Andric (!cast<NI>("LOCAL_SET_" # rc) timm:$local, vt:$src)>; 3560b57cec5SDimitry Andric } 357fe6060f1SDimitry Andric} 358fe6060f1SDimitry Andricdefm "" : LOCAL<I32, global_op32>; 359fe6060f1SDimitry Andricdefm "" : LOCAL<I64, global_op64>; // 64-bit only needed for pointers. 360fe6060f1SDimitry Andricdefm "" : LOCAL<F32, global_op32>; 361fe6060f1SDimitry Andricdefm "" : LOCAL<F64, global_op32>; 362fe6060f1SDimitry Andricdefm "" : LOCAL<V128, global_op32>, Requires<[HasSIMD128]>; 363fe6060f1SDimitry Andricdefm "" : LOCAL<FUNCREF, global_op32>, Requires<[HasReferenceTypes]>; 364fe6060f1SDimitry Andricdefm "" : LOCAL<EXTERNREF, global_op32>, Requires<[HasReferenceTypes]>; 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andriclet isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { 3670b57cec5SDimitry Andricdefm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), 3680b57cec5SDimitry Andric (outs), (ins i32imm_op:$imm), 3690b57cec5SDimitry Andric [(set I32:$res, imm:$imm)], 3700b57cec5SDimitry Andric "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>; 3710b57cec5SDimitry Andricdefm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm), 3720b57cec5SDimitry Andric (outs), (ins i64imm_op:$imm), 3730b57cec5SDimitry Andric [(set I64:$res, imm:$imm)], 3740b57cec5SDimitry Andric "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>; 3750b57cec5SDimitry Andricdefm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm), 3760b57cec5SDimitry Andric (outs), (ins f32imm_op:$imm), 3770b57cec5SDimitry Andric [(set F32:$res, fpimm:$imm)], 3780b57cec5SDimitry Andric "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>; 3790b57cec5SDimitry Andricdefm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm), 3800b57cec5SDimitry Andric (outs), (ins f64imm_op:$imm), 3810b57cec5SDimitry Andric [(set F64:$res, fpimm:$imm)], 3820b57cec5SDimitry Andric "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>; 3830b57cec5SDimitry Andric} // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 3840b57cec5SDimitry Andric 385*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaladdr:$addr)), 386eaeb601bSDimitry Andric (CONST_I32 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr32]>; 387*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaladdr:$addr)), 388eaeb601bSDimitry Andric (CONST_I64 tglobaladdr:$addr)>, Requires<[IsNotPIC, HasAddr64]>; 3890b57cec5SDimitry Andric 390*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaladdr:$addr)), 391e8d8bef9SDimitry Andric (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>; 392*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaladdr:$addr)), 393fe6060f1SDimitry Andric (GLOBAL_GET_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>; 3940b57cec5SDimitry Andric 395*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL tglobaladdr:$addr)), 396e8d8bef9SDimitry Andric (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>; 397*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL tglobaladdr:$addr)), 398e8d8bef9SDimitry Andric (CONST_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>; 399e8d8bef9SDimitry Andric 400*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL tglobaltlsaddr:$addr)), 401e8d8bef9SDimitry Andric (CONST_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>; 402*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL tglobaltlsaddr:$addr)), 403e8d8bef9SDimitry Andric (CONST_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>; 4040b57cec5SDimitry Andric 405*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper tglobaltlsaddr:$addr)), 406*349cc55cSDimitry Andric (GLOBAL_GET_I32 tglobaltlsaddr:$addr)>, Requires<[HasAddr32]>; 407*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper tglobaltlsaddr:$addr)), 408*349cc55cSDimitry Andric (GLOBAL_GET_I64 tglobaltlsaddr:$addr)>, Requires<[HasAddr64]>; 409*349cc55cSDimitry Andric 410*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper texternalsym:$addr)), 411e8d8bef9SDimitry Andric (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>; 412*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper texternalsym:$addr)), 413fe6060f1SDimitry Andric (GLOBAL_GET_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>; 4140b57cec5SDimitry Andric 415*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapper texternalsym:$addr)), 416e8d8bef9SDimitry Andric (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr32]>; 417*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapper texternalsym:$addr)), 418e8d8bef9SDimitry Andric (CONST_I64 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr64]>; 4190b57cec5SDimitry Andric 420*349cc55cSDimitry Andricdef : Pat<(i32 (WebAssemblyWrapperREL texternalsym:$addr)), 421*349cc55cSDimitry Andric (CONST_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>; 422*349cc55cSDimitry Andricdef : Pat<(i64 (WebAssemblyWrapperREL texternalsym:$addr)), 423*349cc55cSDimitry Andric (CONST_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4260b57cec5SDimitry Andric// Additional sets of instructions. 4270b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andricinclude "WebAssemblyInstrMemory.td" 4300b57cec5SDimitry Andricinclude "WebAssemblyInstrCall.td" 4310b57cec5SDimitry Andricinclude "WebAssemblyInstrControl.td" 4320b57cec5SDimitry Andricinclude "WebAssemblyInstrInteger.td" 4330b57cec5SDimitry Andricinclude "WebAssemblyInstrConv.td" 4340b57cec5SDimitry Andricinclude "WebAssemblyInstrFloat.td" 4350b57cec5SDimitry Andricinclude "WebAssemblyInstrAtomics.td" 4360b57cec5SDimitry Andricinclude "WebAssemblyInstrSIMD.td" 4370b57cec5SDimitry Andricinclude "WebAssemblyInstrRef.td" 4380b57cec5SDimitry Andricinclude "WebAssemblyInstrBulkMemory.td" 439e8d8bef9SDimitry Andricinclude "WebAssemblyInstrTable.td" 440