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