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