xref: /llvm-project/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
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 "SparcMCExpr.h"
15 #include "SparcMCTargetDesc.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/Statistic.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:
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 getSImm13OpValue(const MCInst &MI, unsigned OpNo,
75                             SmallVectorImpl<MCFixup> &Fixups,
76                             const MCSubtargetInfo &STI) const;
77   unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
78                                       SmallVectorImpl<MCFixup> &Fixups,
79                                       const MCSubtargetInfo &STI) const;
80   unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
81                                        SmallVectorImpl<MCFixup> &Fixups,
82                                        const MCSubtargetInfo &STI) const;
83 };
84 
85 } // end anonymous namespace
86 
87 void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI,
88                                            SmallVectorImpl<char> &CB,
89                                            SmallVectorImpl<MCFixup> &Fixups,
90                                            const MCSubtargetInfo &STI) const {
91   unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
92   support::endian::write(CB, Bits,
93                          Ctx.getAsmInfo()->isLittleEndian()
94                              ? llvm::endianness::little
95                              : llvm::endianness::big);
96 
97   // Some instructions have phantom operands that only contribute a fixup entry.
98   unsigned SymOpNo = 0;
99   switch (MI.getOpcode()) {
100   default: break;
101   case SP::TLS_CALL:   SymOpNo = 1; break;
102   case SP::GDOP_LDrr:
103   case SP::GDOP_LDXrr:
104   case SP::TLS_ADDrr:
105   case SP::TLS_LDrr:
106   case SP::TLS_LDXrr:  SymOpNo = 3; break;
107   }
108   if (SymOpNo != 0) {
109     const MCOperand &MO = MI.getOperand(SymOpNo);
110     uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
111     assert(op == 0 && "Unexpected operand value!");
112     (void)op; // suppress warning.
113   }
114 
115   ++MCNumEmitted;  // Keep track of the # of mi's emitted.
116 }
117 
118 unsigned SparcMCCodeEmitter::
119 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
120                   SmallVectorImpl<MCFixup> &Fixups,
121                   const MCSubtargetInfo &STI) const {
122   if (MO.isReg())
123     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
124 
125   if (MO.isImm())
126     return MO.getImm();
127 
128   assert(MO.isExpr());
129   const MCExpr *Expr = MO.getExpr();
130   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
131     MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
132     Fixups.push_back(MCFixup::create(0, Expr, Kind));
133     return 0;
134   }
135 
136   int64_t Res;
137   if (Expr->evaluateAsAbsolute(Res))
138     return Res;
139 
140   llvm_unreachable("Unhandled expression!");
141   return 0;
142 }
143 
144 unsigned
145 SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
146                                      SmallVectorImpl<MCFixup> &Fixups,
147                                      const MCSubtargetInfo &STI) const {
148   const MCOperand &MO = MI.getOperand(OpNo);
149 
150   if (MO.isImm())
151     return MO.getImm();
152 
153   assert(MO.isExpr() &&
154          "getSImm13OpValue expects only expressions or an immediate");
155 
156   const MCExpr *Expr = MO.getExpr();
157 
158   // Constant value, no fixup is needed
159   if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
160     return CE->getValue();
161 
162   MCFixupKind Kind;
163   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
164     Kind = MCFixupKind(SExpr->getFixupKind());
165   } else {
166     bool IsPic = Ctx.getObjectFileInfo()->isPositionIndependent();
167     Kind = IsPic ? MCFixupKind(Sparc::fixup_sparc_got13)
168                  : MCFixupKind(Sparc::fixup_sparc_13);
169   }
170 
171   Fixups.push_back(MCFixup::create(0, Expr, Kind));
172   return 0;
173 }
174 
175 unsigned SparcMCCodeEmitter::
176 getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
177                      SmallVectorImpl<MCFixup> &Fixups,
178                      const MCSubtargetInfo &STI) const {
179   const MCOperand &MO = MI.getOperand(OpNo);
180   const MCExpr *Expr = MO.getExpr();
181   const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr);
182 
183   if (MI.getOpcode() == SP::TLS_CALL) {
184     // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
185     // encodeInstruction.
186 #ifndef NDEBUG
187     // Verify that the callee is actually __tls_get_addr.
188     assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
189            "Unexpected expression in TLS_CALL");
190     const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
191     assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
192            "Unexpected function for TLS_CALL");
193 #endif
194     return 0;
195   }
196 
197   MCFixupKind Kind = MCFixupKind(SExpr->getFixupKind());
198   Fixups.push_back(MCFixup::create(0, Expr, Kind));
199   return 0;
200 }
201 
202 unsigned SparcMCCodeEmitter::
203 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
204                   SmallVectorImpl<MCFixup> &Fixups,
205                   const MCSubtargetInfo &STI) const {
206   const MCOperand &MO = MI.getOperand(OpNo);
207   if (MO.isReg() || MO.isImm())
208     return getMachineOpValue(MI, MO, Fixups, STI);
209 
210   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
211                                    (MCFixupKind)Sparc::fixup_sparc_br22));
212   return 0;
213 }
214 
215 unsigned SparcMCCodeEmitter::
216 getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
217                            SmallVectorImpl<MCFixup> &Fixups,
218                            const MCSubtargetInfo &STI) const {
219   const MCOperand &MO = MI.getOperand(OpNo);
220   if (MO.isReg() || MO.isImm())
221     return getMachineOpValue(MI, MO, Fixups, STI);
222 
223   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
224                                    (MCFixupKind)Sparc::fixup_sparc_br19));
225   return 0;
226 }
227 
228 unsigned SparcMCCodeEmitter::
229 getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
230                            SmallVectorImpl<MCFixup> &Fixups,
231                            const MCSubtargetInfo &STI) const {
232   const MCOperand &MO = MI.getOperand(OpNo);
233   if (MO.isReg() || MO.isImm())
234     return getMachineOpValue(MI, MO, Fixups, STI);
235 
236   Fixups.push_back(
237       MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br16));
238 
239   return 0;
240 }
241 
242 #include "SparcGenMCCodeEmitter.inc"
243 
244 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
245                                               MCContext &Ctx) {
246   return new SparcMCCodeEmitter(MCII, Ctx);
247 }
248