1 //===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MipsABIInfo.h"
10 #include "MipsRegisterInfo.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/ADT/StringSwitch.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCDwarf.h"
15 #include "llvm/MC/MCTargetOptions.h"
16 #include "llvm/Support/CommandLine.h"
17 
18 using namespace llvm;
19 
20 // Note: this option is defined here to be visible from libLLVMMipsAsmParser
21 //       and libLLVMMipsCodeGen
22 cl::opt<bool>
23 EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
24               cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
25               cl::init(true));
26 
27 namespace {
28 static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3};
29 
30 static const MCPhysReg Mips64IntRegs[8] = {
31     Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64,
32     Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64};
33 
34 static const MCPhysReg CheriCapArgRegs[8] = {
35     Mips::C3, Mips::C4, Mips::C5, Mips::C6,
36     Mips::C7, Mips::C8, Mips::C9, Mips::C10};
37 
38 }
39 
GetByValArgRegs() const40 ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const {
41   // In the purecap ABI we don't pass parts of byval arguments in registers and
42   // instead always memcpy() the entire struct.
43   if (IsCheriPureCap())
44     return {};
45   if (IsO32())
46     return makeArrayRef(O32IntRegs);
47   if (IsN32() || IsN64())
48     return makeArrayRef(Mips64IntRegs);
49   llvm_unreachable("Unhandled ABI");
50 }
51 
GetVarArgRegs() const52 ArrayRef<MCPhysReg> MipsABIInfo::GetVarArgRegs() const {
53   if (IsCheriPureCap())
54     return makeArrayRef(CheriCapArgRegs);
55   if (IsO32())
56     return makeArrayRef(O32IntRegs);
57   if (IsN32() || IsN64())
58     return makeArrayRef(Mips64IntRegs);
59   llvm_unreachable("Unhandled ABI");
60 }
61 
GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const62 unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const {
63   if (IsO32())
64     return CC != CallingConv::Fast ? 16 : 0;
65   if (IsN32() || IsN64())
66     return 0;
67   llvm_unreachable("Unhandled ABI");
68 }
69 
computeTargetABI(const Triple & TT,StringRef CPU,const MCTargetOptions & Options)70 MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef CPU,
71                                           const MCTargetOptions &Options) {
72   StringRef ABIName = Options.getABIName();
73   if (ABIName.startswith("o32"))
74     return MipsABIInfo::O32();
75   if (ABIName.startswith("n32"))
76     return MipsABIInfo::N32();
77   if (ABIName.startswith("n64"))
78     return MipsABIInfo::N64();
79   if (ABIName.startswith("purecap"))
80     return MipsABIInfo::CheriPureCap();
81   if (TT.getEnvironment() == llvm::Triple::GNUABIN32)
82     return MipsABIInfo::N32();
83   assert(Options.getABIName().empty() && "Unknown ABI option for MIPS");
84   if (TT.getEnvironment() == llvm::Triple::CheriPurecap)
85     return MipsABIInfo::CheriPureCap();
86 
87   if (TT.isMIPS64())
88     return MipsABIInfo::N64();
89   return MipsABIInfo::O32();
90 }
91 
GetStackPtr() const92 unsigned MipsABIInfo::GetStackPtr() const {
93   return IsCheriPureCap() ?
94     Mips::C11 :
95     (ArePtrs64bit() ? Mips::SP_64 : Mips::SP);
96 }
97 
GetFramePtr() const98 unsigned MipsABIInfo::GetFramePtr() const {
99   return IsCheriPureCap() ?
100     Mips::C24 :
101     (ArePtrs64bit() ? Mips::FP_64 : Mips::FP);
102 }
103 
GetBasePtr() const104 unsigned MipsABIInfo::GetBasePtr() const {
105   // FIXME: $c25 is probably not sensible here.
106   return IsCheriPureCap() ?
107     Mips::C25 :
108     (ArePtrs64bit() ? Mips::S7_64 : Mips::S7);
109 }
110 
GetDefaultDataCapability() const111 unsigned MipsABIInfo::GetDefaultDataCapability() const { return Mips::DDC; }
112 
GetGlobalCapability() const113 unsigned MipsABIInfo::GetGlobalCapability() const {
114   return Mips::C26;
115 }
116 
117 // HACK: Update the default CFA register for CHERI purecap
updateCheriInitialFrameStateHack(const MCAsmInfo & MAI,const MCRegisterInfo & MRI)118 void MipsABIInfo::updateCheriInitialFrameStateHack(const MCAsmInfo &MAI,
119                                                    const MCRegisterInfo &MRI) {
120   if (!IsCheriPureCap()) {
121     assert((MRI.getRARegister() == Mips::RA ||
122             MRI.getRARegister() == Mips::RA_64) &&
123            "Wrong RA register");
124     return;
125   }
126 
127   // Some general sanity checks
128   auto ReturnReg = GetReturnAddress();
129   assert(ReturnReg == Mips::C17 && "Wrong RA register");
130   auto StackReg = GetStackPtr();
131   assert(StackReg == Mips::C11 && "Wrong SP register");
132   assert(GetFramePtr() == Mips::C24 && "Wrong FP register");
133 
134   // Update the value of the return register
135   if (MRI.getRARegister() != ReturnReg) {
136     const_cast<MCRegisterInfo&>(MRI).RAReg = ReturnReg;
137   }
138   assert(MRI.getRARegister() == ReturnReg && "Wrong RA register");
139   // Check that we didn't set the PC register:
140   assert(MRI.getProgramCounter() == 0 && "Wrong PC register");
141 
142   // Update the value of the initial frame state (since C11 is set too late)
143   auto &InitialState = MAI.getInitialFrameState();
144   unsigned C11Dwarf = MRI.getDwarfRegNum(StackReg, true);
145   for (const MCCFIInstruction &Inst : InitialState) {
146     if (Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister) {
147       if (Inst.getRegister() != C11Dwarf) {
148         // errs() << __func__ << ": Updating default OpDefCfaRegister from "
149         //       << Inst.getRegister() << " to " << C11Dwarf << "\n";
150         const_cast<MCCFIInstruction &>(Inst).setRegister(C11Dwarf);
151       }
152     } else if (Inst.getOperation() == MCCFIInstruction::OpDefCfa) {
153       if (Inst.getRegister() != C11Dwarf) {
154         // errs() << __func__ << ": Updating default OpDefCfa from "
155         //        << Inst.getRegister() << "to" << C11Dwarf << "\n";
156         const_cast<MCCFIInstruction &>(Inst).setRegister(C11Dwarf);
157       }
158     }
159   }
160 }
161 
GetReturnAddress() const162 unsigned MipsABIInfo::GetReturnAddress() const {
163   return IsCheriPureCap() ?
164     Mips::C17 :
165     (ArePtrs64bit() ? Mips::RA_64 : Mips::RA);
166 }
167 
GetGlobalPtr() const168 unsigned MipsABIInfo::GetGlobalPtr() const {
169   assert(!IsCheriPureCap());
170   return ArePtrs64bit() ? Mips::GP_64 : Mips::GP;
171 }
172 
GetNullPtr() const173 unsigned MipsABIInfo::GetNullPtr() const {
174   return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO;
175 }
176 
GetZeroReg() const177 unsigned MipsABIInfo::GetZeroReg() const {
178   return AreGprs64bit() ? Mips::ZERO_64 : Mips::ZERO;
179 }
180 
GetPtrAdduOp() const181 unsigned MipsABIInfo::GetPtrAdduOp() const {
182   return ArePtrs64bit() ? Mips::DADDu : Mips::ADDu;
183 }
184 
GetPtrAddiuOp() const185 unsigned MipsABIInfo::GetPtrAddiuOp() const {
186   return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu;
187 }
188 
GetPtrSubuOp() const189 unsigned MipsABIInfo::GetPtrSubuOp() const {
190   return ArePtrs64bit() ? Mips::DSUBu : Mips::SUBu;
191 }
192 
GetPtrAndOp() const193 unsigned MipsABIInfo::GetPtrAndOp() const {
194   return ArePtrs64bit() ? Mips::AND64 : Mips::AND;
195 }
196 
GetGPRMoveOp() const197 unsigned MipsABIInfo::GetGPRMoveOp() const {
198   return ArePtrs64bit() ? Mips::OR64 : Mips::OR;
199 }
200 
GetSPMoveOp() const201 unsigned MipsABIInfo::GetSPMoveOp() const {
202   return IsCheriPureCap() ?
203     Mips::CIncOffset :
204     (ArePtrs64bit() ? Mips::OR64 : Mips::OR);
205 }
206 
GetEhDataReg(unsigned I) const207 unsigned MipsABIInfo::GetEhDataReg(unsigned I) const {
208   static const unsigned EhDataReg[] = {
209     Mips::A0, Mips::A1, Mips::A2, Mips::A3
210   };
211   static const unsigned EhDataReg64[] = {
212     Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64
213   };
214 
215   return IsN64() ? EhDataReg64[I] : EhDataReg[I];
216 }
217 
218