Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / InstrucIter-Function.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "common/h/Types.h"
33 #include "arch.h"
34 #include "InstrucIter-Function.h"
35 #include "function.h"
36 #include "image-func.h"
37 #include <sstream>
38 #include <ostream>
39 #include <string>
40 #include <algorithm>
41
42
43 InstrucIter makeIter(int_basicBlock* fromThis)
44 {
45   return InstrucIter(fromThis);
46 }
47
48 std::string dumpSubIter(const InstrucIter& dumpIt)
49 {
50   std::stringstream retVal;
51   retVal << "     - " << dumpIt.begin() << ":" << dumpIt.end();
52   return retVal.str();
53 }
54
55
56 void InstrucIterFunction::debugPrint() const
57 {
58   cerr << " *** II_Function contains " << endl;
59   std::transform(subIters.begin(), subIters.end(), 
60                  std::ostream_iterator<std::string>(cerr, "\n"),
61                  dumpSubIter);
62   cerr << " *** Current address is " << **(this) << endl;
63 }
64
65
66 InstrucIterFunction::InstrucIterFunction(int_function* func) : InstrucIter()
67 {
68   assert(func);
69   std::transform(func->blocks().begin(), func->blocks().end(), std::back_inserter(subIters), makeIter);
70   currentBlock = subIters.begin();
71 }
72
73 InstrucIterFunction::InstrucIterFunction(Address start, int_function* func) : InstrucIter()
74 {
75   assert(func);
76   std::transform(func->blocks().begin(), func->blocks().end(), std::back_inserter(subIters), makeIter);
77   setCurrentAddress(start);
78 }
79
80 InstrucIterFunction::InstrucIterFunction(const InstrucIterFunction& ii) : InstrucIter(ii)
81 {
82   subIters.clear();
83   std::copy(ii.subIters.begin(), ii.subIters.end(), std::back_inserter(subIters));
84   // We can't just copy the iterator because it's over a different range
85   // so we'll find where we should be by address
86   setCurrentAddress(*ii);
87 }
88
89 Address InstrucIterFunction::operator++()
90 {
91   if(currentBlock != subIters.end())
92   {
93     // Increment if not at end of block already
94     if(**currentBlock != currentBlock->end())
95     {
96       ++(*currentBlock);
97     }
98     // If at end of block (either because we were set there, or because we just
99     // incremented, then go ahead to the beginning of the next block
100     if(**currentBlock == currentBlock->end())
101     {
102       ++currentBlock;
103       if(currentBlock != subIters.end())
104       {
105         currentBlock->setCurrentAddress(currentBlock->begin());
106       }
107     }
108   }
109   return **this;
110 }
111
112 Address InstrucIterFunction::operator++(int)
113 {
114   Address ret = **this;
115   ++(*this);
116   return ret;
117 }
118
119 Address InstrucIterFunction::operator--()
120 {
121   if(currentBlock->hasPrev())
122   {
123     --(*currentBlock);
124   }
125   else if(currentBlock != subIters.begin())
126   {
127     --currentBlock;
128     currentBlock->setCurrentAddress(currentBlock->end());
129   }
130   return **this;
131 }
132
133 Address InstrucIterFunction::operator--(int)
134 {
135   Address ret = **this;
136   --(*this);
137   return ret;
138 }
139
140
141 Address InstrucIterFunction::operator*() const
142 {
143   if(currentBlock != subIters.end())
144   {
145     return **currentBlock;
146   }
147   else
148   {
149     return 0;
150   }
151 }
152
153 instruction InstrucIterFunction::getInstruction()
154 {
155   assert(currentBlock != subIters.end());
156   return currentBlock->getInstruction();
157 }
158
159 instruction* InstrucIterFunction::getInsnPtr()
160 {
161   if(currentBlock != subIters.end())
162   {
163     return currentBlock->getInsnPtr();
164   }
165   return NULL;
166 }
167
168 bool InstrucIterFunction::hasMore()
169 {
170   return currentBlock != subIters.end();
171 }
172
173 bool InstrucIterFunction::hasPrev()
174 {
175   return currentBlock != subIters.begin() || currentBlock->hasPrev();
176 }
177
178 Address InstrucIterFunction::peekNext()
179 {
180   assert(hasMore());
181   if(currentBlock->hasMore())
182   {
183     return currentBlock->peekNext();
184   }
185   else
186   {
187     subIterContT::iterator nextBlock = currentBlock;
188     ++nextBlock;
189     if(nextBlock != subIters.end())
190     {
191       return nextBlock->begin();
192     }
193   }
194   return 0;
195 }
196
197 Address InstrucIterFunction::peekPrev()
198 {
199   assert(hasPrev());
200   if(currentBlock->hasPrev())
201   {
202     return currentBlock->peekPrev();
203   }
204   else
205   {
206     subIterContT::iterator prevBlock = currentBlock;
207     --prevBlock;
208     return prevBlock->end();
209   }
210 }
211
212 void InstrucIterFunction::setCurrentAddress(Address a)
213 {
214   subIterContT::iterator tmpBlock = subIters.begin();
215   while(tmpBlock != subIters.end())
216   {
217     if(tmpBlock->containsAddress(a))
218     {
219       currentBlock = tmpBlock;
220       currentBlock->setCurrentAddress(a);
221       break;
222     }
223   }
224   debugPrint();
225 }
226
227 Address InstrucIterFunction::getCurrentAddress()
228 {
229   assert(currentBlock != subIters.end());
230   return currentBlock->getCurrentAddress();
231 }