summaryrefslogtreecommitdiff
path: root/lib/Target/SparcV9/MappingInfo.cpp
blob: 58f19378aa8c565b6971788caa78490694f1a153 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
//===- MappingInfo.cpp - create LLVM info and output to .s file -----------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file contains a FunctionPass called MappingInfoAsmPrinter,
// which creates two maps: one between LLVM Instructions and MachineInstrs
// (the "LLVM I TO MI MAP"), and another between MachineBasicBlocks and
// MachineInstrs (the "BB TO MI MAP").
//
// As a side effect, it outputs this information as .byte directives to
// the assembly file. The output is designed to survive the SPARC assembler,
// in order that the Reoptimizer may read it in from memory later when the
// binary is loaded. Therefore, it may contain some hidden SPARC-architecture
// dependencies. Currently this question is purely theoretical as the
// Reoptimizer works only on the SPARC.
//
// The LLVM I TO MI MAP consists of a set of information for each
// BasicBlock in a Function, ordered from begin() to end(). The information
// for a BasicBlock consists of
//  1) its (0-based) index in the Function,
//  2) the number of LLVM Instructions it contains, and
//  3) information for each Instruction, in sequence from the begin()
//     to the end() of the BasicBlock. The information for an Instruction
//     consists of
//     1) its (0-based) index in the BasicBlock,
//     2) the number of MachineInstrs that correspond to that Instruction
//        (as reported by MachineCodeForInstruction), and
//     3) the MachineInstr number calculated by create_MI_to_number_Key,
//        for each of the MachineInstrs that correspond to that Instruction.
//
// The BB TO MI MAP consists of a three-element tuple for each
// MachineBasicBlock in a function, ordered from begin() to end() of
// its MachineFunction: first, the index of the MachineBasicBlock in the
// function; second, the number of the MachineBasicBlock in the function
// as computed by create_BB_to_MInumber_Key; and third, the number of
// MachineInstrs in the MachineBasicBlock.
//
//===--------------------------------------------------------------------===//

#include "MappingInfo.h"
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "MachineCodeForInstruction.h"
#include "llvm/ADT/StringExtras.h"

namespace llvm {

namespace {
  class MappingInfoAsmPrinter : public FunctionPass { 
    std::ostream &Out;
  public:
    MappingInfoAsmPrinter(std::ostream &out) : Out(out){}
    const char *getPassName () const { return "Instr. Mapping Info Collector"; }
    bool runOnFunction(Function &FI);
    typedef std::map<const MachineInstr*, unsigned> InstructionKey;
  private:
    MappingInfo *currentOutputMap;
    std::map<Function *, unsigned> Fkey; // Function # for all functions.
    bool doInitialization(Module &M);
    void create_BB_to_MInumber_Key(Function &FI, InstructionKey &key);
    void create_MI_to_number_Key(Function &FI, InstructionKey &key);
    void buildBBMIMap (Function &FI, MappingInfo &Map);
    void buildLMIMap (Function &FI, MappingInfo &Map);
    void writeNumber(unsigned X);
    void selectOutputMap (MappingInfo &m) { currentOutputMap = &m; }
    void outByte (unsigned char b) { currentOutputMap->outByte (b); }
    bool doFinalization (Module &M);
  };
}

/// getMappingInfoAsmPrinterPass - Static factory method: returns a new
/// MappingInfoAsmPrinter Pass object, which uses OUT as its output
/// stream for assembly output.
///
ModulePass *getMappingInfoAsmPrinterPass(std::ostream &out){
  return new MappingInfoAsmPrinter(out);
}

/// runOnFunction - Builds up the maps for the given function FI and then
/// writes them out as assembly code to the current output stream OUT.
/// This is an entry point to the pass, called by the PassManager.
///
bool MappingInfoAsmPrinter::runOnFunction(Function &FI) {
  unsigned num = Fkey[&FI]; // Function number for the current function.

  // Create objects to hold the maps.
  MappingInfo LMIMap ("LLVM I TO MI MAP", "LMIMap", num);
  MappingInfo BBMIMap ("BB TO MI MAP", "BBMIMap", num);

  // Now, build the maps.
  buildLMIMap (FI, LMIMap);
  buildBBMIMap (FI, BBMIMap);

  // Now, write out the maps.
  LMIMap.dumpAssembly (Out);
  BBMIMap.dumpAssembly (Out);

  return false; 
}  

/// writeNumber - Write out the number X as a sequence of .byte
/// directives to the current output stream Out. This method performs a
/// run-length encoding of the unsigned integers X that are output.
///
void MappingInfoAsmPrinter::writeNumber(unsigned X) {
  unsigned i=0;
  do {
    unsigned tmp = X & 127;
    X >>= 7;
    if (X) tmp |= 128;
    outByte (tmp);
    ++i;
  } while(X);
}

/// doInitialization - Assign a number to each Function, as follows:
/// Functions are numbered starting at 0 at the begin() of each Module.
/// Functions which are External (and thus have 0 basic blocks) are not
/// inserted into the maps, and are not assigned a number.  The side-effect
/// of this method is to fill in Fkey to contain the mapping from Functions
/// to numbers. (This method is called automatically by the PassManager.)
///
bool MappingInfoAsmPrinter::doInitialization(Module &M) {
  unsigned i = 0;
  for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
    if (FI->isExternal()) continue;
    Fkey[FI] = i;
    ++i;
  }
  return false; // Success.
}

