1 //===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
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 // This file implements the SparcMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "MCTargetDesc/SparcFixupKinds.h"
14 #include "SparcMCTargetDesc.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCFixup.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCObjectFileInfo.h"
26 #include "llvm/MC/MCRegisterInfo.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/MC/MCSymbol.h"
29 #include "llvm/Support/Casting.h"
30 #include "llvm/Support/EndianStream.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include <cassert>
33 #include <cstdint>
34
35 using namespace llvm;
36
37 #define DEBUG_TYPE "mccodeemitter"
38
39 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
40
41 namespace {
42
43 class SparcMCCodeEmitter : public MCCodeEmitter {
44 MCContext &Ctx;
45
46 public:
SparcMCCodeEmitter(const MCInstrInfo &,MCContext & ctx)47 SparcMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)
48 : Ctx(ctx) {}
49 SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
50 SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete;
51 ~SparcMCCodeEmitter() override = default;
52
53 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
54 SmallVectorImpl<MCFixup> &Fixups,
55 const MCSubtargetInfo &STI) const override;
56
57 // getBinaryCodeForInstr - TableGen'erated function for getting the
58 // binary encoding for an instruction.
59 uint64_t getBinaryCodeForInstr(const MCInst &MI,
60 SmallVectorImpl<MCFixup> &Fixups,
61 const MCSubtargetInfo &STI) const;
62
63 /// getMachineOpValue - Return binary encoding of operand. If the machine
64 /// operand requires relocation, record the relocation and return zero.
65 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
66 SmallVectorImpl<MCFixup> &Fixups,
67 const MCSubtargetInfo &STI) const;
68 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
69 SmallVectorImpl<MCFixup> &Fixups,
70 const MCSubtargetInfo &STI) const;
71 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
72 SmallVectorImpl<MCFixup> &Fixups,
73 const MCSubtargetInfo &STI) const;
74 unsigned getSImm5OpValue(const MCInst &MI, unsigned OpNo,
75 SmallVectorImpl<MCFixup> &Fixups,
76 const MCSubtargetInfo &STI) const;
77 unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,
78 SmallVectorImpl<MCFixup> &Fixups,
79 const MCSubtargetInfo &STI) const;
80 unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
81 SmallVectorImpl<MCFixup> &Fixups,
82 const MCSubtargetInfo &STI) const;
83 unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
84 SmallVectorImpl<MCFixup> &Fixups,
85 const MCSubtargetInfo &STI) const;
86 unsigned getCompareAndBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
87 SmallVectorImpl<MCFixup> &Fixups,
88 const MCSubtargetInfo &STI) const;
89 };
90
91 } // end anonymous namespace
92
addFixup(SmallVectorImpl<MCFixup> & Fixups,uint32_t Offset,const MCExpr * Value,uint16_t Kind)93 static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,
94 const MCExpr *Value, uint16_t Kind) {
95 bool PCRel = false;
96 switch (Kind) {
97 case ELF::R_SPARC_PC10:
98 case ELF::R_SPARC_PC22:
99 case ELF::R_SPARC_WDISP10:
100 case ELF::R_SPARC_WDISP16:
101 case ELF::R_SPARC_WDISP19:
102 case ELF::R_SPARC_WDISP22:
103 case Sparc::fixup_sparc_call30:
104 PCRel = true;
105 }
106 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
107 }
108
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const109 void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI,
110 SmallVectorImpl<char> &CB,
111 SmallVectorImpl<MCFixup> &Fixups,
112 const MCSubtargetInfo &STI) const {
113 unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
114 support::endian::write(CB, Bits,
115 Ctx.getAsmInfo()->isLittleEndian()
116 ? llvm::endianness::little
117 : llvm::endianness::big);
118
119 // Some instructions have phantom operands that only contribute a fixup entry.
120 unsigned SymOpNo = 0;
121 switch (MI.getOpcode()) {
122 default: break;
123 case SP::TLS_CALL: SymOpNo = 1; break;
124 case SP::GDOP_LDrr:
125 case SP::GDOP_LDXrr:
126 case SP::TLS_ADDrr:
127 case SP::TLS_LDrr:
128 case SP::TLS_LDXrr: SymOpNo = 3; break;
129 }
130 if (SymOpNo != 0) {
131 const MCOperand &MO = MI.getOperand(SymOpNo);
132 uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
133 assert(op == 0 && "Unexpected operand value!");
134 (void)op; // suppress warning.
135 }
136
137 ++MCNumEmitted; // Keep track of the # of mi's emitted.
138 }
139
140 unsigned SparcMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const141 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
142 SmallVectorImpl<MCFixup> &Fixups,
143 const MCSubtargetInfo &STI) const {
144 if (MO.isReg())
145 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
146
147 if (MO.isImm())
148 return MO.getImm();
149
150 assert(MO.isExpr());
151 const MCExpr *Expr = MO.getExpr();
152 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {
153 addFixup(Fixups, 0, Expr, SExpr->getSpecifier());
154 return 0;
155 }
156
157 int64_t Res;
158 if (Expr->evaluateAsAbsolute(Res))
159 return Res;
160
161 llvm_unreachable("Unhandled expression!");
162 return 0;
163 }
164
getSImm5OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const165 unsigned SparcMCCodeEmitter::getSImm5OpValue(const MCInst &MI, unsigned OpNo,
166 SmallVectorImpl<MCFixup> &Fixups,
167 const MCSubtargetInfo &STI) const {
168 const MCOperand &MO = MI.getOperand(OpNo);
169
170 if (MO.isImm())
171 return MO.getImm();
172
173 assert(MO.isExpr() &&
174 "getSImm5OpValue expects only expressions or an immediate");
175
176 const MCExpr *Expr = MO.getExpr();
177
178 // Constant value, no fixup is needed
179 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
180 return CE->getValue();
181
182 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {
183 addFixup(Fixups, 0, Expr, SExpr->getSpecifier());
184 return 0;
185 }
186 addFixup(Fixups, 0, Expr, ELF::R_SPARC_5);
187 return 0;
188 }
189
190 unsigned
getSImm13OpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const191 SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
192 SmallVectorImpl<MCFixup> &Fixups,
193 const MCSubtargetInfo &STI) const {
194 const MCOperand &MO = MI.getOperand(OpNo);
195
196 if (MO.isImm())
197 return MO.getImm();
198
199 assert(MO.isExpr() &&
200 "getSImm13OpValue expects only expressions or an immediate");
201
202 const MCExpr *Expr = MO.getExpr();
203
204 // Constant value, no fixup is needed
205 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
206 return CE->getValue();
207
208 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {
209 addFixup(Fixups, 0, Expr, SExpr->getSpecifier());
210 return 0;
211 }
212 addFixup(Fixups, 0, Expr, Sparc::fixup_sparc_13);
213 return 0;
214 }
215
216 unsigned SparcMCCodeEmitter::
getCallTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const217 getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
218 SmallVectorImpl<MCFixup> &Fixups,
219 const MCSubtargetInfo &STI) const {
220 if (MI.getOpcode() == SP::TLS_CALL) {
221 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
222 // encodeInstruction.
223 return 0;
224 }
225
226 const MCOperand &MO = MI.getOperand(OpNo);
227 addFixup(Fixups, 0, MO.getExpr(), Sparc::fixup_sparc_call30);
228 return 0;
229 }
230
231 unsigned SparcMCCodeEmitter::
getBranchTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const232 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
233 SmallVectorImpl<MCFixup> &Fixups,
234 const MCSubtargetInfo &STI) const {
235 const MCOperand &MO = MI.getOperand(OpNo);
236 if (MO.isReg() || MO.isImm())
237 return getMachineOpValue(MI, MO, Fixups, STI);
238
239 addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP22);
240 return 0;
241 }
242
getBranchPredTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const243 unsigned SparcMCCodeEmitter::getBranchPredTargetOpValue(
244 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
245 const MCSubtargetInfo &STI) const {
246 const MCOperand &MO = MI.getOperand(OpNo);
247 if (MO.isReg() || MO.isImm())
248 return getMachineOpValue(MI, MO, Fixups, STI);
249
250 addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP19);
251 return 0;
252 }
253
getBranchOnRegTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const254 unsigned SparcMCCodeEmitter::getBranchOnRegTargetOpValue(
255 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
256 const MCSubtargetInfo &STI) const {
257 const MCOperand &MO = MI.getOperand(OpNo);
258 if (MO.isReg() || MO.isImm())
259 return getMachineOpValue(MI, MO, Fixups, STI);
260
261 addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP16);
262 return 0;
263 }
264
getCompareAndBranchTargetOpValue(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const265 unsigned SparcMCCodeEmitter::getCompareAndBranchTargetOpValue(
266 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
267 const MCSubtargetInfo &STI) const {
268 const MCOperand &MO = MI.getOperand(OpNo);
269 if (MO.isImm())
270 return getMachineOpValue(MI, MO, Fixups, STI);
271
272 addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP10);
273 return 0;
274 }
275
276 #include "SparcGenMCCodeEmitter.inc"
277
createSparcMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)278 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
279 MCContext &Ctx) {
280 return new SparcMCCodeEmitter(MCII, Ctx);
281 }
282