brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.4 KiB · 8b4e4fb Raw
236 lines · cpp
1//===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the WebAssembly implementation of the11/// TargetInstrInfo class.12///13//===----------------------------------------------------------------------===//14 15#include "WebAssemblyInstrInfo.h"16#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"17#include "WebAssembly.h"18#include "WebAssemblyMachineFunctionInfo.h"19#include "WebAssemblySubtarget.h"20#include "WebAssemblyUtilities.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/MachineMemOperand.h"24#include "llvm/CodeGen/MachineRegisterInfo.h"25using namespace llvm;26 27#define DEBUG_TYPE "wasm-instr-info"28 29#define GET_INSTRINFO_CTOR_DTOR30#include "WebAssemblyGenInstrInfo.inc"31 32// defines WebAssembly::getNamedOperandIdx33#define GET_INSTRINFO_NAMED_OPS34#include "WebAssemblyGenInstrInfo.inc"35 36WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)37    : WebAssemblyGenInstrInfo(STI, RI, WebAssembly::ADJCALLSTACKDOWN,38                              WebAssembly::ADJCALLSTACKUP,39                              WebAssembly::CATCHRET),40      RI(STI.getTargetTriple()) {}41 42bool WebAssemblyInstrInfo::isReMaterializableImpl(43    const MachineInstr &MI) const {44  switch (MI.getOpcode()) {45  case WebAssembly::CONST_I32:46  case WebAssembly::CONST_I64:47  case WebAssembly::CONST_F32:48  case WebAssembly::CONST_F64:49    // TargetInstrInfo::isReMaterializableImpl misses these50    // because of the ARGUMENTS implicit def, so we manualy override it here.51    return true;52  default:53    return TargetInstrInfo::isReMaterializableImpl(MI);54  }55}56 57void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,58                                       MachineBasicBlock::iterator I,59                                       const DebugLoc &DL, Register DestReg,60                                       Register SrcReg, bool KillSrc,61                                       bool RenamableDest,62                                       bool RenamableSrc) const {63  // This method is called by post-RA expansion, which expects only pregs to64  // exist. However we need to handle both here.65  auto &MRI = MBB.getParent()->getRegInfo();66  const TargetRegisterClass *RC =67      DestReg.isVirtual()68          ? MRI.getRegClass(DestReg)69          : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);70 71  unsigned CopyOpcode = WebAssembly::getCopyOpcodeForRegClass(RC);72 73  BuildMI(MBB, I, DL, get(CopyOpcode), DestReg)74      .addReg(SrcReg, KillSrc ? RegState::Kill : 0);75}76 77MachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl(78    MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const {79  // If the operands are stackified, we can't reorder them.80  WebAssemblyFunctionInfo &MFI =81      *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();82  if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||83      MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg()))84    return nullptr;85 86  // Otherwise use the default implementation.87  return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);88}89 90// Branch analysis.91bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB,92                                         MachineBasicBlock *&TBB,93                                         MachineBasicBlock *&FBB,94                                         SmallVectorImpl<MachineOperand> &Cond,95                                         bool /*AllowModify*/) const {96  const auto &MFI = *MBB.getParent()->getInfo<WebAssemblyFunctionInfo>();97  // WebAssembly has control flow that doesn't have explicit branches or direct98  // fallthrough (e.g. try/catch), which can't be modeled by analyzeBranch. It99  // is created after CFGStackify.100  if (MFI.isCFGStackified())101    return true;102 103  bool HaveCond = false;104  for (MachineInstr &MI : MBB.terminators()) {105    switch (MI.getOpcode()) {106    default:107      // Unhandled instruction; bail out.108      return true;109    case WebAssembly::BR_IF:110      if (HaveCond)111        return true;112      Cond.push_back(MachineOperand::CreateImm(true));113      Cond.push_back(MI.getOperand(1));114      TBB = MI.getOperand(0).getMBB();115      HaveCond = true;116      break;117    case WebAssembly::BR_UNLESS:118      if (HaveCond)119        return true;120      Cond.push_back(MachineOperand::CreateImm(false));121      Cond.push_back(MI.getOperand(1));122      TBB = MI.getOperand(0).getMBB();123      HaveCond = true;124      break;125    case WebAssembly::BR:126      if (!HaveCond)127        TBB = MI.getOperand(0).getMBB();128      else129        FBB = MI.getOperand(0).getMBB();130      break;131    }132    if (MI.isBarrier())133      break;134  }135 136  return false;137}138 139unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,140                                            int *BytesRemoved) const {141  assert(!BytesRemoved && "code size not handled");142 143  MachineBasicBlock::instr_iterator I = MBB.instr_end();144  unsigned Count = 0;145 146  while (I != MBB.instr_begin()) {147    --I;148    if (I->isDebugInstr())149      continue;150    if (!I->isTerminator())151      break;152    // Remove the branch.153    I->eraseFromParent();154    I = MBB.instr_end();155    ++Count;156  }157 158  return Count;159}160 161unsigned WebAssemblyInstrInfo::insertBranch(162    MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,163    ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {164  assert(!BytesAdded && "code size not handled");165 166  if (Cond.empty()) {167    if (!TBB)168      return 0;169 170    BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);171    return 1;172  }173 174  assert(Cond.size() == 2 && "Expected a flag and a successor block");175 176  if (Cond[0].getImm())177    BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]);178  else179    BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(Cond[1]);180  if (!FBB)181    return 1;182 183  BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);184  return 2;185}186 187bool WebAssemblyInstrInfo::reverseBranchCondition(188    SmallVectorImpl<MachineOperand> &Cond) const {189  assert(Cond.size() == 2 && "Expected a flag and a condition expression");190  Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());191  return false;192}193 194ArrayRef<std::pair<int, const char *>>195WebAssemblyInstrInfo::getSerializableTargetIndices() const {196  static const std::pair<int, const char *> TargetIndices[] = {197      {WebAssembly::TI_LOCAL, "wasm-local"},198      {WebAssembly::TI_GLOBAL_FIXED, "wasm-global-fixed"},199      {WebAssembly::TI_OPERAND_STACK, "wasm-operand-stack"},200      {WebAssembly::TI_GLOBAL_RELOC, "wasm-global-reloc"},201      {WebAssembly::TI_LOCAL_INDIRECT, "wasm-local-indirect"}};202  return ArrayRef(TargetIndices);203}204 205const MachineOperand &206WebAssemblyInstrInfo::getCalleeOperand(const MachineInstr &MI) const {207  return WebAssembly::getCalleeOp(MI);208}209 210// This returns true when the instruction defines a value of a TargetIndex211// operand that can be tracked by offsets. For Wasm, this returns true for only212// local.set/local.tees. This is currently used by LiveDebugValues analysis.213//214// These are not included:215// - In theory we need to add global.set here too, but we don't have global216//   indices at this point because they are relocatable and we address them by217//   names until linking, so we don't have 'offsets' (which are used to store218//   local/global indices) to deal with in LiveDebugValues. And we don't219//   associate debug info in values in globals anyway.220// - All other value-producing instructions, i.e. instructions with defs, can221//   define values in the Wasm stack, which is represented by TI_OPERAND_STACK222//   TargetIndex. But they don't have offset info within the instruction itself,223//   and debug info analysis for them is handled separately in224//   WebAssemblyDebugFixup pass, so we don't worry about them here.225bool WebAssemblyInstrInfo::isExplicitTargetIndexDef(const MachineInstr &MI,226                                                    int &Index,227                                                    int64_t &Offset) const {228  unsigned Opc = MI.getOpcode();229  if (WebAssembly::isLocalSet(Opc) || WebAssembly::isLocalTee(Opc)) {230    Index = WebAssembly::TI_LOCAL;231    Offset = MI.explicit_uses().begin()->getImm();232    return true;233  }234  return false;235}236