1*9880d681SAndroid Build Coastguard Worker //===-- WebAssemblyRegisterInfo.cpp - WebAssembly Register Information ----===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker ///
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief This file contains the WebAssembly implementation of the
12*9880d681SAndroid Build Coastguard Worker /// TargetRegisterInfo class.
13*9880d681SAndroid Build Coastguard Worker ///
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyRegisterInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyFrameLowering.h"
19*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyInstrInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyMachineFunctionInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "WebAssemblySubtarget.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetFrameLowering.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetOptions.h"
29*9880d681SAndroid Build Coastguard Worker using namespace llvm;
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "wasm-reg-info"
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker #define GET_REGINFO_TARGET_DESC
34*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyGenRegisterInfo.inc"
35*9880d681SAndroid Build Coastguard Worker
WebAssemblyRegisterInfo(const Triple & TT)36*9880d681SAndroid Build Coastguard Worker WebAssemblyRegisterInfo::WebAssemblyRegisterInfo(const Triple &TT)
37*9880d681SAndroid Build Coastguard Worker : WebAssemblyGenRegisterInfo(0), TT(TT) {}
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker const MCPhysReg *
getCalleeSavedRegs(const MachineFunction *) const40*9880d681SAndroid Build Coastguard Worker WebAssemblyRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const {
41*9880d681SAndroid Build Coastguard Worker static const MCPhysReg CalleeSavedRegs[] = {0};
42*9880d681SAndroid Build Coastguard Worker return CalleeSavedRegs;
43*9880d681SAndroid Build Coastguard Worker }
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker BitVector
getReservedRegs(const MachineFunction &) const46*9880d681SAndroid Build Coastguard Worker WebAssemblyRegisterInfo::getReservedRegs(const MachineFunction & /*MF*/) const {
47*9880d681SAndroid Build Coastguard Worker BitVector Reserved(getNumRegs());
48*9880d681SAndroid Build Coastguard Worker for (auto Reg : {WebAssembly::SP32, WebAssembly::SP64, WebAssembly::FP32,
49*9880d681SAndroid Build Coastguard Worker WebAssembly::FP64})
50*9880d681SAndroid Build Coastguard Worker Reserved.set(Reg);
51*9880d681SAndroid Build Coastguard Worker return Reserved;
52*9880d681SAndroid Build Coastguard Worker }
53*9880d681SAndroid Build Coastguard Worker
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger *) const54*9880d681SAndroid Build Coastguard Worker void WebAssemblyRegisterInfo::eliminateFrameIndex(
55*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum,
56*9880d681SAndroid Build Coastguard Worker RegScavenger * /*RS*/) const {
57*9880d681SAndroid Build Coastguard Worker assert(SPAdj == 0);
58*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *II;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *MI.getParent();
61*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = *MBB.getParent();
62*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MF.getRegInfo();
63*9880d681SAndroid Build Coastguard Worker int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
64*9880d681SAndroid Build Coastguard Worker const MachineFrameInfo &MFI = *MF.getFrameInfo();
65*9880d681SAndroid Build Coastguard Worker int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex);
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker // If this is the address operand of a load or store, make it relative to SP
68*9880d681SAndroid Build Coastguard Worker // and fold the frame offset directly in.
69*9880d681SAndroid Build Coastguard Worker if (MI.mayLoadOrStore() && FIOperandNum == WebAssembly::MemOpAddressOperandNo) {
70*9880d681SAndroid Build Coastguard Worker assert(FrameOffset >= 0 && MI.getOperand(1).getImm() >= 0);
71*9880d681SAndroid Build Coastguard Worker int64_t Offset = MI.getOperand(1).getImm() + FrameOffset;
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker if (static_cast<uint64_t>(Offset) <= std::numeric_limits<uint32_t>::max()) {
74*9880d681SAndroid Build Coastguard Worker MI.getOperand(FIOperandNum - 1).setImm(Offset);
75*9880d681SAndroid Build Coastguard Worker MI.getOperand(FIOperandNum)
76*9880d681SAndroid Build Coastguard Worker .ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false);
77*9880d681SAndroid Build Coastguard Worker return;
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker // If this is an address being added to a constant, fold the frame offset
82*9880d681SAndroid Build Coastguard Worker // into the constant.
83*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() == WebAssembly::ADD_I32) {
84*9880d681SAndroid Build Coastguard Worker MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum);
85*9880d681SAndroid Build Coastguard Worker if (OtherMO.isReg()) {
86*9880d681SAndroid Build Coastguard Worker unsigned OtherMOReg = OtherMO.getReg();
87*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(OtherMOReg)) {
88*9880d681SAndroid Build Coastguard Worker MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg);
89*9880d681SAndroid Build Coastguard Worker // TODO: For now we just opportunistically do this in the case where
90*9880d681SAndroid Build Coastguard Worker // the CONST_I32 happens to have exactly one def and one use. We
91*9880d681SAndroid Build Coastguard Worker // should generalize this to optimize in more cases.
92*9880d681SAndroid Build Coastguard Worker if (Def && Def->getOpcode() == WebAssembly::CONST_I32 &&
93*9880d681SAndroid Build Coastguard Worker MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) {
94*9880d681SAndroid Build Coastguard Worker MachineOperand &ImmMO = Def->getOperand(1);
95*9880d681SAndroid Build Coastguard Worker ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));
96*9880d681SAndroid Build Coastguard Worker MI.getOperand(FIOperandNum)
97*9880d681SAndroid Build Coastguard Worker .ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false);
98*9880d681SAndroid Build Coastguard Worker return;
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker // Otherwise create an i32.add SP, offset and make it the operand.
105*9880d681SAndroid Build Coastguard Worker const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker unsigned FIRegOperand = WebAssembly::SP32;
108*9880d681SAndroid Build Coastguard Worker if (FrameOffset) {
109*9880d681SAndroid Build Coastguard Worker // Create i32.add SP, offset and make it the operand.
110*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *PtrRC =
111*9880d681SAndroid Build Coastguard Worker MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
112*9880d681SAndroid Build Coastguard Worker unsigned OffsetOp = MRI.createVirtualRegister(PtrRC);
113*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::CONST_I32),
114*9880d681SAndroid Build Coastguard Worker OffsetOp)
115*9880d681SAndroid Build Coastguard Worker .addImm(FrameOffset);
116*9880d681SAndroid Build Coastguard Worker FIRegOperand = MRI.createVirtualRegister(PtrRC);
117*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::ADD_I32),
118*9880d681SAndroid Build Coastguard Worker FIRegOperand)
119*9880d681SAndroid Build Coastguard Worker .addReg(WebAssembly::SP32)
120*9880d681SAndroid Build Coastguard Worker .addReg(OffsetOp);
121*9880d681SAndroid Build Coastguard Worker }
122*9880d681SAndroid Build Coastguard Worker MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*IsDef=*/false);
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker unsigned
getFrameRegister(const MachineFunction & MF) const126*9880d681SAndroid Build Coastguard Worker WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
127*9880d681SAndroid Build Coastguard Worker static const unsigned Regs[2][2] = {
128*9880d681SAndroid Build Coastguard Worker /* !isArch64Bit isArch64Bit */
129*9880d681SAndroid Build Coastguard Worker /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64},
130*9880d681SAndroid Build Coastguard Worker /* hasFP */ {WebAssembly::FP32, WebAssembly::FP64}};
131*9880d681SAndroid Build Coastguard Worker const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
132*9880d681SAndroid Build Coastguard Worker return Regs[TFI->hasFP(MF)][TT.isArch64Bit()];
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const136*9880d681SAndroid Build Coastguard Worker WebAssemblyRegisterInfo::getPointerRegClass(const MachineFunction &MF,
137*9880d681SAndroid Build Coastguard Worker unsigned Kind) const {
138*9880d681SAndroid Build Coastguard Worker assert(Kind == 0 && "Only one kind of pointer on WebAssembly");
139*9880d681SAndroid Build Coastguard Worker if (MF.getSubtarget<WebAssemblySubtarget>().hasAddr64())
140*9880d681SAndroid Build Coastguard Worker return &WebAssembly::I64RegClass;
141*9880d681SAndroid Build Coastguard Worker return &WebAssembly::I32RegClass;
142*9880d681SAndroid Build Coastguard Worker }
143