summaryrefslogtreecommitdiff
path: root/src/iconc/typinfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/iconc/typinfer.c')
-rw-r--r--src/iconc/typinfer.c5189
1 files changed, 0 insertions, 5189 deletions
diff --git a/src/iconc/typinfer.c b/src/iconc/typinfer.c
deleted file mode 100644
index 8a96e23..0000000
--- a/src/iconc/typinfer.c
+++ /dev/null
@@ -1,5189 +0,0 @@
-/*
- * typinfer.c - routines to perform type inference.
- */
-#include "../h/gsupport.h"
-#include "../h/lexdef.h"
-#include "ctrans.h"
-#include "csym.h"
-#include "ctree.h"
-#include "ctoken.h"
-#include "cglobals.h"
-#include "ccode.h"
-#include "cproto.h"
-#ifdef TypTrc
-#ifdef HighResTime
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif /* HighResTime */
-#endif /* TypTrc */
-
-/*
- * Information about co-expressions is keep on a list.
- */
-struct t_coexpr {
- nodeptr n; /* code for co-expression */
- int typ_indx; /* relative type number (index) */
- struct store *in_store; /* store entry into co-expression via activation */
- struct store *out_store; /* store at end of co-expression */
-#ifdef OptimizeType
- struct typinfo *act_typ; /* types passed via co-expression activation */
- struct typinfo *rslt_typ; /* types resulting from "co-expression return" */
-#else /* OptimizeType */
- unsigned int *act_typ; /* types passed via co-expression activation */
- unsigned int *rslt_typ; /* types resulting from "co-expression return" */
-#endif /* OptimizeType */
- int iteration;
- struct t_coexpr *next;
- };
-
-struct t_coexpr *coexp_lst;
-
-#ifdef TypTrc
-extern int typealloc; /* flag to account for allocation */
-extern long typespace; /* amount of space for type inference */
-#endif /* TypTrc */
-
-struct symtyps *cur_symtyps; /* maps run-time routine symbols to types */
-
-/*
- * argtyps is the an array of types large enough to accommodate the argument
- * list of any operation.
- */
-struct argtyps {
- struct argtyps *next;
-#ifdef OptimizeType
- struct typinfo *types[1]; /* actual size is max_prm */
-#else /* OptimizeType */
- unsigned int *types[1]; /* actual size is max_prm */
-#endif /* OptimizeType */
- };
-
-/*
- * prototypes for static functions.
- */
-#ifdef OptimizeType
-void and_bits_to_packed (struct typinfo *src,
- struct typinfo *dest, int size);
-struct typinfo *alloc_typ (int n_types);
-unsigned int *alloc_mem_typ (unsigned int n_types);
-int bitset (struct typinfo *typ, int bit);
-void clr_typ (struct typinfo *type, unsigned int bit);
-void clr_packed (struct typinfo *src, int nsize);
-void cpy_packed_to_packed (struct typinfo *src,
- struct typinfo *dest, int nsize);
-static void deref_lcl (struct typinfo *src,
- struct typinfo *dest);
-static int findloops ( struct node *n, int resume,
- struct typinfo *rslt_type);
-static void gen_inv (struct typinfo *prc_typ, nodeptr n);
-int has_type (struct typinfo *typ, int typcd, int clear);
-static void infer_impl (struct implement *impl,
- nodeptr n, struct symtyps *symtyps,
- struct typinfo *rslt_typ);
-int is_empty (struct typinfo *typ);
-int mrg_packed_to_packed (struct typinfo *src,
- struct typinfo *dest, int nsize);
-int other_type (struct typinfo *typ, int typcd);
-static void set_ret (struct typinfo *typ);
-void set_typ (struct typinfo *type, unsigned int bit);
-void typcd_bits (int typcd, struct type *typ);
-static void typ_deref (struct typinfo *src,
- struct typinfo *dest, int chk);
-int xfer_packed_to_bits (struct typinfo *src,
- struct typinfo *dest, int nsize);
-#else /* OptimizeType */
-unsigned int *alloc_typ (int n_types);
-int bitset (unsigned int *typ, int bit);
-void clr_typ (unsigned int *type, unsigned int bit);
-static void deref_lcl (unsigned int *src, unsigned int *dest);
-static int findloops ( struct node *n, int resume,
- unsigned int *rslt_type);
-static void gen_inv (unsigned int *prc_typ, nodeptr n);
-int has_type (unsigned int *typ, int typcd, int clear);
-static void infer_impl (struct implement *impl,
- nodeptr n, struct symtyps *symtyps,
- unsigned int *rslt_typ);
-int is_empty (unsigned int *typ);
-int other_type (unsigned int *typ, int typcd);
-static void set_ret (unsigned int *typ);
-void set_typ (unsigned int *type, unsigned int bit);
-void typcd_bits (int typcd, struct type *typ);
-static void typ_deref (unsigned int *src, unsigned int *dest, int chk);
-#endif /* OptimizeType */
-
-static void abstr_new (struct node *n, struct il_code *il);
-static void abstr_typ (struct il_code *il, struct type *typ);
-static struct store *alloc_stor (int stor_sz, int n_types);
-static void chk_succ (int ret_flag, struct store *susp_stor);
-static struct store *cpy_store (struct store *source);
-static int eval_cond (struct il_code *il);
-static void free_argtyp (struct argtyps *argtyps);
-static void free_store (struct store *store);
-static void free_wktyp (struct type *typ);
-static void find_new (struct node *n);
-static struct argtyps *get_argtyp (void);
-static struct store *get_store (int clear);
-static struct type *get_wktyp (void);
-static void infer_act (nodeptr n);
-static void infer_con (struct rentry *rec, nodeptr n);
-static int infer_il (struct il_code *il);
-static void infer_nd (nodeptr n);
-static void infer_prc (struct pentry *proc, nodeptr n);
-static void mrg_act (struct t_coexpr *coexp,
- struct store *e_store,
- struct type *rslt_typ);
-static void mrg_store (struct store *source, struct store *dest);
-static void side_effect (struct il_code *il);
-static struct symtyps *symtyps (int nsyms);
-
-#ifdef TypTrc
-static void prt_d_typ (FILE *file, struct typinfo *typ);
-static void prt_typ (FILE *file, struct typinfo *typ);
-#endif /* TypTrc */
-
-#define CanFail 1
-
-/*
- * cur_coexp is non-null while performing type inference on code from a
- * create expression. If it is null, the possible current co-expressions
- * must be found from cur_proc.
- */
-struct t_coexpr *cur_coexp = NULL;
-
-struct gentry **proc_map; /* map procedure types to symbol table entries */
-struct rentry **rec_map; /* map record types to record information */
-struct t_coexpr **coexp_map; /* map co-expression types to information */
-
-struct typ_info *type_array;
-
-static int num_new; /* number of types supporting "new" abstract type comp */
-
-/*
- * Data base component codes are mapped to type inferencing information
- * using an array.
- */
-struct compnt_info {
- int frst_bit; /* first bit in bit vector allocated to component */
- int num_bits; /* number of bits allocated to this component */
- struct store *store; /* maps component "reference" to the type it holds */
- };
-static struct compnt_info *compnt_array;
-
-static unsigned int frst_fld; /* bit number of 1st record field */
-static unsigned int n_fld; /* number of record fields */
-static unsigned int frst_gbl; /* bit number of 1st global reference type */
-static unsigned int n_gbl; /* number of global variables */
-static unsigned int n_nmgbl; /* number of named global variables */
-static unsigned int frst_loc; /* bit number of 1st local reference type */
-static unsigned int n_loc; /* maximum number of locals in any procedure */
-
-static unsigned int nxt_bit; /* next unassigned bit in bit vector */
-unsigned int n_icntyp; /* number of non-variable types */
-unsigned int n_intrtyp; /* number of types in intermediate values */
-static unsigned int n_rttyp; /* number of types in runtime computations */
-unsigned int val_mask; /* mask for non-var types in last int of type */
-
-unsigned int null_bit; /* bit for null type */
-unsigned int str_bit; /* bit for string type */
-unsigned int cset_bit; /* bit for cset type */
-unsigned int int_bit; /* bit for integer type */
-unsigned int real_bit; /* bit for real type */
-
-static struct store *fld_stor; /* record fields */
-
-static int *cur_new; /* allocated types for current operation */
-
-static struct store *succ_store = NULL; /* current success store */
-static struct store *fail_store = NULL; /* current failure store */
-
-static struct store *dummy_stor;
-static struct store *store_pool = NULL; /* free list of store structs */
-
-static struct type *type_pool = NULL; /* free list of type structs */
-static struct type cur_rslt = {0, NULL, NULL}; /* result type of operation */
-
-static struct argtyps *argtyp_pool = NULL; /* free list of arg type arrays */
-static struct argtyps *arg_typs = NULL; /* current arg type array */
-
-static int num_args; /* number of arguments for current operation */
-static int n_vararg; /* size of variable part of arg list to run-time routine */
-
-#ifdef OptimizeType
-static struct typinfo *any_typ; /* type bit vector with all bits on */
-struct typinfo *free_typinfo = NULL;
-struct typinfo *start_typinfo = NULL;
-struct typinfo *high_typinfo = NULL;
-struct typinfo *low_typinfo = NULL;
-#else /* OptimizeType */
-static unsigned int *any_typ; /* type bit vector with all bits on */
-#endif /* OptimizeType */
-
-long changed; /* number of changes to type information in this iteration */
-int iteration; /* iteration number for type inferencing */
-
-#ifdef TypTrc
-static FILE *trcfile = NULL; /* output file pointer for tracing */
-static char *trcname = NULL; /* output file name for tracing */
-static char *trc_indent = "";
-#endif /* TypTrc */
-
-
-/*
- * typeinfer - infer types of operands. If "do_typinfer" is set, actually
- * do abstract interpretation, otherwise assume any type for all operands.
- */
-void typeinfer()
- {
- struct gentry *gptr;
- struct lentry *lptr;
- nodeptr call_main;
- struct pentry *p;
- struct rentry *rec;
- struct t_coexpr *coexp;
- struct store *init_store;
- struct store *f_store;
-#ifdef OptimizeType
- struct typinfo *type;
-#else /* OptimizeType */
- unsigned int *type;
-#endif /* OptimizeType */
- struct implement *ip;
- struct lentry **lhash;
- struct lentry **vartypmap;
- int i, j, k;
- int size;
- int flag;
-
-#ifdef TypTrc
- /*
- * Set up for type tracing.
- */
- long start_infer, end_infer;
-
-#ifdef HighResTime
- struct rusage rusage;
-
- getrusage(RUSAGE_SELF, &rusage);
- start_infer = rusage.ru_utime.tv_sec*1000 + rusage.ru_utime.tv_usec/1000;
-#else /* HighResTime */
- start_infer = millisec();
-#endif /* HighResTime */
-
- typealloc = 1; /* note allocation in this phase */
-
- trcname = getenv("TYPTRC");
-
- if (trcname != NULL && strlen(trcname) != 0) {
-
- if (trcname[0] == '|') {
- FILE *popen();
-
- trcfile = popen(trcname+1, "w");
- }
- else
-
- trcfile = fopen(trcname, "w");
-
- if (trcfile == NULL) {
- fprintf(stderr, "TYPTRC: cannot open %s\n", trcname);
- fflush(stderr);
- exit(EXIT_FAILURE);
- }
- }
-#endif /* TypTrc */
-
- /*
- * Make sure max_prm is large enough for any run-time routine.
- */
- for (i = 0; i < IHSize; ++i)
- for (ip = bhash[i]; ip != NULL; ip = ip->blink)
- if (ip->nargs > max_prm)
- max_prm = ip->nargs;
- for (i = 0; i < IHSize; ++i)
- for (ip = ohash[i]; ip != NULL; ip = ip->blink)
- if (ip->nargs > max_prm)
- max_prm = ip->nargs;
-
- /*
- * Allocate an arrays to map data base type codes and component codes
- * to type inferencing information.
- */
- type_array = (struct typ_info *)alloc((unsigned int)(num_typs *
- sizeof(struct typ_info)));
- compnt_array = (struct compnt_info *)alloc((unsigned int)(num_cmpnts *
- sizeof(struct compnt_info)));
-
- /*
- * Find those types that support the "new" abstract type computation
- * assign to them locations in the arrays of allocated types associated
- * with operation invocations. Also initialize the number of type bits.
- * Types with no subtypes have one bit. Types allocated with the the "new"
- * abstract have a default sub-type that is allocated here. Procedures
- * have a subtype to for string invocable operators. Co-expressions
- * have a subtype for &main. Records are handled below.
- */
- num_new = 0;
- for (i = 0; i < num_typs; ++i) {
- if (icontypes[i].support_new)
- type_array[i].new_indx = num_new++;
- type_array[i].num_bits = 1; /* reserve one type bit */
- }
- type_array[list_typ].num_bits = 2; /* default & list for arg to main() */
-
- cur_coexp = NewStruct(t_coexpr);
- cur_coexp->n = NULL;
- cur_coexp->next = NULL;
- coexp_lst = cur_coexp;
-
- if (do_typinfer) {
- /*
- * Go through the syntax tree for each procedure locating program
- * points that may create structures at run time. Allocate the
- * appropriate structure type(s) to each such point.
- */
- for (p = proc_lst; p != NULL; p = p->next) {
- if (p->nargs < 0)
- p->arg_lst = type_array[list_typ].num_bits++; /* list for varargs */
- find_new(Tree1(p->tree)); /* initial clause */
- find_new(Tree2(p->tree)); /* body of procedure */
- }
- }
-
- /*
- * Allocate a type number for each record type (use record number for
- * offset) and a variable type number for each field.
- */
- n_fld = 0;
- if (rec_lst == NULL) {
- type_array[rec_typ].num_bits = 0;
- rec_map = NULL;
- }
- else {
- type_array[rec_typ].num_bits = rec_lst->rec_num + 1;
- rec_map = (struct rentry **)alloc(
- (unsigned int)((rec_lst->rec_num + 1)*sizeof(struct rentry *)));
- for (rec = rec_lst; rec != NULL; rec = rec->next) {
- rec->frst_fld = n_fld;
- n_fld += rec->nfields;
- rec_map[rec->rec_num] = rec;
- }
- }
-
- /*
- * Allocate type numbers to global variables. Don't count those procedure
- * variables that are no longer referenced in the syntax tree. Do count
- * static variables. Also allocate types to procedures, built-in functions,
- * record constructors.
- */
- n_gbl = 0;
- for (i = 0; i < GHSize; i++)
- for (gptr = ghash[i]; gptr != NULL; gptr = gptr->blink) {
- flag = gptr->flag;
- if (flag & F_SmplInv)
- gptr->index = -1; /* unused: set to something not a valid type */
- else {
- gptr->index = n_gbl++;
- if (flag & (F_Proc | F_Record | F_Builtin))
- gptr->init_type = type_array[proc_typ].num_bits++;
- }
- if (flag & F_Proc) {
- for (lptr = gptr->val.proc->statics; lptr != NULL;lptr = lptr->next)
- lptr->val.index = n_gbl++;
- }
- }
- n_nmgbl = n_gbl;
-
- /*
- * Determine relative bit numbers for predefined variable types that
- * are treated as sets of global variables.
- */
- for (i = 0; i < num_typs; ++i)
- if (icontypes[i].deref == DrfGlbl)
- type_array[i].frst_bit = n_gbl++; /* converted to absolute later */
-
- proc_map = (struct gentry **)alloc(
- (unsigned int)((type_array[proc_typ].num_bits)*sizeof(struct gentry *)));
- proc_map[0] = NULL; /* proc type for string invocable operators */
- for (i = 0; i < GHSize; i++)
- for (gptr = ghash[i]; gptr != NULL; gptr = gptr->blink) {
- flag = gptr->flag;
- if (!(flag & F_SmplInv) && (flag & (F_Proc | F_Record | F_Builtin)))
- proc_map[gptr->init_type] = gptr;
- }
-
- /*
- * Allocate type numbers to local variables. The same numbers are reused
- * in different procedures.
- */
- n_loc = 0;
- for (p = proc_lst; p != NULL; p = p->next) {
- i = Abs(p->nargs);
- for (lptr = p->args; lptr != NULL; lptr = lptr->next)
- lptr->val.index = --i;
- i = Abs(p->nargs);
- for (lptr = p->dynams; lptr != NULL; lptr = lptr->next)
- lptr->val.index = i++;
- n_loc = Max(n_loc, i);
-
- /*
- * produce a mapping from the variable types used in this procedure
- * to the corresponding symbol table entries.
- */
- if (n_gbl + n_loc == 0)
- vartypmap = NULL;
- else
- vartypmap = (struct lentry **)alloc(
- (unsigned int)((n_gbl + n_loc)*sizeof(struct lentry *)));
- for (i = 0; i < n_gbl + n_loc; ++i)
- vartypmap[i] = NULL; /* no entries for foreign statics */
- p->vartypmap = vartypmap;
- lhash = p->lhash;
- for (i = 0; i < LHSize; ++i) {
- for (lptr = lhash[i]; lptr != NULL; lptr = lptr->blink) {
- switch (lptr->flag) {
- case F_Global:
- gptr = lptr->val.global;
- if (!(gptr->flag & F_SmplInv))
- vartypmap[gptr->index] = lptr;
- break;
- case F_Static:
- vartypmap[lptr->val.index] = lptr;
- break;
- case F_Dynamic:
- case F_Argument:
- vartypmap[n_gbl + lptr->val.index] = lptr;
- }
- }
- }
- }
-
- /*
- * There is a component reference subtype for every subtype of the
- * associated aggregate type.
- */
- for (i = 0; i < num_cmpnts; ++i)
- compnt_array[i].num_bits = type_array[typecompnt[i].aggregate].num_bits;
-
- /*
- * Assign bits for non-variable (first-class) types.
- */
- nxt_bit = 0;
- for (i = 0; i < num_typs; ++i)
- if (icontypes[i].deref == DrfNone) {
- type_array[i].frst_bit = nxt_bit;
- nxt_bit += type_array[i].num_bits;
- }
-
- n_icntyp = nxt_bit; /* number of first-class types */
-
- /*
- * Load some commonly needed bit numbers into global variable.
- */
- null_bit = type_array[null_typ].frst_bit;
- str_bit = type_array[str_typ].frst_bit;
- cset_bit = type_array[cset_typ].frst_bit;
- int_bit = type_array[int_typ].frst_bit;
- real_bit = type_array[real_typ].frst_bit;
-
- /*
- * Assign bits for predefined variable types that are not treated as
- * sets of globals.
- */
- for (i = 0; i < num_typs; ++i)
- if (icontypes[i].deref == DrfCnst || icontypes[i].deref == DrfSpcl) {
- type_array[i].frst_bit = nxt_bit;
- nxt_bit += type_array[i].num_bits;
- }
-
- /*
- * Assign bits to aggregate compontents that are variables.
- */
- for (i = 0; i < num_cmpnts; ++i)
- if (typecompnt[i].var) {
- compnt_array[i].frst_bit = nxt_bit;
- nxt_bit += compnt_array[i].num_bits;
- }
-
- /*
- * Assign bits to record fields and named variables.
- */
- frst_fld = nxt_bit;
- nxt_bit += n_fld;
- frst_gbl = nxt_bit;
- nxt_bit += n_gbl;
- frst_loc = nxt_bit;
- nxt_bit += n_loc;
-
- /*
- * Convert from relative to ablsolute bit numbers for predefined variable
- * types that are treated as sets of global variables.
- */
- for (i = 0; i < num_typs; ++i)
- if (icontypes[i].deref == DrfGlbl)
- type_array[i].frst_bit += frst_gbl;
-
- n_intrtyp = nxt_bit; /* number of types for intermediate values */
-
- /*
- * Assign bits to aggregate compontents that are not variables. These
- * are the runtime system's internal descriptor reference types.
- */
- for (i = 0; i < num_cmpnts; ++i)
- if (!typecompnt[i].var) {
- compnt_array[i].frst_bit = nxt_bit;
- nxt_bit += compnt_array[i].num_bits;
- }
-
- n_rttyp = nxt_bit; /* total size of type system */
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- /*
- * Output a summary of the type system.
- */
- for (i = 0; i < num_typs; ++i) {
- fprintf(trcfile, "%s", icontypes[i].id);
- if (strcmp(icontypes[i].id, icontypes[i].abrv) != 0)
- fprintf(trcfile, "(%s)", icontypes[i].abrv);
- fprintf(trcfile, " sub-types: %d\n", type_array[i].num_bits);
- }
- }
-#endif /* TypTrc */
-
- /*
- * The division between bits for first-class types and variables types
- * generally occurs in the middle of a word. Set up a mask for extracting
- * the first-class types from this word.
- */
- val_mask = 0;
- i = n_icntyp - (NumInts(n_icntyp) - 1) * IntBits;
- while (i--)
- val_mask = (val_mask << 1) | 1;
-
- if (do_typinfer) {
- /*
- * Create stores large enough for the component references. These
- * are global to the entire program, rather than being propagated
- * from node to node in the syntax tree.
- */
- for (i = 0; i < num_cmpnts; ++i) {
- if (i == str_var)
- size = n_intrtyp;
- else
- size = n_icntyp;
- compnt_array[i].store = alloc_stor(compnt_array[i].num_bits, size);
- }
- fld_stor = alloc_stor(n_fld, n_icntyp);
-
- dummy_stor = get_store(0);
-
- /*
- * First list is arg to main: a list of strings.
- */
- set_typ(compnt_array[lst_elem].store->types[1], str_typ);
- }
-
- /*
- * Set up a type bit vector with all bits on.
- */
-#ifdef OptimizeType
- any_typ = alloc_typ(n_rttyp);
- any_typ->bits = alloc_mem_typ(DecodeSize(any_typ->packed));
- for (i = 0; i < NumInts(n_rttyp); ++i)
- any_typ->bits[i] = ~(unsigned int)0;
-#else /* OptimizeType */
- any_typ = alloc_typ(n_rttyp);
- for (i = 0; i < NumInts(n_rttyp); ++i)
- any_typ[i] = ~(unsigned int)0;
-#endif /* OptimizeType */
-
- /*
- * Initialize stores and return values for procedures. Also initialize
- * flag indicating whether the procedure can be executed.
- */
- call_main = NULL;
- for (p = proc_lst; p != NULL; p = p->next) {
- if (do_typinfer) {
- p->iteration = 0;
- p->ret_typ = alloc_typ(n_intrtyp);
- p->coexprs = alloc_typ(n_icntyp);
- p->in_store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (p->ret_flag & DoesSusp)
- p->susp_store = alloc_stor(n_gbl, n_icntyp);
- else
- p->susp_store = NULL;
- for (i = Abs(p->nargs); i < n_loc; ++i)
- set_typ(p->in_store->types[n_gbl + i], null_bit);
- if (p->nargs < 0)
- set_typ(p->in_store->types[n_gbl + Abs(p->nargs) - 1],
- type_array[list_typ].frst_bit + p->arg_lst);
- if (strcmp(p->name, "main") == 0) {
- /*
- * create a the initial call to main with one list argument.
- */
- call_main = invk_main(p);
- call_main->type = alloc_typ(n_intrtyp);
- Tree2(call_main)->type = alloc_typ(n_intrtyp);
- set_typ(Tree2(call_main)->type, type_array[list_typ].frst_bit + 1);
- call_main->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- }
- p->out_store = alloc_stor(n_gbl, n_icntyp);
- p->reachable = 0;
- }
- else
- p->reachable = 1;
- /*
- * Analyze the code of the procedure to determine where to place stores
- * that survive iterations of type inferencing. Note, both the initial
- * clause and the body of the procedure are bounded.
- */
- findloops(Tree1(p->tree), 0, NULL);
- findloops(Tree2(p->tree), 0, NULL);
- }
-
- /*
- * If type inferencing is suppressed, we have set up very conservative
- * type information and will do no inferencing.
- */
- if (!do_typinfer)
- return;
-
- if (call_main == NULL)
- return; /* no main procedure, cannot continue */
- if (tfatals > 0)
- return; /* don't do inference if there are fatal errors */
-
- /*
- * Construct mapping from co-expression types to information
- * about the co-expressions and finish initializing the information.
- */
- i = type_array[coexp_typ].num_bits;
- coexp_map = (struct t_coexpr **)alloc(
- (unsigned int)(i * sizeof(struct t_coexpr *)));
- for (coexp = coexp_lst; coexp != NULL; coexp = coexp->next) {
- coexp_map[--i] = coexp;
- coexp->typ_indx = i;
- coexp->in_store = alloc_stor(n_gbl + n_loc, n_icntyp);
- coexp->out_store = alloc_stor(n_gbl + n_loc, n_icntyp);
- coexp->act_typ = alloc_typ(n_intrtyp);
- coexp->rslt_typ = alloc_typ(n_intrtyp);
- coexp->iteration = 0;
- }
-
- /*
- * initialize globals
- */
- init_store = get_store(1);
- for (i = 0; i < GHSize; i++)
- for (gptr = ghash[i]; gptr != NULL; gptr = gptr->blink) {
- flag = gptr->flag;
- if (!(flag & F_SmplInv)) {
- type = init_store->types[gptr->index];
- if (flag & (F_Proc | F_Record | F_Builtin))
- set_typ(type, type_array[proc_typ].frst_bit + gptr->init_type);
- else
- set_typ(type, null_bit);
- }
- }
-
- /*
- * Initialize types for predefined variable types.
- */
- for (i = 0; i < num_typs; ++i) {
- type = NULL;
- switch (icontypes[i].deref) {
- case DrfGlbl:
- /*
- * Treated as a global variable.
- */
- type = init_store->types[type_array[i].frst_bit - frst_gbl];
- break;
- case DrfCnst:
- /*
- * Type doesn't change so keep one copy.
- */
- type = alloc_typ(n_intrtyp);
- type_array[i].typ = type;
- break;
- }
- if (type != NULL) {
- /*
- * Determine which types are in the initial type for this variable.
- */
- for (j = 0; j < num_typs; ++j) {
- if (icontypes[i].typ[j] != '.') {
- for (k = 0; k < type_array[j].num_bits; ++k)
- set_typ(type, type_array[j].frst_bit + k);
- }
- }
- }
- }
-
- f_store = get_store(1);
-
- /*
- * Type inferencing iterates over the program until a fixed point is
- * reached.
- */
- changed = 1L; /* force first iteration */
- iteration = 0;
- if (verbose > 1)
- fprintf(stderr, "type inferencing: ");
-
- while (changed > 0L) {
- changed = 0L;
- ++iteration;
-
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "**** iteration %d ****\n", iteration);
-#endif /* TypTrc */
-
- /*
- * Start at the implicit initial call to the main procedure. Inferencing
- * walks the call graph from here.
- */
- succ_store = cpy_store(init_store);
- fail_store = f_store;
- infer_nd(call_main);
-
- /*
- * If requested, monitor the progress of inferencing.
- */
- switch (verbose) {
- case 0:
- case 1:
- break;
- case 2:
- fprintf(stderr, ".");
- break;
- default: /* > 2 */
- if (iteration != 1)
- fprintf(stderr, ", ");
- fprintf(stderr, "%ld", changed);
- }
- }
-
- /*
- * Type inferencing is finished, complete any diagnostic output.
- */
- if (verbose > 1)
- fprintf(stderr, "\n");
-
-#ifdef TypTrc
- if (trcfile != NULL) {
-
-#ifdef HighResTime
- getrusage(RUSAGE_SELF, &rusage);
- end_infer = rusage.ru_utime.tv_sec*1000 + rusage.ru_utime.tv_usec/1000;
-#else /* HighResTime */
- end_infer = millisec();
-#endif /* HighResTime */
- fprintf(trcfile, "\n**** inferencing time: %ld milliseconds\n",
- end_infer - start_infer);
- fprintf(trcfile, "\n**** inferencing space: %ld bytes\n",typespace);
- fclose(trcfile);
- }
- typealloc = 0;
-#endif /* TypTrc */
- }
-
-/*
- * find_new - walk the syntax tree allocating structure types where
- * operations create new structures.
- */
-static void find_new(n)
-struct node *n;
- {
- struct t_coexpr *coexp;
- struct node *cases;
- struct node *clause;
- int nargs;
- int i;
-
- n->new_types = NULL;
- switch (n->n_type) {
- case N_Cset:
- case N_Empty:
- case N_Id:
- case N_Int:
- case N_Next:
- case N_Real:
- case N_Str:
- break;
-
- case N_Bar:
- case N_Break:
- case N_Field:
- case N_Not:
- find_new(Tree0(n));
- break;
-
- case N_Alt:
- case N_Apply:
- case N_Limit:
- case N_Slist:
- find_new(Tree0(n));
- find_new(Tree1(n));
- break;
-
- case N_Activat:
- find_new(Tree1(n));
- find_new(Tree2(n));
- break;
-
- case N_If:
- find_new(Tree0(n)); /* control clause */
- find_new(Tree1(n)); /* then clause */
- find_new(Tree2(n)); /* else clause, may be N_Empty */
- break;
-
- case N_Create:
- /*
- * Allocate a sub-type for the co-expressions created here.
- */
- n->new_types = (int *)alloc((unsigned int)(sizeof(int)));
- n->new_types[0] = type_array[coexp_typ].num_bits++;
- coexp = NewStruct(t_coexpr);
- coexp->n = Tree0(n);
- coexp->next = coexp_lst;
- coexp_lst = coexp;
- find_new(Tree0(n));
- break;
-
- case N_Augop:
- abstr_new(n, Impl0(n)->in_line); /* assignment */
- abstr_new(n, Impl1(n)->in_line); /* the operation */
- find_new(Tree2(n)); /* 1st operand */
- find_new(Tree3(n)); /* 2nd operand */
- break;
-
- case N_Case:
- find_new(Tree0(n)); /* control clause */
- cases = Tree1(n);
- while (cases != NULL) {
- if (cases->n_type == N_Ccls) {
- clause = cases;
- cases = NULL;
- }
- else {
- clause = Tree1(cases);
- cases = Tree0(cases);
- }
-
- find_new(Tree0(clause)); /* value of clause */
- find_new(Tree1(clause)); /* body of clause */
- }
- if (Tree2(n) != NULL)
- find_new(Tree2(n)); /* deflt */
- break;
-
- case N_Invok:
- nargs = Val0(n); /* number of arguments */
- find_new(Tree1(n)); /* thing being invoked */
- for (i = 1; i <= nargs; ++i)
- find_new(n->n_field[i+1].n_ptr); /* arg i */
- break;
-
- case N_InvOp:
- /*
- * This is a call to an operation, this is what we must
- * check for "new" abstract type computation.
- */
- nargs = Val0(n); /* number of arguments */
- abstr_new(n, Impl1(n)->in_line); /* operation */
- for (i = 1; i <= nargs; ++i)
- find_new(n->n_field[i+1].n_ptr); /* arg i */
- break;
-
- case N_InvProc:
- case N_InvRec:
- nargs = Val0(n); /* number of arguments */
- for (i = 1; i <= nargs; ++i)
- find_new(n->n_field[i+1].n_ptr); /* arg i */
- break;
-
- case N_Loop:
- switch ((int)Val0(Tree0(n))) {
- case EVERY:
- case SUSPEND:
- case WHILE:
- case UNTIL:
- find_new(Tree1(n)); /* control clause */
- find_new(Tree2(n)); /* do clause - may be N_Empty*/
- break;
-
- case REPEAT:
- find_new(Tree1(n)); /* clause */
- break;
- }
-
- case N_Ret:
- if (Val0(Tree0(n)) == RETURN)
- find_new(Tree1(n)); /* value - may be N_Empty */
- break;
-
- case N_Scan:
- if (optab[Val0(Tree0(n))].tok.t_type == AUGQMARK)
- abstr_new(n, optab[asgn_loc].binary->in_line);
- find_new(Tree1(n)); /* subject */
- find_new(Tree2(n)); /* body */
- break;
-
- case N_Sect:
- abstr_new(n, Impl0(n)->in_line); /* sectioning */
- if (Impl1(n) != NULL)
- abstr_new(n, Impl1(n)->in_line); /* plus, minus, or nothing */
- find_new(Tree2(n)); /* 1st operand */
- find_new(Tree3(n)); /* 2nd operand */
- find_new(Tree4(n)); /* 3rd operand */
- break;
-
- case N_SmplAsgn:
- case N_SmplAug:
- find_new(Tree3(n));
- break;
-
- default:
- fprintf(stderr, "compiler error: node type %d unknown\n", n->n_type);
- exit(EXIT_FAILURE);
- }
- }
-
-/*
- * abstr_new - find the abstract clauses in the implementation of an operation.
- * If they indicate that the operations creates structures, allocate a
- * type for the structures and associate it with the node in the syntax tree.
- */
-static void abstr_new(n, il)
-struct node *n;
-struct il_code *il;
- {
- int i;
- int num_cases, indx;
- struct typ_info *t_info;
-
- if (il == NULL)
- return;
-
- switch (il->il_type) {
- case IL_New:
- /*
- * We have found a "new" construct in an abstract type computation.
- * Make sure an array has been created to hold the types allocated
- * to this call, then allocate the indicated type if one has not
- * already been allocated.
- */
- if (n->new_types == NULL) {
- n->new_types = (int *)alloc((unsigned int)(num_new * sizeof(int)));
- for (i = 0; i < num_new; ++i)
- n->new_types[i] = -1;
- }
- t_info = &type_array[il->u[0].n]; /* index by type code */
- if (n->new_types[t_info->new_indx] < 0) {
- n->new_types[t_info->new_indx] = t_info->num_bits++;
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) %s\n", n->n_file, n->n_line,
- n->n_col, icontypes[il->u[0].n].id);
-#endif /* TypTrc */
- }
- i = il->u[1].n; /* num args */
- indx = 2;
- while (i--)
- abstr_new(n, il->u[indx++].fld);
- break;
-
- case IL_If1:
- abstr_new(n, il->u[1].fld);
- break;
-
- case IL_If2:
- abstr_new(n, il->u[1].fld);
- abstr_new(n, il->u[2].fld);
- break;
-
- case IL_Tcase1:
- num_cases = il->u[1].n;
- indx = 2;
- for (i = 0; i < num_cases; ++i) {
- indx += 2; /* skip type info */
- abstr_new(n, il->u[indx++].fld); /* action */
- }
- break;
-
- case IL_Tcase2:
- num_cases = il->u[1].n;
- indx = 2;
- for (i = 0; i < num_cases; ++i) {
- indx += 2; /* skip type info */
- abstr_new(n, il->u[indx++].fld); /* action */
- }
- abstr_new(n, il->u[indx].fld); /* default */
- break;
-
- case IL_Lcase:
- num_cases = il->u[0].n;
- indx = 1;
- for (i = 0; i < num_cases; ++i) {
- ++indx; /* skip selection num */
- abstr_new(n, il->u[indx++].fld); /* action */
- }
- abstr_new(n, il->u[indx].fld); /* default */
- break;
-
- case IL_Acase:
- abstr_new(n, il->u[2].fld); /* C_integer action */
- if (largeints)
- abstr_new(n, il->u[3].fld); /* integer action */
- abstr_new(n, il->u[4].fld); /* C_double action */
- break;
-
- case IL_Abstr:
- case IL_Inter:
- case IL_Lst:
- case IL_TpAsgn:
- case IL_Union:
- abstr_new(n, il->u[0].fld);
- abstr_new(n, il->u[1].fld);
- break;
-
- case IL_Compnt:
- case IL_Store:
- case IL_VarTyp:
- abstr_new(n, il->u[0].fld);
- break;
-
- case IL_Block:
- case IL_Call:
- case IL_Const: /* should have been replaced by literal node */
- case IL_Err1:
- case IL_Err2:
- case IL_IcnTyp:
- case IL_Subscr:
- case IL_Var:
- break;
-
- default:
- fprintf(stderr, "compiler error: unknown info in data base\n");
- exit(EXIT_FAILURE);
- }
- }
-
-/*
- * alloc_stor - allocate a store with empty types.
- */
-static struct store *alloc_stor(stor_sz, n_types)
-int stor_sz;
-int n_types;
- {
- struct store *stor;
- int i;
-
- /*
- * If type inferencing is disabled, we don't actually make use of
- * any stores, but the initialization code asks for them anyway.
- */
- if (!do_typinfer)
- return NULL;
-
-#ifdef OptimizeType
- stor = (struct store *)alloc((unsigned int)(sizeof(struct store) +
- ((stor_sz - 1) * sizeof(struct typinfo *))));
- stor->next = NULL;
- stor->perm = 1;
- for (i = 0; i < stor_sz; ++i) {
- stor->types[i] = (struct typinfo *)alloc_typ(n_types);
- }
-#else /* OptimizeType */
- stor = (struct store *)alloc((unsigned int)(sizeof(struct store) +
- ((stor_sz - 1) * sizeof(unsigned int *))));
- stor->next = NULL;
- stor->perm = 1;
- for (i = 0; i < stor_sz; ++i) {
- stor->types[i] = (unsigned int *)alloc_typ(n_types);
- }
-#endif /* OptimizeType */
-
- return stor;
- }
-
-/*
- * findloops - find both explicit loops and implicit loops caused by
- * goal-directed evaluation. Allocate stores for them. Determine which
- * expressions cannot fail (used to eliminate dynamic store allocation
- * for some bounded expressions). Allocate stores for 'if' and 'case'
- * expressions that can be resumed. Initialize expression types.
- * The syntax tree is walked in reverse execution order looking for
- * failure and for generators.
- */
-static int findloops(n, resume, rslt_type)
-struct node *n;
-int resume;
-#ifdef OptimizeType
-struct typinfo *rslt_type;
-#else /* OptimizeType */
-unsigned int *rslt_type;
-#endif /* OptimizeType */
- {
- struct loop {
- int resume;
- int can_fail;
- int every_cntrl;
-#ifdef OptimizeType
- struct typinfo *type;
-#else /* OptimizeType */
- unsigned int *type;
-#endif /* OptimizeType */
- struct loop *prev;
- } loop_info;
- struct loop *loop_sav;
- static struct loop *cur_loop = NULL;
- struct node *cases;
- struct node *clause;
- int can_fail;
- int nargs, i;
-
- n->store = NULL;
- if (!do_typinfer)
- rslt_type = any_typ;
-
- switch (n->n_type) {
- case N_Activat:
- if (rslt_type == NULL)
- rslt_type = alloc_typ(n_intrtyp);
- n->type = rslt_type;
- /*
- * Assume activation can fail.
- */
- can_fail = findloops(Tree2(n), 1, NULL);
- can_fail = findloops(Tree1(n), can_fail, NULL);
- n->symtyps = symtyps(2);
- if (optab[Val0(Tree0(n))].tok.t_type == AUGAT)
- n->symtyps->next = symtyps(2);
- break;
-
- case N_Alt:
- if (rslt_type == NULL)
- rslt_type = alloc_typ(n_intrtyp);
- n->type = rslt_type;
-
-#ifdef TypTrc
- rslt_type = NULL; /* don't share result loc with subexpressions*/
-#endif /* TypTrc */
-
- if (resume)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- can_fail = findloops(Tree0(n), resume, rslt_type) |
- findloops(Tree1(n), resume, rslt_type);
- break;
-
- case N_Apply:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- /*
- * Assume operation can suspend or fail.
- */
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- can_fail = findloops(Tree1(n), 1, NULL);
- can_fail = findloops(Tree0(n), can_fail, NULL);
- n->symtyps = symtyps(max_sym);
- break;
-
- case N_Augop:
- if (rslt_type == NULL)
- rslt_type = alloc_typ(n_intrtyp);
- n->type = rslt_type;
-
- can_fail = resume;
- /*
- * Impl0(n) is assignment.
- */
- if (resume && Impl0(n)->ret_flag & DoesSusp)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(Impl0(n)->ret_flag))
- can_fail = 1;
- /*
- * Impl1(n) is the augmented operation.
- */
- if (can_fail && Impl1(n)->ret_flag & DoesSusp && n->store == NULL)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(Impl1(n)->ret_flag))
- can_fail = 1;
- can_fail = findloops(Tree3(n), can_fail, NULL); /* operand 2 */
- can_fail = findloops(Tree2(n), can_fail, NULL); /* operand 1 */
- n->type = Tree2(n)->type;
- Typ4(n) = alloc_typ(n_intrtyp);
- n->symtyps = symtyps(n_arg_sym(Impl1(n)));
- n->symtyps->next = symtyps(n_arg_sym(Impl0(n)));
- break;
-
- case N_Bar:
- can_fail = findloops(Tree0(n), resume, rslt_type);
- n->type = Tree0(n)->type;
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- break;
-
- case N_Break:
- if (cur_loop == NULL) {
- nfatal(n, "invalid context for break", NULL);
- return 0;
- }
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- loop_sav = cur_loop;
- cur_loop = cur_loop->prev;
- loop_sav->can_fail |= findloops(Tree0(n), loop_sav->resume,
- loop_sav->type);
- cur_loop = loop_sav;
- can_fail = 0;
- break;
-
- case N_Case:
- if (rslt_type == NULL)
- rslt_type = alloc_typ(n_intrtyp);
- n->type = rslt_type;
-
-#ifdef TypTrc
- rslt_type = NULL; /* don't share result loc with subexpressions*/
-#endif /* TypTrc */
-
- if (resume)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
-
- /*
- * control clause is bounded
- */
- can_fail = findloops(Tree0(n), 0, NULL);
-
- cases = Tree1(n);
- while (cases != NULL) {
- if (cases->n_type == N_Ccls) {
- clause = cases;
- cases = NULL;
- }
- else {
- clause = Tree1(cases);
- cases = Tree0(cases);
- }
-
- /*
- * The expression being compared can be resumed.
- */
- findloops(Tree0(clause), 1, NULL);
-
- /*
- * Body.
- */
- can_fail |= findloops(Tree1(clause), resume, rslt_type);
- }
-
- if (Tree2(n) == NULL)
- can_fail = 1;
- else
- can_fail |= findloops(Tree2(n), resume, rslt_type); /* default */
- break;
-
- case N_Create:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- findloops(Tree0(n), 1, NULL); /* co-expression code */
- /*
- * precompute type
- */
- i= type_array[coexp_typ].frst_bit;
- if (do_typinfer)
- i += n->new_types[0];
- set_typ(n->type, i);
- can_fail = resume;
- break;
-
- case N_Cset:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- set_typ(n->type, type_array[cset_typ].frst_bit); /* precompute type */
- can_fail = resume;
- break;
-
- case N_Empty:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- set_typ(n->type, null_bit); /* precompute type */
- can_fail = resume;
- break;
-
- case N_Id: {
- struct lentry *var;
-
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- /*
- * Precompute type
- */
- var = LSym0(n);
- if (var->flag & F_Global)
- set_typ(n->type, frst_gbl + var->val.global->index);
- else if (var->flag & F_Static)
- set_typ(n->type, frst_gbl + var->val.index);
- else
- set_typ(n->type, frst_loc + var->val.index);
- can_fail = resume;
- }
- break;
-
- case N_Field:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- can_fail = findloops(Tree0(n), resume, NULL);
- n->symtyps = symtyps(1);
- break;
-
- case N_If:
- if (rslt_type == NULL)
- rslt_type = alloc_typ(n_intrtyp);
- n->type = rslt_type;
-
-#ifdef TypTrc
- rslt_type = NULL; /* don't share result loc with subexpressions*/
-#endif /* TypTrc */
- /*
- * control clause is bounded
- */
- findloops(Tree0(n), 0, NULL);
- can_fail = findloops(Tree1(n), resume, rslt_type);
- if (Tree2(n)->n_type == N_Empty)
- can_fail = 1;
- else {
- if (resume)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- can_fail |= findloops(Tree2(n), resume, rslt_type);
- }
- break;
-
- case N_Int:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- set_typ(n->type, int_bit); /* precompute type */
- can_fail = resume;
- break;
-
- case N_Invok:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- nargs = Val0(n); /* number of arguments */
- /*
- * Assume operation can suspend and fail.
- */
- if (resume)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- can_fail = 1;
- for (i = nargs; i >= 0; --i)
- can_fail = findloops(n->n_field[i+1].n_ptr, can_fail, NULL);
- n->symtyps = symtyps(max_sym);
- break;
-
- case N_InvOp:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- nargs = Val0(n); /* number of arguments */
- if (resume && Impl1(n)->ret_flag & DoesSusp)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(Impl1(n)->ret_flag))
- can_fail = 1;
- else
- can_fail = resume;
- for (i = nargs; i >= 1; --i)
- can_fail = findloops(n->n_field[i+1].n_ptr, can_fail, NULL);
- n->symtyps = symtyps(n_arg_sym(Impl1(n)));
- break;
-
- case N_InvProc:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- nargs = Val0(n); /* number of arguments */
- if (resume && Proc1(n)->ret_flag & DoesSusp)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (Proc1(n)->ret_flag & DoesFail)
- can_fail = 1;
- else
- can_fail = resume;
- for (i = nargs; i >= 1; --i)
- can_fail = findloops(n->n_field[i+1].n_ptr, can_fail, NULL);
- break;
-
- case N_InvRec:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- nargs = Val0(n); /* number of args */
- if (err_conv)
- can_fail = 1;
- else
- can_fail = resume;
- for (i = nargs; i >= 1; --i)
- can_fail = findloops(n->n_field[i+1].n_ptr, can_fail, NULL);
- break;
-
- case N_Limit:
- findloops(Tree0(n), resume, rslt_type);
- can_fail = findloops(Tree1(n), 1, NULL);
- n->type = Tree0(n)->type;
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- n->symtyps = symtyps(1);
- break;
-
- case N_Loop: {
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- loop_info.prev = cur_loop;
- loop_info.resume = resume;
- loop_info.can_fail = 0;
- loop_info.every_cntrl = 0;
- loop_info.type = n->type;
- cur_loop = &loop_info;
- switch ((int)Val0(Tree0(n))) {
- case EVERY:
- case SUSPEND:
- /*
- * The control clause can be resumed. The body is bounded.
- */
- loop_info.every_cntrl = 1;
- can_fail = findloops(Tree1(n), 1, NULL);
- loop_info.every_cntrl = 0;
- findloops(Tree2(n), 0, NULL);
- break;
-
- case REPEAT:
- /*
- * The loop needs a saved store. The body is bounded.
- */
- findloops(Tree1(n), 0, NULL);
- can_fail = 0;
- break;
-
- case WHILE:
- /*
- * The loop needs a saved store. The control
- * clause and the body are each bounded.
- */
- can_fail = findloops(Tree1(n), 0, NULL);
- findloops(Tree2(n), 0, NULL);
- break;
-
- case UNTIL:
- /*
- * The loop needs a saved store. The control
- * clause and the body are each bounded.
- */
- findloops(Tree1(n), 0, NULL);
- findloops(Tree2(n), 0, NULL);
- can_fail = 1;
- break;
- }
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (do_typinfer && resume)
- n->store->next = alloc_stor(n_gbl + n_loc, n_icntyp);
- can_fail |= cur_loop->can_fail;
- cur_loop = cur_loop->prev;
- }
- break;
-
- case N_Next:
- if (cur_loop == NULL) {
- nfatal(n, "invalid context for next", NULL);
- return 1;
- }
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- can_fail = cur_loop->every_cntrl;
- break;
-
- case N_Not:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- set_typ(n->type, null_bit); /* precompute type */
- /*
- * The expression is bounded.
- */
- findloops(Tree0(n), 0, NULL);
- can_fail = 1;
- break;
-
- case N_Real:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- set_typ(n->type, real_bit); /* precompute type */
- can_fail = resume;
- break;
-
- case N_Ret:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- if (Val0(Tree0(n)) == RETURN) {
- /*
- * The expression is bounded.
- */
- findloops(Tree1(n), 0, NULL);
- }
- can_fail = 0;
- break;
-
- case N_Scan: {
- struct implement *asgn_impl;
-
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- n->symtyps = symtyps(1);
- can_fail = resume;
- if (optab[Val0(Tree0(n))].tok.t_type == AUGQMARK) {
- asgn_impl = optab[asgn_loc].binary;
- if (resume && asgn_impl->ret_flag & DoesSusp)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(asgn_impl->ret_flag))
- can_fail = 1;
- n->symtyps->next = symtyps(n_arg_sym(asgn_impl));
- }
- can_fail = findloops(Tree2(n), can_fail, NULL); /* body */
- can_fail = findloops(Tree1(n), can_fail, NULL); /* subject */
- }
- break;
-
- case N_Sect:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- can_fail = resume;
- /*
- * Impl0(n) is sectioning.
- */
- if (resume && Impl0(n)->ret_flag & DoesSusp)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(Impl0(n)->ret_flag))
- can_fail = 1;
- n->symtyps = symtyps(n_arg_sym(Impl0(n)));
- if (Impl1(n) != NULL) {
- /*
- * Impl1(n) is plus or minus
- */
- if (can_fail && Impl1(n)->ret_flag & DoesSusp && n->store == NULL)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(Impl1(n)->ret_flag))
- can_fail = 1;
- n->symtyps->next = symtyps(n_arg_sym(Impl1(n)));
- }
- can_fail = findloops(Tree4(n), can_fail, NULL); /* operand 3 */
- can_fail = findloops(Tree3(n), can_fail, NULL); /* operand 2 */
- can_fail = findloops(Tree2(n), can_fail, NULL); /* operand 1 */
- break;
-
- case N_Slist:
- /*
- * 1st expression is bounded.
- */
- findloops(Tree0(n), 0, NULL);
- can_fail = findloops(Tree1(n), resume, rslt_type);
- n->type = Tree1(n)->type;
- break;
-
- case N_SmplAsgn:
- can_fail = findloops(Tree3(n), resume, NULL); /* 2nd operand */
- findloops(Tree2(n), can_fail, rslt_type); /* variable */
- n->type = Tree2(n)->type;
- break;
-
- case N_SmplAug:
- can_fail = resume;
- /*
- * Impl1(n) is the augmented operation.
- */
- if (resume && Impl1(n)->ret_flag & DoesSusp)
- n->store = alloc_stor(n_gbl + n_loc, n_icntyp);
- if (MightFail(Impl1(n)->ret_flag))
- can_fail = 1;
- can_fail = findloops(Tree3(n), can_fail, NULL); /* 2nd operand */
- findloops(Tree2(n), can_fail, rslt_type); /* variable */
- n->symtyps = symtyps(n_arg_sym(Impl1(n)));
- n->type = Tree2(n)->type;
- Typ4(n) = alloc_typ(n_intrtyp);
- break;
-
- case N_Str:
- if (rslt_type == NULL)
- n->type = alloc_typ(n_intrtyp);
- else
- n->type = rslt_type;
- set_typ(n->type, str_bit); /* precompute type */
- can_fail = resume;
- break;
-
- default:
- fprintf(stderr, "compiler error: node type %d unknown\n", n->n_type);
- exit(EXIT_FAILURE);
- }
- if (can_fail)
- n->flag = CanFail;
- else
- n->flag = 0;
- return can_fail;
- }
-
-/*
- * symtyps - determine the number of entries needed for a symbol table
- * that maps argument indexes to types for an operation in the
- * data base. Allocate the symbol table.
- */
-static struct symtyps *symtyps(nsyms)
-int nsyms;
- {
- struct symtyps *tab;
-
- if (nsyms == 0)
- return NULL;
-
-#ifdef OptimizeType
- tab = (struct symtyps *)alloc((unsigned int)(sizeof(struct symtyps) +
- (nsyms - 1) * sizeof(struct typinfo *)));
-#else /* OptimizeType */
- tab = (struct symtyps *)alloc((unsigned int)(sizeof(struct symtyps) +
- (nsyms - 1) * sizeof(int *)));
-#endif /* OptimizeType */
- tab->nsyms = nsyms;
- tab->next = NULL;
- while (nsyms)
- tab->types[--nsyms] = alloc_typ(n_intrtyp);
- return tab;
- }
-
-/*
- * infer_proc - perform type inference on a call to an Icon procedure.
- */
-static void infer_prc(proc, n)
-struct pentry *proc;
-nodeptr n;
- {
- struct store *s_store;
- struct store *f_store;
- struct store *store;
- struct pentry *sv_proc;
- struct t_coexpr *sv_coexp;
- struct lentry *lptr;
- nodeptr n1;
- int i;
- int nparams;
- int coexp_bit;
-
- /*
- * Determine what co-expressions the procedure might be called from.
- */
- if (cur_coexp == NULL)
- ChkMrgTyp(n_icntyp, cur_proc->coexprs, proc->coexprs)
- else {
- coexp_bit = type_array[coexp_typ].frst_bit + cur_coexp->typ_indx;
- if (!bitset(proc->coexprs, coexp_bit)) {
- ++changed;
- set_typ(proc->coexprs, coexp_bit);
- }
- }
-
- proc->reachable = 1; /* this procedure can be called */
-
- /*
- * If this procedure can suspend, there may be backtracking paths
- * to this invocation. If so, propagate types of globals from the
- * backtracking paths to the suspends of the procedure and propagate
- * types of locals to the success store of the call.
- */
- if (proc->ret_flag & DoesSusp && n->store != NULL) {
- for (i = 0; i < n_gbl; ++i)
- ChkMrgTyp(n_icntyp, n->store->types[i], proc->susp_store->types[i])
- for (i = 0; i < n_loc; ++i)
- MrgTyp(n_icntyp, n->store->types[n_gbl + i], succ_store->types[n_gbl +
- i])
- }
-
- /*
- * Merge the types of global variables into the "in store" of the
- * procedure. Because the body of the procedure may already have
- * been processed for this pass, the "changed" flag must be set if
- * there is a change of type in the store. This will insure that
- * there will be another iteration in which to propagate the change
- * into the body.
- */
- store = proc->in_store;
- for (i = 0; i < n_gbl; ++i)
- ChkMrgTyp(n_icntyp, succ_store->types[i], store->types[i])
-
-#ifdef TypTrc
- /*
- * Trace the call.
- */
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) %s%s(", n->n_file, n->n_line, n->n_col,
- trc_indent, proc->name);
-#endif /* TypTrc */
-
- /*
- * Get the types of the arguments, starting with the non-varargs part.
- */
- nparams = proc->nargs; /* number of parameters */
- if (nparams < 0)
- nparams = -nparams - 1;
- for (i = 0; i < num_args && i < nparams; ++i) {
- typ_deref(arg_typs->types[i], store->types[n_gbl + i], 1);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- /*
- * Trace the argument type to the call.
- */
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_d_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- }
-
- /*
- * Get the type of the varargs part of the argument list.
- */
- if (proc->nargs < 0)
- while (i < num_args) {
- typ_deref(arg_typs->types[i],
- compnt_array[lst_elem].store->types[proc->arg_lst], 1);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- /*
- * Trace the argument type to the call.
- */
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_d_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- ++i;
- }
-
- /*
- * Missing arguments have the null type.
- */
- while (i < nparams) {
- set_typ(store->types[n_gbl + i], null_bit);
- ++i;
- }
-
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, ")\n");
- {
- char *trc_ind_sav = trc_indent;
- trc_indent = ""; /* staring a new procedure, don't indent tracing */
-#endif /* TypTrc */
-
- /*
- * only perform type inference on the body of a procedure
- * once per iteration
- */
- if (proc->iteration < iteration) {
- proc->iteration = iteration;
- s_store = succ_store;
- f_store = fail_store;
- sv_proc = cur_proc;
- succ_store = cpy_store(proc->in_store);
- cur_proc = proc;
- sv_coexp = cur_coexp;
- cur_coexp = NULL; /* we are not in a create expression */
- /*
- * Perform type inference on the initial clause. Static variables
- * are initialized to null on this path.
- */
- for (lptr = proc->statics; lptr != NULL; lptr = lptr->next)
- set_typ(succ_store->types[lptr->val.index], null_bit);
- n1 = Tree1(proc->tree);
- if (n1->flag & CanFail) {
- /*
- * The initial clause can fail. Because it is bounded, we need
- * a new failure store that we can merge into the success store
- * at the end of the clause.
- */
- store = get_store(1);
- fail_store = store;
- infer_nd(n1);
- mrg_store(store, succ_store);
- free_store(store);
- }
- else
- infer_nd(n1);
- /*
- * Perform type inference on the body of procedure. Execution may
- * pass directly to it without executing initial clause.
- */
- mrg_store(proc->in_store, succ_store);
- n1 = Tree2(proc->tree);
- if (n1->flag & CanFail) {
- /*
- * The body can fail. Because it is bounded, we need a new failure
- * store that we can merge into the success store at the end of
- * the procedure.
- */
- store = get_store(1);
- fail_store = store;
- infer_nd(n1);
- mrg_store(store, succ_store);
- free_store(store);
- }
- else
- infer_nd(n1);
- set_ret(NULL); /* implicit fail */
- free_store(succ_store);
- succ_store = s_store;
- fail_store = f_store;
- cur_proc = sv_proc;
- cur_coexp = sv_coexp;
- }
-
-#ifdef TypTrc
- trc_indent = trc_ind_sav;
- }
-#endif /* TypTrc */
-
- /*
- * Get updated types for global variables at the end of the call.
- */
- store = proc->out_store;
- for (i = 0; i < n_gbl; ++i)
- CpyTyp(n_icntyp, store->types[i], succ_store->types[i]);
-
- /*
- * If the procedure can fail, merge variable types into the failure
- * store.
- */
- if (proc->ret_flag & DoesFail)
- mrg_store(succ_store, fail_store);
-
- /*
- * The return type of the procedure is the result type of the call.
- */
- MrgTyp(n_intrtyp, proc->ret_typ, n->type);
- }
-
-/*
- * cpy_store - make a copy of a store.
- */
-static struct store *cpy_store(source)
-struct store *source;
- {
- struct store *dest;
- int stor_sz;
- int i;
-
- if (source == NULL)
- dest = get_store(1);
- else {
- stor_sz = n_gbl + n_loc;
- dest = get_store(0);
- for (i = 0; i < stor_sz; ++i)
- CpyTyp(n_icntyp, source->types[i], dest->types[i])
- }
- return dest;
- }
-
-/*
- * mrg_store - merge the source store into the destination store.
- */
-static void mrg_store(source, dest)
-struct store *source;
-struct store *dest;
- {
- int i;
-
- if (source == NULL)
- return;
-
- /*
- * Is this store included in the state that must be checked for a fixed
- * point?
- */
- if (dest->perm) {
- for (i = 0; i < n_gbl + n_loc; ++i)
- ChkMrgTyp(n_icntyp, source->types[i], dest->types[i])
- }
- else {
- for (i = 0; i < n_gbl + n_loc; ++i)
- MrgTyp(n_icntyp, source->types[i], dest->types[i])
- }
- }
-
-/*
- * set_ret - Save return type and the store for global variables.
- */
-static void set_ret(typ)
-#ifdef OptimizeType
-struct typinfo *typ;
-#else /* OptimizeType */
-unsigned int *typ;
-#endif /* OptimizeType */
- {
- int i;
-
- /*
- * Merge the return type into the type of the procedure, dereferencing
- * locals in the process.
- */
- if (typ != NULL)
- deref_lcl(typ, cur_proc->ret_typ);
-
- /*
- * Update the types that variables may have upon exit of the procedure.
- */
- for (i = 0; i < n_gbl; ++i)
- MrgTyp(n_icntyp, succ_store->types[i], cur_proc->out_store->types[i]);
- }
-
-/*
- * deref_lcl - dereference local variable sub-types.
- */
-static void deref_lcl(src, dest)
-#ifdef OptimizeType
-struct typinfo *src;
-struct typinfo *dest;
-#else /* OptimizeType */
-unsigned int *src;
-unsigned int *dest;
-#endif /* OptimizeType */
- {
- int i, j;
- int ref_gbl;
- int frst_stv;
- int num_stv;
- struct store *stv_stor;
- struct type *wktyp;
-
- /*
- * Make a copy of the type to be dereferenced.
- */
- wktyp = get_wktyp();
- CpyTyp(n_intrtyp, src, wktyp->bits);
-
- /*
- * Determine which variable types must be dereferenced. Merge the
- * dereferenced type into the return type and delete the variable
- * type. Start with simple local variables.
- */
- for (i = 0; i < n_loc; ++i)
- if (bitset(wktyp->bits, frst_loc + i)) {
- MrgTyp(n_icntyp, succ_store->types[n_gbl + i], wktyp->bits)
- clr_typ(wktyp->bits, frst_loc + i);
- }
-
- /*
- * Check for substring trapped variables. If a sub-string trapped
- * variable references a local, add "string" to the return type.
- * If a sub-string trapped variable references a global, leave the
- * trapped variable in the return type.
- * It is theoretically possible for a sub-string trapped variable type to
- * reference both a local and a global. When the trapped variable type
- * is returned to the calling procedure, the local is re-interpreted
- * as a local of that procedure. This is a "valid" overestimate of
- * of the semantics of the return. Because this is unlikely to occur
- * in real programs, the overestimate is of no practical consequence.
- */
- num_stv = type_array[stv_typ].num_bits;
- frst_stv = type_array[stv_typ].frst_bit;
- stv_stor = compnt_array[str_var].store;
- for (i = 0; i < num_stv; ++i) {
- if (bitset(wktyp->bits, frst_stv + i)) {
- /*
- * We have found substring trapped variable i, see whether it
- * references locals or globals. Globals include structure
- * element references.
- */
- for (j = 0; j < n_loc; ++j)
- if (bitset(stv_stor->types[i], frst_loc + j)) {
- set_typ(wktyp->bits, str_bit);
- break;
- }
- ref_gbl = 0;
- for (j = n_icntyp; j < frst_loc; ++j)
- if (bitset(stv_stor->types[i], j)) {
- ref_gbl = 1;
- break;
- }
- /*
- * Keep the trapped variable only if it references globals.
- */
- if (!ref_gbl)
- clr_typ(wktyp->bits, frst_stv + i);
- }
- }
-
- /*
- * Merge the types into the destination.
- */
- MrgTyp(n_intrtyp, wktyp->bits, dest);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- prt_typ(trcfile, wktyp->bits);
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
-
- free_wktyp(wktyp);
- }
-
-/*
- * get_store - get a store large enough to hold globals and locals.
- */
-static struct store *get_store(clear)
-int clear;
- {
- struct store *store;
- int store_sz;
- int i;
-
- /*
- * Warning, stores for all procedures must be the same size. In some
- * situations involving sub-string trapped variables (for example
- * when using the "default" trapped variable) a referenced local variable
- * type may be interpreted in a procedure to which it does not belong.
- * This represents an impossible execution and type inference may
- * "legally" produce any results for this part of the abstract
- * interpretation. As long as the store is large enough to include any
- * such "impossible" variables, type inference will do something legal.
- * Note that n_loc is the maximum number of locals in any procedure,
- * so store_sz is large enough.
- */
- store_sz = n_gbl + n_loc;
- if ((store = store_pool) == NULL) {
- store = alloc_stor(store_sz, n_icntyp);
- store->perm = 0;
- }
- else {
- store_pool = store_pool->next;
- /*
- * See if the variables in the store should be initialized to the
- * empty type.
- */
- if (clear)
- for (i = 0; i < store_sz; ++i)
- ClrTyp(n_icntyp, store->types[i]);
- }
- return store;
- }
-
-static void free_store(store)
-struct store *store;
- {
- store->next = store_pool;
- store_pool = store;
- }
-
-/*
- * infer_nd - perform type inference on a subtree of the syntax tree.
- */
-static void infer_nd(n)
-nodeptr n;
- {
- struct node *cases;
- struct node *clause;
- struct store *s_store;
- struct store *f_store;
- struct store *store;
- struct loop {
- struct store *succ_store;
- struct store *fail_store;
- struct store *next_store;
- struct store *susp_store;
- struct loop *prev;
- } loop_info;
- struct loop *loop_sav;
- static struct loop *cur_loop;
- struct argtyps *sav_argtyp;
- int sav_nargs;
- struct type *wktyp;
- int i;
-
- switch (n->n_type) {
- case N_Activat:
- infer_act(n);
- break;
-
- case N_Alt:
- f_store = fail_store;
- store = get_store(1);
- fail_store = store;
- infer_nd(Tree0(n)); /* 1st alternative */
-
- /*
- * "Correct" type inferencing of alternation has a performance
- * problem. Propagating stores through nested alternation
- * requires as many iterations as the depth of the nesting.
- * This is solved by adding two edges to the flow graph. These
- * represent impossible execution paths but this does not
- * affect the soundness of type inferencing and, in "real"
- * programs, does not affect the preciseness of its inference.
- * One edge is directly from the 1st alternative to the 2nd.
- * The other is a backtracking edge immediately back into
- * the alternation from the 1st alternative.
- */
- mrg_store(succ_store, store); /* imaginary edge to 2nd alternative */
-
- if (n->store != NULL) {
- mrg_store(succ_store, n->store); /* imaginary backtracking edge */
- mrg_store(n->store, fail_store);
- }
- s_store = succ_store;
- succ_store = store;
- fail_store = f_store;
- infer_nd(Tree1(n)); /* 2nd alternative */
- mrg_store(s_store, succ_store);
- free_store(s_store);
- if (n->store != NULL)
- mrg_store(n->store, fail_store);
- fail_store = n->store;
-#ifdef TypTrc
- MrgTyp(n_intrtyp, Tree0(n)->type, n->type);
- MrgTyp(n_intrtyp, Tree1(n)->type, n->type);
-#else /* TypTrc */
- /*
- * Type is computed by sub-expressions directly into n->type.
- */
-#endif /* TypTrc */
- break;
-
- case N_Apply: {
- struct type *lst_types;
- int frst_lst;
- int num_lst;
- struct store *lstel_stor;
-
- infer_nd(Tree0(n)); /* thing being invoked */
- infer_nd(Tree1(n)); /* list */
-
- frst_lst = type_array[list_typ].frst_bit;
- num_lst = type_array[list_typ].num_bits;
- lstel_stor = compnt_array[lst_elem].store;
-
- /*
- * All that is available is a "summary" of the types of the
- * elements of the list. Each argument to the invocation
- * could be any type in the summary. Set up a maximum length
- * argument list.
- */
- lst_types = get_wktyp();
- typ_deref(Tree1(n)->type, lst_types->bits, 0);
- wktyp = get_wktyp();
- for (i = 0; i < num_lst; ++i)
- if (bitset(lst_types->bits, frst_lst + i))
- MrgTyp(n_icntyp, lstel_stor->types[i], wktyp->bits);
- bitset(wktyp->bits, null_bit); /* arg list extension might be done */
-
- sav_nargs = num_args;
- sav_argtyp = arg_typs;
- num_args = max_prm;
- arg_typs = get_argtyp();
- for (i = 0; i < max_prm; ++i)
- arg_typs->types[i] = wktyp->bits;
- gen_inv(Tree0(n)->type, n); /* inference on general invocation */
-
- free_wktyp(wktyp);
- free_wktyp(lst_types);
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- }
- break;
-
- case N_Augop:
- infer_nd(Tree2(n)); /* 1st operand */
- infer_nd(Tree3(n)); /* 2nd operand */
- /*
- * Perform type inference on the operation.
- */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = 2;
- arg_typs->types[0] = Tree2(n)->type;
- arg_typs->types[1] = Tree3(n)->type;
- infer_impl(Impl1(n), n, n->symtyps, Typ4(n));
- chk_succ(Impl1(n)->ret_flag, n->store);
- /*
- * Perform type inference on the assignment.
- */
- arg_typs->types[1] = Typ4(n);
- infer_impl(Impl0(n), n, n->symtyps->next, n->type);
- chk_succ(Impl0(n)->ret_flag, n->store);
-
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- break;
-
- case N_Bar:
- /*
- * This operation intercepts failure and has an associated
- * resumption store. If backtracking reaches this operation
- * execution may either continue backward or proceed forward
- * again.
- */
- mrg_store(n->store, fail_store);
- mrg_store(n->store, succ_store);
- fail_store = n->store;
- infer_nd(Tree0(n));
- /*
- * Type is computed by operand.
- */
- break;
-
- case N_Break:
- /*
- * The success and failure stores for the operand of break are
- * those associated with the enclosing loop.
- */
- fail_store = cur_loop->fail_store;
- loop_sav = cur_loop;
- cur_loop = cur_loop->prev;
- infer_nd(Tree0(n));
- cur_loop = loop_sav;
- mrg_store(succ_store, cur_loop->succ_store);
- if (cur_loop->susp_store != NULL)
- mrg_store(cur_loop->susp_store, fail_store);
- free_store(succ_store);
- succ_store = get_store(1); /* empty store says: can't get past here */
- fail_store = dummy_stor; /* shouldn't be used */
- /*
- * Result of break is empty type. Result type of expression
- * is computed directly into result type of loop.
- */
- break;
-
- case N_Case:
- f_store = fail_store;
- s_store = get_store(1);
- infer_nd(Tree0(n)); /* control clause */
- cases = Tree1(n);
- while (cases != NULL) {
- if (cases->n_type == N_Ccls) {
- clause = cases;
- cases = NULL;
- }
- else {
- clause = Tree1(cases);
- cases = Tree0(cases);
- }
-
- /*
- * Set up a failure store to capture the effects of failure
- * of the selection clause.
- */
- store = get_store(1);
- fail_store = store;
- infer_nd(Tree0(clause)); /* value of clause */
-
- /*
- * Create the effect of the possible failure of the comparison
- * of the selection value to the control value.
- */
- mrg_store(succ_store, fail_store);
-
- /*
- * The success and failure stores and the result of the body
- * of the clause are those of the whole case expression.
- */
- fail_store = f_store;
- infer_nd(Tree1(clause)); /* body of clause */
- mrg_store(succ_store, s_store);
- free_store(succ_store);
- succ_store = store;
- if (n->store != NULL)
- mrg_store(n->store, fail_store); /* 'case' can be resumed */
-#ifdef TypTrc
- MrgTyp(n_intrtyp, Tree1(clause)->type, n->type);
-#else /* TypTrc */
- /*
- * Type is computed by case clause directly into n->type.
- */
-#endif /* TypTrc */
- }
-
- /*
- * Check for default clause.
- */
- if (Tree2(n) == NULL)
- mrg_store(succ_store, f_store);
- else {
- fail_store = f_store;
- infer_nd(Tree2(n)); /* default */
- mrg_store(succ_store, s_store);
- if (n->store != NULL)
- mrg_store(n->store, fail_store); /* 'case' can be resumed */
-#ifdef TypTrc
- MrgTyp(n_intrtyp, Tree2(n)->type, n->type);
-#else /* TypTrc */
- /*
- * Type is computed by default clause directly into n->type.
- */
-#endif /* TypTrc */
- }
- free_store(succ_store);
- succ_store = s_store;
- if (n->store != NULL)
- fail_store = n->store;
- break;
-
- case N_Create:
- /*
- * Record initial values of local variables for coexpression.
- */
- store = coexp_map[n->new_types[0]]->in_store;
- for (i = 0; i < n_loc; ++i)
- ChkMrgTyp(n_icntyp, succ_store->types[n_gbl + i],
- store->types[n_gbl + i])
- /*
- * Type is precomputed.
- */
- break;
-
- case N_Cset:
- case N_Empty:
- case N_Id:
- case N_Int:
- case N_Real:
- case N_Str:
- /*
- * Type is precomputed.
- */
- break;
-
- case N_Field: {
- struct fentry *fp;
- struct par_rec *rp;
- int frst_rec;
-
- if ((fp = flookup(Str0(Tree1(n)))) == NULL) {
- break; /* error message printed elsewhere */
- }
-
- /*
- * Determine the record types.
- */
- infer_nd(Tree0(n));
- typ_deref(Tree0(n)->type, n->symtyps->types[0], 0);
-
- /*
- * For each record containing this field, get the tupe of
- * the field in that record.
- */
- frst_rec = type_array[rec_typ].frst_bit;
- for (rp = fp->rlist; rp != NULL; rp = rp->next) {
- if (bitset(n->symtyps->types[0], frst_rec + rp->rec->rec_num))
- set_typ(n->type, frst_fld + rp->rec->frst_fld + rp->offset);
- }
- }
- break;
-
- case N_If:
- f_store = fail_store;
- if (Tree2(n)->n_type != N_Empty) {
- /*
- * If there is an else clause, we must set up a failure store
- * to capture the effects of failure of the control clause.
- */
- store = get_store(1);
- fail_store = store;
- }
-
- infer_nd(Tree0(n)); /* control clause */
-
- /*
- * If the control clause succeeds, execution passes into the
- * then clause with the failure store for the entire if expression.
- */
- fail_store = f_store;
- infer_nd(Tree1(n)); /* then clause */
-
- if (Tree2(n)->n_type != N_Empty) {
- if (n->store != NULL)
- mrg_store(n->store, fail_store); /* 'if' expr can be resumed */
- s_store = succ_store;
-
- /*
- * The entering success store of the else clause is the failure
- * store of the control clause. The failure store is that of
- * the entire if expression.
- */
- succ_store = store;
- fail_store = f_store;
- infer_nd(Tree2(n)); /* else clause */
-
- if (n->store != NULL) {
- mrg_store(n->store, fail_store); /* 'if' expr can be resumed */
- fail_store = n->store;
- }
-
- /*
- * Join the exiting success stores of the then and else clauses.
- */
- mrg_store(s_store, succ_store);
- free_store(s_store);
- }
-
-#ifdef TypTrc
- MrgTyp(n_intrtyp, Tree1(n)->type, n->type);
- if (Tree2(n)->n_type != N_Empty)
- MrgTyp(n_intrtyp, Tree2(n)->type, n->type);
-#else /* TypTrc */
- /*
- * Type computed by 'then' and 'else' clauses directly into n->type.
- */
-#endif /* TypTrc */
- break;
-
- case N_Invok:
- /*
- * General invocation.
- */
- infer_nd(Tree1(n)); /* thing being invoked */
-
- /*
- * Perform type inference on all the arguments and copy the
- * results into the argument type array.
- */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = Val0(n); /* number of arguments */
- for (i = 0; i < num_args; ++i) {
- infer_nd(n->n_field[i+2].n_ptr); /* arg i */
- arg_typs->types[i] = n->n_field[i+2].n_ptr->type;
- }
-
- /*
- * If this is mutual evaluation, get the type of the last argument,
- * otherwise do inference on general invocation.
- */
- if (Tree1(n)->n_type == N_Empty) {
- MrgTyp(n_intrtyp, arg_typs->types[num_args - 1], n->type);
- }
- else
- gen_inv(Tree1(n)->type, n);
-
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- break;
-
- case N_InvOp:
- /*
- * Invocation of a run-time operation. Perform inference on all
- * the arguments, copying the results into the argument type
- * array.
- */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = Val0(n); /* number of arguments */
- for (i = 0; i < num_args; ++i) {
- infer_nd(n->n_field[i+2].n_ptr); /* arg i */
- arg_typs->types[i] = n->n_field[i+2].n_ptr->type;
- }
-
- /*
- * Perform inference on operation invocation.
- */
- infer_impl(Impl1(n), n, n->symtyps, n->type);
- chk_succ(Impl1(n)->ret_flag, n->store);
-
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- break;
-
- case N_InvProc:
- /*
- * Invocation of a procedure. Perform inference on all
- * the arguments, copying the results into the argument type
- * array.
- */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = Val0(n); /* number of arguments */
- for (i = 0; i < num_args; ++i) {
- infer_nd(n->n_field[i+2].n_ptr); /* arg i */
- arg_typs->types[i] = n->n_field[i+2].n_ptr->type;
- }
-
- /*
- * Perform inference on the procedure invocation.
- */
- infer_prc(Proc1(n), n);
- chk_succ(Proc1(n)->ret_flag, n->store);
-
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- break;
-
- case N_InvRec:
- /*
- * Invocation of a record constructor. Perform inference on all
- * the arguments, copying the results into the argument type
- * array.
- */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = Val0(n); /* number of arguments */
- for (i = 0; i < num_args; ++i) {
- infer_nd(n->n_field[i+2].n_ptr); /* arg i */
- arg_typs->types[i] = n->n_field[i+2].n_ptr->type;
- }
-
- infer_con(Rec1(n), n); /* inference on constructor invocation */
-
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- break;
-
- case N_Limit:
- infer_nd(Tree1(n)); /* limit */
- typ_deref(Tree1(n)->type, n->symtyps->types[0], 0);
- mrg_store(succ_store, fail_store); /* limit might be 0 */
- mrg_store(n->store, fail_store); /* resumption may bypass expr */
- infer_nd(Tree0(n)); /* expression */
- if (fail_store != NULL)
- mrg_store(n->store, fail_store); /* expression may be resumed */
- fail_store = n->store;
- /*
- * Type is computed by expression being limited.
- */
- break;
-
- case N_Loop: {
- /*
- * Establish stores used by break and next.
- */
- loop_info.prev = cur_loop;
- loop_info.succ_store = get_store(1);
- loop_info.fail_store = fail_store;
- loop_info.next_store = NULL;
- loop_info.susp_store = n->store->next;
- cur_loop = &loop_info;
-
- switch ((int)Val0(Tree0(n))) {
- case EVERY:
- infer_nd(Tree1(n)); /* control clause */
- f_store = fail_store;
-
- /*
- * Next in the do clause resumes the control clause as
- * does success of the do clause.
- */
- loop_info.next_store = fail_store;
- infer_nd(Tree2(n)); /* do clause */
- mrg_store(succ_store, f_store);
- break;
-
- case REPEAT:
- /*
- * The body of the loop can be entered by entering the
- * loop, by executing a next in the body, or by having
- * the loop succeed or fail. n->store captures all but
- * the first case, which is covered by the initial success
- * store.
- */
- fail_store = n->store;
- mrg_store(n->store, succ_store);
- loop_info.next_store = n->store;
- infer_nd(Tree1(n));
- mrg_store(succ_store, n->store);
- break;
-
- case SUSPEND:
- infer_nd(Tree1(n)); /* value */
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) suspend ", n->n_file, n->n_line,
- n->n_col);
-#endif /* TypTrc */
-
- set_ret(Tree1(n)->type); /* set return type of procedure */
-
- /*
- * Get changes to types of global variables from
- * resumption.
- */
- store = cur_proc->susp_store;
- for (i = 0; i < n_gbl; ++i)
- CpyTyp(n_icntyp, store->types[i], succ_store->types[i]);
-
- /*
- * Next in the do clause resumes the control clause as
- * does success of the do clause.
- */
- f_store = fail_store;
- loop_info.next_store = fail_store;
- infer_nd(Tree2(n)); /* do clause */
- mrg_store(succ_store, f_store);
- break;
-
- case WHILE:
- /*
- * The control clause can be entered by entering the loop,
- * executing a next expression, or by having the do clause
- * succeed or fail. n->store captures all but the first case,
- * which is covered by the initial success store.
- */
- mrg_store(n->store, succ_store);
- loop_info.next_store = n->store;
- infer_nd(Tree1(n)); /* control clause */
- fail_store = n->store;
- infer_nd(Tree2(n)); /* do clause */
- mrg_store(succ_store, n->store);
- break;
-
- case UNTIL:
- /*
- * The control clause can be entered by entering the loop,
- * executing a next expression, or by having the do clause
- * succeed or fail. n->store captures all but the first case,
- * which is covered by the initial success store.
- */
- mrg_store(n->store, succ_store);
- loop_info.next_store = n->store;
- f_store = fail_store;
- /*
- * Set up a failure store to capture the effects of failure
- * of the control clause.
- */
- store = get_store(1);
- fail_store = store;
- infer_nd(Tree1(n)); /* control clause */
- mrg_store(succ_store, f_store);
- free_store(succ_store);
- succ_store = store;
- fail_store = n->store;
- infer_nd(Tree2(n)); /* do clause */
- mrg_store(succ_store, n->store);
- break;
- }
- free_store(succ_store);
- succ_store = loop_info.succ_store;
- if (n->store->next != NULL)
- fail_store = n->store->next;
- cur_loop = cur_loop->prev;
- /*
- * Type is computed by break expressions.
- */
- }
- break;
-
- case N_Next:
- if (cur_loop->next_store == NULL)
- mrg_store(succ_store, fail_store); /* control clause of every */
- else
- mrg_store(succ_store, cur_loop->next_store);
- free_store(succ_store);
- succ_store = get_store(1); /* empty store says: can't get past here */
- fail_store = dummy_stor; /* shouldn't be used */
- /*
- * Result is empty type.
- */
- break;
-
- case N_Not:
- /*
- * Set up a failure store to capture the effects of failure
- * of the negated expression, it becomes the success store
- * of the entire expression.
- */
- f_store = fail_store;
- store = get_store(1);
- fail_store = store;
- infer_nd(Tree0(n));
- mrg_store(succ_store, f_store); /* if success, then fail */
- free_store(succ_store);
- succ_store = store;
- fail_store = f_store;
- /*
- * Type is precomputed.
- */
- break;
-
- case N_Ret:
- if (Val0(Tree0(n)) == RETURN) {
- if (Tree1(n)->flag & CanFail) {
- /*
- * Set up a failure store to capture the effects of failure
- * of the returned expression and the corresponding procedure
- * failure.
- */
- store = get_store(1);
- fail_store = store;
- infer_nd(Tree1(n)); /* return value */
- mrg_store(store, succ_store);
- free_store(store);
- }
- else
- infer_nd(Tree1(n)); /* return value */
-
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) return ", n->n_file, n->n_line,
- n->n_col);
-#endif /* TypTrc */
-
- set_ret(Tree1(n)->type);
- }
- else { /* fail */
- set_ret(NULL);
-
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) fail\n", n->n_file, n->n_line,
- n->n_col);
-#endif /* TypTrc */
-
- }
- free_store(succ_store);
- succ_store = get_store(1); /* empty store says: can't get past here */
- fail_store = dummy_stor; /* shouldn't be used */
- /*
- * Empty type.
- */
- break;
-
- case N_Scan: {
- struct implement *asgn_impl;
-
- infer_nd(Tree1(n)); /* subject */
- typ_deref(Tree1(n)->type, n->symtyps->types[0], 0);
- infer_nd(Tree2(n)); /* body */
-
- if (optab[Val0(Tree0(n))].tok.t_type == AUGQMARK) {
- /*
- * Perform type inference on the assignment.
- */
- asgn_impl = optab[asgn_loc].binary;
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = 2;
- arg_typs->types[0] = Tree1(n)->type;
- arg_typs->types[1] = Tree2(n)->type;
- infer_impl(asgn_impl, n, n->symtyps->next, n->type);
- chk_succ(asgn_impl->ret_flag, n->store);
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- }
- else
- MrgTyp(n_intrtyp, Tree2(n)->type, n->type);
- }
- break;
-
- case N_Sect:
- infer_nd(Tree2(n)); /* 1st operand */
- infer_nd(Tree3(n)); /* 2nd operand */
- infer_nd(Tree4(n)); /* 3rd operand */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- if (Impl1(n) != NULL) {
- /*
- * plus or minus.
- */
- num_args = 2;
- arg_typs->types[0] = Tree3(n)->type;
- arg_typs->types[1] = Tree4(n)->type;
- wktyp = get_wktyp();
- infer_impl(Impl1(n), n, n->symtyps->next, wktyp->bits);
- chk_succ(Impl1(n)->ret_flag, n->store);
- arg_typs->types[2] = wktyp->bits;
- }
- else
- arg_typs->types[2] = Tree4(n)->type;
- num_args = 3;
- arg_typs->types[0] = Tree2(n)->type;
- arg_typs->types[1] = Tree3(n)->type;
- /*
- * sectioning
- */
- infer_impl(Impl0(n), n, n->symtyps, n->type);
- chk_succ(Impl0(n)->ret_flag, n->store);
- if (Impl1(n) != NULL)
- free_wktyp(wktyp);
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- break;
-
- case N_Slist:
- f_store = fail_store;
- if (Tree0(n)->flag & CanFail) {
- /*
- * Set up a failure store to capture the effects of failure
- * of the first operand; this is merged into the
- * incoming success store of the second operand.
- */
- store = get_store(1);
- fail_store = store;
- infer_nd(Tree0(n));
- mrg_store(store, succ_store);
- free_store(store);
- }
- else
- infer_nd(Tree0(n));
- fail_store = f_store;
- infer_nd(Tree1(n));
- /*
- * Type is computed by second operand.
- */
- break;
-
- case N_SmplAsgn: {
- /*
- * Optimized assignment to a named variable.
- */
- struct lentry *var;
- int indx;
-
- infer_nd(Tree3(n));
- var = LSym0(Tree2(n));
- if (var->flag & F_Global)
- indx = var->val.global->index;
- else if (var->flag & F_Static)
- indx = var->val.index;
- else
- indx = n_gbl + var->val.index;
- ClrTyp(n_icntyp, succ_store->types[indx]);
- typ_deref(Tree3(n)->type, succ_store->types[indx], 0);
-
-#ifdef TypTrc
- /*
- * Trace assignment.
- */
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) %s%s := ", n->n_file, n->n_line,
- n->n_col, trc_indent, var->name);
- prt_d_typ(trcfile, Tree3(n)->type);
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
- /*
- * Type is precomputed.
- */
- }
- break;
-
- case N_SmplAug: {
- /*
- * Optimized augmented assignment to a named variable.
- */
- struct lentry *var;
- int indx;
-
- /*
- * Perform type inference on the operation.
- */
- infer_nd(Tree3(n)); /* 2nd operand */
-
- /*
- * Set up type array for arguments of operation.
- */
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = 2;
- arg_typs->types[0] = Tree2(n)->type; /* type was precomputed */
- arg_typs->types[1] = Tree3(n)->type;
-
- /*
- * Perform inference on the operation.
- */
- infer_impl(Impl1(n), n, n->symtyps, Typ4(n));
- chk_succ(Impl1(n)->ret_flag, n->store);
-
- /*
- * Perform assignment to the variable.
- */
- var = LSym0(Tree2(n));
- if (var->flag & F_Global)
- indx = var->val.global->index;
- else if (var->flag & F_Static)
- indx = var->val.index;
- else
- indx = n_gbl + var->val.index;
- ClrTyp(n_icntyp, succ_store->types[indx]);
- typ_deref(Typ4(n), succ_store->types[indx], 0);
-
-#ifdef TypTrc
- /*
- * Trace assignment.
- */
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) %s%s := ", n->n_file, n->n_line,
- n->n_col, trc_indent, var->name);
- prt_d_typ(trcfile, Typ4(n));
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
-
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
-
- /*
- * Type is precomputed.
- */
- }
- break;
-
- default:
- fprintf(stderr, "compiler error: node type %d unknown\n", n->n_type);
- exit(EXIT_FAILURE);
- }
- }
-
-/*
- * infer_con - perform type inference for the invocation of a record
- * constructor.
- */
-static void infer_con(rec, n)
-struct rentry *rec;
-nodeptr n;
- {
- int fld_indx;
- int nfields;
- int i;
-
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) %s%s(", n->n_file, n->n_line, n->n_col,
- trc_indent, rec->name);
-#endif /* TypTrc */
-
- /*
- * Dereference argument types into appropriate entries of field store.
- */
- fld_indx = rec->frst_fld;
- nfields = rec->nfields;
- for (i = 0; i < num_args && i < nfields; ++i) {
- typ_deref(arg_typs->types[i], fld_stor->types[fld_indx++], 1);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_d_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- }
-
- /*
- * If there are too few arguments, add null type to appropriate entries
- * of field store.
- */
- while (i < nfields) {
- if (!bitset(fld_stor->types[fld_indx], null_bit)) {
- ++changed;
- set_typ(fld_stor->types[fld_indx], null_bit);
- }
- ++fld_indx;
- ++i;
- }
-
- /*
- * return record type
- */
- set_typ(n->type, type_array[rec_typ].frst_bit + rec->rec_num);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, ") =>> ");
- prt_typ(trcfile, n->type);
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
- }
-
-/*
- * infer_act - perform type inference on coexpression activation.
- */
-static void infer_act(n)
-nodeptr n;
- {
- struct implement *asgn_impl;
- struct store *s_store;
- struct store *f_store;
- struct store *e_store;
- struct store *store;
- struct t_coexpr *sv_coexp;
- struct t_coexpr *coexp;
- struct type *rslt_typ;
- struct argtyps *sav_argtyp;
- int frst_coexp;
- int num_coexp;
- int sav_nargs;
- int i;
- int j;
-
-#ifdef TypTrc
- FILE *trc_save;
-#endif /* TypTrc */
-
- num_coexp = type_array[coexp_typ].num_bits;
- frst_coexp = type_array[coexp_typ].frst_bit;
-
- infer_nd(Tree1(n)); /* value to transmit */
- infer_nd(Tree2(n)); /* coexpression */
-
- /*
- * Dereference the two arguments. Note that only locals in the
- * transmitted value are dereferenced.
- */
-
-#ifdef TypTrc
- trc_save = trcfile;
- trcfile = NULL; /* don't trace value during dereferencing */
-#endif /* TypTrc */
-
- deref_lcl(Tree1(n)->type, n->symtyps->types[0]);
-
-#ifdef TypTrc
- trcfile = trc_save;
-#endif /* TypTrc */
-
- typ_deref(Tree2(n)->type, n->symtyps->types[1], 0);
-
- rslt_typ = get_wktyp();
-
- /*
- * Set up a store for the end of the activation and propagate local
- * variables across the activation; the activation may succeed or
- * fail.
- */
- e_store = get_store(1);
- for (i = 0; i < n_loc; ++i)
- CpyTyp(n_icntyp, succ_store->types[n_gbl + i], e_store->types[n_gbl + i])
- if (fail_store->perm) {
- for (i = 0; i < n_loc; ++i)
- ChkMrgTyp(n_icntyp, succ_store->types[n_gbl + i],
- fail_store->types[n_gbl + i])
- }
- else {
- for (i = 0; i < n_loc; ++i)
- MrgTyp(n_icntyp, succ_store->types[n_gbl + i],
- fail_store->types[n_gbl + i])
- }
-
-
- /*
- * Go through all the co-expressions that might be activated,
- * perform type inference on them, and transmit stores along
- * the execution paths induced by the activation.
- */
- s_store = succ_store;
- f_store = fail_store;
- for (j = 0; j < num_coexp; ++j) {
- if (bitset(n->symtyps->types[1], frst_coexp + j)) {
- coexp = coexp_map[j];
- /*
- * Merge the types of global variables into the "in store" of the
- * co-expression. Because the body of the co-expression may already
- * have been processed for this pass, the "changed" flag must be
- * set if there is a change of type in the store. This will insure
- * that there will be another iteration in which to propagate the
- * change into the body.
- */
- store = coexp->in_store;
- for (i = 0; i < n_gbl; ++i)
- ChkMrgTyp(n_icntyp, s_store->types[i], store->types[i])
-
- ChkMrgTyp(n_intrtyp, n->symtyps->types[0], coexp->act_typ)
-
- /*
- * Only perform type inference on the body of a co-expression
- * once per iteration. The main co-expression has no body.
- */
- if (coexp->iteration < iteration & coexp->n != NULL) {
- coexp->iteration = iteration;
- succ_store = cpy_store(coexp->in_store);
- fail_store = coexp->out_store;
- sv_coexp = cur_coexp;
- cur_coexp = coexp;
- infer_nd(coexp->n);
-
- /*
- * Dereference the locals in the value resulting from
- * the execution of the co-expression body.
- */
-
-#ifdef TypTrc
- if (trcfile != NULL)
- fprintf(trcfile, "%s (%d,%d) %sC%d =>> ", coexp->n->n_file,
- coexp->n->n_line, coexp->n->n_col, trc_indent, j);
-#endif /* TypTrc */
-
- deref_lcl(coexp->n->type, coexp->rslt_typ);
-
- mrg_store(succ_store, coexp->out_store);
- free_store(succ_store);
- cur_coexp = sv_coexp;
- }
-
- /*
- * Get updated types for global variables, assuming the co-expression
- * fails or returns by completing.
- */
- store = coexp->out_store;
- for (i = 0; i < n_gbl; ++i)
- MrgTyp(n_icntyp, store->types[i], e_store->types[i]);
- if (f_store->perm) {
- for (i = 0; i < n_gbl; ++i)
- ChkMrgTyp(n_icntyp, store->types[i], f_store->types[i]);
- }
- else {
- for (i = 0; i < n_gbl; ++i)
- MrgTyp(n_icntyp, store->types[i], f_store->types[i]);
- }
- MrgTyp(n_intrtyp, coexp->rslt_typ, rslt_typ->bits)
- }
- }
-
- /*
- * Control may return from the activation if another co-expression
- * activates the current one. If we are in a create expression,
- * cur_coexp is the current co-expression, otherwise the current
- * procedure may be called within several co-expressions.
- */
- if (cur_coexp == NULL) {
- for (j = 0; j < num_coexp; ++j)
- if (bitset(cur_proc->coexprs, frst_coexp + j))
- mrg_act(coexp_map[j], e_store, rslt_typ);
- }
- else
- mrg_act(cur_coexp, e_store, rslt_typ);
-
- free_store(s_store);
- succ_store = e_store;
- fail_store = f_store;
-
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) %s", n->n_file, n->n_line, n->n_col,
- trc_indent);
- prt_typ(trcfile, n->symtyps->types[0]);
- fprintf(trcfile, " @ ");
- prt_typ(trcfile, n->symtyps->types[1]);
- fprintf(trcfile, " =>> ");
- prt_typ(trcfile, rslt_typ->bits);
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
-
- if (optab[Val0(Tree0(n))].tok.t_type == AUGAT) {
- /*
- * Perform type inference on the assignment.
- */
- asgn_impl = optab[asgn_loc].binary;
- sav_argtyp = arg_typs;
- sav_nargs = num_args;
- arg_typs = get_argtyp();
- num_args = 2;
- arg_typs->types[0] = Tree1(n)->type;
- arg_typs->types[1] = rslt_typ->bits;
- infer_impl(asgn_impl, n, n->symtyps->next, n->type);
- chk_succ(asgn_impl->ret_flag, n->store);
- free_argtyp(arg_typs);
- arg_typs = sav_argtyp;
- num_args = sav_nargs;
- }
- else
- ChkMrgTyp(n_intrtyp, rslt_typ->bits, n->type)
-
- free_wktyp(rslt_typ);
- }
-
-/*
- * mrg_act - merge entry information for the co-expression to the
- * the ending store and result type for the activation being
- * analyzed.
- */
-static void mrg_act(coexp, e_store, rslt_typ)
-struct t_coexpr *coexp;
-struct store *e_store;
-struct type *rslt_typ;
- {
- struct store *store;
- int i;
-
- store = coexp->in_store;
- for (i = 0; i < n_gbl; ++i)
- MrgTyp(n_icntyp, store->types[i], e_store->types[i]);
-
- MrgTyp(n_intrtyp, coexp->act_typ, rslt_typ->bits)
- }
-
-/*
- * typ_deref - perform dereferencing in the abstract type realm.
- */
-static void typ_deref(src, dest, chk)
-#ifdef OptimizeType
-struct typinfo *src;
-struct typinfo *dest;
-#else /* OptimizeType */
-unsigned int *src;
-unsigned int *dest;
-#endif /* OptimizeType */
-int chk;
- {
- struct store *tblel_stor;
- struct store *tbldf_stor;
- struct store *ttv_stor;
- struct store *store;
- unsigned int old;
- int num_tbl;
- int frst_tbl;
- int num_bits;
- int frst_bit;
- int i;
- int j;
- int ret;
-/*
- if (src->bits == NULL) {
- src->bits = alloc_mem_typ(src->size);
- xfer_packed_types(src);
- }
- if (dest->bits == NULL) {
- dest->bits = alloc_mem_typ(dest->size);
- xfer_packed_types(dest);
- }
-*/
- /*
- * copy values to destination
- */
-#ifdef OptimizeType
- if ((src->bits != NULL) && (dest->bits != NULL)) {
- for (i = 0; i < NumInts(n_icntyp) - 1; ++i) {
- old = dest->bits[i];
- dest->bits[i] |= src->bits[i];
- if (chk && (old != dest->bits[i]))
- ++changed;
- }
- old = dest->bits[i];
- dest->bits[i] |= src->bits[i] & val_mask; /* mask out variables */
- if (chk && (old != dest->bits[i]))
- ++changed;
- }
- else if ((src->bits != NULL) && (dest->bits == NULL)) {
- dest->bits = alloc_mem_typ(DecodeSize(dest->packed));
- xfer_packed_types(dest);
- for (i = 0; i < NumInts(n_icntyp) - 1; ++i) {
- old = dest->bits[i];
- dest->bits[i] |= src->bits[i];
- if (chk && (old != dest->bits[i]))
- ++changed;
- }
- old = dest->bits[i];
- dest->bits[i] |= src->bits[i] & val_mask; /* mask out variables */
- if (chk && (old != dest->bits[i]))
- ++changed;
- }
- else if ((src->bits == NULL) && (dest->bits != NULL)) {
- ret = xfer_packed_to_bits(src, dest, n_icntyp);
- if (chk)
- changed += ret;
- }
- else {
- ret = mrg_packed_to_packed(src, dest, n_icntyp);
- if (chk)
- changed += ret;
- }
-#else /* OptimizeType */
- for (i = 0; i < NumInts(n_icntyp) - 1; ++i) {
- old = dest[i];
- dest[i] |= src[i];
- if (chk && (old != dest[i]))
- ++changed;
- }
- old = dest[i];
- dest[i] |= src[i] & val_mask; /* mask out variables */
- if (chk && (old != dest[i]))
- ++changed;
-#endif /* OptimizeType */
-
- /*
- * predefined variables whose types do not change.
- */
- for (i = 0; i < num_typs; ++i) {
- if (icontypes[i].deref == DrfCnst) {
- if (bitset(src, type_array[i].frst_bit))
- if (chk)
- ChkMrgTyp(n_icntyp, type_array[i].typ, dest)
- else
- MrgTyp(n_icntyp, type_array[i].typ, dest)
- }
- }
-
-
- /*
- * substring trapped variables
- */
- num_bits = type_array[stv_typ].num_bits;
- frst_bit = type_array[stv_typ].frst_bit;
- for (i = 0; i < num_bits; ++i)
- if (bitset(src, frst_bit + i))
- if (!bitset(dest, str_bit)) {
- if (chk)
- ++changed;
- set_typ(dest, str_bit);
- }
-
- /*
- * table element trapped variables
- */
- num_bits = type_array[ttv_typ].num_bits;
- frst_bit = type_array[ttv_typ].frst_bit;
- num_tbl = type_array[tbl_typ].num_bits;
- frst_tbl = type_array[tbl_typ].frst_bit;
- tblel_stor = compnt_array[tbl_val].store;
- tbldf_stor = compnt_array[tbl_dflt].store;
- ttv_stor = compnt_array[trpd_tbl].store;
- for (i = 0; i < num_bits; ++i)
- if (bitset(src, frst_bit + i))
- for (j = 0; j < num_tbl; ++j)
- if (bitset(ttv_stor->types[i], frst_tbl + j)) {
- if (chk) {
- ChkMrgTyp(n_icntyp, tblel_stor->types[j], dest)
- ChkMrgTyp(n_icntyp, tbldf_stor->types[j], dest)
- }
- else {
- MrgTyp(n_icntyp, tblel_stor->types[j], dest)
- MrgTyp(n_icntyp, tbldf_stor->types[j], dest)
- }
- }
-
- /*
- * Aggregate compontents that are variables.
- */
- for (i = 0; i < num_cmpnts; ++i) {
- if (typecompnt[i].var) {
- frst_bit = compnt_array[i].frst_bit;
- num_bits = compnt_array[i].num_bits;
- store = compnt_array[i].store;
- for (j = 0; j < num_bits; ++j) {
- if (bitset(src, frst_bit + j))
- if (chk)
- ChkMrgTyp(n_icntyp, store->types[j], dest)
- else
- MrgTyp(n_icntyp, store->types[j], dest)
- }
- }
- }
-
-
- /*
- * record fields
- */
- for (i = 0; i < n_fld; ++i)
- if (bitset(src, frst_fld + i)) {
- if (chk)
- ChkMrgTyp(n_icntyp, fld_stor->types[i], dest)
- else
- MrgTyp(n_icntyp, fld_stor->types[i], dest)
- }
-
- /*
- * global variables
- */
- for (i = 0; i < n_gbl; ++i)
- if (bitset(src, frst_gbl + i)) {
- if (chk)
- ChkMrgTyp(n_icntyp, succ_store->types[i], dest)
- else
- MrgTyp(n_icntyp, succ_store->types[i], dest)
- }
-
- /*
- * local variables
- */
- for (i = 0; i < n_loc; ++i)
- if (bitset(src, frst_loc + i)) {
- if (chk)
- ChkMrgTyp(n_icntyp, succ_store->types[n_gbl + i], dest)
- else
- MrgTyp(n_icntyp, succ_store->types[n_gbl + i], dest)
- }
-}
-
-/*
- * infer_impl - perform type inference on a call to built-in operation
- * using the implementation entry from the data base.
- */
-static void infer_impl(impl, n, symtyps, rslt_typ)
-struct implement *impl;
-nodeptr n;
-struct symtyps *symtyps;
-#ifdef OptimizeType
-struct typinfo *rslt_typ;
-#else /* OptimizeType */
-unsigned int *rslt_typ;
-#endif /* OptimizeType */
- {
-#ifdef OptimizeType
- struct typinfo *typ;
-#else /* OptimizeType */
- unsigned int *typ;
-#endif /* OptimizeType */
- int flag;
- int nparms;
- int i;
- int j;
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) %s", n->n_file, n->n_line, n->n_col,
- trc_indent);
- if (impl->oper_typ == 'K')
- fprintf(trcfile, "&%s", impl->name);
- else
- fprintf(trcfile, "%s(", impl->name);
- }
-#endif /* TypTrc */
- /*
- * Set up the "symbol table" of dereferenced and undereferenced
- * argument types as needed by the operation.
- */
- nparms = impl->nargs;
- j = 0;
- for (i = 0; i < num_args && i < nparms; ++i) {
- if (impl->arg_flgs[i] & RtParm) {
- CpyTyp(n_intrtyp, arg_typs->types[i], symtyps->types[j]);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- ++j;
- }
- if (impl->arg_flgs[i] & DrfPrm) {
- typ_deref(arg_typs->types[i], symtyps->types[j], 0);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (impl->arg_flgs[i] & RtParm)
- fprintf(trcfile, "->");
- else if (i > 0)
- fprintf(trcfile, ", ");
- prt_d_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- ++j;
- }
- }
- if (nparms > 0) {
- /*
- * Check for varargs. Merge remaining arguments into the
- * type of the variable part of the parameter list.
- */
- flag = impl->arg_flgs[nparms - 1];
- if (flag & VarPrm) {
- n_vararg = num_args - nparms + 1;
- if (n_vararg < 0)
- n_vararg = 0;
- typ = symtyps->types[j - 1];
- while (i < num_args) {
- if (flag & RtParm) {
- MrgTyp(n_intrtyp, arg_typs->types[i], typ)
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- }
- else {
- typ_deref(arg_typs->types[i], typ, 0);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_d_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- }
- ++i;
- }
- nparms -= 1; /* Don't extend with nulls into variable part */
- }
- }
- while (i < nparms) {
- if (impl->arg_flgs[i] & RtParm)
- set_typ(symtyps->types[j++], null_bit); /* Extend args with nulls */
- if (impl->arg_flgs[i] & DrfPrm)
- set_typ(symtyps->types[j++], null_bit); /* Extend args with nulls */
- ++i;
- }
-
- /*
- * If this operation can suspend, there may be backtracking paths
- * to this invocation. Merge type information from those paths
- * into the current store.
- */
- if (impl->ret_flag & DoesSusp)
- mrg_store(n->store, succ_store);
-
- cur_symtyps = symtyps;
- cur_rslt.bits = rslt_typ;
- cur_rslt.size = n_intrtyp;
- cur_new = n->new_types;
- infer_il(impl->in_line); /* perform inference on operation */
-
- if (MightFail(impl->ret_flag))
- mrg_store(succ_store, fail_store);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (impl->oper_typ != 'K')
- fprintf(trcfile, ")");
- fprintf(trcfile, " =>> ");
- prt_typ(trcfile, rslt_typ);
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
- }
-
-/*
- * chk_succ - check to see if the operation can succeed. In particular,
- * see if it can suspend. Change the succ_store and failure store
- * appropriately.
- */
-static void chk_succ(ret_flag, susp_stor)
-int ret_flag;
-struct store *susp_stor;
- {
- if (ret_flag & DoesSusp) {
- if (susp_stor != NULL && (ret_flag & DoesRet))
- mrg_store(susp_stor, fail_store); /* "pass along" failure */
- fail_store = susp_stor;
- }
- else if (!(ret_flag & DoesRet)) {
- free_store(succ_store);
- succ_store = get_store(1);
- fail_store = dummy_stor; /* shouldn't be used */
- }
- }
-
-/*
- * infer_il - perform type inference on a piece of code within built-in
- * operation and determine whether execution can get past it.
- */
-static int infer_il(il)
-struct il_code *il;
- {
- struct il_code *il1;
- int condition;
- int case_fnd;
- int ncases;
- int may_fallthru;
- int indx;
- int i;
-
- if (il == NULL)
- return 1;
-
- switch (il->il_type) {
- case IL_Const: /* should have been replaced by literal node */
- return 0;
-
- case IL_If1:
- condition = eval_cond(il->u[0].fld);
- may_fallthru = (condition & MaybeFalse);
- if (condition & MaybeTrue)
- may_fallthru |= infer_il(il->u[1].fld);
- return may_fallthru;
-
- case IL_If2:
- condition = eval_cond(il->u[0].fld);
- may_fallthru = 0;
- if (condition & MaybeTrue)
- may_fallthru |= infer_il(il->u[1].fld);
- if (condition & MaybeFalse)
- may_fallthru |= infer_il(il->u[2].fld);
- return may_fallthru;
-
- case IL_Tcase1:
- type_case(il, infer_il, NULL);
- return 1; /* no point in trying very hard here */
-
- case IL_Tcase2:
- indx = type_case(il, infer_il, NULL);
- if (indx != -1)
- infer_il(il->u[indx].fld); /* default */
- return 1; /* no point in trying very hard here */
-
- case IL_Lcase:
- ncases = il->u[0].n;
- indx = 1;
- case_fnd = 0;
- for (i = 0; i < ncases && !case_fnd; ++i) {
- if (il->u[indx++].n == n_vararg) { /* selection number */
- infer_il(il->u[indx].fld); /* action */
- case_fnd = 1;
- }
- ++indx;
- }
- if (!case_fnd)
- infer_il(il->u[indx].fld); /* default */
- return 1; /* no point in trying very hard here */
-
- case IL_Acase: {
- int maybe_int;
- int maybe_dbl;
-
- eval_arith((int)il->u[0].fld->u[0].n, (int)il->u[1].fld->u[0].n,
- &maybe_int, &maybe_dbl);
- if (maybe_int) {
- infer_il(il->u[2].fld); /* C_integer action */
- if (largeints)
- infer_il(il->u[3].fld); /* integer action */
- }
- if (maybe_dbl)
- infer_il(il->u[4].fld); /* C_double action */
- return 1; /* no point in trying very hard here */
- }
-
- case IL_Err1:
- case IL_Err2:
- return 0;
-
- case IL_Block:
- return il->u[0].n;
-
- case IL_Call:
- return ((il->u[3].n & DoesFThru) != 0);
-
- case IL_Lst:
- if (infer_il(il->u[0].fld))
- return infer_il(il->u[1].fld);
- else
- return 0;
-
- case IL_Abstr:
- /*
- * Handle side effects.
- */
- il1 = il->u[0].fld;
- if (il1 != NULL) {
- while (il1->il_type == IL_Lst) {
- side_effect(il1->u[1].fld);
- il1 = il1->u[0].fld;
- }
- side_effect(il1);
- }
-
- /*
- * Set return type.
- */
- abstr_typ(il->u[1].fld, &cur_rslt);
- return 1;
-
- default:
- fprintf(stderr, "compiler error: unknown info in data base\n");
- exit(EXIT_FAILURE);
- /* NOTREACHED */
- }
- }
-
-/*
- * side_effect - perform a side effect from an abstract clause of a
- * built-in operation.
- */
-static void side_effect(il)
-struct il_code *il;
- {
- struct type *var_typ;
- struct type *val_typ;
- struct store *store;
- int num_bits;
- int frst_bit;
- int i, j;
-
- /*
- * il is IL_TpAsgn, get the variable type and value type, and perform
- * the side effect.
- */
- var_typ = get_wktyp();
- val_typ = get_wktyp();
- abstr_typ(il->u[0].fld, var_typ); /* variable type */
- abstr_typ(il->u[1].fld, val_typ); /* value type */
-
- /*
- * Determine which types that can be assigned to are in the variable
- * type.
- *
- * Aggregate compontents.
- */
- for (i = 0; i < num_cmpnts; ++i) {
- frst_bit = compnt_array[i].frst_bit;
- num_bits = compnt_array[i].num_bits;
- store = compnt_array[i].store;
- for (j = 0; j < num_bits; ++j) {
- if (bitset(var_typ->bits, frst_bit + j))
- ChkMrgTyp(n_icntyp, val_typ->bits, store->types[j])
- }
- }
-
- /*
- * record fields
- */
- for (i = 0; i < n_fld; ++i)
- if (bitset(var_typ->bits, frst_fld + i))
- ChkMrgTyp(n_icntyp, val_typ->bits, fld_stor->types[i]);
-
- /*
- * global variables
- */
- for (i = 0; i < n_gbl; ++i)
- if (bitset(var_typ->bits, frst_gbl + i))
- MrgTyp(n_icntyp, val_typ->bits, succ_store->types[i]);
-
- /*
- * local variables
- */
- for (i = 0; i < n_loc; ++i)
- if (bitset(var_typ->bits, frst_loc + i))
- MrgTyp(n_icntyp, val_typ->bits, succ_store->types[n_gbl + i]);
-
-
- free_wktyp(var_typ);
- free_wktyp(val_typ);
- }
-
-/*
- * abstr_typ - compute the type bits corresponding to an abstract type
- * from an abstract clause of a built-in operation.
- */
-static void abstr_typ(il, typ)
-struct il_code *il;
-struct type *typ;
- {
- struct type *typ1;
- struct type *typ2;
- struct rentry *rec;
- struct store *store;
- struct compnt_info *compnts;
- int num_bits;
- int frst_bit;
- int frst_cmpnt;
- int num_comps;
- int typcd;
- int new_indx;
- int i;
- int j;
- int indx;
- int size;
- int t_indx;
-#ifdef OptimizeType
- struct typinfo *prmtyp;
-#else /* OptimizeType */
- unsigned int *prmtyp;
-#endif /* OptimizeType */
-
- if (il == NULL)
- return;
-
- switch (il->il_type) {
- case IL_VarTyp:
- /*
- * type(<parameter>)
- */
- indx = il->u[0].fld->u[0].n; /* symbol table index of variable */
- if (indx >= cur_symtyps->nsyms) {
- prmtyp = any_typ;
- size = n_rttyp;
- }
- else {
- prmtyp = cur_symtyps->types[indx];
- size = n_intrtyp;
- }
- if (typ->size < size)
- size = typ->size;
- MrgTyp(size, prmtyp, typ->bits);
- break;
-
- case IL_Store:
- /*
- * store[<type>]
- */
- typ1 = get_wktyp();
- abstr_typ(il->u[0].fld, typ1); /* type to be "dereferenced" */
-
- /*
- * Dereference types that are Icon varaibles.
- */
- typ_deref(typ1->bits, typ->bits, 0);
-
- /*
- * "Dereference" aggregate compontents that are not Icon variables.
- */
- for (i = 0; i < num_cmpnts; ++i) {
- if (!typecompnt[i].var) {
- if (i == stv_typ) {
- /*
- * Substring trapped variable stores contain variable
- * references, so the types are larger, but we cannot
- * copy more than the destination holds.
- */
- size = n_intrtyp;
- if (typ->size < size)
- size = typ->size;
- }
- else
- size = n_icntyp;
- frst_bit = compnt_array[i].frst_bit;
- num_bits = compnt_array[i].num_bits;
- store = compnt_array[i].store;
- for (j = 0; j < num_bits; ++j) {
- if (bitset(typ1->bits, frst_bit + j))
- MrgTyp(size, store->types[j], typ->bits);
- }
- }
- }
-
- free_wktyp(typ1);
- break;
-
- case IL_Compnt:
- /*
- * <type>.<component>
- */
- typ1 = get_wktyp();
- abstr_typ(il->u[0].fld, typ1); /* type */
- i = il->u[1].n;
- if (i == CM_Fields) {
- /*
- * The all_fields component must be handled differently
- * from the others.
- */
- frst_bit = type_array[rec_typ].frst_bit;
- num_bits = type_array[rec_typ].num_bits;
- for (i = 0; i < num_bits; ++i)
- if (bitset(typ1->bits, frst_bit + i)) {
- rec = rec_map[i];
- for (j = 0; j < rec->nfields; ++j)
- set_typ(typ->bits, frst_fld + rec->frst_fld + j);
- }
- }
- else {
- /*
- * Use component information arrays to transform type bits to
- * the corresponding component bits.
- */
- frst_bit = type_array[typecompnt[i].aggregate].frst_bit;
- num_bits = type_array[typecompnt[i].aggregate].num_bits;
- frst_cmpnt = compnt_array[i].frst_bit;
- if (!typecompnt[i].var && typ->size < n_rttyp)
- break; /* bad abstract type computation */
- for (i = 0; i < num_bits; ++i)
- if (bitset(typ1->bits, frst_bit + i))
- set_typ(typ->bits, frst_cmpnt + i);
- free_wktyp(typ1);
- }
- break;
-
- case IL_Union:
- /*
- * <type 1> ++ <type 2>
- */
- abstr_typ(il->u[0].fld, typ);
- abstr_typ(il->u[1].fld, typ);
- break;
-
- case IL_Inter:
- /*
- * <type 1> ** <type 2>
- */
- typ1 = get_wktyp();
- typ2 = get_wktyp();
- abstr_typ(il->u[0].fld, typ1);
- abstr_typ(il->u[1].fld, typ2);
- size = n_rttyp;
-#ifdef OptimizeType
- and_bits_to_packed(typ2->bits, typ1->bits, size);
-#else /* OptimizeType */
- for (i = 0; i < NumInts(size); ++i)
- typ1->bits[i] &= typ2->bits[i];
-#endif /* OptimizeType */
- if (typ->size < size)
- size = typ->size;
- MrgTyp(size, typ1->bits, typ->bits);
- free_wktyp(typ1);
- free_wktyp(typ2);
- break;
-
- case IL_New:
- /*
- * new <type-name>(<type 1> , ...)
- *
- * If a type was not allocated for this node, use the default
- * one.
- */
- typ1 = get_wktyp();
- typcd = il->u[0].n; /* type code */
- new_indx = type_array[typcd].new_indx;
- t_indx = 0; /* default is first index of type */
- if (cur_new != NULL && cur_new[new_indx] > 0)
- t_indx = cur_new[new_indx];
-
- /*
- * This RTL expression evaluates to the "new" sub-type.
- */
- set_typ(typ->bits, type_array[typcd].frst_bit + t_indx);
-
- /*
- * Update stores for components based on argument types in the
- * "new" expression.
- */
- num_comps = icontypes[typcd].num_comps;
- j = icontypes[typcd].compnts;
- compnts = &compnt_array[j];
- if (typcd == stv_typ) {
- size = n_intrtyp;
- }
- else
- size = n_icntyp;
- for (i = 0; i < num_comps; ++i) {
- ClrTyp(n_rttyp, typ1->bits);
- abstr_typ(il->u[2 + i].fld, typ1);
- ChkMrgTyp(size, typ1->bits, compnts[i].store->types[t_indx]);
- }
-
- free_wktyp(typ1);
- break;
-
- case IL_IcnTyp:
- typcd_bits((int)il->u[0].n, typ); /* type code */
- break;
- }
- }
-
-/*
- * eval_cond - evaluate the condition of in 'if' statement from a
- * built-in operation. The result can be both true and false because
- * of uncertainty and because more than one execution path may be
- * involved.
- */
-static int eval_cond(il)
-struct il_code *il;
- {
- int cond1;
- int cond2;
-
- switch (il->il_type) {
- case IL_Bang:
- cond1 = eval_cond(il->u[0].fld);
- cond2 = 0;
- if (cond1 & MaybeTrue)
- cond2 = MaybeFalse;
- if (cond1 & MaybeFalse)
- cond2 |= MaybeTrue;
- return cond2;
-
- case IL_And:
- cond1 = eval_cond(il->u[0].fld);
- cond2 = eval_cond(il->u[1].fld);
- return (cond1 & cond2 & MaybeTrue) | ((cond1 | cond2) & MaybeFalse);
-
- case IL_Cnv1:
- case IL_Cnv2:
- return eval_cnv((int)il->u[0].n, (int)il->u[1].fld->u[0].n,
- 0, NULL);
-
- case IL_Def1:
- case IL_Def2:
- return eval_cnv((int)il->u[0].n, (int)il->u[1].fld->u[0].n,
- 1, NULL);
-
- case IL_Is:
- return eval_is((int)il->u[0].n, il->u[1].fld->u[0].n);
-
- default:
- fprintf(stderr, "compiler error: unknown info in data base\n");
- exit(EXIT_FAILURE);
- /* NOTREACHED */
- }
- }
-
-/*
- * eval_cnv - evaluate the conversion of a variable to a specific type
- * to see if it may succeed or fail.
- */
-int eval_cnv(typcd, indx, def, cnv_flags)
-int typcd; /* type to convert to */
-int indx; /* index into symbol table of variable */
-int def; /* flag: conversion has a default value */
-int *cnv_flags; /* return flag for detailed conversion information */
- {
- struct type *may_succeed; /* types where conversion sometimes succeed */
- struct type *must_succeed; /* types where conversion always succeeds */
- struct type *must_cnv; /* types where actual conversion is performed */
- struct type *as_is; /* types where value already has correct type */
-#ifdef OptimizeType
- struct typinfo *typ; /* possible types of the variable */
-#else /* OptimizeType */
- unsigned int *typ;
-#endif /* OptimizeType */
- int cond;
- int i;
-#ifdef OptimizeType
- unsigned int val1, val2;
-#endif /* OptimizeType */
-
- /*
- * Conversions may succeed for strings, integers, csets, and reals.
- * Conversions may fail for any other types. In addition,
- * conversions to integer or real may fail for specific values.
- */
- if (indx >= cur_symtyps->nsyms)
- return MaybeTrue | MaybeFalse;
- typ = cur_symtyps->types[indx];
-
- may_succeed = get_wktyp();
- must_succeed = get_wktyp();
- must_cnv = get_wktyp();
- as_is = get_wktyp();
-
- if (typcd == cset_typ || typcd == TypTCset) {
- set_typ(as_is->bits, cset_bit);
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, int_bit);
- set_typ(must_cnv->bits, real_bit);
-
- set_typ(must_succeed->bits, str_bit);
- set_typ(must_succeed->bits, cset_bit);
- set_typ(must_succeed->bits, int_bit);
- set_typ(must_succeed->bits, real_bit);
- }
- else if (typcd == str_typ || typcd == TypTStr) {
- set_typ(as_is->bits, str_bit);
-
- set_typ(must_cnv->bits, cset_bit);
- set_typ(must_cnv->bits, int_bit);
- set_typ(must_cnv->bits, real_bit);
-
- set_typ(must_succeed->bits, str_bit);
- set_typ(must_succeed->bits, cset_bit);
- set_typ(must_succeed->bits, int_bit);
- set_typ(must_succeed->bits, real_bit);
- }
- else if (typcd == TypCStr) {
- /*
- * as_is is empty.
- */
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
- set_typ(must_cnv->bits, int_bit);
- set_typ(must_cnv->bits, real_bit);
-
- set_typ(must_succeed->bits, str_bit);
- set_typ(must_succeed->bits, cset_bit);
- set_typ(must_succeed->bits, int_bit);
- set_typ(must_succeed->bits, real_bit);
- }
- else if (typcd == real_typ) {
- set_typ(as_is->bits, real_bit);
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
- set_typ(must_cnv->bits, int_bit);
-
- set_typ(must_succeed->bits, int_bit);
- set_typ(must_succeed->bits, real_bit);
- }
- else if (typcd == TypCDbl) {
- /*
- * as_is is empty.
- */
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
- set_typ(must_cnv->bits, int_bit);
- set_typ(must_cnv->bits, real_bit);
-
- set_typ(must_succeed->bits, int_bit);
- set_typ(must_succeed->bits, real_bit);
- }
- else if (typcd == int_typ) {
- set_typ(as_is->bits, int_bit);
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
- set_typ(must_cnv->bits, real_bit);
-
- set_typ(must_succeed->bits, int_bit);
- }
- else if (typcd == TypCInt) {
- /*
- * Note that conversion from an integer to a C integer can be
- * done by changing the way the descriptor is accessed. It
- * is not considered a real conversion. Conversion may fail
- * even for integers if large integers are supported.
- */
- set_typ(as_is->bits, int_bit);
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
- set_typ(must_cnv->bits, real_bit);
-
- if (!largeints)
- set_typ(must_succeed->bits, int_bit);
- }
- else if (typcd == TypEInt) {
- set_typ(as_is->bits, int_bit);
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
-
- set_typ(must_succeed->bits, int_bit);
- }
- else if (typcd == TypECInt) {
- set_typ(as_is->bits, int_bit);
-
- set_typ(must_cnv->bits, str_bit);
- set_typ(must_cnv->bits, cset_bit);
-
- if (!largeints)
- set_typ(must_succeed->bits, int_bit);
- }
-
- MrgTyp(n_icntyp, as_is->bits, may_succeed->bits);
- MrgTyp(n_icntyp, must_cnv->bits, may_succeed->bits);
- if (def) {
- set_typ(may_succeed->bits, null_bit);
- set_typ(must_succeed->bits, null_bit);
- }
-
- /*
- * Determine if the conversion expression may evaluate to true or false.
- */
- cond = 0;
-
-/*
- if (typ->bits == NULL) {
- typ->bits = alloc_mem_typ(typ->size);
- xfer_packed_types(typ);
- }
- if (may_succeed->bits->bits == NULL) {
- may_succeed->bits->bits = alloc_mem_typ(may_succeed->bits->size);
- xfer_packed_types(may_succeed->bits);
- }
- if (must_succeed->bits->bits == NULL) {
- must_succeed->bits->bits = alloc_mem_typ(must_succeed->bits->size);
- xfer_packed_types(must_succeed->bits);
- }
-*/
- for (i = 0; i < NumInts(n_intrtyp); ++i) {
-#ifdef OptimizeType
- if ((typ->bits != NULL) && (may_succeed->bits->bits != NULL)) {
- if (typ->bits[i] & may_succeed->bits->bits[i])
- cond = MaybeTrue;
- }
- else if ((typ->bits == NULL) && (may_succeed->bits->bits != NULL)) {
- val1 = get_bit_vector(typ, i);
- if (val1 & may_succeed->bits->bits[i])
- cond = MaybeTrue;
- }
- else if ((typ->bits != NULL) && (may_succeed->bits->bits == NULL)) {
- val2 = get_bit_vector(may_succeed->bits, i);
- if (typ->bits[i] & val2)
- cond = MaybeTrue;
- }
- else {
- val1 = get_bit_vector(typ, i);
- val2 = get_bit_vector(may_succeed->bits, i);
- if (val1 & val2)
- cond = MaybeTrue;
- }
- if ((typ->bits != NULL) && (must_succeed->bits->bits != NULL)) {
- if (typ->bits[i] & ~must_succeed->bits->bits[i])
- cond |= MaybeFalse;
- }
- else if ((typ->bits == NULL) && (must_succeed->bits->bits != NULL)) {
- val1 = get_bit_vector(typ, i);
- if (val1 & ~must_succeed->bits->bits[i])
- cond |= MaybeFalse;
- }
- else if ((typ->bits != NULL) && (must_succeed->bits->bits == NULL)) {
- val2 = get_bit_vector(must_succeed->bits, i);
- if (typ->bits[i] & ~val2)
- cond |= MaybeFalse;
- }
- else {
- val1 = get_bit_vector(typ, i);
- val2 = get_bit_vector(must_succeed->bits, i);
- if (val1 & ~val2)
- cond |= MaybeFalse;
- }
-#else /* OptimizeType */
- if (typ[i] & may_succeed->bits[i])
- cond = MaybeTrue;
- if (typ[i] & ~must_succeed->bits[i])
- cond |= MaybeFalse;
-#endif /* OptimizeType */
- }
-
- /*
- * See if more detailed information about the conversion is needed.
- */
- if (cnv_flags != NULL) {
- *cnv_flags = 0;
-/*
- if (as_is->bits == NULL) {
- as_is->bits->bits = alloc_mem_typ(as_is->bits->size);
- xfer_packed_types(as_is->bits);
- }
- if (must_cnv->bits->bits == NULL) {
- must_cnv->bits->bits = alloc_mem_typ(must_cnv->bits->size);
- xfer_packed_types(must_cnv->bits);
- }
-*/
- for (i = 0; i < NumInts(n_intrtyp); ++i) {
-#ifdef OptimizeType
- if ((typ->bits != NULL) && (as_is->bits->bits != NULL)) {
- if (typ->bits[i] & as_is->bits->bits[i])
- *cnv_flags |= MayKeep;
- }
- else if ((typ->bits == NULL) && (as_is->bits->bits != NULL)) {
- val1 = get_bit_vector(typ, i);
- if (val1 & as_is->bits->bits[i])
- *cnv_flags |= MayKeep;
- }
- else if ((typ->bits != NULL) && (as_is->bits->bits == NULL)) {
- val2 = get_bit_vector(as_is->bits, i);
- if (typ->bits[i] & val2)
- *cnv_flags |= MayKeep;
- }
- else {
- val1 = get_bit_vector(typ, i);
- val2 = get_bit_vector(as_is->bits, i);
- if (val1 & val2)
- *cnv_flags |= MayKeep;
- }
- if ((typ->bits != NULL) && (must_cnv->bits->bits != NULL)) {
- if (typ->bits[i] & must_cnv->bits->bits[i])
- *cnv_flags |= MayConvert;
- }
- else if ((typ->bits == NULL) && (must_cnv->bits->bits != NULL)) {
- val1 = get_bit_vector(typ, i);
- if (val1 & must_cnv->bits->bits[i])
- *cnv_flags |= MayConvert;
- }
- else if ((typ->bits != NULL) && (must_cnv->bits->bits == NULL)) {
- val2 = get_bit_vector(must_cnv->bits, i);
- if (typ->bits[i] & val2)
- *cnv_flags |= MayConvert;
- }
- else {
- val1 = get_bit_vector(typ, i);
- val2 = get_bit_vector(must_cnv->bits, i);
- if (val1 & val2)
- *cnv_flags |= MayConvert;
- }
-#else /* OptimizeType */
- if (typ[i] & as_is->bits[i])
- *cnv_flags |= MayKeep;
- if (typ[i] & must_cnv->bits[i])
- *cnv_flags |= MayConvert;
-#endif /* OptimizeType */
- }
- if (def && bitset(typ, null_bit))
- *cnv_flags |= MayDefault;
- }
-
- free_wktyp(may_succeed);
- free_wktyp(must_succeed);
- free_wktyp(must_cnv);
- free_wktyp(as_is);
-
- return cond;
- }
-
-/*
- * eval_is - evaluate the result of an 'is' expression within a built-in
- * operation.
- */
-int eval_is(typcd, indx)
-int typcd;
-int indx;
- {
- int cond;
-#ifdef OptimizeType
- struct typinfo *typ;
-#else /* OptimizeType */
- unsigned int *typ;
-#endif /* OptimizeType */
-
- if (indx >= cur_symtyps->nsyms)
- return MaybeTrue | MaybeFalse;
- typ = cur_symtyps->types[indx];
- if (has_type(typ, typcd, 0))
- cond = MaybeTrue;
- else
- cond = 0;
- if (other_type(typ, typcd))
- cond |= MaybeFalse;
- return cond;
- }
-
-/*
- * eval_arith - determine which cases of an arith_case may be taken based
- * on the types of its arguments.
- */
-void eval_arith(indx1, indx2, maybe_int, maybe_dbl)
-int indx1;
-int indx2;
-int *maybe_int;
-int *maybe_dbl;
- {
-#ifdef OptimizeType
- struct typinfo *typ1; /* possible types of first variable */
- struct typinfo *typ2; /* possible types of second variable */
-#else /* OptimizeType */
- unsigned int *typ1; /* possible types of first variable */
- unsigned int *typ2; /* possible types of second variable */
-#endif /* OptimizeType */
- int int1 = 0;
- int int2 = 0;
- int dbl1 = 0;
- int dbl2 = 0;
-
- typ1 = cur_symtyps->types[indx1];
- typ2 = cur_symtyps->types[indx2];
-
- /*
- * First see what might result if you do a convert to numeric on each
- * variable.
- */
- if (bitset(typ1, int_bit))
- int1 = 1;
- if (bitset(typ1, real_bit))
- dbl1 = 1;
- if (bitset(typ1, str_bit) || bitset(typ1, cset_bit)) {
- int1 = 1;
- dbl1 = 1;
- }
- if (bitset(typ2, int_bit))
- int2 = 1;
- if (bitset(typ2, real_bit))
- dbl2 = 1;
- if (bitset(typ2, str_bit) || bitset(typ2, cset_bit)) {
- int2 = 1;
- dbl2 = 1;
- }
-
- /*
- * Use the conversion information to figure out what type of arithmetic
- * might be done.
- */
- if (int1 && int2)
- *maybe_int = 1;
- else
- *maybe_int = 0;
-
- *maybe_dbl = 0;
- if (dbl1 && dbl2)
- *maybe_dbl = 1;
- else if (dbl1 && int2)
- *maybe_dbl = 1;
- else if (int1 && dbl2)
- *maybe_dbl = 1;
- }
-
-/*
- * type_case - Determine which cases are selected in a type_case
- * statement. This routine is used by both type inference and
- * the code generator: a different fnc is passed in each case.
- * In addition, the code generator passes a case_anlz structure.
- */
-int type_case(il, fnc, case_anlz)
-struct il_code *il;
-int (*fnc)();
-struct case_anlz *case_anlz;
- {
- int *typ_vect;
- int i, j;
- int num_cases;
- int num_types;
- int indx;
- int sym_indx;
- int typcd;
- int use_dflt;
-#ifdef OptimizeType
- struct typinfo *typ;
-#else /* OptimizeType */
- unsigned int *typ;
-#endif /* OptimizeType */
- int select;
- struct type *wktyp;
-
- /*
- * Make a copy of the type of the variable the type case is
- * working on.
- */
- sym_indx = il->u[0].fld->u[0].n; /* symbol table index */
- if (sym_indx >= cur_symtyps->nsyms)
- typ = any_typ; /* variable is not a parameter, don't know type */
- else
- typ = cur_symtyps->types[sym_indx];
- wktyp = get_wktyp();
- CpyTyp(n_intrtyp, typ, wktyp->bits);
- typ = wktyp->bits;
-
- /*
- * Loop through all the case clauses.
- */
- num_cases = il->u[1].n;
- indx = 2;
- for (i = 0; i < num_cases; ++i) {
- /*
- * For each of the types selected by this clause, see if the variable's
- * type bit vector contains that type and delete the type from the
- * bit vector (so we know if we need the default when we are done).
- */
- num_types = il->u[indx++].n;
- typ_vect = il->u[indx++].vect;
- select = 0;
- for (j = 0; j < num_types; ++j)
- if (has_type(typ, typ_vect[j], 1)) {
- typcd = typ_vect[j];
- select += 1;
- }
-
- if (select > 0) {
- fnc(il->u[indx].fld); /* action */
-
- /*
- * If this routine was called by the code generator, we need to
- * return extra information.
- */
- if (case_anlz != NULL) {
- ++case_anlz->n_cases;
- if (select == 1) {
- if (case_anlz->il_then == NULL) {
- case_anlz->typcd = typcd;
- case_anlz->il_then = il->u[indx].fld;
- }
- else if (case_anlz->il_else == NULL)
- case_anlz->il_else = il->u[indx].fld;
- }
- else {
- /*
- * There is more than one possible type that will cause
- * us to select this case. It can only be used in the "else".
- */
- if (case_anlz->il_else == NULL)
- case_anlz->il_else = il->u[indx].fld;
- else
- case_anlz->n_cases = 3; /* force no inlining. */
- }
- }
- }
- ++indx;
- }
-
- /*
- * If there are types that have not been handled, indicate this by
- * returning the index of the default clause.
- */
- use_dflt = 0;
- for (i = 0; i < n_intrtyp; ++i)
- if (bitset(typ, i)) {
- use_dflt = 1;
- break;
- }
- free_wktyp(wktyp);
- if (use_dflt)
- return indx;
- else
- return -1;
- }
-
-/*
- * gen_inv - general invocation. The argument list is set up, perform
- * abstract interpretation on each possible things being invoked.
- */
-static void gen_inv(typ, n)
-#ifdef OptimizeType
-struct typinfo *typ;
-#else /* OptimizeType */
-unsigned int *typ;
-#endif /* OptimizeType */
-nodeptr n;
- {
- int ret_flag = 0;
- struct store *s_store;
- struct store *store;
- struct gentry *gptr;
- struct implement *ip;
- struct type *prc_typ;
- int frst_prc;
- int num_prcs;
- int i;
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) {\n", n->n_file, n->n_line, n->n_col);
- trc_indent = " ";
- }
-#endif /* TypTrc */
-
- frst_prc = type_array[proc_typ].frst_bit;
- num_prcs = type_array[proc_typ].num_bits;
-
- /*
- * Dereference the type of the thing being invoked.
- */
- prc_typ = get_wktyp();
- typ_deref(typ, prc_typ->bits, 0);
-
- s_store = succ_store;
- store = get_store(1);
-
- if (bitset(prc_typ->bits, str_bit) ||
- bitset(prc_typ->bits, cset_bit) ||
- bitset(prc_typ->bits, int_bit) ||
- bitset(prc_typ->bits, real_bit)) {
- /*
- * Assume integer invocation; any argument may be the result type.
- */
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) %s{i}(", n->n_file, n->n_line, n->n_col,
- trc_indent);
- }
-#endif /* TypTrc */
-
- for (i = 0; i < num_args; ++i) {
- MrgTyp(n_intrtyp, arg_typs->types[i], n->type);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- if (i > 0)
- fprintf(trcfile, ", ");
- prt_typ(trcfile, arg_typs->types[i]);
- }
-#endif /* TypTrc */
-
- }
-
- /*
- * Integer invocation may succeed or fail.
- */
- ret_flag |= DoesRet | DoesFail;
- mrg_store(s_store, store);
- mrg_store(s_store, fail_store);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, ") =>> ");
- prt_typ(trcfile, n->type);
- fprintf(trcfile, "\n");
- }
-#endif /* TypTrc */
- }
-
- if (bitset(prc_typ->bits, str_bit) ||
- bitset(prc_typ->bits, cset_bit)) {
- /*
- * Assume string invocation; add all procedure types to the thing
- * being invoked.
- */
- for (i = 0; i < num_prcs; ++i)
- set_typ(prc_typ->bits, frst_prc + i);
- }
-
- if (bitset(prc_typ->bits, frst_prc)) {
- /*
- * First procedure type represents all operators that are
- * available via string invocation. Scan the operator table
- * looking for those that are in the string invocation table.
- * Note, this is not particularly efficient or precise.
- */
- for (i = 0; i < IHSize; ++i)
- for (ip = ohash[i]; ip != NULL; ip = ip->blink)
- if (ip->iconc_flgs & InStrTbl) {
- succ_store = cpy_store(s_store);
- infer_impl(ip, n, n->symtyps, n->type);
- ret_flag |= ip->ret_flag;
- mrg_store(succ_store, store);
- free_store(succ_store);
- }
- }
-
- /*
- * Check for procedure, built-in, and record constructor types
- * and perform type inference on invocations of them.
- */
- for (i = 1; i < num_prcs; ++i)
- if (bitset(prc_typ->bits, frst_prc + i)) {
- succ_store = cpy_store(s_store);
- gptr = proc_map[i];
- switch (gptr->flag & (F_Proc | F_Builtin | F_Record)) {
- case F_Proc:
- infer_prc(gptr->val.proc, n);
- ret_flag |= gptr->val.proc->ret_flag;
- break;
- case F_Builtin:
- infer_impl(gptr->val.builtin, n, n->symtyps, n->type);
- ret_flag |= gptr->val.builtin->ret_flag;
- break;
- case F_Record:
- infer_con(gptr->val.rec, n);
- ret_flag |= DoesRet | (err_conv ? DoesFail : 0);
- break;
- }
- mrg_store(succ_store, store);
- free_store(succ_store);
- }
-
- /*
- * If error conversion is supported and a non-procedure value
- * might be invoked, assume the invocation can fail.
- */
- if (err_conv && other_type(prc_typ->bits, proc_typ))
- mrg_store(s_store, fail_store);
-
- free_store(s_store);
- succ_store = store;
- chk_succ(ret_flag, n->store);
-
- free_wktyp(prc_typ);
-
-#ifdef TypTrc
- if (trcfile != NULL) {
- fprintf(trcfile, "%s (%d,%d) }\n", n->n_file, n->n_line, n->n_col);
- trc_indent = "";
- }
-#endif /* TypTrc */
- }
-
-/*
- * get_wktyp - get a dynamically allocated bit vector to use as a
- * work area for doing type computations.
- */
-static struct type *get_wktyp()
- {
- struct type *typ;
-
- if ((typ = type_pool) == NULL) {
- typ = NewStruct(type);
- typ->size = n_rttyp;
- typ->bits = alloc_typ(n_rttyp);
- }
- else {
- type_pool = type_pool->next;
- ClrTyp(n_rttyp, typ->bits);
- }
- return typ;
- }
-
-/*
- * free_wktyp - free a dynamically allocated type bit vector.
- */
-static void free_wktyp(typ)
-struct type *typ;
- {
- typ->next = type_pool;
- type_pool = typ;
- }
-
-#ifdef TypTrc
-
-/*
- * ChkSep - supply a separating space if this is not the first item.
- */
-#define ChkSep(n) (++n > 1 ? " " : "")
-
-/*
- * prt_typ - print a type that can include variable references.
- */
-static void prt_typ(file, typ)
-FILE *file;
-#ifdef OptimizeType
-struct typinfo *typ;
-#else /* OptimizeType */
-unsigned int *typ;
-#endif /* OptimizeType */
- {
- struct gentry *gptr;
- struct lentry *lptr;
- char *name;
- int i, j, k;
- int n;
- int frst_bit;
- int num_bits;
- char *abrv;
-
- fprintf(trcfile, "{");
- n = 0;
- /*
- * Go through the types and see any sub-types are present.
- */
- for (k = 0; k < num_typs; ++k) {
- frst_bit = type_array[k].frst_bit;
- num_bits = type_array[k].num_bits;
- abrv = icontypes[k].abrv;
- if (k == proc_typ) {
- /*
- * procedures, record constructors, and built-in functions.
- */
- for (i = 0; i < num_bits; ++i)
- if (bitset(typ, frst_bit + i)) {
- if (i == 0)
- fprintf(file, "%sops", ChkSep(n));
- else {
- gptr = proc_map[i];
- switch (gptr->flag & (F_Proc | F_Builtin | F_Record)) {
- case F_Proc:
- fprintf(file, "%s%s:%s", ChkSep(n), abrv, gptr->name);
- break;
- case F_Builtin:
- fprintf(file, "%sfnc:%s", ChkSep(n), gptr->name);
- break;
- case F_Record:
- fprintf(file, "%sconstr:%s", ChkSep(n), gptr->name);
- break;
- }
- }
- }
- }
- else if (k == rec_typ) {
- /*
- * records - include record name.
- */
- for (i = 0; i < num_bits; ++i)
- if (bitset(typ, frst_bit + i))
- fprintf(file, "%s%s:%s", ChkSep(n), abrv, rec_map[i]->name);
- }
- else if (icontypes[k].support_new | k == coexp_typ) {
- /*
- * A type with sub-types.
- */
- for (i = 0; i < num_bits; ++i)
- if (bitset(typ, frst_bit + i))
- fprintf(file, "%s%s%d", ChkSep(n), abrv, i);
- }
- else {
- /*
- * A type with no subtypes.
- */
- if (bitset(typ, frst_bit))
- fprintf(file, "%s%s", ChkSep(n), abrv);
- }
- }
-
- for (k = 0; k < num_cmpnts; ++k) {
- if (typecompnt[k].var) {
- /*
- * Structure component that is a variable.
- */
- frst_bit = compnt_array[k].frst_bit;
- num_bits = compnt_array[k].num_bits;
- abrv = typecompnt[k].abrv;
- for (i = 0; i < num_bits; ++i)
- if (bitset(typ, frst_bit + i))
- fprintf(file, "%s%s%d", ChkSep(n), abrv, i);
- }
- }
-
-
- /*
- * record fields
- */
- for (i = 0; i < n_fld; ++i)
- if (bitset(typ, frst_fld + i))
- fprintf(file, "%sfld%d", ChkSep(n), i);
-
- /*
- * global variables
- */
- for (i = 0; i < n_nmgbl; ++i)
- if (bitset(typ, frst_gbl + i)) {
- name = NULL;
- for (j = 0; j < GHSize && name == NULL; j++)
- for (gptr = ghash[j]; gptr != NULL && name == NULL;
- gptr = gptr->blink)
- if (gptr->index == i)
- name = gptr->name;
- for (lptr = cur_proc->statics; lptr != NULL && name == NULL;
- lptr = lptr->next)
- if (lptr->val.index == i)
- name = lptr->name;
- /*
- * Static variables may be returned and dereferenced in a procedure
- * they don't belong to.
- */
- if (name == NULL)
- name = "?static?";
- fprintf(file, "%svar:%s", ChkSep(n), name);
- }
-
- /*
- * local variables
- */
- for (i = 0; i < n_loc; ++i)
- if (bitset(typ, frst_loc + i)) {
- name = NULL;
- for (lptr = cur_proc->args; lptr != NULL && name == NULL;
- lptr = lptr->next)
- if (lptr->val.index == i)
- name = lptr->name;
- for (lptr = cur_proc->dynams; lptr != NULL && name == NULL;
- lptr = lptr->next)
- if (lptr->val.index == i)
- name = lptr->name;
- /*
- * Local variables types may appear in the wrong procedure due to
- * substring trapped variables and the inference of impossible
- * execution paths. Make sure we don't end up with a NULL name.
- */
- if (name == NULL)
- name = "?";
- fprintf(file, "%svar:%s", ChkSep(n), name);
- }
-
- fprintf(trcfile, "}");
- }
-
-/*
- * prt_d_typ - dereference a type and print it.
- */
-static void prt_d_typ(file, typ)
-FILE *file;
-#ifdef OptimizeType
-struct typinfo *typ;
-#else /* OptimizeType */
-unsigned int *typ;
-#endif /* OptimizeType */
-{
- struct type *wktyp;
-
- wktyp = get_wktyp();
- typ_deref(typ, wktyp->bits, 0);
- prt_typ(file, wktyp->bits);
- free_wktyp(wktyp);
-}
-#endif /* TypTrc */
-
-/*
- * get_argtyp - get an array of pointers to type bit vectors for use
- * in constructing an argument list. The array is large enough for the
- * largest argument list.
- */
-static struct argtyps *get_argtyp()
- {
- struct argtyps *argtyps;
-
- if ((argtyps = argtyp_pool) == NULL)
-#ifdef OptimizeType
- argtyps = (struct argtyps *)alloc((unsigned int)(sizeof(struct argtyps) +
- ((max_prm - 1) * sizeof(struct typinfo *))));
-#else /* OptimizeType */
- argtyps = (struct argtyps *)alloc((unsigned int)(sizeof(struct argtyps) +
- ((max_prm - 1) * sizeof(unsigned int *))));
-#endif /* OptimizeType */
- else
- argtyp_pool = argtyp_pool->next;
- return argtyps;
- }
-
-/*
- * free_argtyp - free array of pointers to type bitvectors.
- */
-static void free_argtyp(argtyps)
-struct argtyps *argtyps;
- {
- argtyps->next = argtyp_pool;
- argtyp_pool = argtyps;
- }
-
-/*
- * varsubtyp - examine a type and determine what kinds of variable
- * subtypes it has and whether it has any non-variable subtypes.
- * If the type consists of a single named variable, return its symbol
- * table entry through the parameter "singl".
- */
-int varsubtyp(typ, singl)
-#ifdef OptimizeType
-struct typinfo *typ;
-#else /* OptimizeType */
-unsigned int *typ;
-#endif /* OptimizeType */
-struct lentry **singl;
- {
- struct store *stv_stor;
- int subtypes;
- int n_types;
- int var_indx;
- int frst_bit;
- int num_bits;
- int i, j;
-
-
- subtypes = 0;
- n_types = 0;
- var_indx = -1;
-
- /*
- * check for non-variables.
- */
- for (i = 0; i < n_icntyp; ++i)
- if (bitset(typ, i)) {
- subtypes |= HasVal;
- ++n_types;
- }
-
- /*
- * Predefined variable types.
- */
- for (i = 0; i < num_typs; ++i) {
- if (icontypes[i].deref != DrfNone) {
- frst_bit = type_array[i].frst_bit;
- num_bits = type_array[i].num_bits;
- for (j = 0; j < num_bits; ++j) {
- if (bitset(typ, frst_bit + j)) {
- if (i == stv_typ) {
- /*
- * We have found substring trapped variable j, see whether it
- * references locals or globals.
- */
- if (do_typinfer) {
- stv_stor = compnt_array[str_var].store;
- subtypes |= varsubtyp(stv_stor->types[j], NULL);
- }
- else
- subtypes |= HasLcl | HasPrm | HasGlb;
- }
- else
- subtypes |= HasGlb;
- ++n_types;
- }
- }
- }
- }
-
- /*
- * Aggregate compontents that are variables.
- */
- for (i = 0; i < num_cmpnts; ++i) {
- if (typecompnt[i].var) {
- frst_bit = compnt_array[i].frst_bit;
- num_bits = compnt_array[i].num_bits;
- for (j = 0; j < num_bits; ++j) {
- if (bitset(typ, frst_bit + j)) {
- subtypes |= HasGlb;
- ++n_types;
- }
- }
- }
- }
-
- /*
- * record fields
- */
- for (i = 0; i < n_fld; ++i)
- if (bitset(typ, frst_fld + i)) {
- subtypes |= HasGlb;
- ++n_types;
- }
-
- /*
- * global variables, including statics
- */
- for (i = 0; i < n_gbl; ++i) {
- if (bitset(typ, frst_gbl + i)) {
- subtypes |= HasGlb;
- var_indx = i;
- ++n_types;
- }
- }
-
- /*
- * local variables
- */
- for (i = 0; i < n_loc; ++i) {
- if (bitset(typ, frst_loc + i)) {
- if (i < Abs(cur_proc->nargs))
- subtypes |= HasPrm;
- else
- subtypes |= HasLcl;
- var_indx = n_gbl + i;
- ++n_types;
- }
- }
-
- if (singl != NULL) {
- /*
- * See if the type consists of a single named variable.
- */
- if (n_types == 1 && var_indx != -1)
- *singl = cur_proc->vartypmap[var_indx];
- else
- *singl = NULL;
- }
-
- return subtypes;
- }
-
-/*
- * mark_recs - go through the list of parent records for this field
- * and mark those that are in the type. Also gather information
- * to help generate better code.
- */
-void mark_recs(fp, typ, num_offsets, offset, bad_recs)
-struct fentry *fp;
-#ifdef OptimizeType
-struct typinfo *typ;
-#else /* OptimizeType */
-unsigned int *typ;
-#endif /* OptimizeType */
-int *num_offsets;
-int *offset;
-int *bad_recs;
- {
- struct par_rec *rp;
- struct type *wktyp;
- int frst_rec;
-
- *num_offsets = 0;
- *offset = -1;
- *bad_recs = 0;
-
- wktyp = get_wktyp();
- CpyTyp(n_icntyp, typ, wktyp->bits);
-
- /*
- * For each record containing this field, see if the record is
- * in the type.
- */
- frst_rec = type_array[rec_typ].frst_bit;
- for (rp = fp->rlist; rp != NULL; rp = rp->next) {
- if (bitset(wktyp->bits, frst_rec + rp->rec->rec_num)) {
- /*
- * This record is in the type.
- */
- rp->mark = 1;
- clr_typ(wktyp->bits, frst_rec + rp->rec->rec_num);
- if (*offset != rp->offset) {
- *offset = rp->offset;
- *num_offsets += 1;
- }
- }
- }
-
- /*
- * Are there any records that do not contain this field?
- */
- *bad_recs = has_type(wktyp->bits, rec_typ, 0);
- free_wktyp(wktyp);
- }
-
-/*
- * past_prms - return true if execution might continue past the parameter
- * evaluation. If a parameter has no type, this will not happen.
- */
-int past_prms(n)
-nodeptr n;
- {
- struct implement *impl;
- struct symtyps *symtyps;
- int nparms;
- int nargs;
- int flag;
- int i, j;
-
- nargs = Val0(n);
- impl = Impl1(n);
- symtyps = n->symtyps;
- nparms = impl->nargs;
-
- if (symtyps == NULL)
- return 1;
-
- j = 0;
- for (i = 0; i < nparms; ++i) {
- flag = impl->arg_flgs[i];
- if (flag & VarPrm && i >= nargs)
- break; /* no parameters for variable part of arg list */
- if (flag & RtParm) {
- if (is_empty(symtyps->types[j]))
- return 0;
- ++j;
- }
- if (flag & DrfPrm) {
- if (is_empty(symtyps->types[j]))
- return 0;
- ++j;
- }
- }
- return 1;
- }