/* lang-interf.h,v 1.2 1994/07/05 15:34:09 fbodin Exp */

#ifndef Already_Included_Lang_Interf
#define Already_Included_Lang_Interf 1


/* 
   Omega-test to programming language interface spec

   To adapt the omega test to do data dependence for some language other
   than tiny, use the files ip.[hc], ddomega.[hc], ddomega-use.[hc],
   ddomega-build.[hc], cover.[ch], kill.[ch], refine.[ch], add-assert.[ch],
   debug.[hc], and portable.h unchanged.

   Modify affine.c to create affine_expr structures for each expression
   that may be relevent to the omega test (loop bounds and array
   subscripts).  You may or may not need to modify affine.h.

   Modify ddodriver.c, or provide your own code, to call the omega test
   for all the array pairs where you need to test for dependence, and
   call the test_for_cover, test_for_termination, quick_test_for_kill
   and accurate_test_for_kill if you wish to use them.  If you are
   feeling bold, you may even want to try to get the "zap" functions
   "possible_to_eliminate" and "try_to_eliminate" (in add-assert.c) to
   work.

   The flags in omega2flags.h control some of the optional behaviors
   that can be obtained from the dependence killing & refining code.
   They affect both ddodriver.c and the files that you do not need to
   change.

   If you want to have debugging output, make sure you open the debug
   file and set omegaPrintResult to 1.

   Create a file lang-interf.h, defining numerous macros that the
   omega test needs to access the parsed program.  Your lang-interf.h
   can be based on this generic version, or the lang-interf.h that we
   wrote for tiny, depending on whether you prefer to read my cryptic
   comments here or my even more cryptic code there.  In the generic
   version, the macros are defined to produce a meaningless result of
   the right type, so that ddomega.c, ddomega-use.c, and ddomega-build.c
   can all be compiled.

   In case of trouble, please feel free to contact me at:
   davew@cs.umd.edu
   Department of Computer Science
   A. V. Williams Building
   University of Maryland
   College Park, Maryland 20742

   Remember that it is a federal crime to send explosives or certain
   other dangerous materials in the U.S. Mail.

   David Wonnacott
 */
   

#define NOT_TINY 1

/* include for the sage macro */
/* #include "macro.h"*/

struct _affine_expr; /* define later in affine.h */
struct omegaIterator ; /* define later in this file */
struct omegaLoop;   /* define later in this file */
struct omegaIf;   /* define later in this file */
struct omegaVar;   /* define later in this file */
struct omegaContIter;

/* Note:
   The omega test data dependence functions, and the macros defined
   here, often require strings giving the printed representations of
   data dependences or array accesses, etc.  These strings are used
   only for generating debugging output in trace.out.  If you don't
   care about debugging output, you can just make anything with the
   word "string" in it = "".
 */

/* define the maximum length of a data dependence vector */
#define maxCommonNest 10   /* (32 bits - 6 used in dddir.h) / 4 bits per dd */

typedef enum { ddflow, ddanti, ddoutput, ddreduce, dd_unknown, ddnovalue } ddnature; 


/* define the type "a_access", which identifies an array access,
   and provides access to information about the access (such as
   its depth, line number, the symbol accessed, and the type of
   access (read or write)).

   It must also be possible to extract information about the
   subscript expressions used in the access, with "sub_i_for_access",
   information about the "context" of an access (the enclosing reads
   & writes), with "cont_i_for_access", and information about the
   dependences to or from an access, as per the stuff later in this file.

   accesss_cover_depth and accesss_terminator_depth must be lvalues
   where we can store the depth at which the access is covered or
   terminated.  These should both be initialized to -1.

   accesss_shared_depth must give the number of loops contianing both
   A1 and A2.

   Two a_accesses must be equal in a self-dependence test

   If there is no existing structure that provides all this information,
   you may need to create an aggregate with pointers to the different
   structures you use.
 */

struct omegaAccess {
  
  char *str;
  struct omegaVar *symb;
  struct omegaIterator *subiter;
  struct omegaContIter *context;
  int    inIfStmt;
  int  line,cdepth,tdepth;
  int  depth;
  int idforsage;  
  int  shareddepth;
  int pri;
  int level;
  int fetch;
  int store;
  int update;
  int lexord; 
};

typedef struct omegaAccess *a_access;

