Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / dyninst / test1_37.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 // $Id: test1_37.C,v 1.1 2008/10/30 19:19:24 legendre Exp $
33 /*
34  * #Name: test1_37
35  * #Desc: Instrument Loops
36  * #Dep: 
37  * #Arch:
38  * #Notes:
39  */
40
41 #include "BPatch.h"
42 #include "BPatch_Vector.h"
43 #include "BPatch_addressSpace.h"
44 #include "BPatch_snippet.h"
45
46 #include "test_lib.h"
47 #include "Callbacks.h"
48 #include "dyninst_comp.h"
49
50 class test1_37_Mutator : public DyninstMutator {
51         virtual test_results_t executeTest();
52 };
53
54 extern "C" DLLEXPORT  TestMutator *test1_37_factory() 
55 {
56         return new test1_37_Mutator();
57 }
58
59 //
60 // Start Test Case #37 - (loop instrumentation)
61 //
62
63 // sort basic blocks ascending by block number
64 static void sort_blocks(BPatch_Vector<BPatch_basicBlock*> &a, int n) 
65 {
66         for (int i=0; i<n-1; i++) 
67         {
68                 for (int j=0; j<n-1-i; j++)
69                         if (a[j+1]->getBlockNumber() < a[j]->getBlockNumber()) 
70                         {
71                                 BPatch_basicBlock* tmp = a[j]; 
72                                 a[j] = a[j+1];
73                                 a[j+1] = tmp;
74                         }
75         }
76 }
77
78 /* This method instruments the entry and exit edges of a loop with 
79    the passed-in function. It accomplishes this by looking up the entry
80    and exit blocks of the loop, finding the edges that do not come from
81    or target other blocks in the loop (respectively), and instrumenting
82    those edges. So effectively, this is a test of both our loop detection
83    and edge instrumentation facilities. Two for one, yay!
84  */
85
86 static void instrumentLoops(BPatch_addressSpace *appAddrSpace, BPatch_image *appImage,
87                 BPatch_Vector<BPatch_basicBlockLoop*> &loops,
88                 BPatch_funcCallExpr &callInc) 
89 {            
90         // for each loop (set of basic blocks)
91         for (unsigned int i = 0; i < loops.size(); i++) 
92         {
93                 BPatch_flowGraph *cfg; 
94                 BPatch_Vector<BPatch_point*> * exits;
95                 BPatch_Vector<BPatch_point*> * entries;
96
97                 cfg = loops[i]->getFlowGraph();
98
99                 // Find loop entry and exit points
100                 entries = cfg->findLoopInstPoints(BPatch_locLoopEntry,
101                                 loops[i]);
102                 exits = cfg->findLoopInstPoints(BPatch_locLoopExit,
103                                 loops[i]);
104                 // instrument those points      
105
106                 if (entries->size() == 0) 
107                 {
108                         logerror("**Failed** test #37 (instrument loops)\n");
109                         logerror("   Unable to find loop entry inst point.\n");
110                 }
111
112                 if (exits->size() == 0) 
113                 {
114                         logerror("**Failed** test #37 (instrument loops)\n");
115                         logerror("   Unable to find loop exit inst point.\n");
116                 }
117
118                 unsigned int j;
119                 BPatch_point *p = NULL;
120
121                 for (j=0;j<entries->size();j++) 
122                 {
123                         p = (*entries)[j];
124
125                         BPatchSnippetHandle * han =
126                                 appAddrSpace->insertSnippet(callInc, *p, BPatch_callBefore);
127
128                         // did we insert the snippet?
129                         if (han == NULL) 
130                         {
131                                 logerror("**Failed** test #37 (instrument loops)\n");
132                                 logerror("   Unable to insert snippet at loop entry.\n");
133                                 //cfg->dump();
134                         }
135                 }
136                 for (j=0;j<exits->size();j++) 
137                 {
138                         p = (*exits)[j];
139
140                         BPatchSnippetHandle * han =
141                                 appAddrSpace->insertSnippet(callInc, *p, BPatch_callBefore);
142
143                         // did we insert the snippet?
144                         if (han == NULL) 
145                         {
146                                 logerror("**Failed** test #37 (instrument loops)\n");
147                                 logerror("   Unable to insert snippet at loop exit.\n");
148                                 //cfg->dump();
149                         }
150                 }
151
152                 // we are responsible for releasing the point vectors
153                 delete entries;
154                 delete exits;
155
156                 BPatch_Vector<BPatch_basicBlockLoop*> lps;
157                 loops[i]->getOuterLoops(lps);
158
159                 // recur with this loop's outer loops
160                 instrumentLoops(appAddrSpace, appImage, lps, callInc);
161         }
162 }
163
164 static int instrumentFuncLoopsWithCall(BPatch_addressSpace *appAddrSpace, 
165                 BPatch_image *appImage,
166                 char *call_func,
167                 char *inc_func)
168 {
169         // get function * for call_func
170         BPatch_Vector<BPatch_function *> funcs;
171
172         appImage->findFunction(call_func, funcs);
173         BPatch_function *func = funcs[0];
174
175         // get function * for inc_func
176         BPatch_Vector<BPatch_function *> funcs2;
177         appImage->findFunction(inc_func, funcs2);
178         BPatch_function *incVar = funcs2[0];
179
180         if (func == NULL || incVar == NULL) 
181         {
182                 logerror("**Failed** test #37 (instrument loops)\n");
183                 logerror("    Unable to get funcions.\n");
184                 return -1;
185         }
186
187         // create func expr for incVar
188         BPatch_Vector<BPatch_snippet *> nullArgs;
189         BPatch_funcCallExpr callInc(*incVar, nullArgs);
190         checkCost(callInc);
191
192         // instrument the function's loops
193         BPatch_flowGraph *cfg = func->getCFG();
194         BPatch_Vector<BPatch_basicBlockLoop*> loops;
195         cfg->getOuterLoops(loops);
196
197         instrumentLoops(appAddrSpace, appImage, loops, callInc);
198
199         return 0;
200 }
201
202 test_results_t test1_37_Mutator::executeTest() 
203 {
204         if (isMutateeFortran(appImage)) 
205         {
206                 return SKIPPED;
207         } 
208
209         if (instrumentFuncLoopsWithCall(appAddrSpace, appImage,
210                                 "test1_37_call1", "test1_37_inc1") < 0) 
211         {
212                 return FAILED;
213         }
214
215         if (instrumentFuncLoopsWithCall(appAddrSpace, appImage,
216                                 "test1_37_call2", "test1_37_inc2") < 0) 
217         {
218                 return FAILED;
219         }
220
221         if (instrumentFuncLoopsWithCall(appAddrSpace, appImage,
222                                 "test1_37_call3", "test1_37_inc3") < 0) 
223         {
224                 return FAILED;
225         }
226
227         return PASSED;
228 }
229