MachineCodeEmitter.cpp revision 37efe6764568a3829fee26aba532283131d1a104
1//===-- MachineCodeEmitter.cpp - Implement the MachineCodeEmitter itf -----===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the MachineCodeEmitter interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/CodeGen/MachineCodeEmitter.h"
15#include "llvm/CodeGen/MachineFunction.h"
16#include "llvm/Function.h"
17#include <fstream>
18#include <iostream>
19#include <ios>
20
21using namespace llvm;
22
23namespace {
24  struct DebugMachineCodeEmitter : public MachineCodeEmitter {
25    void startFunction(MachineFunction &F) {
26      std::cout << "\n**** Writing machine code for function: "
27                << F.getFunction()->getName() << "\n";
28    }
29    void finishFunction(MachineFunction &F) {
30      std::cout << "\n";
31    }
32    void startFunctionStub(unsigned StubSize) {
33      std::cout << "\n--- Function stub:\n";
34    }
35    void *finishFunctionStub(const Function *F) {
36      std::cout << "\n--- End of stub for Function\n";
37      return 0;
38    }
39
40    void emitByte(unsigned char B) {
41      std::cout << "0x" << std::hex << (unsigned int)B << std::dec << " ";
42    }
43    void emitWord(unsigned W) {
44      std::cout << "0x" << std::hex << W << std::dec << " ";
45    }
46    void emitWordAt(unsigned W, unsigned *Ptr) {
47      std::cout << "0x" << std::hex << W << std::dec << " (at "
48                << (void*) Ptr << ") ";
49    }
50
51    void addRelocation(const MachineRelocation &MR) {
52      std::cout << "<relocation> ";
53    }
54
55    virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment)
56    { return 0; }
57
58    uint64_t getConstantPoolEntryAddress(unsigned Num) { return 0; }
59    uint64_t getJumpTableEntryAddress(unsigned Num) { return 0; }
60    uint64_t getCurrentPCValue() { return 0; }
61    uint64_t getCurrentPCOffset() { return 0; }
62  };
63
64  class FilePrinterEmitter : public MachineCodeEmitter {
65    std::ofstream actual;
66    std::ostream &o;
67    MachineCodeEmitter &MCE;
68    unsigned counter;
69    unsigned values[4];
70
71  public:
72    FilePrinterEmitter(MachineCodeEmitter &M, std::ostream &os)
73      : o(os), MCE(M), counter(0) {
74      openActual();
75    }
76
77    ~FilePrinterEmitter() {
78      o << "\n";
79      actual.close();
80    }
81
82    void openActual() {
83      actual.open("lli.actual.obj");
84      if (!actual.good()) {
85        std::cerr << "Cannot open 'lli.actual.obj' for writing\n";
86        abort();
87      }
88    }
89
90    void startFunction(MachineFunction &F) {
91      // resolve any outstanding calls
92      MCE.startFunction(F);
93    }
94    void finishFunction(MachineFunction &F) {
95      MCE.finishFunction(F);
96    }
97
98    void emitConstantPool(MachineConstantPool *MCP) {
99      MCE.emitConstantPool(MCP);
100    }
101    void initJumpTableInfo(MachineJumpTableInfo *MJTI) {
102      MCE.initJumpTableInfo(MJTI);
103    }
104    void emitJumpTableInfo(MachineJumpTableInfo *MJTI,
105                           std::map<MachineBasicBlock*,uint64_t> &MBBM) {
106      MCE.emitJumpTableInfo(MJTI, MBBM);
107    }
108
109    void startFunctionStub(unsigned StubSize) {
110      MCE.startFunctionStub(StubSize);
111    }
112
113    void *finishFunctionStub(const Function *F) {
114      return MCE.finishFunctionStub(F);
115    }
116
117    void emitByte(unsigned char B) {
118      MCE.emitByte(B);
119      actual << B; actual.flush();
120
121      values[counter] = (unsigned int) B;
122      if (++counter % 4 == 0 && counter != 0) {
123        o << std::hex;
124        for (unsigned i=0; i<4; ++i) {
125          if (values[i] < 16) o << "0";
126          o << values[i] << " ";
127        }
128
129        o << std::dec << "\t";
130        for (unsigned i=0; i<4; ++i) {
131          for (int j=7; j>=0; --j) {
132            o << ((values[i] >> j) & 1);
133          }
134          o << " ";
135        }
136
137        o << "\n";
138
139        unsigned instr = 0;
140        for (unsigned i=0; i<4; ++i)
141          instr |= values[i] << (i*8);
142
143        o << "--- * --- * --- * --- * ---\n";
144        counter %= 4;
145      }
146    }
147
148    void emitWord(unsigned W) {
149      MCE.emitWord(W);
150    }
151    void emitWordAt(unsigned W, unsigned *Ptr) {
152      MCE.emitWordAt(W, Ptr);
153    }
154    uint64_t getConstantPoolEntryAddress(unsigned Num) {
155      return MCE.getConstantPoolEntryAddress(Num);
156    }
157    uint64_t getJumpTableEntryAddress(unsigned Num) {
158      return MCE.getJumpTableEntryAddress(Num);
159    }
160    virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment)
161    { return MCE.allocateGlobal(size, alignment); }
162
163    uint64_t getCurrentPCValue() {
164      return MCE.getCurrentPCValue();
165    }
166    uint64_t getCurrentPCOffset() {
167      return MCE.getCurrentPCOffset();
168    }
169    void addRelocation(const MachineRelocation &MR) {
170      return MCE.addRelocation(MR);
171    }
172  };
173}
174
175/// createDebugMachineCodeEmitter - Return a dynamically allocated machine
176/// code emitter, which just prints the opcodes and fields out the cout.  This
177/// can be used for debugging users of the MachineCodeEmitter interface.
178///
179MachineCodeEmitter *
180MachineCodeEmitter::createDebugEmitter() {
181  return new DebugMachineCodeEmitter();
182}
183
184MachineCodeEmitter *
185MachineCodeEmitter::createFilePrinterEmitter(MachineCodeEmitter &MCE) {
186  return new FilePrinterEmitter(MCE, std::cerr);
187}
188