#define access_as_string(A)  (A->str)  /* only used in debugging output */
#define accesss_sym(A)	     (A->symb) /* currently only used in 1 assertion */
#define accesss_lineno(A)    (A->line) /* currently only in debugging output */
#define accesss_cover_depth(A)         (A->cdepth)
#define accesss_terminator_depth(A)    (A->tdepth)
#define accesss_depth(A)               (A->depth)
#define accesss_shared_depth(A1,A2)     (A1->shareddepth)
/* this is wrong
#define accesss_shared_depth(A1,A2)    ((A1->depth > A2->depth)?(A1->depth - A2->depth):(A2->depth > A1->depth))
*/

/* does A access a private var - if so, at what level is it private? */
#define access_private_var_p(A)     (A->pri)
#define access_private_var_level(A) (A->level)

#define access_fetch_p(A)  (A->fetch)
#define access_store_p(A)  (A->store)
#define access_update_p(A) (A->update)
/* Are A1 and A2 updates of the same kind (ie both += or both *=) */
#define access_same_update_type_p(A1, A2) 0

/* can we execute A1 and then A2 without going to another iteration */
#define access_lexically_preceeds(A1, A2) (A1->lexord > A2->lexord)


/* pointers to Entry and Exit node for testing for dependence to
   points before or after the routine being analyzed.  It must
   be possible to compare these to a variable of type a_access */

#define Entry		((a_access)0)
#define ExitNode	((a_access)0)

/* define the type "sub_iterator" - an iterator over the
   subscripts of an array access.  We need to test these
   subscripts to see if they are affine expressions of the
   loop index variables and symbolic constants, and if so,
   find the associated affine_expr structure.
   We also need to have access to all the variables used in
   the expression (for the purpose of building the set of
   variables used), via the function sub_i_map_over_cur_vars,
   which calls F(V,ARGS) for each variable V in the expression.
 */
struct omegaIterator {
  
  struct omegaIterator *next;
  int isaffine;
  struct _affine_expr *affine;
  struct omegaVar *constante;
  int cstvalue;
  
} ;

typedef struct omegaIterator *sub_iterator;


#define sub_i_for_access(A)        ((A)->subiter)
#define sub_i_next(SUBI)           (SUBI = SUBI->next)
#define sub_i_done(SUBI)           (SUBI == NULL)
#define sub_i_cur_is_affine(SUBI)  (SUBI->isaffine)
#define sub_i_cur_affine(SUBI)     (SUBI->affine)
/*
#define sub_i_map_over_cur_vars(SUBI,F,ARGS) {(F)(SUBI->constante,ARGS);}
*/
#define sub_i_map_over_cur_vars(SUBI,F,ARGS)


/* define the type "sub_iterator" - an iterator over the
   enclosing contexts of an array access.  Each cont_i_next
   operation must select the next enclosing loop or if.
   We must be able to tell which we have selected, and
   get a "loop_context" or "if_context" object from it.
 */

struct omegaContIter {
  struct omegaContIter *next;
  int depth;
  int line;
  struct omegaLoop *loop;
  struct omegaIf   *ifstmt;
  int loopiter;
};

typedef struct omegaContIter *context_iterator;


/*extern context_iterator cont_i_for_access(a_access a);*/
#define cont_i_for_access(A) (A->context)

#define cont_i_next(C)        (C = C->next)
#define cont_i_done(C)        (C == NULL)
#define cont_i_cur_loop_p(C)  (C->loopiter)
#define cont_i_cur_if_p(C)    (!(C->loopiter))
#define cont_i_cur_if(C)      (C->ifstmt)
#define cont_i_cur_loop(C)    (C->loop)
#define cont_i_cur_depth(C)   (C->depth) 

/* cur_depth valid for loops - # of loops around stmts in this loop */
/* cur_depth is also needed for ifs as of release 3.0 */
/* #define access_is_in_then_or_else_of(A,C) ((A)->inIfStmt)*/
extern int access_is_in_then_or_else_of(a_access A,context_iterator C);



 /* access A is in the then or the else part of C,
    where cont_i_cur_if_p must be true of C */
#define cont_i_cur_lineno(C)  (C->line)


/* a "loop_context" provides information about a loop.
   We need to be able to find affine_exprs for the start
   and end bounds (if a bound is not affine, we should
   get a result for which "is_affine" is false).
   We also need to know if there is a step expression,
   and whether it is known at compile time, and if so,
   what it is.  These last two must be answered by the
   function "loops_step(LOOP,S,KNOWN)", which sets *KNOWN
   to true if the step is known at compile time, and sets
   *S to the step if it is known.
   We must also be able to map a function over all the
   variables used in the start and end bounds (as we did
   for the variables used in the step expressions).
 */


struct omegaLoop {  
  struct omegaVar *symb;
  struct _affine_expr *startl;
  struct _affine_expr *endl;
  int hasstep;
  int stepl;
  int knownstep;
  struct omegaVar *constantestart;
  int cstvaluestart;
  struct omegaVar *constanteend;
  int cstvaluesend;
};

