summaryrefslogtreecommitdiff
path: root/include/llvm/Function.h
blob: 7448dce9fe3a3ec912cf140984825943ab10fabc (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
//===-- llvm/Method.h - Class to represent a single VM method ----*- C++ -*--=//
//
// This file contains the declaration of the Method class, which represents a 
// single Method/function/procedure in the VM.
//
// Note that basic blocks themselves are Def's, because they are referenced
// by instructions like calls and can go in virtual function tables and stuff.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_METHOD_H
#define LLVM_METHOD_H

#include "llvm/SymTabValue.h"
#include "llvm/BasicBlock.h"
#include <list>

class Instruction;
class BasicBlock;
class MethodArgument;
class MethodType;
class Method;
class Module;

typedef UseTy<Method> MethodUse;

class Method : public SymTabValue {
public:
  typedef ValueHolder<MethodArgument, Method> ArgumentListType;
  typedef ValueHolder<BasicBlock    , Method> BasicBlocksType;
private:

  // Important things that make up a method!
  BasicBlocksType  BasicBlocks;    // The basic blocks
  ArgumentListType ArgumentList;   // The formal arguments

  Module *Parent;                  // The module that contains this method

  friend class ValueHolder<Method,Module>;
  void setParent(Module *parent);

public:
  Method(const MethodType *Ty, const string &Name = "");
  ~Method();

  // Specialize setName to handle symbol table majik...
  virtual void setName(const string &name);

  const Type *getReturnType() const;
  const MethodType *getMethodType() const;

  // Is the body of this method unknown? (the basic block list is empty if so)
  // this is true for "extern"al methods.
  bool isMethodExternal() const { return BasicBlocks.empty(); }


  // Get the class structure that this method is contained inside of...
  inline Module *getParent() { return Parent; }
  inline const Module *getParent() const { return Parent; }

  inline const BasicBlocksType  &getBasicBlocks() const { return BasicBlocks; }
  inline       BasicBlocksType  &getBasicBlocks()       { return BasicBlocks; }

  inline const ArgumentListType &getArgumentList() const{ return ArgumentList; }
  inline       ArgumentListType &getArgumentList()      { return ArgumentList; }


  // dropAllReferences() - This function causes all the subinstructions to "let
  // go" of all references that they are maintaining.  This allows one to
  // 'delete' a whole class at a time, even though there may be circular
  // references... first all references are dropped, and all use counts go to
  // zero.  Then everything is delete'd for real.  Note that no operations are
  // valid on an object that has "dropped all references", except operator 
  // delete.
  //
  void dropAllReferences();

  //===--------------------------------------------------------------------===//
  // Method Instruction iterator code
  //===--------------------------------------------------------------------===//
  // 
  template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t> 
  class InstIterator;
  typedef InstIterator<BasicBlocksType, BasicBlocksType::iterator, 
		       BasicBlock::InstListType::iterator,
		       Instruction*> inst_iterator;
  typedef InstIterator<const BasicBlocksType, BasicBlocksType::const_iterator, 
		       BasicBlock::InstListType::const_iterator,
		       const Instruction*> inst_const_iterator;

  // This inner class is used to implement inst_begin() & inst_end() for
  // inst_iterator and inst_const_iterator's.
  //
  template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t>
  class InstIterator {
    typedef _BB_t   BBty;
    typedef _BB_i_t BBIty;
    typedef _BI_t   BIty;
    typedef _II_t   IIty;
    _BB_t  &BBs;      // BasicBlocksType
    _BB_i_t BB;       // BasicBlocksType::iterator
    _BI_t   BI;       // BasicBlock::InstListType::iterator
  public:
    typedef bidirectional_iterator_tag iterator_category;

    template<class M> InstIterator(M &m) 
      : BBs(m.getBasicBlocks()), BB(BBs.begin()) {    // begin ctor
      if (BB != BBs.end()) {
	BI = (*BB)->getInstList().begin();
	resyncInstructionIterator();
      }
    }

    template<class M> InstIterator(M &m, bool) 
      : BBs(m.getBasicBlocks()), BB(BBs.end()) {    // end ctor
    }

    // Accessors to get at the underlying iterators...
    inline BBIty &getBasicBlockIterator()  { return BB; }
    inline BIty  &getInstructionIterator() { return BI; }

    inline IIty operator*()  const { return *BI; }
    inline IIty *operator->() const { return &(operator*()); }

    inline bool operator==(const InstIterator &y) const { 
      return BB == y.BB && (BI == y.BI || BB == BBs.end());
    }
    inline bool operator!=(const InstIterator& y) const { 
      return !operator==(y);
    }

    // resyncInstructionIterator - This should be called if the 
    // InstructionIterator is modified outside of our control.  This resynchs
    // the internals of the InstIterator to a consistent state.
    //
    inline void resyncInstructionIterator() {
      // The only way that the II could be broken is if it is now pointing to
      // the end() of the current BasicBlock and there are successor BBs.
      while (BI == (*BB)->getInstList().end()) {
	++BB; 
	if (BB == BBs.end()) break;
	BI = (*BB)->getInstList().begin();
      }
    }

    InstIterator& operator++() { 
      ++BI;
      resyncInstructionIterator();   // Make sure it is still valid.
      return *this; 
    }
    inline InstIterator operator++(int) { 
      InstIterator tmp = *this; ++*this; return tmp; 
    }
    
    InstIterator& operator--() { 
      while (BB == BBs.end() || BI == (*BB)->getInstList().begin()) {
	--BB;
	BI = (*BB)->getInstList().end();
      }
      --BI;
      return *this; 
    }
    inline InstIterator  operator--(int) { 
      InstIterator tmp = *this; --*this; return tmp; 
    }
  };

  inline inst_iterator inst_begin() { return inst_iterator(*this); }
  inline inst_iterator inst_end()   { return inst_iterator(*this, true); }
  inline inst_const_iterator inst_begin() const { return inst_const_iterator(*this); }
  inline inst_const_iterator inst_end()   const { return inst_const_iterator(*this, true); }
};

#endif