#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>

#define NUMVARWORDS   3      /* number of words required to represent the
                                registers and variables on the SPARC     */
#define MAXFIELD     30      /* maximum characters in a field            */
#define MAXLINE      81      /* maximum characters in an assembly line   */
#define LOG2_INT      5      /* sizeof(int) = 32 = 2**5                  */
#define INT_REM      31      /* if (v & INT_REM) v is not an integer
                                multiple of sizeof(int)*4                */
#define ARGSIZE      20      /* maximum argument size for peephole rule  */
#define MAXRULES    100      /* maximum number of peephole rules         */

#define FALSE         0
#define TRUE          1

/* block status bits */
#define DONE          (1 << 0)

/* used to initialize bvect's */
#define binit() ((bvect) NULL)

/* used to allocate space for a basic block vector */
#define BALLOC  ((unsigned int *) malloc(sizeof(unsigned int)*bvectlen))

/* this will hold the maximum number of nested loops possible. We assume that
 * there will be no more than 32 nestings in a nested loop. We believe this
 * is a very realisitic assumption
 */
#define MAX_NESTED_LOOPS 32


/*
 * block membership bit vector
 */
typedef unsigned int *bvect;

/*
 * variable state structure
 */
typedef unsigned int varstate[NUMVARWORDS];

/*
 * item array type
 */
typedef char **itemarray;





/* instruction types */
enum insttype {
  ARITH_INST,
  BRANCH_INST,
  CALL_INST,
  CMP_INST,
  CONV_INST,
  JUMP_INST,
  LOAD_INST,
  MOV_INST,
  RESTORE_INST,
  RETURN_INST,
  SAVE_INST,
  STORE_INST,
  MISC_INST, /* wso: added */
  COMMENT_LINE,
  DEFINE_LINE
};

#define TOC(t)  (t == BRANCH_INST || t == CALL_INST || t == JUMP_INST || \
                 t == RETURN_INST)

#define INST(t) (t != COMMENT_LINE && t != DEFINE_LINE)

/*
 * assembly line structure
 */
struct assemline {
  char *text;                 /* text of the assembly line               */
  struct assemline *next;     /* next assembly line                      */
  struct assemline *prev;     /* previous assembly line                  */
  enum insttype type;         /* type of assembly line                   */
  int instinfonum;            /* index into instruction information      */
  short numitems;             /* number of strings for instruction       */
  itemarray items;            /* list of strings for the line tokens     */
  varstate sets;              /* variables updated by the instruction    */
  varstate uses;              /* variables used by the instruction       */
  varstate deads;             /* variable values that are last used by
				 the instruction                         */
  struct bblk *blk;           /* block containing the assembly line      */
};

/*
 * basic block structure
 */
struct bblk {
  char *label;                /* label of basic block                     */
  unsigned short num;         /* basic block number                       */
  short loopnest;             /* loop nesting level                       */
  struct assemline *lines;    /* first line in a basic block              */
  struct assemline *lineend;  /* last line in a basic block               */
  struct blist *preds;        /* list of predecessors for a basic block   */
  struct blist *succs;        /* List of successors for a basic block.
				 The first block in the list is the
				 fall-through successor when the block
				 ends with a conditional branch.          */
  struct bblk *up;            /* positionally previous basic block        */
  struct bblk *down;          /* positionally following basic block       */
  bvect dom;                  /* blocks that dominate this one            */
  struct loopnode *loop;      /* set if this block is a loop header       */
  varstate uses;              /* variables used before being set          */
  varstate defs;              /* variables set in this block before used  */
  varstate ins;               /* variables live entering the block        */
  varstate outs;              /* variables live leaving the block         */
  unsigned short status;      /* status field for the block               */
};

/*
 * basic block list structure
 */
struct blist {
  struct bblk *ptr;           /* pointer to block within the list         */
  struct blist *next;         /* pointer to the next blist element        */
};



enum Loop_Val_Type
{
  LOOP_CONSTANT  = -5,
  LOOP_GLOBAL    = -6,
  LOOP_REGISTER  = -7,
  LOOP_UNDEFINED = -8
};


enum CMP_Type
{
#if 0 // bviyer
  EQ = 0,
  NE = 1,
  LT = 2,
  LE = 3,
  GT = 4,
  GE = 5
#else // wso: consistency with loop file format
  EQ = 1,
  NE = 2,
  GT = 3,
  LT = 4,
  GE = 5,
  LE = 6
#endif
};


/*
 * loop information structure
 */
struct loopnode {
  struct loopnode *next;      /* pointer to next loop record              */
  struct bblk *header;        /* pointer to head block of loop            */
  struct bblk *preheader;     /* pointer to the preheader of the loop     */
  struct blist *blocks;       /* blocks in the loop                       */
  varstate invregs;           /* loop invariant variables                 */
  varstate sets;              /* variables updated in loop                */
  int anywrites;              /* any writes to memory?                    */

/* bviyer : information about loop bounds*/
  int loop_no;                /* giving each loop a unique number */
  int loop_bound;             /* this will store the loop bound of the loop */
  char *loop_var_addr;        /* this will store the loop induction var/addr */
  int loop_inc;               /* this will store the increment value of loop */
  enum Loop_Val_Type init_val_type;  /* the type of the initial value */
  int init_val;               /* hold the initial value of the loop */
  char *init_val_reg;         /* hold the initial value register of hte loop */
  enum Loop_Val_Type final_val_type; /* the type of final value */
  int final_val;             /* hold the final valuue of the loop */
  char *final_val_reg;       /* holds the final value register */

  enum CMP_Type compare_type; /* this will return the type of compare that
			       * we are going do
			       */
  
  int predictable;           /* this is set to say if we can predict the loop 
                              * bounds or not. This is mainly to check to see 
                              * if it is a valid  for-loop or not 
                              */
  char *inc_type;             /* holds the loop-incrementer type */

  int count;
  int nested[MAX_NESTED_LOOPS];
  struct loopnode *nested_ptr[MAX_NESTED_LOOPS];
  int dependent[MAX_NESTED_LOOPS];
  int rectangular;            /* tells if the looop is rectangular or not */

  int inc_value; /* wonso */
};

/*
 * instruction information
 */
struct instinfo {
  char *mneumonic;             /* mneumonic of instruction                */
  enum insttype type;          /* instruction class                       */
  int numargs;                 /* number of arguments                     */
  int numdstregs;              /* number of consecutive registers
				  associated with the destination         */
  int numsrcregs;              /* number of consecutive registers
				  associated with each source             */
  int setscc;                  /* condition codes set?                    */
  int datatype;                /* datatype of instruction                 */
};

/*
 * variable information
 */
struct varinfo {
  char *name;                  /* variable name                           */
  short type;                  /* variable type                           */
  short indirect;              /* variable indirectly referenced?         */
};

/* wso 11/06/2005
 * global variable symbol table
 */
struct globalinfo {
  struct globalinfo* next;
  char *name;
  int value;
};

struct localinfo {
  struct localinfo* next;
  char *name;
  int value;
};


#ifndef OPT_H
#define OPT_H
extern struct loopnode *loops;
extern struct globalinfo *globals;
extern struct localinfo *locals;
#endif
