1 //===-- RISCVMCCodeEmitter.cpp - Convert RISCV code to machine code -------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the RISCVMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/RISCVMCTargetDesc.h"
15 #include "llvm/ADT/Statistic.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Support/EndianStream.h"
24 #include "llvm/Support/raw_ostream.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "mccodeemitter"
29 
30 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
31 
32 namespace {
33 class RISCVMCCodeEmitter : public MCCodeEmitter {
34   RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;
35   void operator=(const RISCVMCCodeEmitter &) = delete;
36   MCContext &Ctx;
37 
38 public:
39   RISCVMCCodeEmitter(MCContext &ctx) : Ctx(ctx) {}
40 
41   ~RISCVMCCodeEmitter() override {}
42 
43   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
44                          SmallVectorImpl<MCFixup> &Fixups,
45                          const MCSubtargetInfo &STI) const override;
46 
47   /// TableGen'erated function for getting the binary encoding for an
48   /// instruction.
49   uint64_t getBinaryCodeForInstr(const MCInst &MI,
50                                  SmallVectorImpl<MCFixup> &Fixups,
51                                  const MCSubtargetInfo &STI) const;
52 
53   /// Return binary encoding of operand. If the machine operand requires
54   /// relocation, record the relocation and return zero.
55   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
56                              SmallVectorImpl<MCFixup> &Fixups,
57                              const MCSubtargetInfo &STI) const;
58 };
59 } // end anonymous namespace
60 
61 MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,
62                                               const MCRegisterInfo &MRI,
63                                               MCContext &Ctx) {
64   return new RISCVMCCodeEmitter(Ctx);
65 }
66 
67 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
68                                            SmallVectorImpl<MCFixup> &Fixups,
69                                            const MCSubtargetInfo &STI) const {
70   // For now, we only support RISC-V instructions with 32-bit length
71   uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
72   support::endian::Writer<support::little>(OS).write(Bits);
73   ++MCNumEmitted; // Keep track of the # of mi's emitted.
74 }
75 
76 unsigned
77 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
78                                       SmallVectorImpl<MCFixup> &Fixups,
79                                       const MCSubtargetInfo &STI) const {
80 
81   if (MO.isReg())
82     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
83 
84   if (MO.isImm())
85     return static_cast<unsigned>(MO.getImm());
86 
87   llvm_unreachable("Unhandled expression!");
88   return 0;
89 }
90 
91 #include "RISCVGenMCCodeEmitter.inc"
92