MachineCodeEmitter.cpp revision 8c7bd3615a8722d981a1a7e8a6a2dd3b1d56ef4d
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 getCurrentPCValue() { return 0; }
60    uint64_t getCurrentPCOffset() { return 0; }
61  };
62
63  class FilePrinterEmitter : public MachineCodeEmitter {
64    std::ofstream actual;
65    std::ostream &o;
66    MachineCodeEmitter &MCE;
67    unsigned counter;
68    unsigned values[4];
69
70  public:
71    FilePrinterEmitter(MachineCodeEmitter &M, std::ostream &os)
72      : o(os), MCE(M), counter(0) {
73      openActual();
74    }
75
76    ~FilePrinterEmitter() {
77      o << "\n";
78      actual.close();
79    }
80
81    void openActual() {
82      actual.open("lli.actual.obj");
83      if (!actual.good()) {
84        std::cerr << "Cannot open 'lli.actual.obj' for writing\n";
85        abort();
86      }
87    }
88
89    void startFunction(MachineFunction &F) {
90      // resolve any outstanding calls
91      MCE.startFunction(F);
92    }
93    void finishFunction(MachineFunction &F) {
94      MCE.finishFunction(F);
95    }
96
97    void emitConstantPool(MachineConstantPool *MCP) {
98      MCE.emitConstantPool(MCP);
99    }
100
101    void startFunctionStub(unsigned StubSize) {
102      MCE.startFunctionStub(StubSize);
103    }
104
105    void *finishFunctionStub(const Function *F) {
106      return MCE.finishFunctionStub(F);
107    }
108
109    void emitByte(unsigned char B) {
110      MCE.emitByte(B);
111      actual << B; actual.flush();
112
113      values[counter] = (unsigned int) B;
114      if (++counter % 4 == 0 && counter != 0) {
115        o << std::hex;
116        for (unsigned i=0; i<4; ++i) {
117          if (values[i] < 16) o << "0";
118          o << values[i] << " ";
119        }
120
121        o << std::dec << "\t";
122        for (unsigned i=0; i<4; ++i) {
123          for (int j=7; j>=0; --j) {
124            o << ((values[i] >> j) & 1);
125          }
126          o << " ";
127        }
128
129        o << "\n";
130
131        unsigned instr = 0;
132        for (unsigned i=0; i<4; ++i)
133          instr |= values[i] << (i*8);
134
135        o << "--- * --- * --- * --- * ---\n";
136        counter %= 4;
137      }
138    }
139
140    void emitWord(unsigned W) {
141      MCE.emitWord(W);
142    }
143    void emitWordAt(unsigned W, unsigned *Ptr) {
144      MCE.emitWordAt(W, Ptr);
145    }
146    uint64_t getConstantPoolEntryAddress(unsigned Num) {
147      return MCE.getConstantPoolEntryAddress(Num);
148    }
149
150    virtual unsigned char* allocateGlobal(unsigned size, unsigned alignment)
151    { return MCE.allocateGlobal(size, alignment); }
152
153    uint64_t getCurrentPCValue() {
154      return MCE.getCurrentPCValue();
155    }
156    uint64_t getCurrentPCOffset() {
157      return MCE.getCurrentPCOffset();
158    }
159    void addRelocation(const MachineRelocation &MR) {
160      return MCE.addRelocation(MR);
161    }
162  };
163}
164
165/// createDebugMachineCodeEmitter - Return a dynamically allocated machine
166/// code emitter, which just prints the opcodes and fields out the cout.  This
167/// can be used for debugging users of the MachineCodeEmitter interface.
168///
169MachineCodeEmitter *
170MachineCodeEmitter::createDebugEmitter() {
171  return new DebugMachineCodeEmitter();
172}
173
174MachineCodeEmitter *
175MachineCodeEmitter::createFilePrinterEmitter(MachineCodeEmitter &MCE) {
176  return new FilePrinterEmitter(MCE, std::cerr);
177}
178