cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
54db6c1999-03-27Henrik Grubbström (Grubba) /**/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
4b81751999-11-19Henrik Grubbström (Grubba) RCSID("$Id: las.c,v 1.117 1999/11/19 21:08:05 grubba Exp $");
419ede1996-11-13Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "language.h" #include "interpret.h" #include "las.h" #include "array.h" #include "object.h" #include "stralloc.h" #include "dynamic_buffer.h" #include "lex.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "pike_types.h" #include "constants.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "multiset.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "error.h" #include "docode.h" #include "main.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
6891181996-08-06Fredrik Hübinette (Hubbe) #include "operators.h"
a29e021996-10-15Fredrik Hübinette (Hubbe) #include "callback.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "peep.h"
5d2bb21998-01-26Henrik Grubbström (Grubba) #include "builtin_functions.h"
63c6751998-04-09Fredrik Hübinette (Hubbe) #include "cyclic.h"
011ad31999-10-22Fredrik Hübinette (Hubbe) #include "block_alloc.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  #define LASDEBUG int lasdebug=0; static node *eval(node *); static void optimize(node *n);
969a291999-11-17Henrik Grubbström (Grubba) static node *localopt(node *n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  node *init_node = 0; int num_parse_error;
c3c7031996-12-04Fredrik Hübinette (Hubbe) int cumulative_parse_error=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) extern char *get_type_name(int);
e82b301997-01-29Fredrik Hübinette (Hubbe) #define MAX_GLOBAL 2048
5267b71995-08-09Fredrik Hübinette (Hubbe) 
55a20a1999-11-17Henrik Grubbström (Grubba) int car_is_node(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(n->token) {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_EXTERNAL:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: case F_LOCAL: return 0; default:
046afe1999-11-11Henrik Grubbström (Grubba)  return !!_CAR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
55a20a1999-11-17Henrik Grubbström (Grubba) int cdr_is_node(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(n->token) {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_EXTERNAL:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: case F_LOCAL: case F_CAST: return 0; default:
046afe1999-11-11Henrik Grubbström (Grubba)  return !!_CDR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3c0c281998-01-26Fredrik Hübinette (Hubbe) void check_tree(node *n, int depth) { if(!d_flag) return; if(!n) return; if(n->token==USHRT_MAX) fatal("Free node in tree.\n");
d599c91999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES
046afe1999-11-11Henrik Grubbström (Grubba)  check_node_hash(n);
d599c91999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
046afe1999-11-11Henrik Grubbström (Grubba) 
32e2af1998-11-17Fredrik Hübinette (Hubbe)  if(d_flag<2) return;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  if(!(depth & 1023)) { node *q; for(q=n->parent;q;q=q->parent) if(q->parent==n) fatal("Cyclic node structure found.\n"); } depth++; if(car_is_node(n)) { if(CAR(n)->parent != n) fatal("Parent is wrong.\n"); check_tree(CAR(n),depth); } if(cdr_is_node(n)) { if(CDR(n)->parent != n) fatal("Parent is wrong.\n"); check_tree(CDR(n),depth); } } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) INT32 count_args(node *n) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  int a,b;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n) return 0; switch(n->token) {
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_VAL_LVAL: case F_ARG_LIST:
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  a=count_args(CAR(n)); if(a==-1) return -1; b=count_args(CDR(n)); if(b==-1) return -1; return a+b;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST: if(n->type == void_type_string) return 0; else return count_args(CAR(n)); case F_CASE: case F_FOR: case F_DO: case F_INC_LOOP: case F_DEC_LOOP: case F_DEC_NEQ_LOOP: case F_INC_NEQ_LOOP: case F_BREAK: case F_RETURN: case F_CONTINUE: case F_FOREACH: return 0; case '?': { int tmp1,tmp2;
e260681996-04-11Fredrik Hübinette (Hubbe)  tmp1=count_args(CADR(n)); tmp2=count_args(CDDR(n));
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  if(tmp1==-1 || tmp2==-2) return -1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(tmp1 < tmp2) return tmp1; return tmp2; }
b95bef1996-03-29Fredrik Hübinette (Hubbe)  case F_PUSH_ARRAY: return -1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  default: if(n->type == void_type_string) return 0; return 1; } }
61e9a01998-01-25Fredrik Hübinette (Hubbe) struct pike_string *find_return_type(node *n) { struct pike_string *a,*b;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(!n) return 0; if(!(n->tree_info & OPT_RETURN)) return 0; if(car_is_node(n)) a=find_return_type(CAR(n)); else a=0; if(cdr_is_node(n)) b=find_return_type(CDR(n)); else b=0; if(a) { if(b && a!=b) return mixed_type_string; return a; } return b; }
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  #define NODES 256
011ad31999-10-22Fredrik Hübinette (Hubbe) #undef BLOCK_ALLOC_NEXT #define BLOCK_ALLOC_NEXT u.node.a BLOCK_ALLOC(node_s, NODES);
a8ef6e1996-12-03Fredrik Hübinette (Hubbe) 
011ad31999-10-22Fredrik Hübinette (Hubbe) #undef BLOCK_ALLOC_NEXT #define BLOCK_ALLOC_NEXT next
a8ef6e1996-12-03Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES struct node_hash_table node_hash; static unsigned INT32 hash_node(node *n) { return hashmem((unsigned char *)&(n->token), sizeof(node) - OFFSETOF(node_s, token), sizeof(node)); } static void add_node(node *n) { unsigned INT32 hval = n->hash % node_hash.size; n->next = node_hash.table[hval]; node_hash.table[hval] = n; } static void sub_node(node *n) { node *prior; if (!node_hash.size) { return; } prior = node_hash.table[n->hash % node_hash.size]; if (!prior) { return; } if (prior == n) { node_hash.table[n->hash % node_hash.size] = n->next; } else { while(prior && (prior->next != n)) { prior = prior->next; } if (!prior) { return; } prior->next = n->next; } } static node *freeze_node(node *orig) { unsigned INT32 hash = hash_node(orig);
969a291999-11-17Henrik Grubbström (Grubba)  node *n;
046afe1999-11-11Henrik Grubbström (Grubba) 
a836c01999-11-12Henrik Grubbström (Grubba)  /* free_node() wants a correct hash */ orig->hash = hash; if (orig->node_info & OPT_NOT_SHARED) { /* No need to have this node in the hash-table. */ /* add_node(orig); */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  return check_node_hash(dmalloc_touch(node *, orig));
a836c01999-11-12Henrik Grubbström (Grubba)  }
969a291999-11-17Henrik Grubbström (Grubba)  /* Mark this node as a possible duplicate */ orig->node_info |= OPT_DEFROSTED; /* Make sure we don't find ourselves */ sub_node(orig); n = node_hash.table[hash % node_hash.size];
046afe1999-11-11Henrik Grubbström (Grubba)  while (n) { if ((n->hash == hash) && !MEMCMP(&(n->token), &(orig->token), sizeof(node) - OFFSETOF(node_s, token))) {
a836c01999-11-12Henrik Grubbström (Grubba)  free_node(dmalloc_touch(node *, orig));
046afe1999-11-11Henrik Grubbström (Grubba)  n->refs++;
bf4f7d1999-11-12Henrik Grubbström (Grubba)  return check_node_hash(dmalloc_touch(node *, n));
046afe1999-11-11Henrik Grubbström (Grubba)  } n = n->next; }
969a291999-11-17Henrik Grubbström (Grubba)  orig->node_info &= ~OPT_DEFROSTED;
a836c01999-11-12Henrik Grubbström (Grubba)  add_node(dmalloc_touch(node *, orig));
bf4f7d1999-11-12Henrik Grubbström (Grubba)  return check_node_hash(orig);
046afe1999-11-11Henrik Grubbström (Grubba) } #else /* !SHARED_NODES */ #define freeze_node(X) (X) #endif /* SHARED_NODES */
a44a2c1998-05-01Henrik Grubbström (Grubba) void free_all_nodes(void)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe) {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!compiler_frame)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  { node *tmp;
011ad31999-10-22Fredrik Hübinette (Hubbe)  struct node_s_block *tmp2;
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  int e=0;
c3c7031996-12-04Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifndef PIKE_DEBUG
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(cumulative_parse_error)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  {
3c0c281998-01-26Fredrik Hübinette (Hubbe) #endif
c3c7031996-12-04Fredrik Hübinette (Hubbe) 
011ad31999-10-22Fredrik Hübinette (Hubbe)  for(tmp2=node_s_blocks;tmp2;tmp2=tmp2->next) e+=NODES;
046afe1999-11-11Henrik Grubbström (Grubba)  for(tmp=free_node_ss;tmp;tmp=_CAR(tmp)) e--;
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(e)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  {
c3c7031996-12-04Fredrik Hübinette (Hubbe)  int e2=e;
011ad31999-10-22Fredrik Hübinette (Hubbe)  for(tmp2=node_s_blocks;tmp2;tmp2=tmp2->next)
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  {
c3c7031996-12-04Fredrik Hübinette (Hubbe)  for(e=0;e<NODES;e++) {
046afe1999-11-11Henrik Grubbström (Grubba)  for(tmp=free_node_ss;tmp;tmp=_CAR(tmp))
011ad31999-10-22Fredrik Hübinette (Hubbe)  if(tmp==tmp2->x+e)
c3c7031996-12-04Fredrik Hübinette (Hubbe)  break; if(!tmp) {
011ad31999-10-22Fredrik Hübinette (Hubbe)  tmp=tmp2->x+e;
046afe1999-11-11Henrik Grubbström (Grubba) #if defined(PIKE_DEBUG)
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(!cumulative_parse_error) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr,"Free node at %p, (%s:%d) (token=%d).\n", tmp, tmp->current_file->str, tmp->line_number, tmp->token);
011ad31999-10-22Fredrik Hübinette (Hubbe)  debug_malloc_dump_references(tmp);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  if(tmp->token==F_CONSTANT) print_tree(tmp);
c3c7031996-12-04Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba)  /* else */
c3c7031996-12-04Fredrik Hübinette (Hubbe) #endif { /* Free the node and be happy */ /* Make sure we don't free any nodes twice */
046afe1999-11-11Henrik Grubbström (Grubba)  if(car_is_node(tmp)) _CAR(tmp)=0; if(cdr_is_node(tmp)) _CDR(tmp)=0; #ifdef SHARED_NODES tmp->hash = hash_node(tmp);
cf4df01999-11-12Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 3) { fprintf(stderr, "Freeing node that had %d refs.\n", tmp->refs); } #endif /* PIKE_DEBUG */
046afe1999-11-11Henrik Grubbström (Grubba)  /* Force the node to be freed. */ tmp->refs = 1; #endif /* SHARED_NODES */
3c0c281998-01-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(tmp->type);
c3c7031996-12-04Fredrik Hübinette (Hubbe)  free_node(tmp); } } }
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba) #if defined(PIKE_DEBUG)
c3c7031996-12-04Fredrik Hübinette (Hubbe)  if(!cumulative_parse_error) fatal("Failed to free %d nodes when compiling!\n",e2); #endif
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifndef PIKE_DEBUG
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  }
3c0c281998-01-26Fredrik Hübinette (Hubbe) #endif
011ad31999-10-22Fredrik Hübinette (Hubbe)  free_all_node_s_blocks();
c3c7031996-12-04Fredrik Hübinette (Hubbe)  cumulative_parse_error=0;
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES MEMSET(node_hash.table, 0, sizeof(node *) * node_hash.size); #endif /* SHARED_NODES */
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  } }
a836c01999-11-12Henrik Grubbström (Grubba) void debug_free_node(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { if(!n) return;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1b5eb41998-11-17Fredrik Hübinette (Hubbe)  if(l_flag>9) print_tree(n);
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES { unsigned INT32 hash; if ((hash = hash_node(n)) != n->hash) { fprintf(stderr, "Hash-value is bad 0x%08x != 0x%08x\n", hash, n->hash); print_tree(n); fatal("token:%d, car:%p cdr:%p file:%s line:%d\n",
a836c01999-11-12Henrik Grubbström (Grubba)  n->token, _CAR(n), _CDR(n), n->current_file->str, n->line_number);
046afe1999-11-11Henrik Grubbström (Grubba)  } } #endif /* SHARED_NODES */ #endif /* PIKE_DEBUG */ #ifdef SHARED_NODES
a836c01999-11-12Henrik Grubbström (Grubba)  if (dmalloc_touch(node *, n) && --(n->refs)) {
046afe1999-11-11Henrik Grubbström (Grubba)  return; }
a836c01999-11-12Henrik Grubbström (Grubba)  sub_node(dmalloc_touch(node *, n));
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
1b5eb41998-11-17Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  case USHRT_MAX: fatal("Freeing node again!\n"); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: free_svalue(&(n->u.sval)); break; default: if(car_is_node(n)) free_node(CAR(n)); if(cdr_is_node(n)) free_node(CDR(n)); }
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  n->token=USHRT_MAX; if(n->type) free_string(n->type);
454d541999-09-18Fredrik Hübinette (Hubbe)  if(n->name) free_string(n->name);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3c0c281998-01-26Fredrik Hübinette (Hubbe)  if(n->current_file) free_string(n->current_file); #endif
011ad31999-10-22Fredrik Hübinette (Hubbe)  really_free_node_s(n);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
046afe1999-11-11Henrik Grubbström (Grubba) node *debug_check_node_hash(node *n) { #if defined(PIKE_DEBUG) && defined(SHARED_NODES) if (n && (n->hash != hash_node(n))) {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  fprintf(stderr,"Bad node hash at %p, (%s:%d) (token=%d).\n", n, n->current_file->str, n->line_number, n->token); debug_malloc_dump_references(n); print_tree(n);
046afe1999-11-11Henrik Grubbström (Grubba)  fatal("Bad node hash!\n"); } #endif /* PIKE_DEBUG && SHARED_NODES */ return n; }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* here starts routines to make nodes */
a836c01999-11-12Henrik Grubbström (Grubba) static node *debug_mkemptynode(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
011ad31999-10-22Fredrik Hübinette (Hubbe)  node *res=alloc_node_s();
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES MEMSET(res, 0, sizeof(node)); res->hash = 0; res->refs = 1; #endif /* SHARED_NODES */
a8ef6e1996-12-03Fredrik Hübinette (Hubbe)  res->token=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  res->line_number=lex.current_line;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3c0c281998-01-26Fredrik Hübinette (Hubbe)  copy_shared_string(res->current_file, lex.current_file); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->type=0;
454d541999-09-18Fredrik Hübinette (Hubbe)  res->name=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->node_info=0; res->tree_info=0; res->parent=0; return res; }
a836c01999-11-12Henrik Grubbström (Grubba) #define mkemptynode() dmalloc_touch(node *, debug_mkemptynode()) node *debug_mknode(short token, node *a, node *b)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res;
046afe1999-11-11Henrik Grubbström (Grubba)  #if defined(PIKE_DEBUG) && !defined(SHARED_NODES)
a836c01999-11-12Henrik Grubbström (Grubba)  if(b && a==b)
32e2af1998-11-17Fredrik Hübinette (Hubbe)  fatal("mknode: a and be are the same!\n"); #endif
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(a,0); check_tree(b,0);
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  res = mkemptynode();
a836c01999-11-12Henrik Grubbström (Grubba)  _CAR(res) = dmalloc_touch(node *, a); _CDR(res) = dmalloc_touch(node *, b);
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->node_info = 0; res->tree_info = 0;
046afe1999-11-11Henrik Grubbström (Grubba)  if(a) { a->parent = res; } if(b) { b->parent = res; }
ba6d6c1998-04-19Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba)  res->token = token; res->type = 0; #ifdef SHARED_NODES { node *res2 = freeze_node(res); if (res2 != res) {
a836c01999-11-12Henrik Grubbström (Grubba)  return dmalloc_touch(node *, res2);
046afe1999-11-11Henrik Grubbström (Grubba)  } } #endif /* SHARED_NODES */
ba6d6c1998-04-19Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(token) { case F_CATCH: res->node_info |= OPT_SIDE_EFFECT;
b464611999-11-14Henrik Grubbström (Grubba)  if (a) { res->tree_info |= a->tree_info & ~OPT_BREAK; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_APPLY:
d334771996-04-13Fredrik Hübinette (Hubbe)  if(a && a->token == F_CONSTANT && a->u.sval.type == T_FUNCTION &&
bdb5091996-09-25Fredrik Hübinette (Hubbe)  a->u.sval.subtype == FUNCTION_BUILTIN)
e260681996-04-11Fredrik Hübinette (Hubbe)  { res->node_info |= a->u.sval.u.efun->flags; }else{ res->node_info |= OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND; /* for now */ }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
2a8cd81999-11-18Henrik Grubbström (Grubba)  case F_POP_VALUE: copy_shared_string(res->type, void_type_string); if(a) res->tree_info |= a->tree_info; if(b) res->tree_info |= b->tree_info; break;
6369f61999-03-11Fredrik Hübinette (Hubbe)  case F_MAGIC_SET_INDEX:
b464611999-11-14Henrik Grubbström (Grubba)  res->node_info |= OPT_ASSIGNMENT; /* FALL_THROUGH */ case F_MAGIC_INDEX: res->node_info |= OPT_EXTERNAL_DEPEND;
f9abcf1999-09-16Fredrik Hübinette (Hubbe)  break;
6369f61999-03-11Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_UNDEFINED: res->node_info |= OPT_EXTERNAL_DEPEND | OPT_SIDE_EFFECT; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_RETURN: res->node_info |= OPT_RETURN; break; case F_BREAK: res->node_info |= OPT_BREAK; break; case F_CONTINUE: res->node_info |= OPT_CONTINUE; break; case F_DEFAULT: case F_CASE: res->node_info |= OPT_CASE; break;
b464611999-11-14Henrik Grubbström (Grubba)  case F_INC_LOOP: case F_INC_NEQ_LOOP: case F_DEC_LOOP: case F_DEC_NEQ_LOOP: res->node_info |= OPT_ASSIGNMENT; if (a) { res->tree_info |= a->tree_info; } if (b) { res->tree_info |= (b->tree_info & ~(OPT_BREAK|OPT_CONTINUE)); } break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_SSCANF: if(!b || count_args(b) == 0) break;
b464611999-11-14Henrik Grubbström (Grubba)  res->node_info |= OPT_ASSIGNMENT; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ASSIGN:
b464611999-11-14Henrik Grubbström (Grubba)  case F_MOD_EQ: case F_AND_EQ: case F_MULT_EQ: case F_ADD_EQ: case F_SUB_EQ: case F_DIV_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_XOR_EQ: case F_OR_EQ: res->node_info |= OPT_ASSIGNMENT; if (a) { res->tree_info |= a->tree_info; } if (b) { res->tree_info |= b->tree_info; } break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_INC: case F_DEC: case F_POST_INC: case F_POST_DEC: res->node_info |= OPT_ASSIGNMENT;
b464611999-11-14Henrik Grubbström (Grubba)  if (a) { res->tree_info |= a->tree_info; }
ba6d6c1998-04-19Fredrik Hübinette (Hubbe)  break;
046afe1999-11-11Henrik Grubbström (Grubba)  default: /* We try to optimize most things, but argument lists are hard... */ if(token != F_ARG_LIST && (a || b)) res->node_info |= OPT_TRY_OPTIMIZE;
f9abcf1999-09-16Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba)  if(a) res->tree_info |= a->tree_info; if(b) res->tree_info |= b->tree_info;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
b464611999-11-14Henrik Grubbström (Grubba)  res->tree_info |= res->node_info;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9e52381998-03-01Fredrik Hübinette (Hubbe)  if(d_flag > 3) verify_shared_strings_tables(); #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!num_parse_error && compiler_pass==2)
3c0c281998-01-26Fredrik Hübinette (Hubbe)  { check_tree(res,0);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  optimize(res);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(res,0); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(d_flag > 3) verify_shared_strings_tables(); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkstrnode(struct pike_string *str)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; copy_shared_string(res->type, string_type_string); res->node_info = 0; res->u.sval.type = T_STRING; #ifdef __CHECKER__ res->u.sval.subtype = 0; #endif copy_shared_string(res->u.sval.u.string, str);
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkintnode(int nr)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; res->node_info = 0; res->u.sval.type = T_INT; res->u.sval.subtype = NUMBER_NUMBER; res->u.sval.u.integer = nr;
b660c81999-03-01Fredrik Hübinette (Hubbe)  res->type=get_type_of_svalue( & res->u.sval);
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mknewintnode(int nr)
046afe1999-11-11Henrik Grubbström (Grubba) { node *res = mkemptynode(); res->token = F_CONSTANT;
a836c01999-11-12Henrik Grubbström (Grubba)  res->node_info = OPT_NOT_SHARED;
046afe1999-11-11Henrik Grubbström (Grubba)  res->u.sval.type = T_INT; res->u.sval.subtype = NUMBER_NUMBER; res->u.sval.u.integer = nr; res->type=get_type_of_svalue( & res->u.sval); #ifdef SHARED_NODES res->refs = 1; res->hash = hash_node(res); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkfloatnode(FLOAT_TYPE foo)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; copy_shared_string(res->type, float_type_string); res->u.sval.type = T_FLOAT; #ifdef __CHECKER__ res->u.sval.subtype = 0; #endif res->u.sval.u.float_number = foo;
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkprgnode(struct program *p)
a5787d1999-03-03Fredrik Hübinette (Hubbe) { struct svalue s; s.u.program=p;
046afe1999-11-11Henrik Grubbström (Grubba)  s.type = T_PROGRAM; #ifdef __CHECKER__ s.subtype = 0; #endif
a5787d1999-03-03Fredrik Hübinette (Hubbe)  return mkconstantsvaluenode(&s); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkapplynode(node *func,node *args)
5267b71995-08-09Fredrik Hübinette (Hubbe) { return mknode(F_APPLY, func, args); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkefuncallnode(char *function, node *args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *name;
45e8a81997-01-26Fredrik Hübinette (Hubbe)  node *n;
5267b71995-08-09Fredrik Hübinette (Hubbe)  name = findstring(function);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!name || !(n=find_module_identifier(name)))
5267b71995-08-09Fredrik Hübinette (Hubbe)  { my_yyerror("Internally used efun undefined: %s",function); return mkintnode(0); }
046afe1999-11-11Henrik Grubbström (Grubba)  n = mkapplynode(n, args);
45e8a81997-01-26Fredrik Hübinette (Hubbe)  return n;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkopernode(char *oper_id, node *arg1, node *arg2)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { if(arg1 && arg2) arg1=mknode(F_ARG_LIST,arg1,arg2); return mkefuncallnode(oper_id, arg1); }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mklocalnode(int var, int depth)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
4218011999-01-31Fredrik Hübinette (Hubbe)  struct compiler_frame *f; int e;
5267b71995-08-09Fredrik Hübinette (Hubbe)  node *res = mkemptynode(); res->token = F_LOCAL;
4218011999-01-31Fredrik Hübinette (Hubbe)  f=compiler_frame; for(e=0;e<depth;e++) f=f->previous; copy_shared_string(res->type, f->variable[var].type);
a836c01999-11-12Henrik Grubbström (Grubba)  res->node_info = OPT_NOT_CONST | OPT_NOT_SHARED; res->tree_info = res->node_info;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
046afe1999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
4218011999-01-31Fredrik Hübinette (Hubbe)  res->u.integer.a = var; res->u.integer.b = depth;
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES
a836c01999-11-12Henrik Grubbström (Grubba)  /* FIXME: Not common-subexpression optimized. * Node would need to contain a ref to the current function, * and to the current program. */
046afe1999-11-11Henrik Grubbström (Grubba)  res->hash = hash_node(res); /* return freeze_node(res); */ #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkidentifiernode(int i)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_IDENTIFIER;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  copy_shared_string(res->type, ID_FROM_INT(new_program, i)->type);
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* FIXME */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(new_program, i)->identifier_flags))
3856c31996-11-25Fredrik Hübinette (Hubbe)  { res->node_info = OPT_EXTERNAL_DEPEND; }else{ res->node_info = OPT_NOT_CONST; }
66d51c1997-03-04Fredrik Hübinette (Hubbe)  res->tree_info=res->node_info;
5267b71995-08-09Fredrik Hübinette (Hubbe)  #ifdef __CHECKER__
588aa31999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
046afe1999-11-11Henrik Grubbström (Grubba)  res->u.id.number = i; #ifdef SHARED_NODES res->u.id.prog = new_program; #endif /* SHARED_NODES */ res = freeze_node(res);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(res,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return res; }
bf4f7d1999-11-12Henrik Grubbström (Grubba) node *debug_mktrampolinenode(int i) { node *res = mkemptynode(); res->token = F_TRAMPOLINE; copy_shared_string(res->type, ID_FROM_INT(new_program, i)->type); /* FIXME */ if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(new_program, i)->identifier_flags)) { res->node_info = OPT_EXTERNAL_DEPEND; }else{ res->node_info = OPT_NOT_CONST; } res->tree_info=res->node_info; #ifdef __CHECKER__ _CDR(res) = 0; #endif res->u.id.number = i; #ifdef SHARED_NODES res->u.id.prog = new_program; #endif /* SHARED_NODES */ res = freeze_node(res); check_tree(res,0); return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkexternalnode(int level,
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  int i, struct identifier *id) { node *res = mkemptynode(); res->token = F_EXTERNAL; copy_shared_string(res->type, id->type); /* FIXME */
046afe1999-11-11Henrik Grubbström (Grubba)  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(parent_compilation(level), i)->identifier_flags))
6d22541998-01-28Fredrik Hübinette (Hubbe)  { res->node_info = OPT_EXTERNAL_DEPEND; }else{ res->node_info = OPT_NOT_CONST; }
046afe1999-11-11Henrik Grubbström (Grubba)  res->tree_info = res->node_info;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  #ifdef __CHECKER__
046afe1999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #endif res->u.integer.a = level; res->u.integer.b = i;
1994251999-09-06Fredrik Hübinette (Hubbe)  /* Bzot-i-zot */ new_program->flags |= PROGRAM_USES_PARENT;
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkcastnode(struct pike_string *type,node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res;
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n) return 0;
046afe1999-11-11Henrik Grubbström (Grubba) 
22dd601999-11-18Henrik Grubbström (Grubba)  if (type == void_type_string) return mknode(F_POP_VALUE, n, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(type==n->type) return n;
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  res = mkemptynode(); res->token = F_CAST; copy_shared_string(res->type,type); if(match_types(object_type_string, type) || match_types(object_type_string, type)) res->node_info |= OPT_SIDE_EFFECT;
046afe1999-11-11Henrik Grubbström (Grubba)  _CAR(res) = n; #ifdef SHARED_NODES _CDR(res) = (node *)type; #else /* !SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
046afe1999-11-11Henrik Grubbström (Grubba)  _CDR(res) = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->parent = res;
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
591c0c1997-01-19Fredrik Hübinette (Hubbe) void resolv_constant(node *n) { struct identifier *i;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  struct program *p; INT32 numid;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  if(!n) { push_int(0); }else{ switch(n->token) { case F_CONSTANT: push_svalue(& n->u.sval);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return;
591c0c1997-01-19Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  case F_EXTERNAL: p=parent_compilation(n->u.integer.a); if(!p)
591c0c1997-01-19Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  yyerror("Failed to resolv external constant");
591c0c1997-01-19Fredrik Hübinette (Hubbe)  push_int(0);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  numid=n->u.integer.b; break; case F_IDENTIFIER: p=new_program;
046afe1999-11-11Henrik Grubbström (Grubba)  numid=n->u.id.number;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  break; case F_LOCAL:
9250a61998-07-20Henrik Grubbström (Grubba)  /* FIXME: Ought to have the name of the identifier in the message. */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  yyerror("Expected constant, got local variable"); push_int(0); return;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  case F_GLOBAL:
9250a61998-07-20Henrik Grubbström (Grubba)  /* FIXME: Ought to have the name of the identifier in the message. */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  yyerror("Expected constant, got global variable"); push_int(0); return;
b69ede1998-04-09Fredrik Hübinette (Hubbe)  case F_UNDEFINED:
9250a61998-07-20Henrik Grubbström (Grubba)  if(compiler_pass==2) { /* FIXME: Ought to have the name of the identifier in the message. */
b69ede1998-04-09Fredrik Hübinette (Hubbe)  yyerror("Expected constant, got undefined identifier");
9250a61998-07-20Henrik Grubbström (Grubba)  }
b69ede1998-04-09Fredrik Hübinette (Hubbe)  push_int(0); return;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  default:
c5c2ff1999-07-06Fredrik Hübinette (Hubbe)  { char fnord[1000]; if(is_const(n)) { int args=eval_low(n); if(args==1) return; if(args!=-1) { if(!args) { yyerror("Expected constant, got void expression"); }else{ yyerror("Possible internal error!!!"); pop_n_elems(args-1); return; } } } sprintf(fnord,"Expected constant, got something else (%d)",n->token); yyerror(fnord);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  push_int(0); return; }
c5c2ff1999-07-06Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  i=ID_FROM_INT(p, numid);
086acc1999-09-11Fredrik Hübinette (Hubbe)  /* Warning: * This code doesn't produce function pointers for class constants, * which can be harmful... * /Hubbe */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(IDENTIFIER_IS_CONSTANT(i->identifier_flags)) {
4a7c861999-09-19Henrik Grubbström (Grubba)  push_svalue(&PROG_FROM_INT(p, numid)->constants[i->func.offset].sval);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }else{
9250a61998-07-20Henrik Grubbström (Grubba)  my_yyerror("Identifier '%s' is not a constant", i->name->str);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  push_int(0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  } } }
086acc1999-09-11Fredrik Hübinette (Hubbe) /* Leaves a function or object on the stack */ void resolv_class(node *n)
61e9a01998-01-25Fredrik Hübinette (Hubbe) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  resolv_constant(n); switch(sp[-1].type) { case T_OBJECT: if(!sp[-1].u.object->prog) { pop_stack(); push_int(0); }else{ f_object_program(1); } break;
086acc1999-09-11Fredrik Hübinette (Hubbe)  default:
a786431999-11-18Martin Stjernholm  if (compiler_pass!=1) yyerror("Illegal program identifier");
086acc1999-09-11Fredrik Hübinette (Hubbe)  pop_stack(); push_int(0); case T_FUNCTION: case T_PROGRAM: break; } } /* This one always leaves a program if possible */ void resolv_program(node *n) { check_tree(n,0); resolv_class(n); switch(sp[-1].type) {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  case T_FUNCTION: if(program_from_function(sp-1)) break; default:
a786431999-11-18Martin Stjernholm  if (compiler_pass!=1) yyerror("Illegal program identifier");
61e9a01998-01-25Fredrik Hübinette (Hubbe)  pop_stack(); push_int(0); case T_PROGRAM: break; } }
fae37d1998-08-30Henrik Grubbström (Grubba) node *index_node(node *n, char *node_name, struct pike_string *id)
591c0c1997-01-19Fredrik Hübinette (Hubbe) { node *ret; JMP_BUF tmp;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  if(SETJMP(tmp)) { ONERROR tmp; SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!"); assign_svalue_no_free(sp++, & throw_value); APPLY_MASTER("handle_error", 1); pop_stack(); UNSET_ONERROR(tmp);
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) { my_yyerror("Couldn't index module '%s'.", node_name); } else { yyerror("Couldn't index module."); }
05533f1997-02-06Fredrik Hübinette (Hubbe)  push_int(0);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }else{ resolv_constant(n);
1470d81997-02-27Fredrik Hübinette (Hubbe)  switch(sp[-1].type)
d6aef21997-02-27Fredrik Hübinette (Hubbe)  {
1470d81997-02-27Fredrik Hübinette (Hubbe)  case T_INT:
fae37d1998-08-30Henrik Grubbström (Grubba)  if(!num_parse_error) { if (node_name) { my_yyerror("Failed to index module '%s' (module doesn't exist?)", node_name); } else { yyerror("Failed to index module (module doesn't exist?)"); } }
1470d81997-02-27Fredrik Hübinette (Hubbe)  break; case T_FLOAT: case T_STRING: case T_ARRAY:
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) { my_yyerror("Failed to index module '%s' (Not a module?)", node_name); } else { yyerror("Failed to index module (Not a module?)"); }
e319bb1997-02-28Fredrik Hübinette (Hubbe)  pop_stack(); push_int(0);
1470d81997-02-27Fredrik Hübinette (Hubbe)  break; default:
63c6751998-04-09Fredrik Hübinette (Hubbe)  { DECLARE_CYCLIC(); if(BEGIN_CYCLIC(sp[-1].u.refs, id))
7485201997-02-27Fredrik Hübinette (Hubbe)  {
63c6751998-04-09Fredrik Hübinette (Hubbe)  my_yyerror("Recursive module dependency in '%s'.",id->str); pop_stack(); push_int(0); }else{ SET_CYCLIC_RET(1); ref_push_string(id);
a70ee01999-05-01Henrik Grubbström (Grubba)  { struct svalue *save_sp = sp-2; JMP_BUF recovery; if (SETJMP(recovery)) { /* f_index() threw an error! * * FIXME: Report the error thrown. */ if (sp > save_sp) { pop_n_elems(sp - save_sp); } else if (sp != save_sp) { fatal("f_index() munged stack!\n"); } push_int(0); sp[-1].subtype = NUMBER_UNDEFINED; } else { f_index(2); }
cc20e31999-05-01Henrik Grubbström (Grubba)  UNSETJMP(recovery);
a70ee01999-05-01Henrik Grubbström (Grubba)  }
63c6751998-04-09Fredrik Hübinette (Hubbe)  if(sp[-1].type == T_INT && !sp[-1].u.integer && sp[-1].subtype==NUMBER_UNDEFINED) {
fae37d1998-08-30Henrik Grubbström (Grubba)  if (node_name) { my_yyerror("Index '%s' not present in module '%s'.", id->str, node_name); } else { my_yyerror("Index '%s' not present in module.", id->str); }
63c6751998-04-09Fredrik Hübinette (Hubbe)  } END_CYCLIC();
7485201997-02-27Fredrik Hübinette (Hubbe)  }
d6aef21997-02-27Fredrik Hübinette (Hubbe)  }
63c6751998-04-09Fredrik Hübinette (Hubbe)  }
591c0c1997-01-19Fredrik Hübinette (Hubbe)  } UNSETJMP(tmp); ret=mkconstantsvaluenode(sp-1); pop_stack(); return ret; }
5267b71995-08-09Fredrik Hübinette (Hubbe) int node_is_eq(node *a,node *b) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(a,0); check_tree(b,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(a == b) return 1; if(!a || !b) return 0; if(a->token != b->token) return 0; switch(a->token) { case F_LOCAL:
7d7d7e1999-01-31Fredrik Hübinette (Hubbe)  return a->u.integer.a == b->u.integer.a && a->u.integer.b == b->u.integer.b;
4218011999-01-31Fredrik Hübinette (Hubbe) 
afa3651996-02-10Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE: /* FIXME, the context has to be the same! */
046afe1999-11-11Henrik Grubbström (Grubba)  return a->u.id.number == b->u.id.number;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST: return a->type == b->type && node_is_eq(CAR(a), CAR(b)); case F_CONSTANT: return is_equal(&(a->u.sval), &(b->u.sval)); default: if( a->type != b->type ) return 0; if(car_is_node(a) && !node_is_eq(CAR(a), CAR(b))) return 0; if(cdr_is_node(a) && !node_is_eq(CDR(a), CDR(b))) return 0; return 1; } }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkconstantsvaluenode(struct svalue *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node *res = mkemptynode(); res->token = F_CONSTANT; assign_svalue_no_free(& res->u.sval, s);
046afe1999-11-11Henrik Grubbström (Grubba)  if(s->type == T_OBJECT || (s->type==T_FUNCTION && s->subtype!=FUNCTION_BUILTIN))
e82b301997-01-29Fredrik Hübinette (Hubbe)  {
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->node_info|=OPT_EXTERNAL_DEPEND;
e82b301997-01-29Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  res->type = get_type_of_svalue(s);
046afe1999-11-11Henrik Grubbström (Grubba)  return freeze_node(res);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mkliteralsvaluenode(struct svalue *s)
5683de1995-11-06Fredrik Hübinette (Hubbe) { node *res = mkconstantsvaluenode(s);
046afe1999-11-11Henrik Grubbström (Grubba)  /* FIXME: The following affects other instances of this node, * but probably not too much. */
5683de1995-11-06Fredrik Hübinette (Hubbe)  if(s->type!=T_STRING && s->type!=T_INT && s->type!=T_FLOAT) res->node_info|=OPT_EXTERNAL_DEPEND; return res; }
a836c01999-11-12Henrik Grubbström (Grubba) node *debug_mksvaluenode(struct svalue *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(s->type) { case T_ARRAY: return make_node_from_array(s->u.array);
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET: return make_node_from_multiset(s->u.multiset);
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_MAPPING: return make_node_from_mapping(s->u.mapping); case T_OBJECT:
6d22541998-01-28Fredrik Hübinette (Hubbe)  if(s->u.object == fake_object)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { return mkefuncallnode("this_object", 0);
6d22541998-01-28Fredrik Hübinette (Hubbe)  } if(s->u.object->next == s->u.object) { int x=0; struct object *o; node *n=mkefuncallnode("this_object", 0); for(o=fake_object;o!=s->u.object;o=o->parent) { n=mkefuncallnode("function_object", mkefuncallnode("object_program",n)); } return n;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } break; case T_FUNCTION: {
bdb5091996-09-25Fredrik Hübinette (Hubbe)  if(s->subtype != FUNCTION_BUILTIN)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
6d22541998-01-28Fredrik Hübinette (Hubbe)  if(s->u.object == fake_object)
5267b71995-08-09Fredrik Hübinette (Hubbe)  return mkidentifiernode(s->subtype);
6d22541998-01-28Fredrik Hübinette (Hubbe)  if(s->u.object->next == s->u.object) { int x=0; struct object *o; for(o=fake_object->parent;o!=s->u.object;o=o->parent) x++; return mkexternalnode(x, s->subtype, ID_FROM_INT(o->prog, s->subtype)); }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* yyerror("Non-constant function pointer! (should not happen!)"); */ } } } return mkconstantsvaluenode(s); } /* these routines operates on parsetrees and are mostly used by the * optimizer */
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef DEAD_CODE
5267b71995-08-09Fredrik Hübinette (Hubbe) node *copy_node(node *n) { node *b;
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n) return n; switch(n->token) { case F_LOCAL:
06983f1996-09-22Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
046afe1999-11-11Henrik Grubbström (Grubba)  b=mknewintnode(0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  *b=*n; copy_shared_string(b->type, n->type); return b;
046afe1999-11-11Henrik Grubbström (Grubba)  default: #ifdef SHARED_NODES n->refs++; return n; #else /* !SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST: b=mkcastnode(n->type,copy_node(CAR(n))); break; case F_CONSTANT: b=mksvaluenode(&(n->u.sval)); break; default: switch((car_is_node(n) << 1) | cdr_is_node(n)) { default: fatal("fooo?\n"); case 3: b=mknode(n->token, copy_node(CAR(n)), copy_node(CDR(n))); break; case 2: b=mknode(n->token, copy_node(CAR(n)), CDR(n)); break; case 1: b=mknode(n->token, CAR(n), copy_node(CDR(n))); break; case 0: b=mknode(n->token, CAR(n), CDR(n)); } if(n->type) copy_shared_string(b->type, n->type); else b->type=0;
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
43fc171999-09-19Fredrik Hübinette (Hubbe)  if(n->name) { if(b->name) free_string(b->name); add_ref(b->name=n->name); }
48bd9c1999-09-22Henrik Grubbström (Grubba)  /* FIXME: Should b->name be kept if n->name is NULL? * /grubba 1999-09-22 */
5267b71995-08-09Fredrik Hübinette (Hubbe)  b->line_number = n->line_number; b->node_info = n->node_info; b->tree_info = n->tree_info; return b; }
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* DEAD_CODE */
5267b71995-08-09Fredrik Hübinette (Hubbe)  int is_const(node *n) {
05533f1997-02-06Fredrik Hübinette (Hubbe)  if(!n) return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return !(n->tree_info & (OPT_SIDE_EFFECT | OPT_NOT_CONST | OPT_ASSIGNMENT | OPT_CASE | OPT_CONTINUE | OPT_BREAK | OPT_RETURN )); } int node_is_tossable(node *n) { return !(n->tree_info & (OPT_SIDE_EFFECT | OPT_ASSIGNMENT | OPT_CASE | OPT_CONTINUE | OPT_BREAK | OPT_RETURN )); } /* this one supposes that the value is optimized */ int node_is_true(node *n) { if(!n) return 0; switch(n->token) { case F_CONSTANT: return !IS_ZERO(& n->u.sval); default: return 0; } } /* this one supposes that the value is optimized */ int node_is_false(node *n) { if(!n) return 0; switch(n->token) { case F_CONSTANT: return IS_ZERO(& n->u.sval); default: return 0; } }
cc5e511998-06-05Fredrik Hübinette (Hubbe) int node_may_overload(node *n, int lfun) { if(!n) return 0; if(!n->type) return 1; return type_may_overload(n->type->str, lfun); }
6930181996-02-25Fredrik Hübinette (Hubbe) node **last_cmd(node **a)
5267b71995-08-09Fredrik Hübinette (Hubbe) { node **n; if(!a || !*a) return (node **)NULL;
2a8cd81999-11-18Henrik Grubbström (Grubba)  if(((*a)->token == F_CAST) || ((*a)->token == F_POP_VALUE)) return last_cmd(&_CAR(*a));
920d201999-11-06Henrik Grubbström (Grubba)  if(((*a)->token != F_ARG_LIST) && ((*a)->token != F_COMMA_EXPR)) return a;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CDR(*a)) {
2a8cd81999-11-18Henrik Grubbström (Grubba)  if(CDR(*a)->token != F_CAST && CDR(*a)->token != F_POP_VALUE && CAR(*a)->token != F_ARG_LIST && /* FIXME: typo? */ CAR(*a)->token != F_COMMA_EXPR) /* FIXME: typo? */
046afe1999-11-11Henrik Grubbström (Grubba)  return &_CDR(*a); if((n=last_cmd(&_CDR(*a))))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; } if(CAR(*a)) {
2a8cd81999-11-18Henrik Grubbström (Grubba)  if(CAR(*a)->token != F_CAST && CAR(*a)->token != F_POP_VALUE && CAR(*a)->token != F_ARG_LIST &&
920d201999-11-06Henrik Grubbström (Grubba)  CAR(*a)->token != F_COMMA_EXPR)
046afe1999-11-11Henrik Grubbström (Grubba)  return &_CAR(*a); if((n=last_cmd(&_CAR(*a))))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; } return 0; } static node **low_get_arg(node **a,int *nr) { node **n; if(a[0]->token != F_ARG_LIST) { if(!(*nr)--) return a; else return NULL; } if(CAR(*a))
046afe1999-11-11Henrik Grubbström (Grubba)  if((n=low_get_arg(&_CAR(*a),nr)))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; if(CDR(*a))
046afe1999-11-11Henrik Grubbström (Grubba)  if((n=low_get_arg(&_CDR(*a),nr)))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return n; return 0; }
6930181996-02-25Fredrik Hübinette (Hubbe) node **my_get_arg(node **a,int n) { return low_get_arg(a,&n); }
cc5e511998-06-05Fredrik Hübinette (Hubbe)  node **is_call_to(node *n, c_fun f) { switch(n->token) { case F_APPLY: if(CAR(n) && CAR(n)->token == F_CONSTANT && CAR(n)->u.sval.type == T_FUNCTION && CAR(n)->u.sval.subtype == FUNCTION_BUILTIN && CAR(n)->u.sval.u.efun->function == f)
046afe1999-11-11Henrik Grubbström (Grubba)  return &_CDR(n);
cc5e511998-06-05Fredrik Hübinette (Hubbe)  } return 0; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  static void low_print_tree(node *foo,int needlval) { if(!foo) return;
32e2af1998-11-17Fredrik Hübinette (Hubbe)  if(l_flag>9)
5219721998-11-06Fredrik Hübinette (Hubbe)  {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "/*%x*/",foo->tree_info);
5219721998-11-06Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(foo->token) {
046afe1999-11-11Henrik Grubbström (Grubba)  case USHRT_MAX: fprintf(stderr, "FREED_NODE"); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_LOCAL:
046afe1999-11-11Henrik Grubbström (Grubba)  if(needlval) fputc('&', stderr);
4218011999-01-31Fredrik Hübinette (Hubbe)  if(foo->u.integer.b) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "$<%ld>%ld",(long)foo->u.integer.b,(long)foo->u.integer.a);
4218011999-01-31Fredrik Hübinette (Hubbe)  }else{
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "$%ld",(long)foo->u.integer.a);
4218011999-01-31Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case '?':
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "("); low_print_tree(_CAR(foo),0); fprintf(stderr, ")?(");
a836c01999-11-12Henrik Grubbström (Grubba)  if (_CDR(foo)) { low_print_tree(_CADR(foo),0); fprintf(stderr, "):("); low_print_tree(_CDDR(foo),0); } else { fprintf(stderr, "0:0"); }
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, ")");
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_IDENTIFIER:
046afe1999-11-11Henrik Grubbström (Grubba)  if(needlval) fputc('&', stderr); if (new_program) { fprintf(stderr, "%s",ID_FROM_INT(new_program, foo->u.id.number)->name->str); } else { fprintf(stderr, "unknown identifier"); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
4218011999-01-31Fredrik Hübinette (Hubbe)  case F_TRAMPOLINE:
046afe1999-11-11Henrik Grubbström (Grubba)  if (new_program) { fprintf(stderr, "trampoline<%s>", ID_FROM_INT(new_program, foo->u.id.number)->name->str); } else { fprintf(stderr, "trampoline<unknown identifier>"); }
4218011999-01-31Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ASSIGN:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CDR(foo),1); fprintf(stderr, "="); low_print_tree(_CAR(foo),0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
2a8cd81999-11-18Henrik Grubbström (Grubba)  case F_POP_VALUE: fprintf(stderr, "{"); low_print_tree(_CAR(foo), 0); fprintf(stderr, "}"); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CAST: { char *s; init_buf(); low_describe_type(foo->type->str); s=simple_free_buf();
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "(%s){",s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free(s);
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); fprintf(stderr, "}");
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; }
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ARG_LIST:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); if(_CAR(foo) && _CDR(foo))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
046afe1999-11-11Henrik Grubbström (Grubba)  if(_CAR(foo)->type == void_type_string && _CDR(foo)->type == void_type_string) fprintf(stderr, ";\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  else
046afe1999-11-11Henrik Grubbström (Grubba)  fputc(',', stderr);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CDR(foo),needlval);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return;
2a32691998-01-31Fredrik Hübinette (Hubbe)  case F_ARRAY_LVALUE:
046afe1999-11-11Henrik Grubbström (Grubba)  fputc('[', stderr); low_print_tree(_CAR(foo),1); fputc(']', stderr);
2a32691998-01-31Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_LVALUE_LIST:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),1); if(_CAR(foo) && _CDR(foo)) fputc(',', stderr); low_print_tree(_CDR(foo),1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; case F_CONSTANT: { char *s; init_buf(); describe_svalue(& foo->u.sval, 0, 0); s=simple_free_buf();
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%s",s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free(s); break; } case F_VAL_LVAL:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); fprintf(stderr, ",&"); low_print_tree(_CDR(foo),0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; case F_APPLY:
046afe1999-11-11Henrik Grubbström (Grubba)  low_print_tree(_CAR(foo),0); fprintf(stderr, "("); low_print_tree(_CDR(foo),0); fprintf(stderr, ")");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; default: if(!car_is_node(foo) && !cdr_is_node(foo)) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%s",get_token_name(foo->token));
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } if(foo->token<256) {
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%c(",foo->token);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "%s(",get_token_name(foo->token));
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
046afe1999-11-11Henrik Grubbström (Grubba)  if(car_is_node(foo)) low_print_tree(_CAR(foo),0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(car_is_node(foo) && cdr_is_node(foo))
046afe1999-11-11Henrik Grubbström (Grubba)  fputc(',', stderr); if(cdr_is_node(foo)) low_print_tree(_CDR(foo),0); fprintf(stderr, ")");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } } void print_tree(node *n) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  check_tree(n,0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  low_print_tree(n,0);
046afe1999-11-11Henrik Grubbström (Grubba)  fprintf(stderr, "\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  fflush(stdout); } /* The following routines needs much better commenting */ struct used_vars {
e82b301997-01-29Fredrik Hübinette (Hubbe)  int err;
5267b71995-08-09Fredrik Hübinette (Hubbe)  char locals[MAX_LOCAL]; char globals[MAX_GLOBAL]; }; #define VAR_BLOCKED 0 #define VAR_UNUSED 1 #define VAR_USED 3 static void do_and_vars(struct used_vars *a,struct used_vars *b) { int e; for(e=0;e<MAX_LOCAL;e++) a->locals[e]|=b->locals[e]; for(e=0;e<MAX_GLOBAL;e++) a->globals[e]|=b->globals[e];
e82b301997-01-29Fredrik Hübinette (Hubbe)  a->err|=b->err;
5267b71995-08-09Fredrik Hübinette (Hubbe)  free((char *)b); } static struct used_vars *copy_vars(struct used_vars *a) { struct used_vars *ret; ret=(struct used_vars *)xalloc(sizeof(struct used_vars)); MEMCPY((char *)ret,(char *)a,sizeof(struct used_vars)); return ret; } static int find_used_variables(node *n, struct used_vars *p, int noblock, int overwrite) { struct used_vars *a; char *q; if(!n) return 0; switch(n->token) { case F_LOCAL:
4218011999-01-31Fredrik Hübinette (Hubbe)  /* FIXME: handle local variable depth */ q=p->locals+n->u.integer.a;
5267b71995-08-09Fredrik Hübinette (Hubbe)  goto set_pointer; case F_IDENTIFIER:
046afe1999-11-11Henrik Grubbström (Grubba)  q=p->globals+n->u.id.number; if(n->u.id.number > MAX_GLOBAL)
e82b301997-01-29Fredrik Hübinette (Hubbe)  { p->err=1; return 0; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  set_pointer: if(overwrite) { if(*q == VAR_UNUSED && !noblock) *q = VAR_BLOCKED; } else {
e82b301997-01-29Fredrik Hübinette (Hubbe)  if(*q == VAR_UNUSED) *q = VAR_USED;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } break; case F_ASSIGN: find_used_variables(CAR(n),p,noblock,0); find_used_variables(CDR(n),p,noblock,1); break; case '?': find_used_variables(CAR(n),p,noblock,0); a=copy_vars(p); find_used_variables(CADR(n),a,noblock,0); find_used_variables(CDDR(n),p,noblock,0); do_and_vars(p,a); break; case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_INC_LOOP: case F_DEC_LOOP: case F_FOREACH: case F_FOR: find_used_variables(CAR(n),p,noblock,0); a=copy_vars(p); find_used_variables(CDR(n),a,noblock,0); do_and_vars(p,a); break; case F_SWITCH: find_used_variables(CAR(n),p,noblock,0); a=copy_vars(p); find_used_variables(CDR(n),a,1,0); do_and_vars(p,a); break; case F_DO: a=copy_vars(p); find_used_variables(CAR(n),a,noblock,0); do_and_vars(p,a); find_used_variables(CDR(n),p,noblock,0); break; default: if(car_is_node(n)) find_used_variables(CAR(n),p,noblock,0); if(cdr_is_node(n)) find_used_variables(CDR(n),p,noblock,0); } return 0; } /* no subtility needed */ static void find_written_vars(node *n, struct used_vars *p, int lvalue) { if(!n) return; switch(n->token) { case F_LOCAL:
4218011999-01-31Fredrik Hübinette (Hubbe)  if(lvalue) p->locals[n->u.integer.a]=VAR_USED;
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
587a7c1998-08-05Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
e82b301997-01-29Fredrik Hübinette (Hubbe)  if(lvalue) {
046afe1999-11-11Henrik Grubbström (Grubba)  if(n->u.id.number>=MAX_GLOBAL)
e82b301997-01-29Fredrik Hübinette (Hubbe)  { p->err=1; return; }
046afe1999-11-11Henrik Grubbström (Grubba)  p->globals[n->u.id.number]=VAR_USED;
e82b301997-01-29Fredrik Hübinette (Hubbe)  } break; case F_APPLY: if(n->tree_info & OPT_SIDE_EFFECT)
49e54b1997-02-10Fredrik Hübinette (Hubbe)  MEMSET(p->globals, VAR_USED, MAX_GLOBAL);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_INDEX:
dffa011997-01-15Fredrik Hübinette (Hubbe)  case F_ARROW:
5267b71995-08-09Fredrik Hübinette (Hubbe)  find_written_vars(CAR(n), p, lvalue); find_written_vars(CDR(n), p, 0); break; case F_INC: case F_DEC: case F_POST_INC: case F_POST_DEC: find_written_vars(CAR(n), p, 1); break; case F_ASSIGN: find_written_vars(CAR(n), p, 0); find_written_vars(CDR(n), p, 1); break;
5219721998-11-06Fredrik Hübinette (Hubbe)  case F_AND_EQ: case F_OR_EQ: case F_XOR_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_ADD_EQ: case F_SUB_EQ: case F_MULT_EQ: case F_MOD_EQ: case F_DIV_EQ: find_written_vars(CAR(n), p, 1); find_written_vars(CDR(n), p, 0); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_SSCANF: find_written_vars(CAR(n), p, 0); find_written_vars(CDR(n), p, 1); break;
2a32691998-01-31Fredrik Hübinette (Hubbe)  case F_ARRAY_LVALUE: find_written_vars(CAR(n), p, 1); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_LVALUE_LIST: find_written_vars(CAR(n), p, 1); find_written_vars(CDR(n), p, 1); break; case F_VAL_LVAL: find_written_vars(CAR(n), p, 0); find_written_vars(CDR(n), p, 1); break; default: if(car_is_node(n)) find_written_vars(CAR(n), p, 0); if(cdr_is_node(n)) find_written_vars(CDR(n), p, 0); } } /* return 1 if A depends on B */ static int depend_p2(node *a,node *b) { struct used_vars aa,bb; int e; if(!a || !b || is_const(a)) return 0;
3b79fa1997-02-10Fredrik Hübinette (Hubbe)  aa.err=0; bb.err=0;
49e54b1997-02-10Fredrik Hübinette (Hubbe)  MEMSET((char *)aa.locals, VAR_UNUSED, MAX_LOCAL); MEMSET((char *)bb.locals, VAR_UNUSED, MAX_LOCAL); MEMSET((char *)aa.globals, VAR_UNUSED, MAX_GLOBAL); MEMSET((char *)bb.globals, VAR_UNUSED, MAX_GLOBAL);
5267b71995-08-09Fredrik Hübinette (Hubbe)  find_used_variables(a,&aa,0,0); find_written_vars(b,&bb,0);
e82b301997-01-29Fredrik Hübinette (Hubbe)  if(aa.err || bb.err) return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  for(e=0;e<MAX_LOCAL;e++) if(aa.locals[e]==VAR_USED && bb.locals[e]!=VAR_UNUSED) return 1; for(e=0;e<MAX_GLOBAL;e++) if(aa.globals[e]==VAR_USED && bb.globals[e]!=VAR_UNUSED) return 1; return 0; }
5219721998-11-06Fredrik Hübinette (Hubbe) static int depend_p3(node *a,node *b)
5267b71995-08-09Fredrik Hübinette (Hubbe) { if(!b) return 0;
e82b301997-01-29Fredrik Hübinette (Hubbe) #if 0
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!(b->tree_info & OPT_SIDE_EFFECT) && (b->tree_info & OPT_EXTERNAL_DEPEND)) return 1;
e82b301997-01-29Fredrik Hübinette (Hubbe) #endif if((a->tree_info & OPT_EXTERNAL_DEPEND)) return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return depend_p2(a,b); }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5219721998-11-06Fredrik Hübinette (Hubbe) static int depend_p(node *a,node *b) { int ret; if(l_flag > 3) { fprintf(stderr,"Checking if: "); print_tree(a); fprintf(stderr,"Depends on: "); print_tree(b); if(depend_p3(a,b)) { fprintf(stderr,"The answer is (durumroll) : yes\n"); return 1; }else{ fprintf(stderr,"The answer is (durumroll) : no\n"); return 0; } } return depend_p3(a,b); } #else #define depend_p depend_p3 #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) static int cntargs(node *n) { if(!n) return 0; switch(n->token) { case F_CAST: case F_APPLY: return n->type != void_type_string;
2a8cd81999-11-18Henrik Grubbström (Grubba)  case F_POP_VALUE:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_FOREACH: case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_INC_LOOP: case F_DEC_LOOP: return 0;
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_VAL_LVAL: case F_LVALUE_LIST: case F_ARG_LIST: return cntargs(CAR(n))+cntargs(CDR(n)); /* this might not be true, but it doesn't matter very much */ default: return 1; } }
086acc1999-09-11Fredrik Hübinette (Hubbe) static int function_type_max=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) static void low_build_function_type(node *n) { if(!n) return;
086acc1999-09-11Fredrik Hübinette (Hubbe)  if(function_type_max++ > 999) { reset_type_stack(); push_type(T_MIXED); push_type(T_MIXED); /* is varargs */ push_type(T_MANY); return; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ARG_LIST: low_build_function_type(CDR(n)); low_build_function_type(CAR(n)); break; case F_PUSH_ARRAY: /* We let this ruin type-checking for now.. */ reset_type_stack();
0d202a1995-10-20Fredrik Hübinette (Hubbe)  push_type(T_MIXED);
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_type(T_MIXED); /* is varargs */ push_type(T_MANY); return; default: if(n->type) { if(n->type == void_type_string) return; push_finished_type(n->type); }else{ push_type(T_MIXED); } } } void fix_type_field(node *n) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *type_a,*type_b;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(n->type) return; /* assume it is correct */ switch(n->token) {
cb22561995-10-11Fredrik Hübinette (Hubbe)  case F_LAND: case F_LOR:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || CAR(n)->type == void_type_string || !CDR(n) || CDR(n)->type == void_type_string) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Conditional contains void expression.");
e9b1771999-11-18Henrik Grubbström (Grubba)  copy_shared_string(n->type, mixed_type_string); }
cb22561995-10-11Fredrik Hübinette (Hubbe)  if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe)  if(!match_types(CDR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe)  if(CAR(n)->type == CDR(n)->type) { copy_shared_string(n->type,CAR(n)->type); }else{
e9b1771999-11-18Henrik Grubbström (Grubba)  /* FIXME: Shouldn't it be an or? */
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,mixed_type_string); } break;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
da55f91996-05-03Fredrik Hübinette (Hubbe)  case F_ASSIGN:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) { my_yyerror("Assigning a void expression."); copy_shared_string(n->type, void_type_string); break; } else if(CAR(n) && CDR(n) &&
52082c1999-08-20Martin Stjernholm  /* a["b"]=c and a->b=c can be valid when a is an array */
e9b1771999-11-18Henrik Grubbström (Grubba)  CDR(n)->token != F_INDEX && CDR(n)->token != F_ARROW && !match_types(CDR(n)->type,CAR(n)->type)) {
3856c31996-11-25Fredrik Hübinette (Hubbe)  my_yyerror("Bad type in assignment.");
e9b1771999-11-18Henrik Grubbström (Grubba)  }
48137d1998-02-28Fredrik Hübinette (Hubbe)  copy_shared_string(n->type, CAR(n)->type);
da55f91996-05-03Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_INDEX:
dffa011997-01-15Fredrik Hübinette (Hubbe)  case F_ARROW:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) { my_yyerror("Indexing a void expression."); /* The optimizer converts this to an expression returning 0. */ copy_shared_string(n->type, mixed_type_string); } else { type_a=CAR(n)->type; type_b=CDR(n)->type; if(!check_indexing(type_a, type_b, n)) if(!catch_level) my_yyerror("Indexing on illegal type."); n->type=index_type(type_a,n); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case F_APPLY:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) { my_yyerror("Calling a void expression."); /* The optimizer converts this to an expression returning 0. */
4b81751999-11-19Henrik Grubbström (Grubba)  if (!n->type) { copy_shared_string(n->type, mixed_type_string); }
e9b1771999-11-18Henrik Grubbström (Grubba)  } else {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *s;
b8cda21997-01-21Fredrik Hübinette (Hubbe)  struct pike_string *f;
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  INT32 max_args,args;
0d202a1995-10-20Fredrik Hübinette (Hubbe)  push_type(T_MIXED); /* match any return type, even void */
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_type(T_VOID); /* not varargs */ push_type(T_MANY);
086acc1999-09-11Fredrik Hübinette (Hubbe)  function_type_max=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  low_build_function_type(CDR(n)); push_type(T_FUNCTION); s=pop_type();
b8cda21997-01-21Fredrik Hübinette (Hubbe)  f=CAR(n)->type?CAR(n)->type:mixed_type_string; n->type=check_call(s,f);
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  args=count_arguments(s);
d429a71998-02-24Fredrik Hübinette (Hubbe)  max_args=count_arguments(f); if(max_args<0) max_args=0x7fffffff;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!n->type) {
b8cda21997-01-21Fredrik Hübinette (Hubbe)  char *name;
3856c31996-11-25Fredrik Hübinette (Hubbe)  switch(CAR(n)->token) {
4218011999-01-31Fredrik Hübinette (Hubbe) #if 0 /* FIXME */ case F_TRAMPOLINE; #endif
3856c31996-11-25Fredrik Hübinette (Hubbe)  case F_IDENTIFIER:
046afe1999-11-11Henrik Grubbström (Grubba)  name=ID_FROM_INT(new_program, CAR(n)->u.id.number)->name->str;
3856c31996-11-25Fredrik Hübinette (Hubbe)  break;
b8cda21997-01-21Fredrik Hübinette (Hubbe) 
3856c31996-11-25Fredrik Hübinette (Hubbe)  case F_CONSTANT:
0d3ea51998-01-19Fredrik Hübinette (Hubbe)  switch(CAR(n)->u.sval.type) { case T_FUNCTION:
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  if(CAR(n)->u.sval.subtype == FUNCTION_BUILTIN) { name=CAR(n)->u.sval.u.efun->name->str; }else{ name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog, CAR(n)->u.sval.subtype)->name->str; }
0d3ea51998-01-19Fredrik Hübinette (Hubbe)  break; case T_ARRAY: name="array call"; break; case T_PROGRAM: name="clone call"; break; default: name="`() (function call)"; break; }
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  break;
0d3ea51998-01-19Fredrik Hübinette (Hubbe) 
3856c31996-11-25Fredrik Hübinette (Hubbe)  default:
0d3ea51998-01-19Fredrik Hübinette (Hubbe)  name="unknown function";
b8cda21997-01-21Fredrik Hübinette (Hubbe)  }
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  if(max_args < args) {
9a78b21999-11-18Henrik Grubbström (Grubba)  my_yyerror("Too many arguments to %s.",name);
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  } else if(max_correct_args == args)
b8cda21997-01-21Fredrik Hübinette (Hubbe)  {
9a78b21999-11-18Henrik Grubbström (Grubba)  my_yyerror("Too few arguments to %s.",name);
b8cda21997-01-21Fredrik Hübinette (Hubbe)  }else{ my_yyerror("Bad argument %d to %s.", max_correct_args+1, name);
3856c31996-11-25Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  copy_shared_string(n->type, mixed_type_string); } free_string(s);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } case '?':
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe) 
1aac411999-11-19Henrik Grubbström (Grubba)  if(!CDR(n) || !CADR(n) || !CDDR(n))
5267b71995-08-09Fredrik Hübinette (Hubbe)  { copy_shared_string(n->type,void_type_string); return; } if(CADR(n)->type == CDDR(n)->type) { copy_shared_string(n->type,CADR(n)->type); return; } copy_shared_string(n->type,mixed_type_string);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break; case F_RETURN:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Returning a void expression.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(compiler_frame && compiler_frame->current_return_type && !match_types(compiler_frame->current_return_type,CAR(n)->type) && !( compiler_frame->current_return_type==void_type_string && CAR(n)->token == F_CONSTANT && IS_ZERO(& CAR(n)->u.sval) ) )
cb22561995-10-11Fredrik Hübinette (Hubbe)  {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Wrong return type.");
cb22561995-10-11Fredrik Hübinette (Hubbe)  } /* Fall through */
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_INC_LOOP: case F_DEC_LOOP: case F_DEC_NEQ_LOOP: case F_INC_NEQ_LOOP: case F_CASE: case F_CONTINUE: case F_BREAK:
e9b1771999-11-18Henrik Grubbström (Grubba)  case F_DEFAULT:
5267b71995-08-09Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break; case F_DO:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CDR(n) || (CDR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("do - while(): Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CDR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression do - while().");
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string); break; case F_FOR:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("for(): Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad conditional expression for().");
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string); break; case F_SWITCH:
e9b1771999-11-18Henrik Grubbström (Grubba)  if (!CAR(n) || (CAR(n)->type == void_type_string)) {
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("switch(): Conditional expression is void.");
e9b1771999-11-18Henrik Grubbström (Grubba)  } else if(!match_types(CAR(n)->type,mixed_type_string))
9a78b21999-11-18Henrik Grubbström (Grubba)  yyerror("Bad switch expression.");
cb22561995-10-11Fredrik Hübinette (Hubbe)  copy_shared_string(n->type,void_type_string); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_CONSTANT: n->type = get_type_of_svalue(& n->u.sval);
cb22561995-10-11Fredrik Hübinette (Hubbe)  break;
920d201999-11-06Henrik Grubbström (Grubba)  case F_COMMA_EXPR:
5267b71995-08-09Fredrik Hübinette (Hubbe)  case F_ARG_LIST: if(!CAR(n) || CAR(n)->type==void_type_string) { if(CDR(n)) copy_shared_string(n->type,CDR(n)->type); else copy_shared_string(n->type,void_type_string); return; } if(!CDR(n) || CDR(n)->type==void_type_string) { if(CAR(n)) copy_shared_string(n->type,CAR(n)->type); else copy_shared_string(n->type,void_type_string); return; } default: copy_shared_string(n->type,mixed_type_string); } } static void zapp_try_optimize(node *n) {
86bea91997-01-31Fredrik Hübinette (Hubbe)  if(!n) return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  n->node_info &=~ OPT_TRY_OPTIMIZE; n->tree_info &=~ OPT_TRY_OPTIMIZE; if(car_is_node(n)) zapp_try_optimize(CAR(n)); if(cdr_is_node(n)) zapp_try_optimize(CDR(n)); }
969a291999-11-17Henrik Grubbström (Grubba) #if defined(SHARED_NODES) && !defined(IN_TPIKE)
36dd451999-11-17Henrik Grubbström (Grubba) static void find_usage(node *n, unsigned char *usage,
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char *switch_u, const unsigned char *cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  const unsigned char *break_u, const unsigned char *catch_u)
969a291999-11-17Henrik Grubbström (Grubba) { if (!n) return; switch(n->token) { case F_ASSIGN: if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) { usage[CDR(n)->u.integer.a] = 0;
55a20a1999-11-17Henrik Grubbström (Grubba)  } else if (CDR(n)->token == F_ARRAY_LVALUE) {
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return;
36dd451999-11-17Henrik Grubbström (Grubba)  case F_SSCANF: { int i; /* catch_usage is restored if sscanf throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } /* Only the first two arguments are evaluated. */ if (CAR(n)) { find_usage(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); find_usage(CAAR(n), usage, switch_u, cont_u, break_u, catch_u); } return; } case F_CATCH: { unsigned char catch_usage[MAX_LOCAL]; int i; MEMCPY(catch_usage, usage, MAX_LOCAL); find_usage(CAR(n), usage, switch_u, cont_u, catch_usage, catch_usage); for(i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_usage[i]; } return; } case F_APPLY: { int i; /* catch_usage is restored if the function throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u); find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u); return; }
55a20a1999-11-17Henrik Grubbström (Grubba)  case F_LVALUE_LIST:
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  if (CAR(n)) { if ((CAR(n)->token == F_LOCAL) && (!CAR(n)->u.integer.b)) { usage[CAR(n)->u.integer.a] = 0; } } return; case F_ARRAY_LVALUE:
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  return;
969a291999-11-17Henrik Grubbström (Grubba)  case F_CONTINUE: MEMCPY(usage, cont_u, MAX_LOCAL); return; case F_BREAK: MEMCPY(usage, break_u, MAX_LOCAL); return; case F_DEFAULT: case F_CASE: { int i;
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u); find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { switch_u[i] |= usage[i]; } return; } case F_SWITCH: { unsigned char break_usage[MAX_LOCAL]; unsigned char switch_usage[MAX_LOCAL]; int i; MEMSET(switch_usage, 0, MAX_LOCAL); MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_usage, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { usage[i] |= switch_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_RETURN: MEMSET(usage, 0, MAX_LOCAL); /* FIXME: The function arguments should be marked "used", since * they are seen in backtraces. */ return; case F_LOR: case F_LAND: { unsigned char trail_usage[MAX_LOCAL]; int i; MEMCPY(trail_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i=0; i < MAX_LOCAL; i++) { usage[i] |= trail_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case '?': { unsigned char cadr_usage[MAX_LOCAL]; unsigned char cddr_usage[MAX_LOCAL]; int i; MEMCPY(cadr_usage, usage, MAX_LOCAL); MEMCPY(cddr_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CADR(n), cadr_usage, switch_u, cont_u, break_u, catch_u); find_usage(CDDR(n), cddr_usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for (i=0; i < MAX_LOCAL; i++) { usage[i] = cadr_usage[i] | cddr_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_DO: { unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL]; MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, break_usage, continue_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_FOR: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL]; node *car1, cadr, cddr;
55a20a1999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL); /* for(;a;b) c; is handled like: * * if (a) { do { c; b; } while(a); } */
36dd451999-11-17Henrik Grubbström (Grubba)  MEMSET(loop_usage, 0, MAX_LOCAL); find_usage(CAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { find_usage(CDDR(n), loop_usage, switch_u, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, loop_usage, MAX_LOCAL); find_usage(CADR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); }
969a291999-11-17Henrik Grubbström (Grubba) 
55a20a1999-11-17Henrik Grubbström (Grubba)  for (i = 0; i < MAX_LOCAL; i++) {
36dd451999-11-17Henrik Grubbström (Grubba)  usage[i] |= loop_usage[i];
55a20a1999-11-17Henrik Grubbström (Grubba)  }
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_FOREACH: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* Find the usage from the loop */ MEMSET(loop_usage, 0, MAX_LOCAL);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); if (CDAR(n)->token == F_LOCAL) { if (!(CDAR(n)->u.integer.b)) { loop_usage[CDAR(n)->u.integer.a] = 0; } } else if (CDAR(n)->token == F_LVALUE_LIST) { find_usage(CDAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); } for(i=0; i < MAX_LOCAL; i++) { usage[i] |= loop_usage[i]; } find_usage(CAAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return; } case F_LOCAL: /* Use of local variable. */ if (!n->u.integer.b) { /* Recently used, and used at all */ usage[n->u.integer.a] = 3; } return; default: if (cdr_is_node(n)) {
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  } if (car_is_node(n)) {
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  } return; } } /* Note: Always builds a new tree. */ static node *low_localopt(node *n, unsigned char *usage, unsigned char *switch_u, const unsigned char *cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  const unsigned char *break_u, const unsigned char *catch_u)
969a291999-11-17Henrik Grubbström (Grubba) { node *car, *cdr; if (!n) return NULL; switch(n->token) { case F_ASSIGN: if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) { /* Assignment of local variable */ if (!(usage[CDR(n)->u.integer.a] & 1)) { /* Value isn't used. */
1aac411999-11-19Henrik Grubbström (Grubba)  struct pike_string *ref_type; MAKE_CONSTANT_SHARED_STRING(ref_type, tOr(tComplex, tString)); if (!match_types(CDR(n)->type, ref_type)) { /* The variable doesn't hold a refcounted value. */ free_string(ref_type); return low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u); } free_string(ref_type);
969a291999-11-17Henrik Grubbström (Grubba)  } usage[CDR(n)->u.integer.a] = 0;
55a20a1999-11-17Henrik Grubbström (Grubba)  cdr = CDR(n); ADD_NODE_REF(cdr); } else if (CDR(n)->token == F_ARRAY_LVALUE) {
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  } else { cdr = CDR(n); ADD_NODE_REF(cdr);
969a291999-11-17Henrik Grubbström (Grubba)  } return mknode(F_ASSIGN, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u), cdr); case F_SSCANF: { int i; /* catch_usage is restored if sscanf throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } /* Only the first two arguments are evaluated. */ if (CAR(n)) { cdr = low_localopt(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); car = low_localopt(CAAR(n), usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { ADD_NODE_REF(CDR(n)); } return mknode(F_SSCANF, mknode(F_ARG_LIST, car, cdr), CDR(n)); } ADD_NODE_REF(n); return n; } case F_CATCH: { unsigned char catch_usage[MAX_LOCAL]; int i; MEMCPY(catch_usage, usage, MAX_LOCAL); car = low_localopt(CAR(n), usage, switch_u, cont_u, catch_usage, catch_usage); for(i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_usage[i]; } return mknode(F_CATCH, car, 0); } break; case F_APPLY: { int i; /* catch_usage is restored if the function throws an error. */ for (i=0; i < MAX_LOCAL; i++) { usage[i] |= catch_u[i]; } cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u); car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u); return mknode(F_APPLY, car, cdr); }
55a20a1999-11-17Henrik Grubbström (Grubba)  case F_LVALUE_LIST:
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
55a20a1999-11-17Henrik Grubbström (Grubba)  if (CAR(n)) { if ((CAR(n)->token == F_LOCAL) && (!CAR(n)->u.integer.b)) { /* Array assignment of local variable. */ if (!(usage[CDR(n)->u.integer.a] & 1)) { /* Variable isn't used. */ /* FIXME: Warn? */ } usage[CAR(n)->u.integer.a] = 0; } ADD_NODE_REF(CAR(n)); } return mknode(F_LVALUE_LIST, CAR(n), cdr); case F_ARRAY_LVALUE: return mknode(F_ARRAY_LVALUE, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u), 0);
55a20a1999-11-17Henrik Grubbström (Grubba) 
969a291999-11-17Henrik Grubbström (Grubba)  case F_CAST: return mkcastnode(n->type, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u));
969a291999-11-17Henrik Grubbström (Grubba)  case F_CONTINUE: MEMCPY(usage, cont_u, MAX_LOCAL); ADD_NODE_REF(n); return n; case F_BREAK: MEMCPY(usage, break_u, MAX_LOCAL); ADD_NODE_REF(n); return n; case F_DEFAULT: case F_CASE: { int i;
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u); car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { switch_u[i] |= usage[i]; } return mknode(n->token, car, cdr); } case F_SWITCH: { unsigned char break_usage[MAX_LOCAL]; unsigned char switch_usage[MAX_LOCAL]; int i; MEMSET(switch_usage, 0, MAX_LOCAL); MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_usage, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i = 0; i < MAX_LOCAL; i++) { usage[i] |= switch_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(F_SWITCH, car, cdr); } case F_RETURN: MEMSET(usage, 0, MAX_LOCAL); /* FIXME: The function arguments should be marked "used", since * they are seen in backtraces. */ return mknode(F_RETURN, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u), 0);
969a291999-11-17Henrik Grubbström (Grubba)  case F_LOR: case F_LAND: { unsigned char trail_usage[MAX_LOCAL]; int i; MEMCPY(trail_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for(i=0; i < MAX_LOCAL; i++) { usage[i] |= trail_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(n->token, car, cdr); } case '?': { unsigned char cadr_usage[MAX_LOCAL]; unsigned char cddr_usage[MAX_LOCAL]; int i; MEMCPY(cadr_usage, usage, MAX_LOCAL); MEMCPY(cddr_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CADR(n), cadr_usage, switch_u, cont_u, break_u, catch_u); cdr = low_localopt(CDDR(n), cddr_usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  for (i=0; i < MAX_LOCAL; i++) { usage[i] = cadr_usage[i] | cddr_usage[i]; } cdr = mknode(':', car, cdr);
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode('?', car, cdr); } case F_DO: { unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* Find the usage from the loop */ find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u); MEMCPY(continue_usage, usage, MAX_LOCAL); find_usage(CAR(n), usage, switch_u, continue_usage, break_usage, catch_u); for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= break_usage[i]; } cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  car = low_localopt(CAR(n), usage, switch_u, continue_usage, break_usage, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(F_DO, car, cdr); } case F_FOR: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
55a20a1999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* * if (a A|B) { * B * do { * B * c; * continue: * D * b; * C * } while (a A|B); * A * } * break: * A
969a291999-11-17Henrik Grubbström (Grubba)  */
36dd451999-11-17Henrik Grubbström (Grubba)  /* Find the usage from the loop. */ MEMSET(loop_usage, 0, MAX_LOCAL); find_usage(CAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { find_usage(CDDR(n), loop_usage, switch_u, cont_u, break_usage, catch_u); MEMCPY(continue_usage, loop_usage, MAX_LOCAL); find_usage(CADR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); } for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= loop_usage[i]; } /* The last thing to be evaluated is the conditional */ car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u); if (CDR(n)) { node *cadr, *cddr;
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  /* The incrementor */ cddr = low_localopt(CDDR(n), usage, switch_u, cont_u, break_usage, catch_u); MEMCPY(continue_usage, usage, MAX_LOCAL); /* The body */ cadr = low_localopt(CADR(n), usage, switch_u, continue_usage, break_usage, catch_u); cdr = mknode(':', cadr, cddr); } else { cdr = 0; }
969a291999-11-17Henrik Grubbström (Grubba) 
55a20a1999-11-17Henrik Grubbström (Grubba)  for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= break_usage[i]; }
36dd451999-11-17Henrik Grubbström (Grubba)  /* The conditional is also the first thing to be evaluated. */ find_usage(car, usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(F_FOR, car, cdr); } case F_FOREACH: {
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char loop_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  unsigned char break_usage[MAX_LOCAL]; unsigned char continue_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  int i;
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(break_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  /* * D * arr = copy_value(arr); * int i = 0; * A|B * while (i < sizeof(arr)) { * B * loopvar = arr[i]; * C * body; * continue: * A|B * } * break: * A */ /* Find the usage from the loop */ MEMSET(loop_usage, 0, MAX_LOCAL);
969a291999-11-17Henrik Grubbström (Grubba)  MEMCPY(continue_usage, usage, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  find_usage(CDR(n), loop_usage, switch_u, continue_usage, break_usage, catch_u); if (CDAR(n)->token == F_LOCAL) { if (!(CDAR(n)->u.integer.b)) { loop_usage[CDAR(n)->u.integer.a] = 0; } } else if (CDAR(n)->token == F_LVALUE_LIST) { find_usage(CDAR(n), loop_usage, switch_u, cont_u, break_u, catch_u); } for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= loop_usage[i]; } MEMCPY(continue_usage, usage, MAX_LOCAL); cdr = low_localopt(CDR(n), usage, switch_u, continue_usage, break_usage, catch_u); if (CDAR(n)->token == F_LOCAL) { if (!(CDAR(n)->u.integer.b)) { usage[CDAR(n)->u.integer.a] = 0; } } else if (CDAR(n)->token == F_LVALUE_LIST) { find_usage(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); } for (i = 0; i < MAX_LOCAL; i++) { usage[i] |= break_usage[i]; } car = low_localopt(CAAR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  ADD_NODE_REF(CDAR(n)); return mknode(F_FOREACH, mknode(F_VAL_LVAL, car, CDAR(n)), cdr); } case F_LOCAL: /* Use of local variable. */ if (!n->u.integer.b) { /* Recently used, and used at all */ usage[n->u.integer.a] = 3; } ADD_NODE_REF(n); return n; default: if (cdr_is_node(n)) {
36dd451999-11-17Henrik Grubbström (Grubba)  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
969a291999-11-17Henrik Grubbström (Grubba)  return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u),
969a291999-11-17Henrik Grubbström (Grubba)  cdr); } if (car_is_node(n)) { ADD_NODE_REF(CDR(n)); return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u,
36dd451999-11-17Henrik Grubbström (Grubba)  break_u, catch_u),
969a291999-11-17Henrik Grubbström (Grubba)  CDR(n)); } ADD_NODE_REF(n); return n; } } static node *localopt(node *n) { unsigned char usage[MAX_LOCAL]; unsigned char b_usage[MAX_LOCAL]; unsigned char c_usage[MAX_LOCAL]; unsigned char s_usage[MAX_LOCAL];
36dd451999-11-17Henrik Grubbström (Grubba)  unsigned char catch_usage[MAX_LOCAL];
969a291999-11-17Henrik Grubbström (Grubba)  node *n2; MEMSET(usage, 0, MAX_LOCAL); MEMSET(b_usage, 0, MAX_LOCAL); MEMSET(c_usage, 0, MAX_LOCAL); MEMSET(s_usage, 0, MAX_LOCAL);
36dd451999-11-17Henrik Grubbström (Grubba)  MEMSET(catch_usage, 0, MAX_LOCAL);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  n2 = low_localopt(n, usage, s_usage, c_usage, b_usage, catch_usage);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 0) { if ((n2 != n) || (l_flag > 4)) { fprintf(stderr, "\nBefore localopt: "); print_tree(n);
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  fprintf(stderr, "After localopt: "); print_tree(n2); } } #endif /* PIKE_DEBUG */
969a291999-11-17Henrik Grubbström (Grubba) 
36dd451999-11-17Henrik Grubbström (Grubba)  free_node(n);
969a291999-11-17Henrik Grubbström (Grubba)  return n2; } #endif /* SHARED_NODES && !IN_TPIKE */
5267b71995-08-09Fredrik Hübinette (Hubbe) static void optimize(node *n) { node *tmp1, *tmp2, *tmp3;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  INT32 save_line = lex.current_line;
5267b71995-08-09Fredrik Hübinette (Hubbe)  do {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  if(car_is_node(n) && ((CAR(n)->node_info & (OPT_OPTIMIZED|OPT_DEFROSTED)) != OPT_OPTIMIZED))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  CAR(n)->parent = n; n = CAR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  continue; }
bf4f7d1999-11-12Henrik Grubbström (Grubba)  if(cdr_is_node(n) && ((CDR(n)->node_info & (OPT_OPTIMIZED|OPT_DEFROSTED)) != OPT_OPTIMIZED))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  CDR(n)->parent = n; n = CDR(n);
5267b71995-08-09Fredrik Hübinette (Hubbe)  continue; }
bf4f7d1999-11-12Henrik Grubbström (Grubba)  #if defined(SHARED_NODES) if ((n->node_info & OPT_DEFROSTED) && (n->parent)) { #ifndef IN_TPIKE /* Add ref since both freeze_node() and use_tmp1 will free it. */ ADD_NODE_REF(n); /* We don't want freeze_node() to find this node in the hash-table. */ tmp1 = freeze_node(n); if (tmp1 != n) { /* n was a duplicate node. Use the original. */ goto use_tmp1; } /* Remove the extra ref from n */ free_node(n);
969a291999-11-17Henrik Grubbström (Grubba) #else /* IN_TPIKE */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->node_info &= ~OPT_DEFROSTED;
969a291999-11-17Henrik Grubbström (Grubba) #endif /* !IN_TPIKE */
bf4f7d1999-11-12Henrik Grubbström (Grubba)  if (n->node_info & OPT_OPTIMIZED) { /* No need to check this node any more. */ n = n->parent; continue; } } #endif /* SHARED_NODES && !IN_TPIKE */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  lex.current_line = n->line_number;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
66d51c1997-03-04Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  n->tree_info = n->node_info; if(car_is_node(n)) n->tree_info |= CAR(n)->tree_info; if(cdr_is_node(n)) n->tree_info |= CDR(n)->tree_info;
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(!n->parent) break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(n->tree_info & (OPT_NOT_CONST| OPT_SIDE_EFFECT| OPT_EXTERNAL_DEPEND| OPT_ASSIGNMENT)) { if(car_is_node(n) && !(CAR(n)->tree_info & (OPT_NOT_CONST| OPT_SIDE_EFFECT| OPT_EXTERNAL_DEPEND| OPT_ASSIGNMENT)) && (CAR(n)->tree_info & OPT_TRY_OPTIMIZE) && CAR(n)->token != ':') {
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES sub_node(n); #endif /* SHARED_NODES */ _CAR(n) = eval(CAR(n)); #ifdef SHARED_NODES n->hash = hash_node(n);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->node_info |= OPT_DEFROSTED;
046afe1999-11-11Henrik Grubbström (Grubba)  add_node(n); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CAR(n)) CAR(n)->parent = n; zapp_try_optimize(CAR(n)); /* avoid infinite loops */ continue; } if(cdr_is_node(n) && !(CDR(n)->tree_info & (OPT_NOT_CONST| OPT_SIDE_EFFECT| OPT_EXTERNAL_DEPEND| OPT_ASSIGNMENT)) && (CDR(n)->tree_info & OPT_TRY_OPTIMIZE) && CDR(n)->token != ':') {
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES sub_node(n); #endif /* SHARED_NODES */ _CDR(n) = eval(CDR(n)); #ifdef SHARED_NODES n->hash = hash_node(n);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->node_info |= OPT_DEFROSTED;
046afe1999-11-11Henrik Grubbström (Grubba)  add_node(n); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CDR(n)) CDR(n)->parent = n; zapp_try_optimize(CDR(n)); /* avoid infinite loops */ continue; } } fix_type_field(n);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(n->type);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(l_flag > 3 && n)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
b464611999-11-14Henrik Grubbström (Grubba)  fprintf(stderr,"Optimizing (tree info=%04x):",n->tree_info);
5267b71995-08-09Fredrik Hübinette (Hubbe)  print_tree(n); } #endif
7018811999-11-08Henrik Grubbström (Grubba) #ifndef IN_TPIKE
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(n->token) {
7018811999-11-08Henrik Grubbström (Grubba) #include "treeopt.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  use_car:
71e11e1999-11-12Henrik Grubbström (Grubba)  ADD_NODE_REF2(CAR(n), tmp1 = CAR(n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  goto use_tmp1; use_cdr:
71e11e1999-11-12Henrik Grubbström (Grubba)  ADD_NODE_REF2(CDR(n), tmp1 = CDR(n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  goto use_tmp1;
5392401999-11-06Henrik Grubbström (Grubba)  zap_node: tmp1 = 0; goto use_tmp1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  use_tmp1:
bf4f7d1999-11-12Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (l_flag > 4) { fprintf(stderr, "Optimized: "); print_tree(n); fprintf(stderr, "Result: "); print_tree(tmp1); } #endif /* PIKE_DEBUG */
046afe1999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES sub_node(n->parent); #endif /* SHARED_NODES */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(CAR(n->parent) == n)
a836c01999-11-12Henrik Grubbström (Grubba)  _CAR(n->parent) = tmp1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  else
a836c01999-11-12Henrik Grubbström (Grubba)  _CDR(n->parent) = tmp1;
046afe1999-11-11Henrik Grubbström (Grubba)  #ifdef SHARED_NODES n->parent->hash = hash_node(n->parent); add_node(n->parent);
bf4f7d1999-11-12Henrik Grubbström (Grubba)  n->parent->node_info |= OPT_DEFROSTED;
046afe1999-11-11Henrik Grubbström (Grubba) #endif /* SHARED_NODES */
5392401999-11-06Henrik Grubbström (Grubba)  if(tmp1) tmp1->parent = n->parent; else tmp1 = n->parent;
046afe1999-11-11Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n);
046afe1999-11-11Henrik Grubbström (Grubba)  n = tmp1;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(l_flag > 3) {
bf4f7d1999-11-12Henrik Grubbström (Grubba)  fprintf(stderr,"Result: ");
5267b71995-08-09Fredrik Hübinette (Hubbe)  print_tree(n); } #endif continue; }
7018811999-11-08Henrik Grubbström (Grubba) #endif /* !IN_TPIKE */
5267b71995-08-09Fredrik Hübinette (Hubbe)  n->node_info |= OPT_OPTIMIZED; n=n->parent; }while(n);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  lex.current_line = save_line;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
a29e021996-10-15Fredrik Hübinette (Hubbe) struct timer_oflo { INT32 counter; int yes; };
d085c71996-11-18Fredrik Hübinette (Hubbe) static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored)
a29e021996-10-15Fredrik Hübinette (Hubbe) { struct timer_oflo *foo=(struct timer_oflo *)tmp; if(foo->counter-- < 0) { foo->yes=1;
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  pike_throw();
a29e021996-10-15Fredrik Hübinette (Hubbe)  } }
5267b71995-08-09Fredrik Hübinette (Hubbe) int eval_low(node *n) {
5c8e891995-10-29Fredrik Hübinette (Hubbe)  unsigned INT16 num_strings, num_constants; INT32 jump;
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue *save_sp = sp; int ret;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if(l_flag > 3 && n) { fprintf(stderr,"Evaluating (tree info=%x):",n->tree_info); print_tree(n); } #endif
8271d01998-04-19Per Hedbor  if(num_parse_error) return -1;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  num_strings=new_program->num_strings; num_constants=new_program->num_constants;
5267b71995-08-09Fredrik Hübinette (Hubbe)  jump=PC; store_linenumbers=0;
a836c01999-11-12Henrik Grubbström (Grubba)  docode(dmalloc_touch(node *, n));
5267b71995-08-09Fredrik Hübinette (Hubbe)  ins_f_byte(F_DUMB_RETURN); store_linenumbers=1; ret=-1; if(!num_parse_error) {
a29e021996-10-15Fredrik Hübinette (Hubbe)  struct callback *tmp_callback; struct timer_oflo foo; /* This is how long we try to optimize before giving up... */ foo.counter=10000; foo.yes=0; tmp_callback=add_to_callback(&evaluator_callbacks, check_evaluation_time, (void *)&foo,0);
6d22541998-01-28Fredrik Hübinette (Hubbe)  if(apply_low_safe_and_stupid(fake_object, jump))
5267b71995-08-09Fredrik Hübinette (Hubbe)  { /* Generate error message */
9649491998-02-27Fredrik Hübinette (Hubbe)  if(!catch_level)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
9649491998-02-27Fredrik Hübinette (Hubbe)  if(throw_value.type == T_ARRAY && throw_value.u.array->size) { union anything *a; a=low_array_get_item_ptr(throw_value.u.array, 0, T_STRING); if(a) { yyerror(a->string->str); }else{ yyerror("Nonstandard error format."); }
1994251999-09-06Fredrik Hübinette (Hubbe)  } else if(throw_value.type == T_OBJECT) { ref_push_object(throw_value.u.object); push_int(0); f_index(2); if(sp[-1].type != T_STRING) yyerror("Nonstandard error format."); else yyerror(sp[-1].u.string->str); pop_stack(); } else {
5267b71995-08-09Fredrik Hübinette (Hubbe)  yyerror("Nonstandard error format."); } } }else{
a29e021996-10-15Fredrik Hübinette (Hubbe)  if(foo.yes) pop_n_elems(sp-save_sp); else ret=sp-save_sp;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
a29e021996-10-15Fredrik Hübinette (Hubbe)  remove_callback(tmp_callback);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  while(new_program->num_strings > num_strings)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  new_program->num_strings--; free_string(new_program->strings[new_program->num_strings]);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  while(new_program->num_constants > num_constants)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
8132f31999-09-19Henrik Grubbström (Grubba)  struct program_constant *p_const;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  new_program->num_constants--;
8132f31999-09-19Henrik Grubbström (Grubba)  p_const = new_program->constants + new_program->num_constants; free_svalue(&p_const->sval); if (p_const->name) { free_string(p_const->name); p_const->name = NULL; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  new_program->num_program=jump;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; } static node *eval(node *n) { int args; extern struct svalue *sp; if(!is_const(n) || n->token==':') return n; args=eval_low(n); switch(args) { case -1: return n; break; case 0:
9649491998-02-27Fredrik Hübinette (Hubbe)  if(catch_level) return n;
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n); n=0; break; case 1:
9649491998-02-27Fredrik Hübinette (Hubbe)  if(catch_level && IS_ZERO(sp-1)) { pop_stack(); return n; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n); n=mksvaluenode(sp-1); pop_stack(); break; default: free_node(n); n=NULL; while(args--) { n=mknode(F_ARG_LIST,mksvaluenode(sp-1),n); pop_stack(); } }
a836c01999-11-12Henrik Grubbström (Grubba)  return dmalloc_touch(node *, n);
5267b71995-08-09Fredrik Hübinette (Hubbe) } INT32 last_function_opt_info;
329cc01997-02-17Fredrik Hübinette (Hubbe) static int stupid_args(node *n, int expected,int vargs)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
329cc01997-02-17Fredrik Hübinette (Hubbe)  if(!n) return expected; switch(n->token) { case F_PUSH_ARRAY: if(!vargs) return -1; if(stupid_args(CAR(n), expected,vargs) == expected+1) return 65535; return -1; case F_ARG_LIST: expected=stupid_args(CAR(n), expected,vargs); if(expected==-1) return -1; return stupid_args(CDR(n), expected,vargs); case F_LOCAL:
4218011999-01-31Fredrik Hübinette (Hubbe)  return (!n->u.integer.b && n->u.integer.a==expected) ? expected + 1 : -1;
329cc01997-02-17Fredrik Hübinette (Hubbe)  default: return -1; } }
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) static int is_null_branch(node *n)
329cc01997-02-17Fredrik Hübinette (Hubbe) { if(!n) return 1;
2a8cd81999-11-18Henrik Grubbström (Grubba)  if((n->token==F_CAST && n->type==void_type_string) || n->token == F_POP_VALUE)
329cc01997-02-17Fredrik Hübinette (Hubbe)  return is_null_branch(CAR(n)); if(n->token==F_ARG_LIST) return is_null_branch(CAR(n)) && is_null_branch(CDR(n)); return 0; } static struct svalue *is_stupid_func(node *n, int args,
3aa7831999-06-02Fredrik Hübinette (Hubbe)  int vargs, struct pike_string *type)
329cc01997-02-17Fredrik Hübinette (Hubbe) { node *a,*b; int tmp; while(1) { if(!n) return 0; if(n->token == F_ARG_LIST) { if(is_null_branch(CAR(n))) n=CDR(n); else n=CAR(n); continue; }
2a8cd81999-11-18Henrik Grubbström (Grubba)  if((n->token == F_CAST && n->type==void_type_string) || n->token == F_POP_VALUE)
329cc01997-02-17Fredrik Hübinette (Hubbe)  { n=CAR(n); continue; } break; }
9669e81997-02-27Fredrik Hübinette (Hubbe)  if(!n || n->token != F_RETURN) return 0;
329cc01997-02-17Fredrik Hübinette (Hubbe)  n=CAR(n);
9669e81997-02-27Fredrik Hübinette (Hubbe)  if(!n || n->token != F_APPLY) return 0;
329cc01997-02-17Fredrik Hübinette (Hubbe)  tmp=stupid_args(CDR(n),0,vargs); if(!(vargs?tmp==65535:tmp==args)) return 0; n=CAR(n);
9669e81997-02-27Fredrik Hübinette (Hubbe)  if(!n || n->token != F_CONSTANT) return 0;
a609b51998-01-28Fredrik Hübinette (Hubbe) 
3aa7831999-06-02Fredrik Hübinette (Hubbe)  if((count_arguments(n->type) < 0) == !vargs) return 0; if(minimum_arguments(type) < minimum_arguments(n->type)) return 0;
a609b51998-01-28Fredrik Hübinette (Hubbe) 
3aa7831999-06-02Fredrik Hübinette (Hubbe)  return &n->u.sval;
329cc01997-02-17Fredrik Hübinette (Hubbe) } int dooptcode(struct pike_string *name, node *n, struct pike_string *type, int modifiers) { union idptr tmp; int args, vargs, ret; struct svalue *foo;
046afe1999-11-11Henrik Grubbström (Grubba)  check_tree(check_node_hash(n),0);
3c0c281998-01-26Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(a_flag > 1)
d334771996-04-13Fredrik Hübinette (Hubbe)  fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
329cc01997-02-17Fredrik Hübinette (Hubbe)  args=count_arguments(type); if(args < 0) { args=~args; vargs=IDENTIFIER_VARARGS; }else{ vargs=0; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(compiler_pass==1)
329cc01997-02-17Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  tmp.offset=-1;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1b5eb41998-11-17Fredrik Hübinette (Hubbe)  if(a_flag > 4) { fprintf(stderr,"Making prototype (pass 1) for: "); print_tree(n); } #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }else{
969a291999-11-17Henrik Grubbström (Grubba) #if defined(SHARED_NODES) && !defined(IN_TPIKE) /* Try the local variable usage analyser. */ n = localopt(check_node_hash(n)); /* Try optimizing some more. */ optimize(n); #endif /* SHARED_NODES && !IN_TPIKE */ n = mknode(F_ARG_LIST,check_node_hash(n),0);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
046afe1999-11-11Henrik Grubbström (Grubba)  if((foo=is_stupid_func(check_node_hash(n), args, vargs, type)))
329cc01997-02-17Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN) { tmp.c_fun=foo->u.efun->function; ret=define_function(name, type, modifiers, IDENTIFIER_C_FUNCTION | vargs, &tmp); free_node(n);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1be5391998-01-29Fredrik Hübinette (Hubbe)  if(a_flag > 1) fprintf(stderr,"Identifer (C) = %d\n",ret); #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return ret; }
329cc01997-02-17Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  tmp.offset=PC; add_to_program(compiler_frame->max_number_of_locals); add_to_program(args);
329cc01997-02-17Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(a_flag > 2) { fprintf(stderr,"Coding: ");
046afe1999-11-11Henrik Grubbström (Grubba)  print_tree(check_node_hash(n));
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!num_parse_error) {
a7538d1998-05-12Fredrik Hübinette (Hubbe)  extern int remove_clear_locals; remove_clear_locals=args; if(vargs) remove_clear_locals++;
046afe1999-11-11Henrik Grubbström (Grubba)  do_code_block(check_node_hash(n));
a7538d1998-05-12Fredrik Hübinette (Hubbe)  remove_clear_locals=0x7fffffff;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
329cc01997-02-17Fredrik Hübinette (Hubbe)  ret=define_function(name, type, modifiers, IDENTIFIER_PIKE_FUNCTION | vargs, &tmp);
1be5391998-01-29Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1be5391998-01-29Fredrik Hübinette (Hubbe)  if(a_flag > 1) fprintf(stderr,"Identifer = %d\n",ret); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_node(n);
329cc01997-02-17Fredrik Hübinette (Hubbe)  return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
66d51c1997-03-04Fredrik Hübinette (Hubbe)