Added BPatch_retExpr
[dyninst.git] / dyninstAPI / src / ast.C
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /* 
43  * $Log: ast.C,v $
44  * Revision 1.45  1997/07/10 21:44:53  hollings
45  * Added BPatch_retExpr
46  * Added null type for returnOp and paramOp
47  *
48  * Revision 1.44  1997/06/23 19:15:49  buck
49  * Added features to the dyninst API library, including an optional "else"
50  * in a BPatch_ifExpr; the BPatch_setMutationsActive call to temporarily
51  * disable all snippets; and the replaceFunctionCall and removeFunctionCall
52  * member functions of BPatch_thread to retarget or NOOP out a function
53  * call.
54  *
55  * Revision 1.1.1.3  1997/05/13 18:51:35  buck
56  * Update Maryland repository with changes from Wisconsin as of 5/13/97.
57  *
58  * Revision 1.43  1997/05/08 00:38:47  mjrg
59  * Changes for Windows NT port; added flags for loading libdyninst dynamically
60  *
61  * Revision 1.42  1997/05/07 19:02:53  naim
62  * Getting rid of old support for threads and turning it off until the new
63  * version is finished. Additionally, new superTable, baseTable and superVector
64  * classes for future support of multiple threads. The fastInferiorHeap class has
65  * also changed - naim
66  *
67  * Revision 1.41  1997/04/29 16:58:50  buck
68  * Added features to dyninstAPI library, including the ability to delete
69  * inserted snippets and the start of type checking.
70  *
71  * Revision 1.1.1.1  1997/04/01 20:24:59  buck
72  * Update Maryland repository with latest from Wisconsin.
73  *
74  * Revision 1.40  1997/03/18 19:44:07  buck
75  * first commit of dyninst library.  Also includes:
76  *      moving templates from paradynd to dyninstAPI
77  *      converting showError into a function (in showerror.C)
78  *      many ifdefs for BPATCH_LIBRARY in dyinstAPI/src.
79  *
80  * Revision 1.39  1997/03/14 15:58:59  lzheng
81  * Dealing with complier optimization related to the return value
82  *
83  * Revision 1.38  1997/02/26 23:42:48  mjrg
84  * First part on WindowsNT port: changes for compiling with Visual C++;
85  * moved unix specific code to unix.C
86  *
87  * Revision 1.37  1997/02/21 20:13:16  naim
88  * Moving files from paradynd to dyninstAPI + moving references to dataReqNode
89  * out of the ast class. The is the first pre-dyninstAPI commit! - naim
90  *
91  * Revision 1.36  1997/01/27 19:40:36  naim
92  * Part of the base instrumentation for supporting multithreaded applications
93  * (vectors of counter/timers) implemented for all current platforms +
94  * different bug fixes - naim
95  *
96  * Revision 1.35  1996/11/14 14:42:52  naim
97  * Minor fix to my previous commit - naim
98  *
99  * Revision 1.34  1996/11/14 14:26:57  naim
100  * Changing AstNodes back to pointers to improve performance - naim
101  *
102  * Revision 1.33  1996/11/12 17:48:34  mjrg
103  * Moved the computation of cost to the basetramp in the x86 platform,
104  * and changed other platform to keep code consistent.
105  * Removed warnings, and made changes for compiling with Visual C++
106  *
107  * Revision 1.32  1996/11/11 01:45:30  lzheng
108  * Moved the instructions which is used to caculate the observed cost
109  * from the miniTramps to baseTramp
110  *
111  * Revision 1.31  1996/10/31 08:36:58  tamches
112  * the shm-sampling commit; added noCost param to some fns
113  *
114  * Revision 1.30  1996/10/04 16:12:38  naim
115  * Optimization for code generation (use of immediate operations whenever
116  * possible). This first commit is only for the sparc platform. Other platforms
117  * should follow soon - naim
118  *
119  * Revision 1.29  1996/09/13 21:41:57  mjrg
120  * Implemented opcode ReturnVal for ast's to get the return value of functions.
121  * Added missing calls to free registers in Ast.generateCode and emitFuncCall.
122  * Removed architecture dependencies from inst.C.
123  * Changed code to allow base tramps of variable size.
124  *
125  * Revision 1.28  1996/08/21 18:02:35  mjrg
126  * Changed the ast nodes generated for timers. This just affects the ast
127  * nodes, not the code generated.
128  *
129  * Revision 1.27  1996/08/20 19:07:30  lzheng
130  * Implementation of moving multiple instructions sequence and
131  * splitting the instrumentations into two phases.
132  *
133  * Revision 1.26  1996/08/16 21:18:14  tamches
134  * updated copyright for release 1.1
135  *
136  * Revision 1.25  1996/05/12 05:15:56  tamches
137  * aix 4.1 commit
138  *
139  * Revision 1.24  1996/04/26 20:16:16  lzheng
140  * Move part of code in AstNode::generateCode to machine dependent file.
141  * (Those code are put into the procedure emitFuncCall)
142  *
143  * Revision 1.23  1996/04/10 18:00:11  lzheng
144  * Added multiple arguments to calls for HPUX by using stack instead of extra
145  * registers.
146  *
147  * Revision 1.22  1996/04/08 21:21:11  lzheng
148  * changes for HP generateCode and emitFuncCall
149  *
150  * Revision 1.21  1996/03/25 20:20:39  tamches
151  * the reduce-mem-leaks-in-paradynd commit
152  *
153  * Revision 1.20  1996/03/20 17:02:36  mjrg
154  * Added multiple arguments to calls.
155  * Instrument pvm_send instead of pvm_recv to get tags.
156  *
157  * Revision 1.19  1995/12/19 01:04:44  hollings
158  * Moved the implementation of registerSpace::readOnlyRegister to processor
159  *   specific files (since it is).
160  * Fixed a bug in Power relOps cases.
161  *
162  */
163
164 #include "dyninstAPI/src/symtab.h"
165 #include "dyninstAPI/src/pdThread.h"
166 #include "dyninstAPI/src/process.h"
167 #include "dyninstAPI/src/inst.h"
168 #include "dyninstAPI/src/instP.h"
169 #include "dyninstAPI/src/dyninstP.h"
170 #include "dyninstAPI/src/ast.h"
171 #include "dyninstAPI/src/util.h"
172 #include "paradynd/src/showerror.h"
173 #if defined(BPATCH_LIBRARY)
174 #include "dyninstAPI/h/BPatch.h"
175 #include "dyninstAPI/src/BPatch_type.h"
176 #endif
177
178 #ifndef BPATCH_LIBRARY
179 #include "rtinst/h/rtinst.h"
180 #include "paradynd/src/metric.h"
181 #endif
182
183 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)
184 #include "dyninstAPI/src/inst-sparc.h"
185 #elif defined(hppa1_1_hp_hpux)
186 #include "dyninstAPI/src/inst-hppa.h"
187 #elif defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
188 #include "dyninstAPI/src/inst-power.h"
189 #elif defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0)
190 #include "dyninstAPI/src/inst-x86.h"
191 #else
192 #endif
193
194 extern registerSpace *regSpace;
195 extern bool doNotOverflow(int value);
196
197 registerSpace::registerSpace(int deadCount, int *dead, int liveCount, int *live)
198 {
199     int i;
200
201     numRegisters = deadCount + liveCount;
202     registers = new registerSlot[numRegisters];
203
204     // load dead ones
205     for (i=0; i < deadCount; i++) {
206         registers[i].number = dead[i];
207         registers[i].inUse = false;
208         registers[i].mustRestore = false;
209         registers[i].needsSaving = false;
210         registers[i].startsLive = false;
211     }
212
213     // load live ones;
214     for (i=0; i < liveCount; i++) {
215         registers[i+deadCount].number = live[i];
216         registers[i+deadCount].inUse = false;
217         registers[i+deadCount].mustRestore = false;
218         registers[i+deadCount].needsSaving = true;
219         registers[i+deadCount].startsLive = true;
220 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
221         if (registers[i+deadCount].number == REG_MT) {
222           registers[i+deadCount].inUse = true;
223           registers[i+deadCount].needsSaving = true;
224         }
225 #endif
226     }
227
228 }
229
230 reg registerSpace::allocateRegister(char *insn, unsigned &base, bool noCost) 
231 {
232     int i;
233     for (i=0; i < numRegisters; i++) {
234         if (!registers[i].inUse && !registers[i].needsSaving) {
235             registers[i].inUse = true;
236             highWaterRegister = (highWaterRegister > i) ? 
237                  highWaterRegister : i;
238             return(registers[i].number);
239         }
240     }
241
242     // now consider ones that need saving
243     for (i=0; i < numRegisters; i++) {
244         if (!registers[i].inUse) {
245 #if !defined(rs6000_ibm_aix4_1)
246             // MT_AIX: we are not saving registers on demand on the power
247             // architecture. Instead, we save/restore registers in the base
248             // trampoline - naim
249             emit(saveRegOp, registers[i].number, 0, 0, insn, base, noCost);
250 #endif
251             registers[i].inUse = true;
252 #if !defined(rs6000_ibm_aix4_1)
253             // MT_AIX
254             registers[i].mustRestore = true;
255 #endif
256             // prevent general spill (func call) from saving this register.
257             registers[i].needsSaving = false;
258             highWaterRegister = (highWaterRegister > i) ? 
259                  highWaterRegister : i;
260             return(registers[i].number);
261         }
262     }
263
264     logLine("==> WARNING! run out of registers...\n");
265     abort();
266     return(-1);
267 }
268
269 bool registerSpace::is_keep_register(reg k)
270 {
271   for (unsigned i=0;i<keep_list.size();i++) {
272     if (keep_list[i]==k) return(true);
273   }
274   return(false);
275 }
276
277 void registerSpace::keep_register(reg k)
278 {
279   if (!is_keep_register(k)) {
280     keep_list += k;
281 #if defined(ASTDEBUG)
282     sprintf(errorLine,"==> keeping register %d, size is %d <==\n",k,keep_list.size());
283     logLine(errorLine);
284 #endif
285   }
286 }
287
288 void registerSpace::unkeep_register(reg k) {
289   unsigned ksize = keep_list.size();
290   for (unsigned i=0;i<ksize;i++) {
291     if (keep_list[i]==k) {
292       keep_list[i]=keep_list[ksize-1];
293       ksize--;
294       keep_list.resize(ksize);
295       freeRegister(k);
296 #if defined(ASTDEBUG)
297       sprintf(errorLine,"==> un-keeping register %d, size is %d <==\n",k,keep_list.size());
298       logLine(errorLine);
299 #endif
300       break;
301     }
302   }
303 }
304
305 void registerSpace::freeRegister(int reg) {
306     int i;
307     if (is_keep_register(reg)) return;
308     for (i=0; i < numRegisters; i++) {
309         if (registers[i].number == reg) {
310             registers[i].inUse = false;
311             return;
312         }
313     }
314 }
315
316 bool registerSpace::isFreeRegister(int reg) {
317     int i;
318     for (i=0; i < numRegisters; i++) {
319         if ((registers[i].number == reg) &&
320             (registers[i].inUse == true)) {
321             return false;
322         }
323     }
324     return true;
325 }
326
327 void registerSpace::resetSpace() {
328     int i;
329     for (i=0; i < numRegisters; i++) {
330         if (registers[i].inUse && (registers[i].number != REG_MT)) {
331           sprintf(errorLine,"WARNING: register %d is still in use\n",registers[i].number);
332           logLine(errorLine);
333         }
334         registers[i].inUse = false;
335         registers[i].mustRestore = false;
336         registers[i].needsSaving = registers[i].startsLive;
337 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
338         if (registers[i].number == REG_MT) {
339           registers[i].inUse = true;
340           registers[i].needsSaving = true;
341         }
342 #endif
343     }
344     highWaterRegister = 0;
345 }
346
347 //
348 // How to use AstNodes:
349 //
350 // In order to avoid memory leaks, it is important to define and delete
351 // AstNodes properly. The general rules are the following:
352 //
353 // 1.- Any AstNode defined locally, should be destroyed at the end of that
354 //     procedure. The only exception occurs when we are returning a pointer
355 //     to the AstNode as a result of the function (i.e. we need to keep the
356 //     value alive).
357 // 2.- Every time we assign an AstNode to another, we have to use the
358 //     "assignAst" function. This function will update the reference count
359 //     of the AstNode being assigned and it will return a pointer to it. If
360 //     we are creating a new AstNode (e.g. AstNode *t1 = new AstNode(...))
361 //     then it is not necessary to use assign, because the constructor will
362 //     automatically increment the reference count for us.
363 // 3.- "removeAst" is the procedure to be used everytime we want to delete
364 //     an AstNode. In general, if an AstNode is re-used several times, it
365 //     should be enough to delete the root of the DAG to delete all nodes.
366 //     However, there are exceptions like this one:
367 //     AstNode *t1, *t2, *t3;
368 //     t1 = AstNode(...);   rc-t1=1
369 //     t2 = AstNode(...);   rc-t2=1
370 //     t3 = AstNode(t1,t2); rc-t1=2, rc-t2=2, rc-t3=1
371 //     if we say:
372 //     removeAst(t3);
373 //     it will delete t3, but not t1 or t2 (because the rc will be 1 for both
374 //     of them). Therefore, we need to add the following:
375 //     removeAst(t1); removeAst(t2);
376 //     We only delete AstNodes when the reference count is 0.
377 //
378
379 AstNode &AstNode::operator=(const AstNode &src) {
380    logLine("Calling AstNode COPY constructor\n");
381    if (&src == this)
382       return *this; // the usual check for x=x
383
384    // clean up self before overwriting self; i.e., release memory
385    // currently in use so it doesn't become leaked.
386    if (loperand) {
387       if (src.loperand) {
388         if (loperand!=src.loperand) {
389           removeAst(loperand);
390         }
391       } else {
392         removeAst(loperand);
393       }
394    }
395    if (roperand) {
396       if (src.roperand) {
397         if (roperand!=src.roperand) {
398           removeAst(roperand);
399         }
400       } else {
401         removeAst(roperand);
402       }
403    }
404    if (eoperand) {
405       if (src.eoperand) {
406         if (eoperand!=src.eoperand) {
407           removeAst(eoperand);
408         }
409       } else {
410         removeAst(eoperand);
411       }
412    }
413    if (type == operandNode && oType == ConstantString)
414        free((char *)oValue);
415    referenceCount = src.referenceCount;
416    referenceCount++;
417
418    type = src.type;
419    if (type == opCodeNode)
420       op = src.op; // defined only for operand nodes
421
422    if (type == callNode) {
423       callee = src.callee; // defined only for call nodes
424       for (unsigned i=0;i<src.operands.size();i++) 
425         operands += assignAst(src.operands[i]);
426    }
427
428    if (type == operandNode) {
429       oType = src.oType;
430       // XXX This is for the string type.  If/when we fix the string type to
431       // make it less of a hack, we'll need to change this.
432       if (oType == ConstantString)
433           oValue = P_strdup((char *)src.oValue);
434       else
435           oValue = src.oValue;
436    }
437
438    loperand = assignAst(src.loperand);
439    roperand = assignAst(src.roperand);
440    eoperand = assignAst(src.eoperand);
441
442    firstInsn = src.firstInsn;
443    lastInsn = src.lastInsn;
444
445 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)
446    astFlag = src.astFlag;
447 #endif
448
449    bptype = src.bptype;
450    doTypeCheck = src.doTypeCheck;
451
452    return *this;
453 }
454
455 #if defined(ASTDEBUG)
456 static int ASTcount=0;
457
458 void ASTcounter()
459 {
460   ASTcount++;
461   sprintf(errorLine,"AstNode CONSTRUCTOR - ASTcount is %d\n",ASTcount);
462   logLine(errorLine);
463 }
464
465 void ASTcounterNP()
466 {
467   ASTcount++;
468 }
469 #endif
470
471 AstNode::AstNode() {
472 #if defined(ASTDEBUG)
473    ASTcounter();
474 #endif
475 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
476     astFlag = false;
477 #endif
478    // used in mdl.C
479    type = opCodeNode;
480    op = noOp;
481    loperand = roperand = eoperand = NULL;
482    referenceCount = 1;
483    useCount = 0;
484    kept_register = -1;
485    // "operands" is left as an empty vector
486    bptype = NULL;
487    doTypeCheck = true;
488 }
489
490 AstNode::AstNode(const string &func, AstNode *l, AstNode *r) {
491 #if defined(ASTDEBUG)
492     ASTcounter();
493 #endif
494 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
495     astFlag = false;
496 #endif
497     referenceCount = 1;
498     useCount = 0;
499     kept_register = -1;
500     type = callNode;
501     callee = func;
502     if (l) operands += assignAst(l);
503     if (r) operands += assignAst(r);
504     bptype = NULL;
505     doTypeCheck = true;
506 }
507
508 AstNode::AstNode(const string &func, AstNode *l) {
509 #if defined(ASTDEBUG)
510     ASTcounter();
511 #endif
512 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
513     astFlag = false;
514 #endif
515     referenceCount = 1;
516     useCount = 0;
517     kept_register = -1;
518     loperand = assignAst(l);
519     roperand = NULL;
520     eoperand = NULL;
521     type = callNode;
522     callee = func;
523     if (l) operands += assignAst(l);
524     bptype = NULL;
525     doTypeCheck = true;
526 }
527
528 AstNode::AstNode(const string &func, vector<AstNode *> &ast_args) {
529 #if defined(ASTDEBUG)
530    ASTcounter();
531 #endif
532 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
533     astFlag = false;
534 #endif
535    referenceCount = 1;
536    useCount = 0;
537    kept_register = -1;
538    for (unsigned i=0;i<ast_args.size();i++) 
539      if (ast_args[i]) operands += assignAst(ast_args[i]);
540    loperand = roperand = eoperand = NULL;
541    type = callNode;
542    callee = func;
543    bptype = NULL;
544    doTypeCheck = true;
545 }
546
547 AstNode::AstNode(operandType ot, void *arg) {
548 #if defined(ASTDEBUG)
549     ASTcounterNP();
550 #endif
551 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
552     astFlag = false;
553 #endif
554     referenceCount = 1;
555     useCount = 0;
556     kept_register = -1;
557     type = operandNode;
558     oType = ot;
559     if (ot == ConstantString)
560         oValue = (void *)P_strdup((char *)arg);
561     else
562         oValue = (void *) arg;
563     loperand = roperand = eoperand = NULL;
564     bptype = NULL;
565     doTypeCheck = true;
566 };
567
568 AstNode::AstNode(operandType ot, AstNode *l) {
569 #if defined(ASTDEBUG)
570     ASTcounter();
571 #endif
572 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
573     astFlag = false;
574 #endif
575     referenceCount = 1;
576     useCount = 0;
577     kept_register = -1;
578     type = operandNode;
579     oType = ot;
580     oValue = NULL;
581     roperand = NULL;
582     eoperand = NULL;
583     loperand = assignAst(l);
584     bptype = NULL;
585     doTypeCheck = true;
586 };
587
588 AstNode::AstNode(AstNode *l, AstNode *r) {
589 #if defined(ASTDEBUG)
590    ASTcounter();
591 #endif
592 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
593     astFlag = false;
594 #endif
595    referenceCount = 1;
596    useCount = 0;
597    kept_register = -1;
598    type = sequenceNode;
599    loperand = assignAst(l);
600    roperand = assignAst(r);
601    eoperand = NULL;
602    bptype = NULL;
603    doTypeCheck = true;
604 };
605
606 AstNode::AstNode(opCode ot) {
607 #if defined(ASTDEBUG)
608    ASTcounter();
609 #endif
610 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
611     astFlag = false;
612 #endif
613    // a private constructor
614    referenceCount = 1;
615    useCount = 0;
616    kept_register = -1;
617    type = opCodeNode;
618    op = ot;
619    loperand = roperand = eoperand = NULL;
620    bptype = NULL;
621    doTypeCheck = true;
622 }
623
624 AstNode::AstNode(opCode ot, AstNode *l) {
625 #if defined(ASTDEBUG)
626    ASTcounter();
627 #endif
628 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
629     astFlag = false;
630 #endif
631    // a private constructor
632    referenceCount = 1;
633    useCount = 0;
634    kept_register = -1;
635    type = opCodeNode;
636    op = ot;
637    loperand = assignAst(l);
638    roperand = NULL;
639    eoperand = NULL;
640    bptype = NULL;
641    doTypeCheck = true;
642 }
643
644 AstNode::AstNode(opCode ot, AstNode *l, AstNode *r, AstNode *e) {
645 #if defined(ASTDEBUG)
646    ASTcounter();
647 #endif
648 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
649     astFlag = false;
650 #endif
651    referenceCount = 1;
652    useCount = 0;
653    kept_register = -1;
654    type = opCodeNode;
655    op = ot;
656    loperand = assignAst(l);
657    roperand = assignAst(r);
658    eoperand = assignAst(e);
659    bptype = NULL;
660    doTypeCheck = true;
661 };
662
663 AstNode::AstNode(AstNode *src) {
664 #if defined(ASTDEBUG)
665    ASTcounter();
666 #endif
667 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
668     astFlag = false;
669 #endif
670    referenceCount = 1;
671    useCount = 0;
672    kept_register = -1;
673
674    type = src->type;   
675    if (type == opCodeNode)
676       op = src->op;             // defined only for operand nodes
677
678    if (type == callNode) {
679       callee = src->callee;     // defined only for call nodes
680       for (unsigned i=0;i<src->operands.size();i++) {
681         if (src->operands[i]) operands += assignAst(src->operands[i]);
682       }
683    }
684
685    if (type == operandNode) {
686       oType = src->oType;
687       // XXX This is for the string type.  If/when we fix the string type to
688       // make it less of a hack, we'll need to change this.
689       if (oType == ConstantString)
690           oValue = P_strdup((char *)src->oValue);
691       else
692           oValue = src->oValue;
693    }
694
695    loperand = assignAst(src->loperand);
696    roperand = assignAst(src->roperand);
697    eoperand = assignAst(src->eoperand);
698    firstInsn = src->firstInsn;
699    lastInsn = src->lastInsn;
700    bptype = src->bptype;
701    doTypeCheck = src->doTypeCheck;
702 }
703
704 #if defined(ASTDEBUG)
705 void AstNode::printRC()
706 {
707     sprintf(errorLine,"RC referenceCount=%d\n",referenceCount);
708     logLine(errorLine);
709     if (loperand) {
710       logLine("RC loperand\n");
711       loperand->printRC();
712     }
713     if (roperand) {
714       logLine("RC roperand\n");
715       roperand->printRC();
716     }
717     if (eoperand) {
718       logLine("RC eoperand\n");
719       eoperand->printRC();
720     }
721 }
722 #endif
723
724 AstNode::~AstNode() {
725 #if defined(ASTDEBUG)
726   ASTcount--;
727   sprintf(errorLine,"AstNode DESTRUCTOR - ASTcount is %d\n",ASTcount);
728   logLine(errorLine);
729 #endif
730   if (loperand) {
731     removeAst(loperand);
732   }
733   if (roperand) {
734     removeAst(roperand);
735   }
736   if (eoperand) {
737     removeAst(eoperand);
738   }
739   if (type==callNode) {
740     for (unsigned i=0;i<operands.size();i++) {
741       removeAst(operands[i]);
742     }
743   } else if (type == operandNode && oType == ConstantString) {
744       free(oValue);
745   }
746 }
747
748 //
749 // Increments/decrements the reference counter for the operands of a call 
750 // node. If "flag" is true, it increments the counter. Otherwise, it 
751 // decrements it.
752 //
753 void AstNode::updateOperandsRC(bool flag)
754 {
755   if (type==callNode) {
756     for (unsigned i=0;i<operands.size();i++) {
757       if (operands[i]) {
758         if (flag) operands[i]->referenceCount++;
759         else operands[i]->referenceCount--;
760       }
761     }
762   }
763 }
764
765 //
766 // This procedure should be use every time we assign an AstNode pointer,
767 // because it increments the reference counter.
768 //
769 AstNode *assignAst(AstNode *src) {
770   if (src) {
771     src->referenceCount++;
772     src->updateOperandsRC(true);
773   }
774   return(src);
775 }
776
777 //
778 // Decrements the reference count for "ast". If it is "0", it calls the 
779 // AstNode destructor.
780 //
781 void removeAst(AstNode *&ast) {
782   if (ast) {
783     assert(ast->referenceCount>0);
784     ast->referenceCount--;
785     if (ast->referenceCount==0) {
786       delete ast;
787       ast=NULL;
788     } else {
789       ast->updateOperandsRC(false);
790     }
791   }
792 }
793
794 //
795 // This procedure decrements the reference count for "ast" until it is 0.
796 //
797 void terminateAst(AstNode *&ast) {
798   while (ast) {
799     removeAst(ast);
800   }
801 }
802
803 int AstNode::generateTramp(process *proc, char *i, 
804                            unsigned &count, 
805                            int &trampCost, bool noCost) {
806     static AstNode *trailer=NULL;
807     if (!trailer) trailer = new AstNode(trampTrailer); // private constructor
808                                                        // used to estimate cost
809     static AstNode *preambleTemplate=NULL;
810     if (!preambleTemplate) {
811       AstNode *tmp1 = new AstNode(Constant, (void *) 0);
812       preambleTemplate = new AstNode(trampPreamble, tmp1);
813       removeAst(tmp1);
814     }
815     // private constructor; assumes NULL for right child
816     
817     trampCost = preambleTemplate->cost() + cost() + trailer->cost();
818     int cycles = trampCost;
819
820     AstNode *preamble, *tmp2;
821     tmp2 = new AstNode(Constant, (void *) cycles);
822     preamble = new AstNode(trampPreamble, tmp2); 
823     removeAst(tmp2);
824     // private constructor; assumes NULL for right child
825
826     initTramps(); // needed to initialize regSpace below
827                   // shouldn't we do a "delete regSpace" first to avoid
828                   // leaking memory?
829
830     regSpace->resetSpace();
831     reg return_reg;
832     if (type != opCodeNode || op != noOp) {
833         reg tmp;
834         preamble->generateCode(proc, regSpace, i, count, noCost);
835         removeAst(preamble);
836         tmp = generateCode(proc, regSpace, i, count, noCost);
837         regSpace->freeRegister(tmp);
838         return_reg = trailer->generateCode(proc, regSpace, i, count, noCost);
839     } else {
840         removeAst(preamble);
841         return_reg = (unsigned) emit(op, 1, 0, 0, i, count, noCost);
842     }
843     regSpace->resetSpace();
844     return(return_reg);
845 }
846
847 bool isPowerOf2(int value, int &result)
848 {
849   if (value<=0) return(false);
850   if (value==1) {
851     result=0;
852     return(true);
853   }
854   if ((value%2)!=0) return(false);
855   if (isPowerOf2(value/2,result)) {
856     result++;
857     return(true);
858   }
859   else return(false);
860 }
861
862 void AstNode::setUseCount(void)
863 {
864   useCount++;
865   if (useCount>1) return;
866   kept_register=-1;
867   if (loperand) loperand->setUseCount();
868   if (roperand) roperand->setUseCount();
869   if (eoperand) eoperand->setUseCount();
870 }
871
872 void AstNode::cleanUseCount(void)
873 {
874   useCount=0;
875   kept_register=-1;
876   if (loperand) loperand->cleanUseCount();
877   if (roperand) roperand->cleanUseCount();
878   if (eoperand) eoperand->cleanUseCount();
879 }
880
881 #if defined(ASTDEBUG)
882 void AstNode::printUseCount(void)
883 {
884   static int i=0;
885   i++;
886   sprintf(errorLine,"(%d)=>useCount is %d\n",i,useCount);
887   logLine(errorLine);
888   if (loperand) {
889     sprintf(errorLine,"(%d)=>loperand\n",i);
890     logLine(errorLine);
891     loperand->printUseCount();
892   }
893   if (roperand) {
894     sprintf(errorLine,"(%d)=>roperand\n",i);
895     logLine(errorLine);
896     roperand->printUseCount();  
897   }
898   if (eoperand) {
899     sprintf(errorLine,"(%d)=>eoperand\n",i);
900     logLine(errorLine);
901     eoperand->printUseCount();  
902   }
903 }
904 #endif
905
906 //
907 // This procedure generates code for an AST DAG. If there is a sub-graph
908 // being shared between more than 1 node, then the code is generated only
909 // once for this sub-graph and the register where the return value of the
910 // sub-graph is stored, is kept allocated until the last node sharing the
911 // sub-graph has used it (freeing it afterwards). A count called "useCount"
912 // is used to determine whether a particular node or sub-graph is being
913 // shared. At the end of the call to generate code, this count must be 0
914 // for every node. Another important issue to notice is that we have to make
915 // sure that if a node is not calling generate code recursively for either
916 // its left or right operands, we then need to make sure that we update the
917 // "useCount" for these nodes (otherwise we might be keeping registers
918 // allocated without reason). 
919 //
920 // This code was modified in order to set the proper "useCount" for every
921 // node in the DAG before calling the original generateCode procedure (now
922 // generateCode_phase2). This means that we are traversing the DAG twice,
923 // but with the advantage of potencially generating more efficient code.
924 //
925 // Note: a complex Ast DAG might require more registers than the ones 
926 // currently available. In order to fix this problem, we will need to 
927 // implement a "virtual" register allocator - naim 11/06/96
928 //
929 reg AstNode::generateCode(process *proc,
930                           registerSpace *rs,
931                           char *insn, 
932                           unsigned &base, bool noCost) {
933   cleanUseCount();
934   setUseCount();
935   reg tmp=generateCode_phase2(proc,rs,insn,base,noCost);
936   return(tmp);
937 }
938
939 reg AstNode::generateCode_phase2(process *proc,
940                                  registerSpace *rs,
941                                  char *insn, 
942                                  unsigned &base, bool noCost) {
943     unsigned addr;
944     unsigned fromAddr;
945     unsigned startInsn;
946     reg src1, src2;
947     reg src = -1;
948     reg dest = -1;
949     reg right_dest = -1;
950
951     useCount--;
952     if (kept_register>=0) {
953 #if defined(ASTDEBUG)
954       sprintf(errorLine,"==> Returning register %d <==\n",kept_register);
955       logLine(errorLine);
956 #endif
957       if (useCount==0) {
958         rs->unkeep_register(kept_register);
959         reg tmp=kept_register;
960         kept_register=-1;
961         return(tmp);
962       }
963       return(kept_register);
964     }
965
966     if (type == opCodeNode) {
967         if (op == ifOp) {
968             // This ast cannot be shared because it doesn't return a register
969             src = loperand->generateCode_phase2(proc, rs, insn, base, noCost);
970             startInsn = base;
971             fromAddr = emit(op, src, (reg) 0, (reg) 0, insn, base, noCost);
972             rs->freeRegister(src);
973             reg tmp = roperand->generateCode_phase2(proc, rs, insn, base, noCost);
974             rs->freeRegister(tmp);
975
976             // Is there and else clause?  If yes, generate branch over it
977             unsigned else_fromAddr;
978             unsigned else_startInsn = base;
979             if (eoperand) {
980                 else_fromAddr = emit(branchOp, (reg) 0, (reg) 0, (reg) 0,
981                                      insn, base, noCost);
982             }
983
984             // call emit again now with correct offset.
985             (void) emit(op, src, (reg) 0, (reg) ((int)base - (int)fromAddr), 
986                         insn, startInsn, noCost);
987             // sprintf(errorLine,branch forward %d\n", base - fromAddr);
988            
989             if (eoperand) {
990                 // If there's an else clause, we need to generate code for it.
991                 tmp = eoperand->generateCode_phase2(proc, rs, insn, base,
992                                                     noCost);
993                 rs->freeRegister(tmp);
994
995                 // We also need to fix up the branch at the end of the "true"
996                 // clause to jump around the "else" clause.
997                 emit(branchOp, (reg) 0, (reg) 0,
998                      ((int)base - (int)else_fromAddr),
999                      insn, else_startInsn, noCost);
1000             }
1001         } else if (op == storeOp) {
1002             // This ast cannot be shared because it doesn't return a register
1003             // Check loperand because we are not generating code for it on
1004             // this node.
1005             loperand->useCount--;
1006             if (loperand->useCount==0 && loperand->kept_register>=0) {
1007               rs->unkeep_register(loperand->kept_register);
1008               loperand->kept_register=-1;
1009             }
1010             src1 = roperand->generateCode_phase2(proc, rs, insn, base, noCost);
1011             src2 = rs->allocateRegister(insn, base, noCost);
1012             addr = (unsigned) loperand->oValue;
1013             assert(addr != 0); // check for NULL
1014             (void) emit(op, src1, src2, (reg) addr, insn, base, noCost);
1015             rs->freeRegister(src1);
1016             rs->freeRegister(src2);
1017         } else if (op == storeIndirOp) {
1018             src1 = roperand->generateCode_phase2(proc, rs, insn, base, noCost);
1019             dest = loperand->generateCode_phase2(proc, rs, insn, base, noCost);
1020             (void) emit(op, src1, 0, dest, insn, base, noCost);          
1021             rs->freeRegister(src1);
1022             rs->freeRegister(dest);
1023         } else if (op == trampTrailer) {
1024             // This ast cannot be shared because it doesn't return a register
1025             return((unsigned) emit(op, 0, 0, 0, insn, base, noCost));
1026         } else if (op == trampPreamble) {
1027             // This ast cannot be shared because it doesn't return a register
1028 #ifdef i386_unknown_solaris2_5
1029             // loperand is a constant AST node with the cost, in cycles.
1030             int cost = noCost ? 0 : (int) loperand->oValue;
1031             int costAddr = 0; // for now... (won't change if noCost is set)
1032             loperand->useCount--;
1033
1034 #ifndef SHM_SAMPLING
1035             bool err;
1036             costAddr = proc->findInternalAddress("DYNINSTobsCostLow", true, err);
1037             if (err) {
1038 //              logLine("Internal error: unable to find addr of DYNINSTobsCostLow\n");
1039                 showErrorCallback(79, "");
1040                 P_abort();
1041             }
1042 #else
1043             if (!noCost)
1044                costAddr = (int)proc->getObsCostLowAddrInApplicSpace();
1045 #endif
1046             return (unsigned) emit(op, 0, 0, 0, insn, base, noCost);
1047 #endif
1048         } else {
1049             AstNode *left = assignAst(loperand);
1050             AstNode *right = assignAst(roperand);
1051
1052             if (left && right) {
1053               if (left->type == operandNode && left->oType == Constant) {
1054                 if (type == opCodeNode) {
1055                   if (op == plusOp) {
1056                     AstNode *temp = assignAst(right);
1057                     right = assignAst(left);
1058                     left = assignAst(temp);
1059                     removeAst(temp);
1060                   } else if (op == timesOp) {
1061                     if (right->type == operandNode) {
1062                       if (right->oType != Constant) {
1063                         AstNode *temp = assignAst(right);
1064                         right = assignAst(left);
1065                         left = assignAst(temp);
1066                         removeAst(temp);
1067                       }
1068                       else {
1069                         int result;
1070                         if (!isPowerOf2((int)right->oValue,result) &&
1071                              isPowerOf2((int)left->oValue,result))
1072                         {
1073                           AstNode *temp = assignAst(right);
1074                           right = assignAst(left);
1075                           left = assignAst(temp);
1076                           removeAst(temp);
1077                         }
1078                       }
1079                     }
1080                   }
1081                 }
1082               }
1083             }
1084
1085             if (left)
1086               src = left->generateCode_phase2(proc, rs, insn, base, noCost);
1087
1088             rs->freeRegister(src);
1089             dest = rs->allocateRegister(insn, base, noCost);
1090             if (useCount>0) {
1091               kept_register=dest;
1092               rs->keep_register(dest);
1093             }
1094
1095             if (right && (right->type == operandNode) &&
1096                 (right->oType == Constant) &&
1097                 doNotOverflow((int)right->oValue) &&
1098                 (type == opCodeNode))
1099             {
1100               emitImm(op, src, (reg)right->oValue, dest, insn, base, noCost);
1101               right->useCount--;
1102               if (right->useCount==0 && right->kept_register>=0) {
1103                 rs->unkeep_register(right->kept_register);
1104                 right->kept_register=-1;
1105               }
1106             }
1107             else {
1108               if (right)
1109                 right_dest = right->generateCode_phase2(proc, rs, insn, base, noCost);
1110               rs->freeRegister(right_dest);
1111               (void) emit(op, src, right_dest, dest, insn, base, noCost);
1112             }
1113             removeAst(left);
1114             removeAst(right);
1115         }
1116     } else if (type == operandNode) {
1117         dest = rs->allocateRegister(insn, base, noCost);
1118         if (useCount>0) {
1119           kept_register=dest;
1120           rs->keep_register(dest);
1121         }
1122         if (oType == Constant) {
1123             (void) emit(loadConstOp, (reg) oValue, dest, dest, insn, base, noCost);
1124         } else if (oType == ConstantPtr) {
1125             (void) emit(loadConstOp, (reg) (*(unsigned int *) oValue),
1126                 dest, dest, insn, base, noCost);
1127         } else if (oType == DataPtr) {
1128             addr = (unsigned) oValue;
1129             assert(addr != 0); // check for NULL
1130             (void) emit(loadConstOp, (reg) addr, dest, dest, insn, base, noCost);
1131         } else if (oType == DataIndir) {
1132             src = loperand->generateCode_phase2(proc, rs, insn, base, noCost);
1133             (void) emit(loadIndirOp, src, 0, dest, insn, base, noCost); 
1134             rs->freeRegister(src);
1135         } else if (oType == DataReg) {
1136             rs->unkeep_register(dest);
1137             rs->freeRegister(dest);
1138             dest = (reg)oValue;
1139             if (useCount>0) {
1140               kept_register=dest;
1141               rs->keep_register(dest);
1142             }
1143         } else if (oType == DataId) {
1144             (void) emit(loadConstOp, (reg) oValue, dest, dest, insn, base, noCost);
1145         } else if (oType == DataValue) {
1146             addr = (unsigned) oValue;
1147
1148             assert(addr != 0); // check for NULL
1149             (void) emit(loadOp, (reg) addr, dest, dest, insn, base, noCost);
1150         } else if (oType == ReturnVal) {
1151             rs->unkeep_register(dest);
1152             rs->freeRegister(dest);
1153             src = rs->allocateRegister(insn, base, noCost);
1154 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
1155             if (loperand) {
1156                 unsigned emitOptReturn(unsigned, reg, char *, unsigned &, bool);
1157                 dest = emitOptReturn(loperand -> oValue, src, insn, base, noCost);
1158             }
1159             else if (astFlag)
1160                 dest = emit(getSysRetValOp, 0, 0, src, insn, base, noCost);
1161             else 
1162 #endif
1163                 dest = emit(getRetValOp, 0, 0, src, insn, base, noCost);
1164             if (useCount>0) {
1165               kept_register=dest;
1166               rs->keep_register(dest);
1167             }
1168             if (src != dest) {
1169                 rs->freeRegister(src);
1170             }
1171         } else if (oType == Param) {
1172             rs->unkeep_register(dest);
1173             rs->freeRegister(dest);
1174             src = rs->allocateRegister(insn, base, noCost);
1175             // return the actual reg it is in.
1176 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)  
1177             if (astFlag)
1178                 dest = emit(getSysParamOp, (reg)oValue, 0, src, insn, base, noCost);
1179             else 
1180 #endif
1181                 dest = emit(getParamOp, (reg)oValue, 0, src, insn, base, noCost);
1182             if (useCount>0) {
1183               kept_register=dest;
1184               rs->keep_register(dest);
1185             }
1186             if (src != dest) {
1187                 rs->freeRegister(src);
1188             }
1189         } else if (oType == DataAddr) {
1190           addr = (unsigned) oValue;
1191           emit(loadOp, (reg) addr, dest, dest, insn, base, noCost);
1192         } else if (oType == ConstantString) {
1193           // XXX This is for the string type.  If/when we fix the string type
1194           // to make it less of a hack, we'll need to change this.
1195           int len = strlen((char *)oValue) + 1;
1196           addr = (unsigned) inferiorMalloc(proc, len, dataHeap);
1197           proc->writeDataSpace((char *)addr, len, (char *)oValue);
1198           emit(loadConstOp, (reg) addr, dest, dest, insn, base, noCost);
1199         }
1200     } else if (type == callNode) {
1201         dest = emitFuncCall(callOp, rs, insn, base, operands, callee, proc, noCost);
1202         if (useCount>0) {
1203           kept_register=dest;
1204           rs->keep_register(dest);
1205         }
1206     } else if (type == sequenceNode) {
1207         (void) loperand->generateCode_phase2(proc, rs, insn, base, noCost);
1208         return(roperand->generateCode_phase2(proc, rs, insn, base, noCost));
1209     }
1210
1211     return(dest);
1212 }
1213
1214
1215 #if defined(ASTDEBUG)
1216 string getOpString(opCode op)
1217 {
1218     switch (op) {
1219         case plusOp: return("+");
1220         case minusOp: return("-");
1221         case timesOp: return("*");
1222         case divOp: return("/");
1223         case lessOp: return("<");
1224         case leOp: return("<=");
1225         case greaterOp: return(">");
1226         case geOp: return(">=");
1227         case eqOp: return("==");
1228         case neOp: return("!=");
1229         case loadOp: return("lda");
1230         case loadConstOp: return("load");
1231         case storeOp: return("=");
1232         case ifOp: return("if");
1233         case trampPreamble: return("preTramp");
1234         case trampTrailer: return("goto");
1235         case noOp: return("nop");
1236         case andOp: return("and");
1237         case orOp: return("or");
1238         case loadIndirOp: return("load&");
1239         case storeIndirOp: return("=&");
1240         default: return("ERROR");
1241     }
1242 }
1243 #endif
1244
1245 int AstNode::cost() const {
1246     int total = 0;
1247     int getInsnCost(opCode t);
1248
1249     if (type == opCodeNode) {
1250         if (op == ifOp) {
1251             if (loperand) total += loperand->cost();
1252             total += getInsnCost(op);
1253             int rcost = 0, ecost = 0;
1254             if (roperand) {
1255                 rcost = roperand->cost();
1256                 if (eoperand)
1257                     rcost += getInsnCost(branchOp);
1258             }
1259             if (eoperand)
1260                 ecost = eoperand->cost();
1261             if (rcost > ecost)      
1262                 total += rcost;
1263             else
1264                 total += ecost;
1265         } else if (op == storeOp) {
1266             if (roperand) total += roperand->cost();
1267             total += getInsnCost(op);
1268         } else if (op == storeIndirOp) {
1269             if (loperand) total += loperand->cost();
1270             if (roperand) total += roperand->cost();
1271             total += getInsnCost(op);
1272         } else if (op == trampTrailer) {
1273             total = getInsnCost(op);
1274         } else if (op == trampPreamble) {
1275             total = getInsnCost(op);
1276         } else {
1277             if (loperand) 
1278                 total += loperand->cost();
1279             if (roperand) 
1280                 total += roperand->cost();
1281             total += getInsnCost(op);
1282         }
1283     } else if (type == operandNode) {
1284         if (oType == Constant) {
1285             total = getInsnCost(loadConstOp);
1286         } else if (oType == DataPtr) {
1287             total = getInsnCost(loadConstOp);
1288         } else if (oType == DataValue) {
1289             total = getInsnCost(loadOp);
1290         } else if (oType == DataId) {
1291             total = getInsnCost(loadConstOp);
1292         } else if (oType == DataIndir) {
1293             total = getInsnCost(loadIndirOp);
1294             total += loperand->cost();
1295         } else if (oType == DataReg) {
1296             total = getInsnCost(loadIndirOp);
1297         } else if (oType == Param) {
1298             total = getInsnCost(getParamOp);
1299         }
1300     } else if (type == callNode) {
1301         total = getPrimitiveCost(callee);
1302         for (unsigned u = 0; u < operands.size(); u++)
1303           if (operands[u]) total += operands[u]->cost();
1304     } else if (type == sequenceNode) {
1305         if (loperand) total += loperand->cost();
1306         if (roperand) total += roperand->cost();
1307     }
1308     return(total);
1309 }
1310
1311 #if defined(ASTDEBUG)
1312 void AstNode::print() const {
1313     if (type == operandNode) {
1314         if (oType == Constant) {
1315             sprintf(errorLine, " %d", (int) oValue);
1316             logLine(errorLine);
1317         } else if (oType == DataPtr) {
1318             sprintf(errorLine, " %d", (int) oValue);
1319             logLine(errorLine);
1320         } else if (oType == DataValue) {
1321             sprintf(errorLine, "@%d", (int) oValue);
1322             logLine(errorLine);
1323         } else if (oType == DataIndir) {
1324             logLine("@[");
1325             loperand->print();
1326             logLine("]");
1327         } else if (oType == DataReg) {
1328             sprintf(errorLine," reg%d ",(int)oValue);
1329             logLine(errorLine);
1330             loperand->print();
1331         } else if (oType == Param) {
1332             sprintf(errorLine, "param[%d]", (int) oValue);
1333             logLine(errorLine);
1334         }
1335     } else if (type == opCodeNode) {
1336         ostrstream os(errorLine, 1024, ios::out);
1337         os << "(" << getOpString(op) << ends;
1338         logLine(errorLine);
1339         if (loperand) loperand->print();
1340         if (roperand) roperand->print();
1341         if (eoperand) eoperand->print();
1342         logLine(")");
1343     } else if (type == callNode) {
1344         ostrstream os(errorLine, 1024, ios::out);
1345         os << "(" << callee << ends;
1346         logLine(errorLine);
1347         for (unsigned u = 0; u < operands.size(); u++)
1348           operands[u]->print();
1349         logLine(")");
1350     } else if (type == sequenceNode) {
1351         if (loperand) loperand->print();
1352         logLine(",");
1353         if (roperand) roperand->print();
1354     }
1355 }
1356 #endif
1357
1358 AstNode *createIf(AstNode *expression, AstNode *action) 
1359 {
1360   AstNode *t;
1361   t = new AstNode(ifOp, expression, action);
1362   return(t);
1363 }
1364
1365 #ifndef BPATCH_LIBRARY
1366
1367 // Multithreaded case with shared memory sampling
1368
1369 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1370
1371 AstNode *computeAddress(void *level, void *index, int type)
1372 {
1373   AstNode *t0=NULL,*t1=NULL,*t2=NULL,*t3=NULL;
1374   AstNode *t4=NULL,*t5=NULL,*t6=NULL,*t7=NULL;
1375   AstNode *t8=NULL,*t9=NULL,*t10=NULL,*t11=NULL;
1376   int tSize;
1377
1378   /* DYNINSTthreadTable[0][thr_self()] */
1379   t0 = new AstNode(AstNode::DataReg, (void *)REG_MT);
1380
1381   /* Now we compute the offset for the corresponding level. We assume */
1382   /* that the DYNINSTthreadTable is stored by rows - naim 4/18/97 */
1383   if ((int)level != 0) {
1384     tSize = sizeof(unsigned);
1385     t1 = new AstNode(AstNode::Constant, (void *)MAX_NUMBER_OF_THREADS);
1386     t2 = new AstNode(AstNode::Constant, level);
1387     t3 = new AstNode(timesOp, t1, t2);
1388     t4 = new AstNode(AstNode::Constant, (void *)tSize);
1389     t5 = new AstNode(timesOp, t3, t4); /* offset including just level */
1390
1391     /* Given the level and tid, we compute the position in the thread */
1392     /* table. */
1393     t6 = new AstNode(plusOp, t0, t5);
1394
1395     /* We then read the address, which is really the base address of the */
1396     /* vector of counters and timers in the shared memory segment. */
1397     t7 = new AstNode(AstNode::DataIndir, t6); 
1398   } else {
1399     /* if level is 0, we don't need to compute the offset */
1400     t7 = new AstNode(AstNode::DataIndir, t0);
1401   }
1402
1403   /* Finally, using the index as an offset, we compute the address of the */
1404   /* counter/timer. */
1405   if (type==0) {
1406     /* intCounter */
1407     tSize = sizeof(intCounter);
1408   } else {
1409     /* Timer */
1410     tSize = sizeof(tTimer);
1411   }
1412   t8 = new AstNode(AstNode::Constant, (void *)index);
1413   t9 = new AstNode(AstNode::Constant, (void *)tSize);
1414   t10 = new AstNode(timesOp, t8, t9);
1415   t11 = new AstNode(plusOp, t7, t10); /* address of counter/timer */
1416
1417   removeAst(t0);
1418   removeAst(t1);
1419   removeAst(t2);
1420   removeAst(t3);
1421   removeAst(t4);
1422   removeAst(t5);
1423   removeAst(t6);
1424   removeAst(t7);
1425   removeAst(t8);
1426   removeAst(t9);
1427   removeAst(t10);
1428   return(t11);
1429 }
1430
1431 AstNode *createTimer(const string &func, void *level, void *index,
1432                      vector<AstNode *> &ast_args)
1433 {
1434   AstNode *t0=NULL,*t1=NULL;
1435
1436   t0 = computeAddress(level,index,1); /* 1 means tTimer */
1437   ast_args += assignAst(t0);
1438   removeAst(t0);
1439   t1 = new AstNode(func, ast_args);
1440   for (unsigned i=0;i<ast_args.size();i++) removeAst(ast_args[i]);  
1441
1442   return(t1);
1443 }
1444
1445 AstNode *createCounter(const string &func, void *level, void *index, 
1446                        AstNode *ast) 
1447
1448   AstNode *t0=NULL,*t1=NULL,*t2=NULL,*t3=NULL;
1449
1450   t0 = computeAddress(level,index,0); /* 0 means intCounter */
1451
1452   if (func == "addCounter") {
1453     t1 = new AstNode(AstNode::DataIndir, t0);
1454     t2 = new AstNode(plusOp, t1, ast);
1455     t3 = new AstNode(storeIndirOp, t0, t2);
1456   } else if (func == "subCounter") {
1457     t1 = new AstNode(AstNode::DataIndir, t0);
1458     t2 = new AstNode(minusOp, t1, ast);
1459     t3 = new AstNode(storeIndirOp, t0, t2);
1460   } else if (func == "setCounter") {
1461     t3 = new AstNode(storeIndirOp, t0, ast);
1462   }
1463
1464   removeAst(t0);
1465   removeAst(t1);
1466   removeAst(t2);
1467
1468   return(t3);
1469 }
1470
1471 #else
1472
1473 // Single threaded case
1474
1475 AstNode *createTimer(const string &func, void *dataPtr, 
1476                      vector<AstNode *> &ast_args)
1477 {
1478   AstNode *t0=NULL,*t1=NULL;
1479
1480   t0 = new AstNode(AstNode::DataPtr, (void *) dataPtr);
1481   ast_args += assignAst(t0);
1482   removeAst(t0);
1483   t1 = new AstNode(func, ast_args);
1484   for (unsigned i=0;i<ast_args.size();i++) removeAst(ast_args[i]);  
1485   return(t1);
1486 }
1487
1488 AstNode *createCounter(const string &func, void *dataPtr, 
1489                        AstNode *ast) 
1490 {
1491    AstNode *t0=NULL, *t1=NULL, *t2=NULL;
1492
1493    t0 = new AstNode(AstNode::DataValue, (void *)dataPtr);
1494    if (func=="addCounter") {
1495      t1 = new AstNode(plusOp,t0,ast);
1496      t2 = new AstNode(storeOp,t0,t1);
1497    } else if (func=="subCounter") {
1498      t1 = new AstNode(minusOp,t0,ast);
1499      t2 = new AstNode(storeOp,t0,t1);
1500    } else if (func=="setCounter") {
1501      t2 = new AstNode(storeOp,t0,ast);
1502    } else abort();
1503    removeAst(t0);
1504    removeAst(t1);
1505    return(t2);
1506 }
1507
1508 #endif
1509 #endif
1510
1511 #ifdef BPATCH_LIBRARY
1512 BPatch_type *AstNode::checkType()
1513 {
1514     BPatch_type *ret = NULL;
1515     BPatch_type *lType = NULL, *rType = NULL, *eType = NULL;
1516     bool errorFlag = false;
1517
1518     assert(BPatch::bpatch != NULL);     /* We'll use this later. */
1519
1520     assert( (!loperand && !roperand) || getType() == NULL );
1521
1522     if (loperand)
1523         lType = loperand->checkType();
1524
1525     if (roperand)
1526         rType = roperand->checkType();
1527
1528     if (eoperand)
1529         eType = eoperand->checkType();
1530
1531     if (lType == BPatch::bpatch->type_Error ||
1532         rType == BPatch::bpatch->type_Error)
1533         errorFlag = true;
1534
1535     
1536     switch (type) { // Type here is nodeType, not BPatch library type
1537         case sequenceNode:
1538             ret = rType;
1539             break;
1540         case opCodeNode:
1541             if (op == ifOp) {
1542                 // XXX No checking for now.  Should check that loperand
1543                 // is boolean.
1544                 ret = BPatch::bpatch->type_Untyped;
1545             } else if (op == noOp) {
1546                 ret = BPatch::bpatch->type_Untyped;
1547             } else {
1548                 if (lType != NULL && rType != NULL) {
1549                     if (!lType->isCompatible(*rType)) {
1550                         errorFlag = true;
1551                     }
1552                 }
1553                 // XXX The following line must change to decide based on the
1554                 // types and operation involved what the return type of the
1555                 // expression will be.
1556                 ret = lType;
1557             }
1558             break;
1559         case operandNode:
1560             assert(loperand == NULL && roperand == NULL);
1561             if ((oType == Param) || (oType == ReturnVal)) {
1562                 // XXX Params and ReturnVals untyped for now
1563                 ret = BPatch::bpatch->type_Untyped; 
1564             } else
1565                 ret = getType();
1566             assert(ret != NULL);
1567             break;
1568         case callNode:
1569             for (int i = 0; i < operands.size(); i++) {
1570                 BPatch_type *operandType = operands[i]->checkType();
1571                 /* XXX Check operands for compatibility */
1572                 if (operandType == BPatch::bpatch->type_Error)
1573                     errorFlag = true;
1574             }
1575             /* XXX Should set to return type of function. */
1576             ret = BPatch::bpatch->type_Untyped;
1577             break;
1578       default:
1579         assert(0);
1580     }
1581
1582     assert(ret != NULL);
1583
1584     if (errorFlag && doTypeCheck) {
1585         ret = BPatch::bpatch->type_Error;
1586     }
1587
1588     return ret;
1589 }
1590 #endif