LLVM 22.0.0git
SparcMCCodeEmitter.cpp
Go to the documentation of this file.
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
14#include "SparcMCTargetDesc.h"
16#include "llvm/ADT/Statistic.h"
18#include "llvm/MC/MCAsmInfo.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"
28#include "llvm/MC/MCSymbol.h"
32#include <cassert>
33#include <cstdint>
34
35using namespace llvm;
36
37#define DEBUG_TYPE "mccodeemitter"
38
39STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
40
41namespace {
42
43class SparcMCCodeEmitter : public MCCodeEmitter {
44 MCContext &Ctx;
45
46public:
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
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,
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,
67 const MCSubtargetInfo &STI) const;
68 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
70 const MCSubtargetInfo &STI) const;
71 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
73 const MCSubtargetInfo &STI) const;
74 unsigned getSImm5OpValue(const MCInst &MI, unsigned OpNo,
76 const MCSubtargetInfo &STI) const;
77 unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,
79 const MCSubtargetInfo &STI) const;
80 unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
82 const MCSubtargetInfo &STI) const;
83 unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
85 const MCSubtargetInfo &STI) const;
86 unsigned getCompareAndBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
88 const MCSubtargetInfo &STI) const;
89};
90
91} // end anonymous namespace
92
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:
104 PCRel = true;
105 }
106 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
107}
108
109void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI,
112 const MCSubtargetInfo &STI) const {
113 unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
114 support::endian::write(CB, Bits,
115 Ctx.getAsmInfo()->isLittleEndian()
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
140unsigned SparcMCCodeEmitter::
141getMachineOpValue(const MCInst &MI, const MCOperand &MO,
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
165unsigned SparcMCCodeEmitter::getSImm5OpValue(const MCInst &MI, unsigned OpNo,
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
190unsigned
191SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
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
216unsigned SparcMCCodeEmitter::
217getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
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);
228 return 0;
229}
230
231unsigned SparcMCCodeEmitter::
232getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
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
243unsigned 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
254unsigned 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
265unsigned 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
279 MCContext &Ctx) {
280 return new SparcMCCodeEmitter(MCII, Ctx);
281}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, unsigned FixupKind, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI)
getBranchTargetOpValue - Helper function to get the branch target operand, which is either an immedia...
#define op(i)
IRTranslator LLVM IR MI
This file defines the SmallVector class.
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
MCCodeEmitter & operator=(const MCCodeEmitter &)=delete
Context object for machine code objects.
Definition: MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition: MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
int64_t getImm() const
Definition: MCInst.h:84
bool isImm() const
Definition: MCInst.h:66
bool isReg() const
Definition: MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:73
const MCExpr * getExpr() const
Definition: MCInst.h:118
bool isExpr() const
Definition: MCInst.h:69
Generic base class for all target subtargets.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
LLVM Value Representation.
Definition: Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ fixup_sparc_13
fixup_sparc_13 - 13-bit fixup
@ CE
Windows NT (Windows on ARM)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:92
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
MCCodeEmitter * createSparcMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)