MachineFunction.cpp revision 3927af8d70c0809c6286b3d14b350a2f04bd024b
1//===-- MachineFunction.cpp -----------------------------------------------===//
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// Collect native machine code information for a function.  This allows
11// target-specific information about the generated code to be stored with each
12// function.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/CodeGen/MachineFunctionPass.h"
17#include "llvm/CodeGen/MachineInstr.h"
18#include "llvm/CodeGen/SSARegMap.h"
19#include "llvm/CodeGen/MachineFunctionInfo.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineConstantPool.h"
22#include "llvm/CodeGen/Passes.h"
23#include "llvm/Target/TargetMachine.h"
24#include "llvm/Target/TargetFrameInfo.h"
25#include "llvm/Function.h"
26#include "llvm/Instructions.h"
27#include "llvm/Type.h"
28#include "Support/LeakDetector.h"
29#include "Support/GraphWriter.h"
30#include <fstream>
31#include <iostream>
32#include <sstream>
33
34using namespace llvm;
35
36static AnnotationID MF_AID(
37                 AnnotationManager::getID("CodeGen::MachineCodeForFunction"));
38
39
40namespace {
41  struct Printer : public MachineFunctionPass {
42    std::ostream *OS;
43    const std::string Banner;
44
45    Printer (std::ostream *_OS, const std::string &_Banner) :
46      OS (_OS), Banner (_Banner) { }
47
48    const char *getPassName() const { return "MachineFunction Printer"; }
49
50    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
51      AU.setPreservesAll();
52    }
53
54    bool runOnMachineFunction(MachineFunction &MF) {
55      (*OS) << Banner;
56      MF.print (*OS);
57      return false;
58    }
59  };
60}
61
62/// Returns a newly-created MachineFunction Printer pass. The default output
63/// stream is std::cerr; the default banner is empty.
64///
65FunctionPass *llvm::createMachineFunctionPrinterPass(std::ostream *OS,
66                                                     const std::string &Banner) {
67  return new Printer(OS, Banner);
68}
69
70namespace {
71  struct Deleter : public MachineFunctionPass {
72    const char *getPassName() const { return "Machine Code Deleter"; }
73
74    bool runOnMachineFunction(MachineFunction &MF) {
75      // Delete the annotation from the function now.
76      MachineFunction::destruct(MF.getFunction());
77      return true;
78    }
79  };
80}
81
82/// MachineCodeDeletion Pass - This pass deletes all of the machine code for
83/// the current function, which should happen after the function has been
84/// emitted to a .s file or to memory.
85FunctionPass *llvm::createMachineCodeDeleter() {
86  return new Deleter();
87}
88
89
90
91//===---------------------------------------------------------------------===//
92// MachineFunction implementation
93//===---------------------------------------------------------------------===//
94MachineBasicBlock* ilist_traits<MachineBasicBlock>::createNode()
95{
96    MachineBasicBlock* dummy = new MachineBasicBlock();
97    LeakDetector::removeGarbageObject(dummy);
98    return dummy;
99}
100
101void ilist_traits<MachineBasicBlock>::transferNodesFromList(
102    iplist<MachineBasicBlock, ilist_traits<MachineBasicBlock> >& toList,
103    ilist_iterator<MachineBasicBlock> first,
104    ilist_iterator<MachineBasicBlock> last)
105{
106    if (Parent != toList.Parent)
107        for (; first != last; ++first)
108            first->Parent = toList.Parent;
109}
110
111MachineFunction::MachineFunction(const Function *F,
112                                 const TargetMachine &TM)
113  : Annotation(MF_AID), Fn(F), Target(TM) {
114  SSARegMapping = new SSARegMap();
115  MFInfo = new MachineFunctionInfo(*this);
116  FrameInfo = new MachineFrameInfo();
117  ConstantPool = new MachineConstantPool();
118  BasicBlocks.Parent = this;
119}
120
121MachineFunction::~MachineFunction() {
122  BasicBlocks.clear();
123  delete SSARegMapping;
124  delete MFInfo;
125  delete FrameInfo;
126  delete ConstantPool;
127}
128
129void MachineFunction::dump() const { print(std::cerr); }
130
131void MachineFunction::print(std::ostream &OS) const {
132  OS << "# Machine code for " << Fn->getName () << "():\n";
133
134  // Print Frame Information
135  getFrameInfo()->print(*this, OS);
136
137  // Print Constant Pool
138  getConstantPool()->print(OS);
139
140  for (const_iterator BB = begin(); BB != end(); ++BB)
141    BB->print(OS);
142
143  OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
144}
145
146/// CFGOnly flag - This is used to control whether or not the CFG graph printer
147/// prints out the contents of basic blocks or not.  This is acceptable because
148/// this code is only really used for debugging purposes.
149///
150static bool CFGOnly = false;
151
152namespace llvm {
153template<>
154struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits {
155  static std::string getGraphName(const MachineFunction *F) {
156    return "CFG for '" + F->getFunction()->getName() + "' function";
157  }
158
159  static std::string getNodeLabel(const MachineBasicBlock *Node,
160                                  const MachineFunction *Graph) {
161    if (CFGOnly && Node->getBasicBlock() &&
162        !Node->getBasicBlock()->getName().empty())
163      return Node->getBasicBlock()->getName() + ":";
164
165    std::ostringstream Out;
166    if (CFGOnly) {
167      Out << Node->getNumber() << ':';
168      return Out.str();
169    }
170
171    Node->print(Out);
172
173    std::string OutStr = Out.str();
174    if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
175
176    // Process string output to make it nicer...
177    for (unsigned i = 0; i != OutStr.length(); ++i)
178      if (OutStr[i] == '\n') {                            // Left justify
179        OutStr[i] = '\\';
180        OutStr.insert(OutStr.begin()+i+1, 'l');
181      }
182    return OutStr;
183  }
184};
185}
186
187void MachineFunction::viewCFG() const
188{
189  std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot";
190  std::cerr << "Writing '" << Filename << "'... ";
191  std::ofstream F(Filename.c_str());
192
193  if (!F) {
194    std::cerr << "  error opening file for writing!\n";
195    return;
196  }
197
198  WriteGraph(F, this);
199  F.close();
200  std::cerr << "\n";
201
202  std::cerr << "Running 'dot' program... " << std::flush;
203  if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
204              + " > /tmp/cfg.tempgraph.ps").c_str())) {
205    std::cerr << "Error running dot: 'dot' not in path?\n";
206  } else {
207    std::cerr << "\n";
208    system("gv /tmp/cfg.tempgraph.ps");
209  }
210  system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str());
211}
212
213void MachineFunction::viewCFGOnly() const
214{
215  CFGOnly = true;
216  viewCFG();
217  CFGOnly = false;
218}
219
220// The next two methods are used to construct and to retrieve
221// the MachineCodeForFunction object for the given function.
222// construct() -- Allocates and initializes for a given function and target
223// get()       -- Returns a handle to the object.
224//                This should not be called before "construct()"
225//                for a given Function.
226//
227MachineFunction&
228MachineFunction::construct(const Function *Fn, const TargetMachine &Tar)
229{
230  assert(Fn->getAnnotation(MF_AID) == 0 &&
231         "Object already exists for this function!");
232  MachineFunction* mcInfo = new MachineFunction(Fn, Tar);
233  Fn->addAnnotation(mcInfo);
234  return *mcInfo;
235}
236
237void MachineFunction::destruct(const Function *Fn) {
238  bool Deleted = Fn->deleteAnnotation(MF_AID);
239  assert(Deleted && "Machine code did not exist for function!");
240}
241
242MachineFunction& MachineFunction::get(const Function *F)
243{
244  MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID);
245  assert(mc && "Call construct() method first to allocate the object");
246  return *mc;
247}
248
249void MachineFunction::clearSSARegMap() {
250  delete SSARegMapping;
251  SSARegMapping = 0;
252}
253
254//===----------------------------------------------------------------------===//
255//  MachineFrameInfo implementation
256//===----------------------------------------------------------------------===//
257
258/// CreateStackObject - Create a stack object for a value of the specified type.
259///
260int MachineFrameInfo::CreateStackObject(const Type *Ty, const TargetData &TD) {
261  return CreateStackObject(TD.getTypeSize(Ty), TD.getTypeAlignment(Ty));
262}
263
264int MachineFrameInfo::CreateStackObject(const TargetRegisterClass *RC) {
265  return CreateStackObject(RC->getSize(), RC->getAlignment());
266}
267
268
269void MachineFrameInfo::print(const MachineFunction &MF, std::ostream &OS) const{
270  int ValOffset = MF.getTarget().getFrameInfo()->getOffsetOfLocalArea();
271
272  for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
273    const StackObject &SO = Objects[i];
274    OS << "  <fi #" << (int)(i-NumFixedObjects) << "> is ";
275    if (SO.Size == 0)
276      OS << "variable sized";
277    else
278      OS << SO.Size << " byte" << (SO.Size != 1 ? "s" : " ");
279
280    if (i < NumFixedObjects)
281      OS << " fixed";
282    if (i < NumFixedObjects || SO.SPOffset != -1) {
283      int Off = SO.SPOffset - ValOffset;
284      OS << " at location [SP";
285      if (Off > 0)
286	OS << "+" << Off;
287      else if (Off < 0)
288	OS << Off;
289      OS << "]";
290    }
291    OS << "\n";
292  }
293
294  if (HasVarSizedObjects)
295    OS << "  Stack frame contains variable sized objects\n";
296}
297
298void MachineFrameInfo::dump(const MachineFunction &MF) const {
299  print(MF, std::cerr);
300}
301
302
303//===----------------------------------------------------------------------===//
304//  MachineConstantPool implementation
305//===----------------------------------------------------------------------===//
306
307void MachineConstantPool::print(std::ostream &OS) const {
308  for (unsigned i = 0, e = Constants.size(); i != e; ++i)
309    OS << "  <cp #" << i << "> is" << *(Value*)Constants[i] << "\n";
310}
311
312void MachineConstantPool::dump() const { print(std::cerr); }
313
314//===----------------------------------------------------------------------===//
315//  MachineFunctionInfo implementation
316//===----------------------------------------------------------------------===//
317
318static unsigned
319ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
320                           unsigned &maxOptionalNumArgs)
321{
322  const TargetFrameInfo &frameInfo = *target.getFrameInfo();
323
324  unsigned maxSize = 0;
325
326  for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB)
327    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
328      if (const CallInst *callInst = dyn_cast<CallInst>(I))
329        {
330          unsigned numOperands = callInst->getNumOperands() - 1;
331          int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs();
332          if (numExtra <= 0)
333            continue;
334
335          unsigned sizeForThisCall = numExtra * 8;
336
337          if (maxSize < sizeForThisCall)
338            maxSize = sizeForThisCall;
339
340          if ((int)maxOptionalNumArgs < numExtra)
341            maxOptionalNumArgs = (unsigned) numExtra;
342        }
343
344  return maxSize;
345}
346
347// Align data larger than one L1 cache line on L1 cache line boundaries.
348// Align all smaller data on the next higher 2^x boundary (4, 8, ...),
349// but not higher than the alignment of the largest type we support
350// (currently a double word). -- see class TargetData).
351//
352// This function is similar to the corresponding function in EmitAssembly.cpp
353// but they are unrelated.  This one does not align at more than a
354// double-word boundary whereas that one might.
355//
356inline unsigned
357SizeToAlignment(unsigned size, const TargetMachine& target)
358{
359  const unsigned short cacheLineSize = 16;
360  if (size > (unsigned) cacheLineSize / 2)
361    return cacheLineSize;
362  else
363    for (unsigned sz=1; /*no condition*/; sz *= 2)
364      if (sz >= size || sz >= target.getTargetData().getDoubleAlignment())
365        return sz;
366}
367
368
369void MachineFunctionInfo::CalculateArgSize() {
370  maxOptionalArgsSize = ComputeMaxOptionalArgsSize(MF.getTarget(),
371						   MF.getFunction(),
372                                                   maxOptionalNumArgs);
373  staticStackSize = maxOptionalArgsSize
374    + MF.getTarget().getFrameInfo()->getMinStackFrameSize();
375}
376
377int
378MachineFunctionInfo::computeOffsetforLocalVar(const Value* val,
379					      unsigned &getPaddedSize,
380					      unsigned  sizeToUse)
381{
382  if (sizeToUse == 0) {
383    // All integer types smaller than ints promote to 4 byte integers.
384    if (val->getType()->isIntegral() && val->getType()->getPrimitiveSize() < 4)
385      sizeToUse = 4;
386    else
387      sizeToUse = MF.getTarget().getTargetData().getTypeSize(val->getType());
388  }
389  unsigned align = SizeToAlignment(sizeToUse, MF.getTarget());
390
391  bool growUp;
392  int firstOffset = MF.getTarget().getFrameInfo()->getFirstAutomaticVarOffset(MF,
393						 			     growUp);
394  int offset = growUp? firstOffset + getAutomaticVarsSize()
395                     : firstOffset - (getAutomaticVarsSize() + sizeToUse);
396
397  int aligned = MF.getTarget().getFrameInfo()->adjustAlignment(offset, growUp, align);
398  getPaddedSize = sizeToUse + abs(aligned - offset);
399
400  return aligned;
401}
402
403
404int MachineFunctionInfo::allocateLocalVar(const Value* val,
405                                          unsigned sizeToUse) {
406  assert(! automaticVarsAreaFrozen &&
407         "Size of auto vars area has been used to compute an offset so "
408         "no more automatic vars should be allocated!");
409
410  // Check if we've allocated a stack slot for this value already
411  //
412  hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
413  if (pair != offsets.end())
414    return pair->second;
415
416  unsigned getPaddedSize;
417  unsigned offset = computeOffsetforLocalVar(val, getPaddedSize, sizeToUse);
418  offsets[val] = offset;
419  incrementAutomaticVarsSize(getPaddedSize);
420  return offset;
421}
422
423int
424MachineFunctionInfo::allocateSpilledValue(const Type* type)
425{
426  assert(! spillsAreaFrozen &&
427         "Size of reg spills area has been used to compute an offset so "
428         "no more register spill slots should be allocated!");
429
430  unsigned size  = MF.getTarget().getTargetData().getTypeSize(type);
431  unsigned char align = MF.getTarget().getTargetData().getTypeAlignment(type);
432
433  bool growUp;
434  int firstOffset = MF.getTarget().getFrameInfo()->getRegSpillAreaOffset(MF, growUp);
435
436  int offset = growUp? firstOffset + getRegSpillsSize()
437                     : firstOffset - (getRegSpillsSize() + size);
438
439  int aligned = MF.getTarget().getFrameInfo()->adjustAlignment(offset, growUp, align);
440  size += abs(aligned - offset); // include alignment padding in size
441
442  incrementRegSpillsSize(size);  // update size of reg. spills area
443
444  return aligned;
445}
446
447int
448MachineFunctionInfo::pushTempValue(unsigned size)
449{
450  unsigned align = SizeToAlignment(size, MF.getTarget());
451
452  bool growUp;
453  int firstOffset = MF.getTarget().getFrameInfo()->getTmpAreaOffset(MF, growUp);
454
455  int offset = growUp? firstOffset + currentTmpValuesSize
456                     : firstOffset - (currentTmpValuesSize + size);
457
458  int aligned = MF.getTarget().getFrameInfo()->adjustAlignment(offset, growUp,
459							      align);
460  size += abs(aligned - offset); // include alignment padding in size
461
462  incrementTmpAreaSize(size);    // update "current" size of tmp area
463
464  return aligned;
465}
466
467void MachineFunctionInfo::popAllTempValues() {
468  resetTmpAreaSize();            // clear tmp area to reuse
469}
470