LLVM  16.0.0git
SystemZMCCodeEmitter.cpp
Go to the documentation of this file.
1 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ 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 SystemZMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
15 #include "SystemZInstrInfo.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCFixup.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCRegisterInfo.h"
27 #include <cassert>
28 #include <cstdint>
29 
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "mccodeemitter"
33 
34 namespace {
35 
36 class SystemZMCCodeEmitter : public MCCodeEmitter {
37  const MCInstrInfo &MCII;
38  MCContext &Ctx;
39 
40  mutable unsigned MemOpsEmitted;
41 
42 public:
43  SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
44  : MCII(mcii), Ctx(ctx) {
45  }
46 
47  ~SystemZMCCodeEmitter() override = default;
48 
49  // OVerride MCCodeEmitter.
50  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
52  const MCSubtargetInfo &STI) const override;
53 
54 private:
55  // Automatically generated by TableGen.
56  uint64_t getBinaryCodeForInstr(const MCInst &MI,
58  const MCSubtargetInfo &STI) const;
59 
60  // Called by the TableGen code to get the binary encoding of operand
61  // MO in MI. Fixups is the list of fixups against MI.
62  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
64  const MCSubtargetInfo &STI) const;
65 
66  // Return the displacement value for the OpNum operand. If it is a symbol,
67  // add a fixup for it and return 0.
68  uint64_t getDispOpValue(const MCInst &MI, unsigned OpNum,
70  SystemZ::FixupKind Kind) const;
71 
72  // Called by the TableGen code to get the binary encoding of an address.
73  // The index or length, if any, is encoded first, followed by the base,
74  // followed by the displacement. In a 20-bit displacement,
75  // the low 12 bits are encoded before the high 8 bits.
76  uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
78  const MCSubtargetInfo &STI) const;
79  uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
81  const MCSubtargetInfo &STI) const;
82  uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
84  const MCSubtargetInfo &STI) const;
85  uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
87  const MCSubtargetInfo &STI) const;
88  uint64_t getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
90  const MCSubtargetInfo &STI) const;
91  uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
93  const MCSubtargetInfo &STI) const;
94  uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
96  const MCSubtargetInfo &STI) const;
97  uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
99  const MCSubtargetInfo &STI) const;
100 
101  // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
102  // Offset bytes from the start of MI. Add the fixup to Fixups
103  // and return the in-place addend, which since we're a RELA target
104  // is always 0. If AllowTLS is true and optional operand OpNum + 1
105  // is present, also emit a TLS call fixup for it.
106  uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
108  unsigned Kind, int64_t Offset,
109  bool AllowTLS) const;
110 
111  uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
113  const MCSubtargetInfo &STI) const {
114  return getPCRelEncoding(MI, OpNum, Fixups,
115  SystemZ::FK_390_PC16DBL, 2, false);
116  }
117  uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
119  const MCSubtargetInfo &STI) const {
120  return getPCRelEncoding(MI, OpNum, Fixups,
121  SystemZ::FK_390_PC32DBL, 2, false);
122  }
123  uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
125  const MCSubtargetInfo &STI) const {
126  return getPCRelEncoding(MI, OpNum, Fixups,
127  SystemZ::FK_390_PC16DBL, 2, true);
128  }
129  uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
131  const MCSubtargetInfo &STI) const {
132  return getPCRelEncoding(MI, OpNum, Fixups,
133  SystemZ::FK_390_PC32DBL, 2, true);
134  }
135  uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
137  const MCSubtargetInfo &STI) const {
138  return getPCRelEncoding(MI, OpNum, Fixups,
139  SystemZ::FK_390_PC12DBL, 1, false);
140  }
141  uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
143  const MCSubtargetInfo &STI) const {
144  return getPCRelEncoding(MI, OpNum, Fixups,
145  SystemZ::FK_390_PC16DBL, 4, false);
146  }
147  uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
149  const MCSubtargetInfo &STI) const {
150  return getPCRelEncoding(MI, OpNum, Fixups,
151  SystemZ::FK_390_PC24DBL, 3, false);
152  }
153 };
154 
155 } // end anonymous namespace
156 
157 void SystemZMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
159  const MCSubtargetInfo &STI) const {
160  MemOpsEmitted = 0;
161  uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
162  unsigned Size = MCII.get(MI.getOpcode()).getSize();
163  // Big-endian insertion of Size bytes.
164  unsigned ShiftValue = (Size * 8) - 8;
165  for (unsigned I = 0; I != Size; ++I) {
166  OS << uint8_t(Bits >> ShiftValue);
167  ShiftValue -= 8;
168  }
169 }
170 
171 uint64_t SystemZMCCodeEmitter::
172 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
174  const MCSubtargetInfo &STI) const {
175  if (MO.isReg())
176  return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
177  if (MO.isImm())
178  return static_cast<uint64_t>(MO.getImm());
179  llvm_unreachable("Unexpected operand type!");
180 }
181 
182 uint64_t SystemZMCCodeEmitter::
183 getDispOpValue(const MCInst &MI, unsigned OpNum,
185  SystemZ::FixupKind Kind) const {
186  const MCOperand &MO = MI.getOperand(OpNum);
187  if (MO.isImm()) {
188  ++MemOpsEmitted;
189  return static_cast<uint64_t>(MO.getImm());
190  }
191  if (MO.isExpr()) {
192  // All instructions follow the pattern where the first displacement has a
193  // 2 bytes offset, and the second one 4 bytes.
194  unsigned ByteOffs = MemOpsEmitted++ == 0 ? 2 : 4;
195  Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind,
196  MI.getLoc()));
197  assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
198  return 0;
199  }
200  llvm_unreachable("Unexpected operand type!");
201 }
202 
203 uint64_t SystemZMCCodeEmitter::
204 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
206  const MCSubtargetInfo &STI) const {
207  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
208  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
209  assert(isUInt<4>(Base) && isUInt<12>(Disp));
210  return (Base << 12) | Disp;
211 }
212 
213 uint64_t SystemZMCCodeEmitter::
214 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
216  const MCSubtargetInfo &STI) const {
217  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
218  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
219  assert(isUInt<4>(Base) && isInt<20>(Disp));
220  return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
221 }
222 
223 uint64_t SystemZMCCodeEmitter::
224 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
226  const MCSubtargetInfo &STI) const {
227  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
228  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
229  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
230  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
231  return (Index << 16) | (Base << 12) | Disp;
232 }
233 
234 uint64_t SystemZMCCodeEmitter::
235 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
237  const MCSubtargetInfo &STI) const {
238  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
239  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
240  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
241  assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
242  return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
243  | ((Disp & 0xff000) >> 12);
244 }
245 
246 uint64_t SystemZMCCodeEmitter::
247 getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
249  const MCSubtargetInfo &STI) const {
250  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
251  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
252  uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
253  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
254  return (Len << 16) | (Base << 12) | Disp;
255 }
256 
257 uint64_t SystemZMCCodeEmitter::
258 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
260  const MCSubtargetInfo &STI) const {
261  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
262  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
263  uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
264  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
265  return (Len << 16) | (Base << 12) | Disp;
266 }
267 
268 uint64_t SystemZMCCodeEmitter::
269 getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
271  const MCSubtargetInfo &STI) const {
272  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
273  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
274  uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
275  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
276  return (Len << 16) | (Base << 12) | Disp;
277 }
278 
279 uint64_t SystemZMCCodeEmitter::
280 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
282  const MCSubtargetInfo &STI) const {
283  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
284  uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
285  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
286  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
287  return (Index << 16) | (Base << 12) | Disp;
288 }
289 
290 uint64_t
291 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
293  unsigned Kind, int64_t Offset,
294  bool AllowTLS) const {
295  SMLoc Loc = MI.getLoc();
296  const MCOperand &MO = MI.getOperand(OpNum);
297  const MCExpr *Expr;
298  if (MO.isImm())
299  Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
300  else {
301  Expr = MO.getExpr();
302  if (Offset) {
303  // The operand value is relative to the start of MI, but the fixup
304  // is relative to the operand field itself, which is Offset bytes
305  // into MI. Add Offset to the relocation value to cancel out
306  // this difference.
307  const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
308  Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
309  }
310  }
311  Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind, Loc));
312 
313  // Output the fixup for the TLS marker if present.
314  if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
315  const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
316  Fixups.push_back(MCFixup::create(
317  0, MOTLS.getExpr(), (MCFixupKind)SystemZ::FK_390_TLS_CALL, Loc));
318  }
319  return 0;
320 }
321 
322 #include "SystemZGenMCCodeEmitter.inc"
323 
325  MCContext &Ctx) {
326  return new SystemZMCCodeEmitter(MCII, Ctx);
327 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:108
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::SystemZ::FK_390_20
@ FK_390_20
Definition: SystemZMCFixups.h:24
llvm::MCOperand::isReg
bool isReg() const
Definition: MCInst.h:61
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:76
MCCodeEmitter.h
llvm::MCConstantExpr::create
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
llvm::SystemZ::FK_390_PC16DBL
@ FK_390_PC16DBL
Definition: SystemZMCFixups.h:19
llvm::MCFixup::create
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
ErrorHandling.h
llvm::tgtok::Bits
@ Bits
Definition: TGLexer.h:50
SystemZMCTargetDesc.h
llvm::SystemZ::FK_390_PC12DBL
@ FK_390_PC12DBL
Definition: SystemZMCFixups.h:18
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::createSystemZMCCodeEmitter
MCCodeEmitter * createSystemZMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Definition: SystemZMCCodeEmitter.cpp:324
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
SystemZInstrInfo.h
llvm::SystemZ::FK_390_PC24DBL
@ FK_390_PC24DBL
Definition: SystemZMCFixups.h:20
MCContext.h
MCInstrInfo.h
llvm::MCOperand::getImm
int64_t getImm() const
Definition: MCInst.h:80
llvm::SystemZ::FK_390_TLS_CALL
@ FK_390_TLS_CALL
Definition: SystemZMCFixups.h:22
MCInst.h
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::AArch64::Fixups
Fixups
Definition: AArch64FixupKinds.h:17
MCSubtargetInfo.h
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::SystemZ::FK_390_12
@ FK_390_12
Definition: SystemZMCFixups.h:23
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::MCOperand::isImm
bool isImm() const
Definition: MCInst.h:62
uint64_t
I
#define I(x, y, z)
Definition: MD5.cpp:58
MCRegisterInfo.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::SystemZ::FK_390_PC32DBL
@ FK_390_PC32DBL
Definition: SystemZMCFixups.h:21
llvm::MCBinaryExpr::createAdd
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
MCFixup.h
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
SystemZMCFixups.h
llvm::MCCodeEmitter
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
llvm::MCOperand::getExpr
const MCExpr * getExpr() const
Definition: MCInst.h:114
llvm::SystemZ::FixupKind
FixupKind
Definition: SystemZMCFixups.h:16
llvm::MCOperand::isExpr
bool isExpr() const
Definition: MCInst.h:65
llvm::MCFixupKind
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
SmallVector.h
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
raw_ostream.h
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:76
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
llvm::MCOperand::getReg
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69