/// create_BB_to_MInumber_Key -- Assign a number to each MachineBasicBlock
/// in the given Function, as follows: Numbering starts at zero in each
/// Function. MachineBasicBlocks are numbered from begin() to end()
/// in the Function's corresponding MachineFunction. Each successive
/// MachineBasicBlock increments the numbering by the number of instructions
/// it contains. The side-effect of this method is to fill in the parameter
/// KEY with the mapping of MachineBasicBlocks to numbers. KEY
/// is keyed on MachineInstrs, so each MachineBasicBlock is represented
/// therein by its first MachineInstr.
///
void MappingInfoAsmPrinter::create_BB_to_MInumber_Key(Function &FI,
                                                     InstructionKey &key) {
  unsigned i = 0;
  MachineFunction &MF = MachineFunction::get(&FI);
  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
       BI != BE; ++BI) {
    MachineBasicBlock &miBB = *BI;
    key[&miBB.front()] = i;
    i = i+(miBB.size());
  }
}

/// create_MI_to_number_Key - Assign a number to each MachineInstr
/// in the given Function with respect to its enclosing MachineBasicBlock, as
/// follows: Numberings start at 0 in each MachineBasicBlock. MachineInstrs
/// are numbered from begin() to end() in their MachineBasicBlock. Each
/// MachineInstr is numbered, then the numbering is incremented by 1. The
/// side-effect of this method is to fill in the parameter KEY
/// with the mapping from MachineInstrs to numbers.
///
void MappingInfoAsmPrinter::create_MI_to_number_Key(Function &FI,
                                                   InstructionKey &key) {
  MachineFunction &MF = MachineFunction::get(&FI);
  for (MachineFunction::iterator BI=MF.begin(), BE=MF.end(); BI != BE; ++BI) {
    MachineBasicBlock &miBB = *BI;
    unsigned j = 0;
    for(MachineBasicBlock::iterator miI = miBB.begin(), miE = miBB.end();
        miI != miE; ++miI, ++j) {
      key[miI] = j;
    }
  }
}

/// buildBBMIMap - Build the BB TO MI MAP for the function FI,
/// and save it into the parameter MAP.
///
void MappingInfoAsmPrinter::buildBBMIMap(Function &FI, MappingInfo &Map) {
  unsigned bb = 0;

  // First build temporary table used to write out the map.
  InstructionKey BBkey;
  create_BB_to_MInumber_Key(FI, BBkey);

  selectOutputMap (Map);
  MachineFunction &MF = MachineFunction::get(&FI);  
  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
       BI != BE; ++BI, ++bb) {
    MachineBasicBlock &miBB = *BI;
    writeNumber(bb);
    writeNumber(BBkey[&miBB.front()]);
    writeNumber(miBB.size());
  }
}