typedef struct omegaLoop  *loop_context;

#define loop_var_id(LOOP)        (LOOP->symb)
#define loop_start(LOOP)         (LOOP->startl)
#define loop_end(LOOP)           (LOOP->endl)
#define loop_has_step_p(LOOP)    (LOOP->hasstep)
#define loops_step(LOOP,S,KNOWN) { *S = LOOP->stepl; *KNOWN = LOOP->knownstep; }
/*
#define loop_map_over_start_vars(LOOP,F,ARGS) {(F)(LOOP->constantestart,ARGS);}
#define loop_map_over_end_vars(LOOP,F,ARGS)   {(F)(LOOP->constanteend,ARGS);}
*/
#define loop_map_over_start_vars(LOOP,F,ARGS) 
#define loop_map_over_end_vars(LOOP,F,ARGS) 

/* an "if context" provides information about the conditions
   surrounding an array access.
   The current code can handle ifs with single >, >=, <, or <= conditions.
   Note that it is not OK to just leave this out - it will prevent the
   refinement, cover, termination, and kill tests from determining whether
   or not they have exact information.
   If, for some reason, you can not supply this information,
   make sure that the context iterator for an array access in an if
   yeilds one if_context for which if_condition_ok is false
 */



typedef enum { greater = 0, greater_eq = 1, less = 2, less_eq = 3 }
	if_compare_operators;


struct omegaIf {  
  int condOK;
  int ident;
  if_compare_operators oper;
  struct _affine_expr *left;
  struct _affine_expr *right;
  int partelse;
};

typedef struct omegaIf  *if_context;

#define if_condition_ok(IC)	(IC->condOK)
#define if_compare_op(IC)	(IC->oper)  /* one of if_compare_operators */
#define if_compare_left(IC)	(IC->left)  /* lhs of compare op */
#define if_compare_right(IC)	(IC->right)  /* rhs of compare op */
#define if_else_branch(IC)	(IC->partelse)      /* true in body of "else" clause */
#define if_map_over_vars(IC,F,ARGS)


/* define the type used to identify a variable (typically
   a pointer into the symbol table or some such).
   It must be possible to tell the difference between a loop
   index and a symbolic constant, and for a loop index, we must
   be able to find the depth of the loop.
   We must also be able to associate a integer "tag" with each
   variable - all tags must start out with the value UNTAGGED.
 */

struct omegaVar {
  int loop;
  int constp;
  int indexp;
  int tag;
  char *name;
};


typedef struct omegaVar *var_id;

#define var_id_const_p(AE_VAR)   (AE_VAR->constp)
#define var_id_index_p(AE_VAR)   (AE_VAR->indexp)
#define var_ids_loop_no(AE_VAR)  (AE_VAR->loop)
#define var_ids_tag(AE_VAR)      (AE_VAR->tag)
#define var_ids_name(AE_VAR)     (AE_VAR->name)  /* only for debug */
#define UNTAGGED -1


/* representations of Data Dependences follow -
   You probably should not change these, but simply convert from
   this format into whatever you use, and vice versa, when getting
   information from/to the omega test
 */

/* information about dd direction vectors.
   works only if unsigned long int has at least 32 bits */
#include "dddir.h"

/*
   A dir_and_dist_info structure contains information about a dependence
   This is the form in which some of the omega test functions expect
   dependence information.
*/

#include "portable.h"
typedef struct DD_info {
    uint         nest;
    dddirection  direction;
    dddirection  restraint;
    bool         distanceKnown[maxCommonNest];
    int          distance[maxCommonNest];
    void *       dd_graph_node_to_be_cloned;
	/*  dd_graph_node_to_be_cloned points to the structure 
	    that must be duplicated when we need to make a copy
	    of an existing entry in the dependence graph using
	    the function clone_dd_graph_node_for_refinement */

    DD_info()
    {
        nest = 0;
        direction = 0;
        restraint = 0;
        for (int z = 0; z < maxCommonNest; ++z)
        {
            distanceKnown[z] = false;
            distance[z] = 0;
        }
        dd_graph_node_to_be_cloned = NULL;
    }
} dir_and_dist_info;

/* Duplicate the dd graph node, setting "isRefined" in the copy.
   This bit will hopefully get cleaner in the next release */
void clone_dd_graph_node_for_refinement(void *dd_graph_node_to_be_cloned);

