1 //===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===// 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 /// \brief This file contains the WebAssembly implementation of the 12 /// TargetInstrInfo class. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #include "WebAssemblyInstrInfo.h" 17 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 18 #include "WebAssemblySubtarget.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/MachineMemOperand.h" 22 #include "llvm/CodeGen/MachineRegisterInfo.h" 23 using namespace llvm; 24 25 #define DEBUG_TYPE "wasm-instr-info" 26 27 #define GET_INSTRINFO_CTOR_DTOR 28 #include "WebAssemblyGenInstrInfo.inc" 29 30 WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI) 31 : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN, 32 WebAssembly::ADJCALLSTACKUP), 33 RI(STI.getTargetTriple()) {} 34 35 void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 36 MachineBasicBlock::iterator I, 37 DebugLoc DL, unsigned DestReg, 38 unsigned SrcReg, bool KillSrc) const { 39 const TargetRegisterClass *RC = 40 MBB.getParent()->getRegInfo().getRegClass(SrcReg); 41 42 unsigned CopyLocalOpcode; 43 if (RC == &WebAssembly::I32RegClass) 44 CopyLocalOpcode = WebAssembly::COPY_LOCAL_I32; 45 else if (RC == &WebAssembly::I64RegClass) 46 CopyLocalOpcode = WebAssembly::COPY_LOCAL_I64; 47 else if (RC == &WebAssembly::F32RegClass) 48 CopyLocalOpcode = WebAssembly::COPY_LOCAL_F32; 49 else if (RC == &WebAssembly::F64RegClass) 50 CopyLocalOpcode = WebAssembly::COPY_LOCAL_F64; 51 else 52 llvm_unreachable("Unexpected register class"); 53 54 BuildMI(MBB, I, DL, get(CopyLocalOpcode), DestReg) 55 .addReg(SrcReg, KillSrc ? RegState::Kill : 0); 56 } 57 58 // Branch analysis. 59 bool WebAssemblyInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, 60 MachineBasicBlock *&TBB, 61 MachineBasicBlock *&FBB, 62 SmallVectorImpl<MachineOperand> &Cond, 63 bool /*AllowModify*/) const { 64 bool HaveCond = false; 65 for (MachineInstr &MI : iterator_range<MachineBasicBlock::instr_iterator>( 66 MBB.getFirstInstrTerminator(), MBB.instr_end())) { 67 switch (MI.getOpcode()) { 68 default: 69 // Unhandled instruction; bail out. 70 return true; 71 case WebAssembly::BR_IF: 72 if (HaveCond) 73 return true; 74 Cond.push_back(MachineOperand::CreateImm(true)); 75 Cond.push_back(MI.getOperand(0)); 76 TBB = MI.getOperand(1).getMBB(); 77 HaveCond = true; 78 break; 79 case WebAssembly::BR_UNLESS: 80 if (HaveCond) 81 return true; 82 Cond.push_back(MachineOperand::CreateImm(false)); 83 Cond.push_back(MI.getOperand(0)); 84 TBB = MI.getOperand(1).getMBB(); 85 HaveCond = true; 86 break; 87 case WebAssembly::BR: 88 if (!HaveCond) 89 TBB = MI.getOperand(0).getMBB(); 90 else 91 FBB = MI.getOperand(0).getMBB(); 92 break; 93 } 94 if (MI.isBarrier()) 95 break; 96 } 97 98 return false; 99 } 100 101 unsigned WebAssemblyInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 102 MachineBasicBlock::instr_iterator I = MBB.instr_end(); 103 unsigned Count = 0; 104 105 while (I != MBB.instr_begin()) { 106 --I; 107 if (I->isDebugValue()) 108 continue; 109 if (!I->isTerminator()) 110 break; 111 // Remove the branch. 112 I->eraseFromParent(); 113 I = MBB.instr_end(); 114 ++Count; 115 } 116 117 return Count; 118 } 119 120 unsigned WebAssemblyInstrInfo::InsertBranch(MachineBasicBlock &MBB, 121 MachineBasicBlock *TBB, 122 MachineBasicBlock *FBB, 123 ArrayRef<MachineOperand> Cond, 124 DebugLoc DL) const { 125 if (Cond.empty()) { 126 if (!TBB) 127 return 0; 128 129 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB); 130 return 1; 131 } 132 133 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 134 135 if (Cond[0].getImm()) { 136 BuildMI(&MBB, DL, get(WebAssembly::BR_IF)) 137 .addOperand(Cond[1]) 138 .addMBB(TBB); 139 } else { 140 BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)) 141 .addOperand(Cond[1]) 142 .addMBB(TBB); 143 } 144 if (!FBB) 145 return 1; 146 147 BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB); 148 return 2; 149 } 150 151 bool WebAssemblyInstrInfo::ReverseBranchCondition( 152 SmallVectorImpl<MachineOperand> &Cond) const { 153 assert(Cond.size() == 2 && "Expected a flag and a successor block"); 154 Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm()); 155 return false; 156 } 157