Make <target>CodeEmitter::getBinaryCodeForInstr() a const method.
[oota-llvm.git] / lib / Target / ARM / ARMMCCodeEmitter.cpp
1 //===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM 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 ARMMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "arm-emitter"
15 #include "ARM.h"
16 #include "ARMInstrInfo.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace llvm;
23
24 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
25
26 namespace {
27 class ARMMCCodeEmitter : public MCCodeEmitter {
28   ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
29   void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
30   const TargetMachine &TM;
31   const TargetInstrInfo &TII;
32   MCContext &Ctx;
33
34 public:
35   ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
36     : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
37   }
38
39   ~ARMMCCodeEmitter() {}
40
41   // getBinaryCodeForInstr - TableGen'erated function for getting the
42   // binary encoding for an instruction.
43   unsigned getBinaryCodeForInstr(const MCInst &MI) const;
44
45   /// getMachineOpValue - Return binary encoding of operand. If the machine
46   /// operand requires relocation, record the relocation and return zero.
47   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO);
48   unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) {
49     return getMachineOpValue(MI, MI.getOperand(OpIdx));
50   }
51
52   unsigned getNumFixupKinds() const {
53     assert(0 && "ARMMCCodeEmitter::getNumFixupKinds() not yet implemented.");
54     return 0;
55   }
56
57   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
58     static MCFixupKindInfo rtn;
59     assert(0 && "ARMMCCodeEmitter::getFixupKindInfo() not yet implemented.");
60     return rtn;
61   }
62
63   static unsigned GetARMRegNum(const MCOperand &MO) {
64     // FIXME: getARMRegisterNumbering() is sufficient?
65     assert(0 && "ARMMCCodeEmitter::GetARMRegNum() not yet implemented.");
66     return 0;
67   }
68
69   void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
70     OS << (char)C;
71     ++CurByte;
72   }
73
74   void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
75                     raw_ostream &OS) const {
76     // Output the constant in little endian byte order.
77     for (unsigned i = 0; i != Size; ++i) {
78       EmitByte(Val & 255, CurByte, OS);
79       Val >>= 8;
80     }
81   }
82
83   void EmitImmediate(const MCOperand &Disp,
84                      unsigned ImmSize, MCFixupKind FixupKind,
85                      unsigned &CurByte, raw_ostream &OS,
86                      SmallVectorImpl<MCFixup> &Fixups,
87                      int ImmOffset = 0) const;
88
89   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
90                          SmallVectorImpl<MCFixup> &Fixups) const;
91 };
92
93 } // end anonymous namespace
94
95
96 MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &,
97                                              TargetMachine &TM,
98                                              MCContext &Ctx) {
99   return new ARMMCCodeEmitter(TM, Ctx);
100 }
101
102 void ARMMCCodeEmitter::
103 EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
104               unsigned &CurByte, raw_ostream &OS,
105               SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const {
106   assert(0 && "ARMMCCodeEmitter::EmitImmediate() not yet implemented.");
107 }
108
109 void ARMMCCodeEmitter::
110 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
111                   SmallVectorImpl<MCFixup> &Fixups) const {
112   unsigned Opcode = MI.getOpcode();
113   const TargetInstrDesc &Desc = TII.get(Opcode);
114   uint64_t TSFlags = Desc.TSFlags;
115
116   // Pseudo instructions don't get encoded.
117   if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
118     return;
119
120   ++MCNumEmitted;  // Keep track of the # of mi's emitted
121   switch (TSFlags & ARMII::FormMask) {
122   default: {
123     llvm_unreachable("Unhandled instruction encoding format!");
124     break;
125   }
126   }
127 }
128
129 // FIXME: These #defines shouldn't be necessary. Instead, tblgen should
130 // be able to generate code emitter helpers for either variant, like it
131 // does for the AsmWriter.
132 #define ARMCodeEmitter ARMMCCodeEmitter
133 #define MachineInstr MCInst
134 #include "ARMGenCodeEmitter.inc"
135 #undef ARMCodeEmitter
136 #undef MachineInstr