#define d_info_do_eq(D_INFO, J) \
    if (ddextract1((D_INFO)->direction,(J)) == ddeq)  \
    { \
	(D_INFO)->distanceKnown[(J)] = 1; \
	(D_INFO)->distance[(J)] = 0; \
    }

#if ! defined NDEBUG
#define d_info_inv(D_INFO) \
    { \
	int i; \
	for (i=1; i<=(D_INFO)->nest; i++) { \
	    if (ddextract1((D_INFO)->direction,i) == ddeq) { \
         if (!((D_INFO)->distanceKnown[i] && (D_INFO)->distance[i] == 0))\
         {\
            printf("%lld %lld %lld\n", (D_INFO)->nest, (D_INFO)->direction, (D_INFO)->restraint);\
            for (int z = 0; z < maxCommonNest; ++z)\
                printf("[%d]: %d %d\n", z, (D_INFO)->distanceKnown[z], (D_INFO)->distance[z]);\
         }\
		assert((D_INFO)->distanceKnown[i] && (D_INFO)->distance[i] == 0); \
	    } \
	} \
    }
#else
#define d_info_inv(X)
#endif



/* 
	odd_iterators are now obsolete.
	they have been replaced.
 */

/* dd_in_iterators and dd_out_iterators allow iteration thru all the
   dependences into a given access or out of a given access.

   We may need to find the source or destination node of the current
   dependence, or find out whether it is a flow or output dependence,
   and whether it covers or terminates.

   We must also be able to identify a dependence, so that we don't
   test it against itself in certain circumstances

   For either type, we must be able to select the current dependence,
   which we identify with the type dd_current.

   From this current element, we may determine the nesting level, or
   information about the dependence distances or directions or the
   restraint vector.
*/

typedef void *dd_in_iterator;  /* iterate thru dds in to an access */
typedef void *dd_out_iterator; /* iterate thru dds out from an access */

typedef void *dd_current;      /* point to the dd the iterator is on */

#define dd_current_nest(DDC)         (3)
#define dd_current_dist(DDC)         ((int *)0)  /* distance array */
#define dd_current_dist_known(DDC,j) 1 /* dd_current_dist(DDC)[j] meaningful?*/
#define dd_current_dir(DDC)          (*((dddirection *)0)) /* direction */
#define dd_current_restr(DDC)        (*((dddirection *)0)) /* restraint */
#define dd_current_as_string(DDC)    "a dependence"
#define dd_current_src(DDC)          ((a_access) 0)
#define dd_current_dest(DDC)         ((a_access) 0)


#define dd_i_i_for_access(ACC)  ((dd_in_iterator) 0)
#define dd_i_i_done(DD_I_I)     (1)
#define dd_i_i_next(DD_I_I)     

#define dd_i_i_current(DD_I_I)          ((dd_current) 0)
#define dd_i_i_cur_src(DD_I_I)          ((a_access) 0)
#define dd_i_i_cur_dest(DD_I_I)         ((a_access) 0)
#define dd_i_i_cur_flow_p(DD_I_I)       0
#define dd_i_i_cur_output_p(DD_I_I)     0
#define dd_i_i_cur_cover_p(DD_I_I)      0
#define dd_i_i_cur_is(DD_I_I, DEP)      (dd_i_i_current(DD_I_I) == (DEP))

#define dd_o_i_for_access(ACC)  ((dd_out_iterator) 0)
#define dd_o_i_done(DD_O_I)     1
#define dd_o_i_next(DD_O_I)     

#define dd_o_i_current(DD_O_I)          ((dd_current) 0)
#define dd_o_i_cur_src(DD_O_I)          ((a_access) 0)
#define dd_o_i_cur_dest(DD_O_I)         ((a_access) 0)
#define dd_o_i_cur_output_p(DD_O_I)     0
#define dd_o_i_cur_terminate_p(DD_O_I)  0
#define dd_o_i_cur_is(DD_O_I, DEP)      (dd_o_i_current(DD_O_I) == (DEP))


/* the function "store_dependence" will be called when the omega test
   has detected a data dependence.  It should convert from the
   dir_and_dist_info into whatever form is used by the rest of the system */

void store_dependence(ddnature nature, a_access from_access,
		      a_access to_access, dir_and_dist_info *d_info);


/* convert dd nodes into stuff our functions can handle */
void ddnode_to_dir_and_dist(dd_current, dir_and_dist_info *);

/* copy info from a dir_and_dist_info into an existing dd node */
void dir_and_dist_into_ddnode(const dir_and_dist_info *ddi, dd_current);


/* take inequality number GEQ, and turn it into an assertion */
#define add_GEQ_assertion(P, VARS, GEQ) ;


#endif