/// buildLMIMap - Build the LLVM I TO MI MAP for the function FI,
/// and save it into the parameter MAP.
///
void MappingInfoAsmPrinter::buildLMIMap(Function &FI, MappingInfo &Map) {
  unsigned bb = 0;
  // First build temporary table used to write out the map.
  InstructionKey MIkey;
  create_MI_to_number_Key(FI, MIkey);

  selectOutputMap (Map);
  for (Function::iterator BI = FI.begin(), BE = FI.end(); 
       BI != BE; ++BI, ++bb) {
    unsigned li = 0;
    writeNumber(bb);
    writeNumber(BI->size());
    for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE;
         ++II, ++li) {
      MachineCodeForInstruction& miI = MachineCodeForInstruction::get(II);
      writeNumber(li);
      writeNumber(miI.size());
      for (MachineCodeForInstruction::iterator miII = miI.begin(), 
           miIE = miI.end(); miII != miIE; ++miII) {
	     writeNumber(MIkey[*miII]);
      }
    }
  } 
}

void MappingInfo::byteVector::dumpAssembly (std::ostream &Out) {
  for (iterator i = begin (), e = end (); i != e; ++i)
	Out << ".byte " << (int)*i << "\n";
}

static void writePrologue (std::ostream &Out, const std::string &comment,
			   const std::string &symName) {
  // Prologue:
  // Output a comment describing the object.
  Out << "!" << comment << "\n";   
  // Switch the current section to .rodata in the assembly output:
  Out << "\t.section \".rodata\"\n\t.align 8\n";  
  // Output a global symbol naming the object:
  Out << "\t.global " << symName << "\n";    
  Out << "\t.type " << symName << ",#object\n"; 
  Out << symName << ":\n"; 
}

static void writeEpilogue (std::ostream &Out, const std::string &symName) {
  // Epilogue:
  // Output a local symbol marking the end of the object:
  Out << ".end_" << symName << ":\n";    
  // Output size directive giving the size of the object:
  Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
      << "\n";
}

void MappingInfo::dumpAssembly (std::ostream &Out) {
  const std::string &name (symbolPrefix + utostr (functionNumber));
  writePrologue (Out, comment, name);
  // The LMIMap and BBMIMap are supposed to start with a length word:
  Out << "\t.word .end_" << name << "-" << name << "\n";
  bytes.dumpAssembly (Out);
  writeEpilogue (Out, name);
}

/// doFinalization - This method writes out two tables, named
/// FunctionBB and FunctionLI, which map Function numbers (as in
/// doInitialization) to the BBMIMap and LMIMap tables. (This used to
/// be the "FunctionInfo" pass.)
///
bool MappingInfoAsmPrinter::doFinalization (Module &M) {
  unsigned f;
  
  writePrologue(Out, "FUNCTION TO BB MAP", "FunctionBB");
  f=0;
  for(Module::iterator FI = M.begin (), FE = M.end (); FE != FI; ++FI) {
    if (FI->isExternal ())
      continue;
    Out << "\t.xword BBMIMap" << f << "\n";
    ++f;
  }
  writeEpilogue(Out, "FunctionBB");
  
  writePrologue(Out, "FUNCTION TO LI MAP", "FunctionLI");
  f=0;
  for(Module::iterator FI = M.begin (), FE = M.end (); FE != FI; ++FI) {
    if (FI->isExternal ())
      continue;
    Out << "\t.xword LMIMap" << f << "\n";
    ++f;
  }
  writeEpilogue(Out, "FunctionLI");
  
  return false;
}

} // End llvm namespace