Bug fix for reused snippets in 64-bit function calls
[dyninst.git] / dyninstAPI / src / ast.h
1 /*
2  * Copyright (c) 1996-2011 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: ast.h,v 1.107 2008/05/12 22:12:47 giri Exp $
33
34 #ifndef AST_HDR
35 #define AST_HDR
36
37 //
38 // Define a AST class for use in generating primitive and pred calls
39 //
40
41
42 #include <stdio.h>
43 #include <string>
44 #include "common/h/Vector.h"
45 #include "common/h/Dictionary.h"
46 #include "common/h/Types.h"
47
48
49 #include "BPatch_snippet.h"
50
51 // The great experiment: boost shared_ptr libraries
52 #include <dyn_detail/boost/shared_ptr.hpp>
53 #include "BPatch_type.h"
54
55 #include "arch-forward-decl.h" // instruction
56
57 class process;
58 class AddressSpace;
59 class instPoint;
60 class func_instance;
61 class int_variable;
62
63 class codeGen;
64 class codeRange;
65 class BPatch_instruction; // Memory, etc. are at BPatch. Might want to move 'em.
66 //class BPatch_type;
67 class image_variable;
68
69
70
71
72 // a register number, e.g. [0,31]
73 // typedef int reg; // see new Register type in "common/h/Types.h"
74
75 #include "opcode.h"
76
77 // Register retention mechanism...
78 // If we've already calculated a result, then we want to reuse it if it's
79 // still available. This means it was calculated along a path that reaches the
80 // current point (not inside a conditional) and the register hasn't been
81 // reused. We handle this so:
82 //
83 // 1) Iterate over the AST tree and see if any node is reached more than once;
84 // if so, mark it as potentially being worth keeping around. We can do this
85 // because we use pointers; a better approach would be a comparison operator.
86 // 2) Start generation at "level 0". 
87 // 3) When a conditional AST is reached, generate each child at level+1.
88 // 4) When the AST is reached during code generation, and doesn't have a register:
89 // 4a) Allocate a register for it;
90 // 4b) Enter that register, the AST node, and the current level in the global table.
91 // 5) If it does have a register, reuse it. 
92 // 6) When the conditionally executed branch is finished, clean all entries in
93 // the table with that level value (undoing all kept registers along that
94 // path).
95 // 7) If we need a register, the register allocator (registerSpace) can forcibly
96 // undo this optimization and grab a register. Grab the register from the AstNode
97 // with the lowest usage count.
98
99 class AstNode;
100 typedef dyn_detail::boost::shared_ptr<AstNode> AstNodePtr;
101 class AstMiniTrampNode;
102 typedef dyn_detail::boost::shared_ptr<AstMiniTrampNode> AstMiniTrampNodePtr;
103
104 typedef enum {
105    cfj_unset = 0,
106    cfj_none = 1,
107    cfj_jump = 2,
108    cfj_call = 3
109 } cfjRet_t;
110
111 class registerSpace;
112
113 class regTracker_t {
114 public:
115         class commonExpressionTracker {
116         public:
117                 Register keptRegister;  
118                 int keptLevel;
119                 commonExpressionTracker() : keptRegister(REG_NULL), keptLevel(-1) {};
120         };
121
122         int condLevel;
123         
124         static unsigned astHash(AstNode * const &ast);
125
126         regTracker_t() : condLevel(0), tracker(astHash) {};
127
128         dictionary_hash<AstNode *, commonExpressionTracker> tracker;
129
130         void addKeptRegister(codeGen &gen, AstNode *n, Register reg);
131         void removeKeptRegister(codeGen &gen, AstNode *n);
132         Register hasKeptRegister(AstNode *n);
133         bool stealKeptRegister(Register reg); 
134
135         void reset();
136
137         void increaseConditionalLevel();
138         void decreaseAndClean(codeGen &gen);
139         void cleanKeptRegisters(int level);
140         void debugPrint();
141         
142
143 };
144
145 class dataReqNode;
146 class AstNode {
147  public:
148    enum nodeType { sequenceNode_t, opCodeNode_t, operandNode_t, callNode_t, scrambleRegisters_t};
149    enum operandType { Constant, 
150                       ConstantString,
151                       DataReg,
152                       DataIndir,
153                       Param,
154                       ParamAtCall,
155                       ParamAtEntry,
156                       ReturnVal, 
157                       ReturnAddr, // address of a return instruction
158                       DataAddr,  // Used to represent a variable in memory
159                       FrameAddr, // Calculate FP 
160                       RegOffset, // Calculate *reg + offset; oValue is reg, loperand->oValue is offset. 
161                       //PreviousStackFrameDataReg,
162                       //RegValue, // A possibly spilled, possibly saved register.
163                       // Both the above are now: origRegister 
164                       origRegister,
165                       variableAddr,
166                       variableValue,
167                       undefOperandType };
168
169
170
171    enum memoryType {
172       EffectiveAddr,
173       BytesAccessed };
174
175    //Error reporting for dynC_API
176   protected:
177    int lineNum;
178    int columnNum;
179    char *snippetName;
180
181    bool lineInfoSet;
182    bool columnInfoSet;
183    bool snippetNameSet;
184
185   public:
186    virtual std::string format(std::string indent);
187    std::string convert(operandType type);
188    std::string convert(opCode op);
189
190    int getLineNum();
191    int getColumnNum();
192    char *getSnippetName();
193
194    void setLineNum(int ln);
195    void setColumnNum(int cn);
196    void setSnippetName(char *n);
197
198    bool hasLineInfo();
199    bool hasColumnInfo();
200    bool hasNameInfo();
201    
202    AstNode(); // mdl.C
203
204    // Factory methods....
205    static AstNodePtr nullNode();
206
207    static AstNodePtr labelNode(std::string &label);
208
209    static AstNodePtr operandNode(operandType ot, void *arg);
210    static AstNodePtr operandNode(operandType ot, AstNodePtr ast);
211    static AstNodePtr operandNode(operandType ot, const image_variable* iv);
212
213    static AstNodePtr memoryNode(memoryType ot, int which);
214
215    static AstNodePtr sequenceNode(pdvector<AstNodePtr > &sequence);
216         
217    static AstNodePtr variableNode(std::vector<AstNodePtr>&ast_wrappers_, std::vector<std::pair<Offset, Offset> > *ranges = NULL);
218
219    static AstNodePtr operatorNode(opCode ot, 
220                                   AstNodePtr l = AstNodePtr(), 
221                                   AstNodePtr r = AstNodePtr(), 
222                                   AstNodePtr e = AstNodePtr());
223
224    static AstNodePtr funcCallNode(const std::string &func, pdvector<AstNodePtr > &args, AddressSpace *addrSpace = NULL);
225    static AstNodePtr funcCallNode(func_instance *func, pdvector<AstNodePtr > &args);
226    static AstNodePtr funcCallNode(func_instance *func); // Special case for function call replacement.
227    static AstNodePtr funcCallNode(Address addr, pdvector<AstNodePtr > &args); // For when you absolutely need
228    // to jump somewhere.
229
230    static AstNodePtr insnNode(BPatch_instruction *insn);
231
232    // Acquire the thread index value - a 0...n labelling of threads.
233    static AstNodePtr threadIndexNode();
234
235    static AstNodePtr scrambleRegistersNode();
236    
237    
238    // TODO...
239    // Needs some way of marking what to save and restore... should be a registerSpace, really
240
241 #if 0
242    static AstNodePtr saveStateNode();
243    static AstNodePtr restoreStateNode();
244    static AstNodePtr trampGuardNode();
245 #endif
246
247    static AstNodePtr miniTrampNode(AstNodePtr tramp);
248
249    static AstNodePtr originalAddrNode();
250    static AstNodePtr actualAddrNode();
251    static AstNodePtr dynamicTargetNode();
252
253    AstNode(AstNodePtr src);
254    //virtual AstNode &operator=(const AstNode &src);
255         
256    virtual ~AstNode();
257         
258    virtual bool generateCode(codeGen &gen, 
259                              bool noCost, 
260                              Address &retAddr,
261                              Register &retReg);
262
263    // Can't use default references....
264    virtual bool generateCode(codeGen &gen, 
265                              bool noCost);
266
267    // Can't use default references....
268    virtual bool generateCode(codeGen &gen, 
269                              bool noCost, 
270                              Register &retReg) { 
271       Address unused = ADDR_NULL;
272       return generateCode(gen, noCost,  unused, retReg);
273    }
274
275    // I don't know if there is an overload between address and register...
276    // so we'll toss in two different return types.
277    virtual bool generateCode_phase2(codeGen &gen,
278                                     bool noCost,
279                                     Address &retAddr,
280                                     Register &retReg);
281
282    // Perform whatever pre-processing steps are necessary.
283    virtual bool initRegisters(codeGen &gen);
284         
285    // Select the appropriate Variable AST as part of pre-processing
286    // steps before code generation.
287    virtual void setVariableAST(codeGen &) {}
288
289    unsigned getTreeSize();
290
291    bool decRefCount();
292
293    bool previousComputationValid(Register &reg,
294                                  codeGen &gen);
295    // Remove any kept register at a greater level than
296    // that provided (AKA that had been calculated within
297    // a conditional statement)
298    void cleanRegTracker(regTracker_t *tracker, int level);
299
300    virtual AstNodePtr operand() const { return AstNodePtr(); }
301
302
303
304    virtual bool containsFuncCall() const = 0;
305    virtual cfjRet_t containsFuncJump() const = 0;
306    virtual bool usesAppRegister() const = 0;
307
308    enum CostStyleType { Min, Avg, Max };
309    int minCost() const {  return costHelper(Min);  }
310    int avgCost() const {  return costHelper(Avg);  }
311    int maxCost() const {  return costHelper(Max);  }
312
313         // return the # of instruction times in the ast.
314         virtual int costHelper(enum CostStyleType) const { return 0; }; 
315
316    int referenceCount;     // Reference count for freeing memory
317    int useCount;           // Reference count for generating code
318    void setUseCount(); // Set values for useCount
319    int getSize() { return size; };
320    void cleanUseCount(void);
321    bool checkUseCount(registerSpace*, bool&);
322    void printUseCount(void);
323
324    virtual const std::vector<AstNodePtr> getArgs() { return std::vector<AstNodePtr>(); }; // to quiet compiler
325
326
327    virtual void setChildren(pdvector<AstNodePtr > &children);
328    virtual AstNodePtr deepCopy() { return AstNodePtr(this);};
329    
330
331         // Occasionally, we do not call .generateCode_phase2 for the
332         // referenced node, but generate code by hand. This routine decrements
333         // its use count properly
334         void decUseCount(codeGen &gen);
335
336         // Our children may have incorrect useCounts (most likely they 
337         // assume that we will not bother them again, which is wrong)
338         void fixChildrenCounts();
339
340         // Check if the node can be kept at all. Some nodes (e.g., storeOp)
341         // can not be cached
342         virtual bool canBeKept() const = 0;
343
344         // Allocate a register and make it available for sharing if our
345    // node is shared
346         Register allocateAndKeep(codeGen &gen, bool noCost);
347
348    // If someone needs to take this guy away.
349    bool stealRegister(Register reg);
350
351         // Check to see if path1 is a subpath of path2
352         bool subpath(const pdvector<AstNode*> &path1, 
353                 const pdvector<AstNode*> &path2) const;
354
355         // Return all children of this node ([lre]operand, ..., operands[])
356         virtual void getChildren(pdvector<AstNodePtr> &); 
357
358    void printRC(void);
359         virtual bool accessesParam(void);
360
361         virtual void setOValue(void *) { assert(0); }
362         virtual const void *getOValue() const { assert(0); return NULL; }
363         virtual const image_variable* getOVar() const {
364       return NULL;
365         }
366         
367         virtual void emitVariableStore(opCode, Register, Register, codeGen&, 
368                                   bool, registerSpace*, 
369                                   int, const instPoint*, AddressSpace*)
370         {
371       assert(!"Never call this on anything but an operand");
372         }
373         virtual void emitVariableLoad(opCode, Register, Register, codeGen&, 
374                                  bool, registerSpace*, 
375                                  int, const instPoint*, AddressSpace*)
376         {
377       assert(!"Never call this on anything but an operand");
378         }
379         // only function that's defined in metric.C (only used in metri.C)
380         bool condMatch(AstNode* a,
381                   pdvector<dataReqNode*> &data_tuple1,
382                   pdvector<dataReqNode*> &data_tuple2,
383                   pdvector<dataReqNode*> datareqs1,
384                   pdvector<dataReqNode*> datareqs2);
385
386
387         // DEBUG
388    virtual operandType getoType() const { return undefOperandType; }
389
390    virtual void setConstFunc(bool) {};
391
392  protected:
393         BPatch_type *bptype;  // type of corresponding BPatch_snippet
394         bool doTypeCheck;           // should operands be type checked
395         int size;                   // size of the operations (in bytes)
396
397
398  public:
399         // Functions for getting and setting type decoration used by the
400         // dyninst API library
401         //AstNode(operandType ot, int which); // for memory access
402         BPatch_type *getType();
403         void              setType(BPatch_type *t);
404         void              setTypeChecking(bool x) { doTypeCheck = x; }
405         virtual BPatch_type       *checkType();
406
407  private:
408    static AstNodePtr originalAddrNode_;
409    static AstNodePtr actualAddrNode_;
410    static AstNodePtr dynamicTargetNode_;
411 };
412
413
414 class AstNullNode : public AstNode {
415  public:
416
417     AstNullNode() : AstNode() {};
418
419    virtual std::string format(std::string indent);
420     virtual bool containsFuncCall() const;
421     virtual cfjRet_t containsFuncJump() const;
422     virtual bool usesAppRegister() const;
423     
424     bool canBeKept() const { return true; }
425  private:
426     virtual bool generateCode_phase2(codeGen &gen,
427                                      bool noCost,
428                                      Address &retAddr,
429                                      Register &retReg);
430 };
431
432 class AstLabelNode : public AstNode {
433  public:
434     AstLabelNode(std::string &label) : AstNode(), label_(label), generatedAddr_(0) {};
435     virtual bool containsFuncCall() const;
436     virtual cfjRet_t containsFuncJump() const;
437     virtual bool usesAppRegister() const;
438
439         bool canBeKept() const { return true; }
440  private:
441     virtual bool generateCode_phase2(codeGen &gen,
442                                      bool noCost,
443                                      Address &retAddr,
444                                      Register &retReg);
445     std::string label_;
446     Address generatedAddr_;
447 };
448
449 class AstOperatorNode : public AstNode {
450  public:
451
452     AstOperatorNode(opCode opC, AstNodePtr l, AstNodePtr r = AstNodePtr(), AstNodePtr e = AstNodePtr());
453     
454     ~AstOperatorNode() {
455         //printf("at ~AstOperatorode()\n");
456         //debugPrint();
457     }
458
459
460    virtual std::string format(std::string indent);
461     virtual int costHelper(enum CostStyleType costStyle) const; 
462
463     virtual BPatch_type   *checkType();
464     virtual bool accessesParam(void);         // Does this AST access "Param"
465
466     virtual bool canBeKept() const;
467
468     virtual void getChildren(pdvector<AstNodePtr> &children);
469     
470     virtual void setChildren(pdvector<AstNodePtr> &children);
471     virtual AstNodePtr deepCopy();
472
473     virtual bool containsFuncCall() const;
474     virtual cfjRet_t containsFuncJump() const;
475     virtual bool usesAppRegister() const;
476  
477
478     // We override initRegisters in the case of writing to an original register.
479     virtual bool initRegisters(codeGen &gen);
480     
481     virtual void setVariableAST(codeGen &gen);
482
483  private:
484
485     virtual bool generateCode_phase2(codeGen &gen,
486                                      bool noCost,
487                                      Address &retAddr,
488                                      Register &retReg);
489
490     bool generateOptimizedAssignment(codeGen &gen, bool noCost);
491
492     AstOperatorNode() {};
493     opCode op;
494     AstNodePtr loperand;
495     AstNodePtr roperand;
496     AstNodePtr eoperand;
497 };
498
499
500 class AstOperandNode : public AstNode {
501     friend class AstOperatorNode; // ARGH
502  public:
503
504     // Direct operand
505     AstOperandNode(operandType ot, void *arg);
506
507     // And an indirect (say, a load)
508     AstOperandNode(operandType ot, AstNodePtr l);
509
510     AstOperandNode(operandType ot, const image_variable* iv);
511     
512     ~AstOperandNode() {
513         //printf("at ~AstOperandNode()\n");
514         //debugPrint();
515         if (oType == ConstantString) free((char *)oValue);
516     }
517         
518     // Arguably, the previous should be an operation...
519     // however, they're kinda endemic.
520
521    virtual std::string format(std::string indent);
522
523     virtual operandType getoType() const { return oType; };
524
525     virtual void setOValue(void *o) { oValue = o; }
526     virtual const void *getOValue() const { return oValue; };
527     virtual const image_variable* getOVar() const 
528     {
529       return oVar;
530     }
531     
532
533     virtual AstNodePtr operand() const { return operand_; }
534
535     virtual int costHelper(enum CostStyleType costStyle) const; 
536         
537     virtual BPatch_type   *checkType();
538
539     virtual bool accessesParam(void) { return (oType == Param || oType == ParamAtEntry || oType == ParamAtCall); };
540     virtual bool canBeKept() const;
541         
542     virtual void getChildren(pdvector<AstNodePtr> &children);
543     
544     virtual void setChildren(pdvector<AstNodePtr> &children);
545     virtual AstNodePtr deepCopy();
546
547     virtual void setVariableAST(codeGen &gen);
548
549     virtual bool containsFuncCall() const;
550     virtual cfjRet_t containsFuncJump() const;
551     virtual bool usesAppRegister() const;
552  
553     virtual void emitVariableStore(opCode op, Register src1, Register src2, codeGen& gen, 
554                            bool noCost, registerSpace* rs, 
555                            int size, const instPoint* point, AddressSpace* as);
556     virtual void emitVariableLoad(opCode op, Register src2, Register dest, codeGen& gen, 
557                           bool noCost, registerSpace* rs, 
558                           int size, const instPoint* point, AddressSpace* as);
559
560     virtual bool initRegisters(codeGen &gen);
561         
562  private:
563     virtual bool generateCode_phase2(codeGen &gen,
564                                      bool noCost,
565                                      Address &retAddr,
566                                      Register &retReg);
567     int_variable* lookUpVar(AddressSpace* as);
568     
569     AstOperandNode() {};
570
571     operandType oType;
572     void *oValue;
573     const image_variable* oVar;
574     AstNodePtr operand_;
575 };
576
577
578 class AstCallNode : public AstNode {
579  public:
580
581     AstCallNode(func_instance *func, pdvector<AstNodePtr>&args);
582     AstCallNode(const std::string &str, pdvector<AstNodePtr>&args);
583     AstCallNode(Address addr, pdvector<AstNodePtr> &args);
584     AstCallNode(func_instance *func);
585     
586     ~AstCallNode() {}
587
588    virtual std::string format(std::string indent);
589
590     virtual int costHelper(enum CostStyleType costStyle) const; 
591         
592     virtual BPatch_type   *checkType();
593     virtual bool accessesParam(); 
594     virtual bool canBeKept() const;
595
596     virtual void getChildren(pdvector<AstNodePtr> &children);
597     
598     virtual void setChildren(pdvector<AstNodePtr> &children);
599     virtual AstNodePtr deepCopy();
600
601     virtual void setVariableAST(codeGen &gen);
602     virtual bool containsFuncCall() const; 
603     virtual cfjRet_t containsFuncJump() const;
604     virtual bool usesAppRegister() const;
605  
606     void setConstFunc(bool val) { constFunc_ = val; }
607
608     virtual bool initRegisters(codeGen &gen);
609
610  private:
611     virtual bool generateCode_phase2(codeGen &gen,
612                                      bool noCost,
613                                      Address &retAddr,
614                                      Register &retReg);
615
616     AstCallNode() {};
617     // Sometimes we just don't have enough information...
618     const std::string func_name_;
619     Address func_addr_;
620     
621     func_instance *func_;
622     pdvector<AstNodePtr> args_;
623
624     bool callReplace_; // Node is intended for function call replacement
625     bool constFunc_;  // True if the output depends solely on 
626     // input parameters, or can otherwise be guaranteed to not change
627     // if executed multiple times in the same sequence - AKA 
628     // "can be kept".
629 };
630
631
632 class AstSequenceNode : public AstNode {
633  public:
634     AstSequenceNode(pdvector<AstNodePtr> &sequence);
635
636     ~AstSequenceNode() {}
637
638    virtual std::string format(std::string indent);
639
640     virtual int costHelper(enum CostStyleType costStyle) const; 
641
642     virtual BPatch_type   *checkType();
643     virtual bool accessesParam();
644     virtual bool canBeKept() const;
645
646     virtual void getChildren(pdvector<AstNodePtr> &children);
647     
648     virtual void setChildren(pdvector<AstNodePtr> &children);
649     virtual AstNodePtr deepCopy();
650
651     virtual void setVariableAST(codeGen &gen);
652     virtual bool containsFuncCall() const;
653     virtual cfjRet_t containsFuncJump() const;
654     virtual bool usesAppRegister() const;
655  
656
657  private:
658     virtual bool generateCode_phase2(codeGen &gen,
659                                      bool noCost,
660                                      Address &retAddr,
661                                      Register &retReg);
662
663     AstSequenceNode() {};
664     pdvector<AstNodePtr> sequence_;
665 };
666
667 class AstVariableNode : public AstNode {
668   public:
669     AstVariableNode(std::vector<AstNodePtr>&ast_wrappers, std::vector<std::pair<Offset, Offset> >*ranges);
670
671     ~AstVariableNode() {}
672
673     virtual std::string format(std::string indent);
674
675     virtual int costHelper(enum CostStyleType costStyle) const; 
676
677     virtual BPatch_type   *checkType() { return getType(); }
678     virtual bool accessesParam();
679     virtual bool canBeKept() const;
680     virtual operandType getoType() const { return ast_wrappers_[index]->getoType(); };
681     virtual AstNodePtr operand() const { return ast_wrappers_[index]->operand(); }
682     virtual const void *getOValue() const { return ast_wrappers_[index]->getOValue(); };
683
684     virtual void setVariableAST(codeGen &gen);
685
686     virtual void getChildren(pdvector<AstNodePtr> &children);
687     
688     virtual void setChildren(pdvector<AstNodePtr> &children);
689     virtual AstNodePtr deepCopy();
690
691     virtual bool containsFuncCall() const;
692     virtual cfjRet_t containsFuncJump() const;
693     virtual bool usesAppRegister() const;
694  
695
696  private:
697     virtual bool generateCode_phase2(codeGen &gen,
698                                      bool noCost,
699                                      Address &retAddr,
700                                      Register &retReg);
701
702     AstVariableNode() {};
703     std::vector<AstNodePtr>ast_wrappers_;
704     std::vector<std::pair<Offset, Offset> > *ranges_;
705     unsigned index;
706
707 };
708
709 class AstInsnNode : public AstNode {
710  public: 
711
712     AstInsnNode(instruction *insn, Address addr);
713
714
715     // Template methods...
716     virtual bool overrideBranchTarget(AstNodePtr) { return false; }
717     virtual bool overrideLoadAddr(AstNodePtr) { return false; }
718     virtual bool overrideStoreAddr(AstNodePtr) { return false; }
719
720         bool canBeKept() const { return false; }
721    virtual bool containsFuncCall() const;
722    virtual cfjRet_t containsFuncJump() const;
723    virtual bool usesAppRegister() const;
724  
725  protected:
726     virtual bool generateCode_phase2(codeGen &gen,
727                                      bool noCost,
728                                      Address &retAddr,
729                                      Register &retReg);
730
731     AstInsnNode() {};
732     instruction *insn_;
733     Address origAddr_; // The instruction class should wrap an address, but _wow_
734     // reengineering
735 };
736
737 class AstInsnBranchNode : public AstInsnNode {
738  public:
739     AstInsnBranchNode(instruction *insn, Address addr) : AstInsnNode(insn, addr), target_() {};
740
741
742     virtual bool overrideBranchTarget(AstNodePtr t) { target_ = t; return true; }
743     virtual bool containsFuncCall() const;
744     virtual cfjRet_t containsFuncJump() const;
745     virtual bool usesAppRegister() const;
746  
747
748     virtual void setVariableAST(codeGen &gen);
749     
750  protected:
751     virtual bool generateCode_phase2(codeGen &gen,
752                                      bool noCost,
753                                      Address &retAddr,
754                                      Register &retReg);
755     
756     AstNodePtr target_;
757 };
758
759 class AstInsnMemoryNode : public AstInsnNode {
760  public:
761     AstInsnMemoryNode(instruction *insn, Address addr) : AstInsnNode(insn, addr), load_(), store_() {};
762
763     virtual bool overrideLoadAddr(AstNodePtr l) { load_ = l; return true; }
764     virtual bool overrideStoreAddr(AstNodePtr s) { store_ = s; return true; }
765     virtual bool containsFuncCall() const;
766     virtual cfjRet_t containsFuncJump() const;
767     virtual bool usesAppRegister() const;
768  
769     virtual void setVariableAST(codeGen &gen);
770
771  protected:
772     virtual bool generateCode_phase2(codeGen &gen,
773                                      bool noCost,
774                                      Address &retAddr,
775                                      Register &retReg);
776     
777     AstNodePtr load_;
778     AstNodePtr store_;
779 };
780
781
782 class AstMiniTrampNode : public AstNode {
783  public:
784     AstMiniTrampNode(AstNodePtr ast) {
785        if (ast != AstNodePtr())
786           ast->referenceCount++;
787        ast_ = ast;
788     }
789
790
791     Address generateTramp(codeGen &gen, 
792                           int &trampCost, 
793                           bool noCost);
794             
795     virtual ~AstMiniTrampNode() {}    
796
797     virtual bool accessesParam(void) { return ast_->accessesParam(); } 
798
799     virtual void getChildren(pdvector<AstNodePtr> &children);
800     
801     virtual void setChildren(pdvector<AstNodePtr> &children);
802     virtual AstNodePtr deepCopy();
803
804     virtual void setVariableAST(codeGen &gen);
805
806     virtual bool containsFuncCall() const;
807     virtual cfjRet_t containsFuncJump() const;
808     virtual bool usesAppRegister() const;
809  
810
811     bool canBeKept() const;
812
813     AstNodePtr getAST() { return ast_; }
814  private:
815     AstMiniTrampNode() {};
816
817     bool inline_;
818     AstNodePtr ast_;
819 };
820
821 class AstMemoryNode : public AstNode {
822  public:
823     AstMemoryNode(memoryType mem, unsigned which);
824         bool canBeKept() const;
825
826    virtual std::string format(std::string indent);
827    virtual bool containsFuncCall() const;
828    virtual cfjRet_t containsFuncJump() const;
829    virtual bool usesAppRegister() const;
830  
831
832  private:
833     virtual bool generateCode_phase2(codeGen &gen,
834                                      bool noCost,
835                                      Address &retAddr,
836                                      Register &retReg);
837     
838     AstMemoryNode() {};
839     memoryType mem_;
840     unsigned which_;
841 };
842
843 class AstOriginalAddrNode : public AstNode {
844  public:
845     AstOriginalAddrNode() {};
846
847     virtual ~AstOriginalAddrNode() {};
848
849
850     virtual BPatch_type *checkType() { return getType(); };
851     virtual bool canBeKept() const { return true; }
852     virtual bool containsFuncCall() const;
853     virtual cfjRet_t containsFuncJump() const;
854     virtual bool usesAppRegister() const;
855  
856
857  private:
858     virtual bool generateCode_phase2(codeGen &gen,
859                                      bool noCost,
860                                      Address &retAddr,
861                                      Register &retReg);
862 };
863
864 class AstActualAddrNode : public AstNode {
865  public:
866     AstActualAddrNode() {};
867
868     virtual ~AstActualAddrNode() {};
869
870
871     virtual BPatch_type *checkType() { return getType(); };
872     virtual bool canBeKept() const { return false; }
873     virtual bool containsFuncCall() const;
874     virtual cfjRet_t containsFuncJump() const;
875     virtual bool usesAppRegister() const;
876  
877  private:
878     virtual bool generateCode_phase2(codeGen &gen,
879                                      bool noCost,
880                                      Address &retAddr,
881                                      Register &retReg);
882 };
883
884 class AstDynamicTargetNode : public AstNode {
885  public:
886     AstDynamicTargetNode() {};
887
888     virtual ~AstDynamicTargetNode() {};
889
890
891     virtual BPatch_type *checkType() { return getType(); };
892     virtual bool canBeKept() const { return false; }
893     virtual bool containsFuncCall() const;
894     virtual cfjRet_t containsFuncJump() const;
895     virtual bool usesAppRegister() const;
896  
897  private:
898     virtual bool generateCode_phase2(codeGen &gen,
899                                      bool noCost,
900                                      Address &retAddr,
901                                      Register &retReg);
902 };
903 class AstScrambleRegistersNode : public AstNode {
904  public:
905     AstScrambleRegistersNode() {};
906
907     virtual ~AstScrambleRegistersNode() {};
908
909     virtual bool canBeKept() const { return false; }
910     virtual bool containsFuncCall() const;
911     virtual cfjRet_t containsFuncJump() const;
912     virtual bool usesAppRegister() const;
913  
914  private:
915     virtual bool generateCode_phase2(codeGen &gen,
916                                      bool noCost,
917                                      Address &retAddr,
918                                      Register &retReg);
919 };
920
921
922 void emitLoadPreviousStackFrameRegister(Address register_num,
923                                         Register dest,
924                                         codeGen &gen,
925                                         int size,
926                                         bool noCost);
927 void emitStorePreviousStackFrameRegister(Address register_num,
928                                          Register src,
929                                          codeGen &gen,
930                                          int size,
931                                          bool noCost);
932
933
934 #endif /* AST_HDR */