e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
2814552003-10-10Martin Stjernholm || $Id: peep.c,v 1.90 2003/10/10 01:18:25 mast Exp $
e576bb2002-10-11Martin Nilsson */
1b10db2002-10-08Martin Nilsson 
2199ed1996-04-13Fredrik Hübinette (Hubbe) #include "global.h" #include "language.h" #include "stralloc.h" #include "dynamic_buffer.h" #include "program.h" #include "las.h" #include "docode.h" #include "main.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
2199ed1996-04-13Fredrik Hübinette (Hubbe) #include "lex.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
66d51c1997-03-04Fredrik Hübinette (Hubbe) #include "peep.h"
062e9d1998-03-04Fredrik Hübinette (Hubbe) #include "dmalloc.h"
7310011998-05-01Henrik Grubbström (Grubba) #include "stuff.h"
327b991999-10-25Fredrik Hübinette (Hubbe) #include "bignum.h"
f76b4c2000-05-11Henrik Grubbström (Grubba) #include "opcodes.h"
d9a93b2001-07-01Fredrik Hübinette (Hubbe) #include "builtin_functions.h" #include "constants.h"
6a21702001-07-17Fredrik Hübinette (Hubbe) #include "interpret.h"
dd6bca2001-07-20Henrik Grubbström (Grubba) #include "pikecode.h"
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
2814552003-10-10Martin Stjernholm RCSID("$Id: peep.c,v 1.90 2003/10/10 01:18:25 mast Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
66d51c1997-03-04Fredrik Hübinette (Hubbe) static void asm_opt(void);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  dynamic_buffer instrbuf;
9ca13e2003-06-12Martin Nilsson #ifdef PIKE_DEBUG
2d12341997-03-10Fredrik Hübinette (Hubbe) static int hasarg(int opcode) { return instrs[opcode-F_OFFSET].flags & I_HASARG; }
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
a96ce92000-04-19Fredrik Hübinette (Hubbe) static int hasarg2(int opcode) { return instrs[opcode-F_OFFSET].flags & I_HASARG2; } static void dump_instr(p_instr *p) { if(!p) return; fprintf(stderr,"%s",get_token_name(p->opcode)); if(hasarg(p->opcode)) { fprintf(stderr,"(%d",p->arg); if(hasarg2(p->opcode)) fprintf(stderr,",%d",p->arg2); fprintf(stderr,")"); } } #endif
be478c1997-08-30Henrik Grubbström (Grubba) void init_bytecode(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
0412562002-10-04Marcus Comstedt  initialize_buf(&instrbuf);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void exit_bytecode(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
7a35a42000-08-14Henrik Grubbström (Grubba)  ptrdiff_t e, length;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  p_instr *c; c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr); for(e=0;e<length;e++) free_string(c->file); toss_buffer(&instrbuf); }
7a35a42000-08-14Henrik Grubbström (Grubba) ptrdiff_t insert_opcode2(unsigned int f, INT32 b, INT32 c, INT32 current_line, struct pike_string *current_file)
2199ed1996-04-13Fredrik Hübinette (Hubbe) { p_instr *p;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
a96ce92000-04-19Fredrik Hübinette (Hubbe)  if(!hasarg2(f) && c)
5aad932002-08-15Marcus Comstedt  Pike_fatal("hasarg2(%d) is wrong!\n",f);
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif p=(p_instr *)low_make_buf_space(sizeof(p_instr), &instrbuf);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(!instrbuf.s.len)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Low make buf space failed!!!!!!\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif p->opcode=f; p->line=current_line; copy_shared_string(p->file, current_file); p->arg=b;
a96ce92000-04-19Fredrik Hübinette (Hubbe)  p->arg2=c;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  return p - (p_instr *)instrbuf.s.str; }
7a35a42000-08-14Henrik Grubbström (Grubba) ptrdiff_t insert_opcode1(unsigned int f, INT32 b, INT32 current_line, struct pike_string *current_file)
a96ce92000-04-19Fredrik Hübinette (Hubbe) { #ifdef PIKE_DEBUG if(!hasarg(f) && b)
5aad932002-08-15Marcus Comstedt  Pike_fatal("hasarg(%d) is wrong!\n",f);
a96ce92000-04-19Fredrik Hübinette (Hubbe) #endif return insert_opcode2(f,b,0,current_line,current_file); }
7a35a42000-08-14Henrik Grubbström (Grubba) ptrdiff_t insert_opcode0(int f,int current_line, struct pike_string *current_file)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(hasarg(f))
5aad932002-08-15Marcus Comstedt  Pike_fatal("hasarg(%d) is wrong!\n",f);
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
a96ce92000-04-19Fredrik Hübinette (Hubbe)  return insert_opcode1(f,0,current_line, current_file);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
419fab1997-03-09Fredrik Hübinette (Hubbe) 
2199ed1996-04-13Fredrik Hübinette (Hubbe) void update_arg(int instr,INT32 arg) { p_instr *p;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
645e261996-04-23Fredrik Hübinette (Hubbe)  if(instr > (long)instrbuf.s.len / (long)sizeof(p_instr) || instr < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("update_arg outside known space.\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif p=(p_instr *)instrbuf.s.str; p[instr].arg=arg; }
80fe612001-07-21Fredrik Hübinette (Hubbe) #ifndef FLUSH_CODE_GENERATOR_STATE #define FLUSH_CODE_GENERATOR_STATE() #endif
2199ed1996-04-13Fredrik Hübinette (Hubbe) /**** Bytecode Generator *****/
66d51c1997-03-04Fredrik Hübinette (Hubbe) void assemble(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
bedc662003-09-26Henrik Grubbström (Grubba)  INT32 max_label=-1,tmp;
66d51c1997-03-04Fredrik Hübinette (Hubbe)  INT32 *labels, *jumps, *uses;
7a35a42000-08-14Henrik Grubbström (Grubba)  ptrdiff_t e, length;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  p_instr *c;
7386972001-06-30Fredrik Hübinette (Hubbe)  int reoptimize=!(debug_options & NO_PEEP_OPTIMIZING);
85f4f52001-01-31Martin Stjernholm #ifdef PIKE_DEBUG
bedc662003-09-26Henrik Grubbström (Grubba)  INT32 max_pointer=-1;
c6c6232002-08-30Henrik Grubbström (Grubba)  int synch_depth = 0;
4974fa2002-11-07Henrik Grubbström (Grubba)  size_t fun_start = Pike_compiler->new_program->num_program;
85f4f52001-01-31Martin Stjernholm #endif
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr);
c6c6232002-08-30Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
bedc662003-09-26Henrik Grubbström (Grubba)  if((a_flag > 1 && store_linenumbers) || a_flag > 2) { for (e = 0; e < length; e++) {
c6c6232002-08-30Henrik Grubbström (Grubba)  if (c[e].opcode == F_POP_SYNCH_MARK) synch_depth--; fprintf(stderr, "~~~%4d %4lx %*s", c[e].line,
3bc7a62002-09-24Henrik Grubbström (Grubba)  DO_NOT_WARN((unsigned long)e), synch_depth, "");
c6c6232002-08-30Henrik Grubbström (Grubba)  dump_instr(c+e); fprintf(stderr,"\n"); if (c[e].opcode == F_SYNCH_MARK) synch_depth++; }
bedc662003-09-26Henrik Grubbström (Grubba)  if (synch_depth) { Pike_fatal("Unbalanced sync_mark/pop_sync_mark: %d\n", synch_depth); }
c6c6232002-08-30Henrik Grubbström (Grubba)  } #endif
bedc662003-09-26Henrik Grubbström (Grubba)  for(e=0;e<length;e++,c++) { if(c->opcode == F_LABEL) {
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(c->arg > max_label) max_label = c->arg;
bedc662003-09-26Henrik Grubbström (Grubba)  } #ifdef PIKE_DEBUG else if (instrs[c->opcode - F_OFFSET].flags & I_POINTER) { if (c->arg > max_pointer) max_pointer = c->arg; } #endif /* PIKE_DEBUG */ } #ifdef PIKE_DEBUG if (max_pointer > max_label) { fprintf(stderr, "Reference to undefined label %d > %d\n" "Bad instructions are marked with '***':\n", max_pointer, max_label); c=(p_instr *)instrbuf.s.str; for(e=0;e<length;e++,c++) { if (c->opcode == F_POP_SYNCH_MARK) synch_depth--; fprintf(stderr, " * %4d %4lx ", c->line, DO_NOT_WARN((unsigned long)e)); dump_instr(c); if ((instrs[c->opcode - F_OFFSET].flags & I_POINTER) && (c->arg > max_label)) { fprintf(stderr, " ***\n"); } else { fprintf(stderr, "\n"); } if (c->opcode == F_SYNCH_MARK) synch_depth++; } Pike_fatal("Reference to undefined label %d > %d\n", max_pointer, max_label); } #endif /* PIKE_DEBUG */
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
61e9a01998-01-25Fredrik Hübinette (Hubbe)  labels=(INT32 *)xalloc(sizeof(INT32) * (max_label+2)); jumps=(INT32 *)xalloc(sizeof(INT32) * (max_label+2)); uses=(INT32 *)xalloc(sizeof(INT32) * (max_label+2));
66d51c1997-03-04Fredrik Hübinette (Hubbe) 
928f952000-11-30Fredrik Hübinette (Hubbe)  while(reoptimize)
66d51c1997-03-04Fredrik Hübinette (Hubbe)  {
928f952000-11-30Fredrik Hübinette (Hubbe)  reoptimize=0; for(e=0;e<=max_label;e++) { labels[e]=jumps[e]=-1; uses[e]=0; } c=(p_instr *)instrbuf.s.str;
c6c6232002-08-30Henrik Grubbström (Grubba)  length=instrbuf.s.len / sizeof(p_instr);
928f952000-11-30Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++)
c6c6232002-08-30Henrik Grubbström (Grubba)  if(c[e].opcode == F_LABEL && c[e].arg>=0) {
928f952000-11-30Fredrik Hübinette (Hubbe)  labels[c[e].arg]=DO_NOT_WARN((INT32)e);
c6c6232002-08-30Henrik Grubbström (Grubba)  }
928f952000-11-30Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++)
66d51c1997-03-04Fredrik Hübinette (Hubbe)  {
928f952000-11-30Fredrik Hübinette (Hubbe)  if(instrs[c[e].opcode-F_OFFSET].flags & I_POINTER)
66d51c1997-03-04Fredrik Hübinette (Hubbe)  {
928f952000-11-30Fredrik Hübinette (Hubbe)  while(1)
419fab1997-03-09Fredrik Hübinette (Hubbe)  {
1f88bf2001-09-24Henrik Grubbström (Grubba)  int tmp;
928f952000-11-30Fredrik Hübinette (Hubbe)  tmp=labels[c[e].arg]; while(tmp<length && (c[tmp].opcode == F_LABEL || c[tmp].opcode == F_NOP)) tmp++; if(tmp>=length) break; if(c[tmp].opcode==F_BRANCH) { c[e].arg=c[tmp].arg; continue; }
419fab1997-03-09Fredrik Hübinette (Hubbe) #define TWOO(X,Y) (((X)<<8)+(Y))
928f952000-11-30Fredrik Hübinette (Hubbe)  switch(TWOO(c[e].opcode,c[tmp].opcode)) { case TWOO(F_LOR,F_BRANCH_WHEN_NON_ZERO): c[e].opcode=F_BRANCH_WHEN_NON_ZERO; case TWOO(F_LOR,F_LOR): c[e].arg=c[tmp].arg; continue; case TWOO(F_LAND,F_BRANCH_WHEN_ZERO): c[e].opcode=F_BRANCH_WHEN_ZERO; case TWOO(F_LAND,F_LAND): c[e].arg=c[tmp].arg; continue; case TWOO(F_LOR, F_RETURN): c[e].opcode=F_RETURN_IF_TRUE;
2814552003-10-10Martin Stjernholm  goto pointer_opcode_done;
928f952000-11-30Fredrik Hübinette (Hubbe)  case TWOO(F_BRANCH, F_RETURN): case TWOO(F_BRANCH, F_RETURN_0): case TWOO(F_BRANCH, F_RETURN_1): case TWOO(F_BRANCH, F_RETURN_LOCAL): if(c[e].file) free_string(c[e].file); c[e]=c[tmp]; if(c[e].file) add_ref(c[e].file);
2814552003-10-10Martin Stjernholm  goto pointer_opcode_done;
928f952000-11-30Fredrik Hübinette (Hubbe)  }
71c5b92000-11-27Fredrik Hübinette (Hubbe)  break;
419fab1997-03-09Fredrik Hübinette (Hubbe)  }
2814552003-10-10Martin Stjernholm #ifdef PIKE_DEBUG if (c[e].arg < 0 || c[e].arg > max_label) Pike_fatal ("Invalid index into uses: %d\n", c[e].arg); #endif
928f952000-11-30Fredrik Hübinette (Hubbe)  uses[c[e].arg]++;
66d51c1997-03-04Fredrik Hübinette (Hubbe)  }
2814552003-10-10Martin Stjernholm  pointer_opcode_done:;
66d51c1997-03-04Fredrik Hübinette (Hubbe)  }
928f952000-11-30Fredrik Hübinette (Hubbe)  for(e=0;e<=max_label;e++) { if(!uses[e] && labels[e]>=0) { c[labels[e]].opcode=F_NOP; reoptimize++; } } if(!reoptimize) break; asm_opt();
3bc7a62002-09-24Henrik Grubbström (Grubba) #if 1
2814552003-10-10Martin Stjernholm #ifdef PIKE_DEBUG if (a_flag > 3) fprintf(stderr, "Rerunning optimizer.\n"); #endif
3bc7a62002-09-24Henrik Grubbström (Grubba) #else /* !1 */
928f952000-11-30Fredrik Hübinette (Hubbe)  reoptimize=0;
3bc7a62002-09-24Henrik Grubbström (Grubba) #endif /* 1 */
66d51c1997-03-04Fredrik Hübinette (Hubbe)  } c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr); for(e=0;e<=max_label;e++) labels[e]=jumps[e]=-1;
85f4f52001-01-31Martin Stjernholm #ifdef PIKE_DEBUG synch_depth = 0; #endif
80fe612001-07-21Fredrik Hübinette (Hubbe)  FLUSH_CODE_GENERATOR_STATE();
2199ed1996-04-13Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c6c6232002-08-30Henrik Grubbström (Grubba)  if (c != (((p_instr *)instrbuf.s.str)+e)) { Pike_fatal("Instruction loop deviates. 0x%04x != 0x%04x\n", e, DO_NOT_WARN((INT32)(c - ((p_instr *)instrbuf.s.str)))); }
2ba9191999-10-23Fredrik Hübinette (Hubbe)  if((a_flag > 2 && store_linenumbers) || a_flag > 3)
2199ed1996-04-13Fredrik Hübinette (Hubbe)  {
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_POP_SYNCH_MARK) synch_depth--; fprintf(stderr, "===%4d %4lx %*s", c->line,
1302b12001-08-14Martin Stjernholm  DO_NOT_WARN((unsigned long)PIKE_PC), synch_depth, "");
a96ce92000-04-19Fredrik Hübinette (Hubbe)  dump_instr(c); fprintf(stderr,"\n");
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_SYNCH_MARK) synch_depth++;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } #endif if(store_linenumbers) store_linenumber(c->line, c->file); switch(c->opcode) {
873ceb2000-04-30Fredrik Hübinette (Hubbe)  case F_NOP:
928f952000-11-30Fredrik Hübinette (Hubbe)  case F_NOTREACHED:
873ceb2000-04-30Fredrik Hübinette (Hubbe)  case F_START_FUNCTION: break;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  case F_ALIGN:
dd6bca2001-07-20Henrik Grubbström (Grubba)  ins_align(c->arg);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  break;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  case F_BYTE:
dd6bca2001-07-20Henrik Grubbström (Grubba)  ins_byte((unsigned char)(c->arg));
873ceb2000-04-30Fredrik Hübinette (Hubbe)  break;
9b08a21998-03-31Fredrik Hübinette (Hubbe)  case F_DATA:
dd6bca2001-07-20Henrik Grubbström (Grubba)  ins_data(c->arg);
9b08a21998-03-31Fredrik Hübinette (Hubbe)  break;
a468a02001-07-24Henrik Grubbström (Grubba)  case F_ENTRY: #ifdef INS_ENTRY INS_ENTRY(); #endif /* INS_ENTRY */ break;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  case F_LABEL:
873ceb2000-04-30Fredrik Hübinette (Hubbe)  if(c->arg == -1) break;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(c->arg > max_label || c->arg < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("max_label calculation failed!\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(labels[c->arg] != -1)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Duplicate label!\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
80fe612001-07-21Fredrik Hübinette (Hubbe)  FLUSH_CODE_GENERATOR_STATE();
b783bb2001-08-15Marcus Comstedt  labels[c->arg] = DO_NOT_WARN((INT32)PIKE_PC);
9be5602002-11-12Henrik Grubbström (Grubba)  if ((e+1 < length) && (c[1].opcode != F_LABEL) && (c[1].opcode != F_BYTE) && (c[1].opcode != F_DATA)) { /* Don't add redundant code before labels or raw data. */ UPDATE_PC(); }
2199ed1996-04-13Fredrik Hübinette (Hubbe)  break;
3958992001-06-23Fredrik Hübinette (Hubbe)  case F_VOLATILE_RETURN: ins_f_byte(F_RETURN); break;
0420702002-11-02Henrik Grubbström (Grubba)  case F_POINTER: #ifdef PIKE_DEBUG if(c->arg > max_label || c->arg < 0) Pike_fatal("Jump to unknown label?\n"); #endif tmp = DO_NOT_WARN((INT32)PIKE_PC); ins_pointer(jumps[c->arg]); jumps[c->arg]=tmp; break;
2d12341997-03-10Fredrik Hübinette (Hubbe)  default:
5bb0f12002-05-11Martin Stjernholm  switch(instrs[c->opcode - F_OFFSET].flags & I_IS_MASK)
2d12341997-03-10Fredrik Hübinette (Hubbe)  {
f142842003-08-06Martin Stjernholm  case I_ISPTRJUMP:
852c152001-07-23Fredrik Hübinette (Hubbe) #ifdef INS_F_JUMP tmp=INS_F_JUMP(c->opcode); if(tmp != -1) {
2dea8f2001-08-16Marcus Comstedt  UPDATE_F_JUMP(tmp, jumps[c->arg]);
852c152001-07-23Fredrik Hübinette (Hubbe)  jumps[c->arg]=~tmp; break; } #endif
2d12341997-03-10Fredrik Hübinette (Hubbe)  ins_f_byte(c->opcode);
7951942000-04-20Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
0420702002-11-02Henrik Grubbström (Grubba)  if(c->arg > max_label || c->arg < 0) Pike_fatal("Jump to unknown label?\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
1302b12001-08-14Martin Stjernholm  tmp = DO_NOT_WARN((INT32)PIKE_PC);
dd6bca2001-07-20Henrik Grubbström (Grubba)  ins_pointer(jumps[c->arg]);
2d12341997-03-10Fredrik Hübinette (Hubbe)  jumps[c->arg]=tmp; break;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
f142842003-08-06Martin Stjernholm  case I_ISPTRJUMPARGS:
b401532002-11-02Henrik Grubbström (Grubba) #ifdef INS_F_JUMP_WITH_TWO_ARGS tmp = INS_F_JUMP_WITH_TWO_ARGS(c->opcode, c->arg, c->arg2); if(tmp != -1) { #ifdef ADJUST_PIKE_PC if (instrs[c->opcode - F_OFFSET].flags & I_PC_AT_NEXT) ADJUST_PIKE_PC (PIKE_PC); #endif /* Step ahead to the pointer instruction, and inline it. */ #ifdef PIKE_DEBUG if (c[1].opcode != F_POINTER) { Pike_fatal("Expected opcode %s to be followed by a pointer\n", instrs[c->opcode - F_OFFSET].name); } #endif /* PIKE_DEBUG */ c++; e++; UPDATE_F_JUMP(tmp, jumps[c->arg]); jumps[c->arg]=~tmp; break; } #endif /* INS_F_JUMP_WITH_TWO_ARGS */ /* FALL_THROUGH * * Note that the pointer in this case will be handled by the * next turn through the loop. */
dd6bca2001-07-20Henrik Grubbström (Grubba)  case I_TWO_ARGS:
f142842003-08-06Martin Stjernholm  case I_ISJUMPARGS:
dd6bca2001-07-20Henrik Grubbström (Grubba)  ins_f_byte_with_2_args(c->opcode, c->arg, c->arg2); break;
0420702002-11-02Henrik Grubbström (Grubba) 
f142842003-08-06Martin Stjernholm  case I_ISPTRJUMPARG:
b401532002-11-02Henrik Grubbström (Grubba) #ifdef INS_F_JUMP_WITH_ARG tmp = INS_F_JUMP_WITH_ARG(c->opcode, c->arg); if(tmp != -1) { #ifdef ADJUST_PIKE_PC if (instrs[c->opcode - F_OFFSET].flags & I_PC_AT_NEXT) ADJUST_PIKE_PC (PIKE_PC); #endif /* Step ahead to the pointer instruction, and inline it. */ #ifdef PIKE_DEBUG if (c[1].opcode != F_POINTER) { Pike_fatal("Expected opcode %s to be followed by a pointer\n", instrs[c->opcode - F_OFFSET].name); } #endif /* PIKE_DEBUG */ c++; e++; UPDATE_F_JUMP(tmp, jumps[c->arg]); jumps[c->arg]=~tmp; break; } #endif /* INS_F_JUMP_WITH_ARG */ /* FALL_THROUGH * * Note that the pointer in this case will be handled by the * next turn through the loop. */
dd6bca2001-07-20Henrik Grubbström (Grubba)  case I_HASARG:
f142842003-08-06Martin Stjernholm  case I_ISJUMPARG:
dd6bca2001-07-20Henrik Grubbström (Grubba)  ins_f_byte_with_arg(c->opcode, c->arg); break;
2d12341997-03-10Fredrik Hübinette (Hubbe)  case 0:
f142842003-08-06Martin Stjernholm  case I_ISJUMP:
2199ed1996-04-13Fredrik Hübinette (Hubbe)  ins_f_byte(c->opcode);
2d12341997-03-10Fredrik Hübinette (Hubbe)  break;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2d12341997-03-10Fredrik Hübinette (Hubbe)  default:
5aad932002-08-15Marcus Comstedt  Pike_fatal("Unknown instruction type.\n");
2d12341997-03-10Fredrik Hübinette (Hubbe) #endif }
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }
852c152001-07-23Fredrik Hübinette (Hubbe) 
5bb0f12002-05-11Martin Stjernholm #ifdef ADJUST_PIKE_PC if (instrs[c->opcode - F_OFFSET].flags & I_PC_AT_NEXT) ADJUST_PIKE_PC (PIKE_PC); #endif
0420702002-11-02Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (instrs[c->opcode - F_OFFSET].flags & I_HASPOINTER) {
dabab32002-11-04Henrik Grubbström (Grubba)  if ((e+1 >= length) || (c[1].opcode != F_POINTER)) {
0420702002-11-02Henrik Grubbström (Grubba)  Pike_fatal("Expected instruction %s to be followed by a pointer.\n"
dabab32002-11-04Henrik Grubbström (Grubba)  "Got %s (%d != %d)\n.",
0420702002-11-02Henrik Grubbström (Grubba)  instrs[c->opcode - F_OFFSET].name,
dabab32002-11-04Henrik Grubbström (Grubba)  (e+1 < length)?instrs[c[1].opcode - F_OFFSET].name:"EOI", (e+1 < length)?c[1].opcode:0, F_POINTER);
0420702002-11-02Henrik Grubbström (Grubba)  } } #endif /* PIKE_DEBUG */
852c152001-07-23Fredrik Hübinette (Hubbe) #ifdef ALIGN_PIKE_JUMPS if(e+1 < length) {
b401532002-11-02Henrik Grubbström (Grubba)  /* FIXME: Note that this code won't work for opcodes of type
f142842003-08-06Martin Stjernholm  * I_ISPTRJUMPARG or I_ISPTRJUMPARGS, since c may already
b401532002-11-02Henrik Grubbström (Grubba)  * have been advanced to the corresponding F_POINTER. * With the current opcode set this is a non-issue, but... * /grubba 2002-11-02 */
852c152001-07-23Fredrik Hübinette (Hubbe)  switch(c->opcode) { case F_RETURN: case F_VOLATILE_RETURN: case F_BRANCH: case F_RETURN_0: case F_RETURN_1: case F_RETURN_LOCAL: #define CALLS(X) \ case PIKE_CONCAT3(F_,X,_AND_RETURN): \ case PIKE_CONCAT3(F_MARK_,X,_AND_RETURN): CALLS(APPLY) CALLS(CALL_FUNCTION) CALLS(CALL_LFUN) CALLS(CALL_BUILTIN)
1302b12001-08-14Martin Stjernholm  while( ((INT32) PIKE_PC & (ALIGN_PIKE_JUMPS-1) ) )
852c152001-07-23Fredrik Hübinette (Hubbe)  ins_byte(0); } } #endif
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c++; } for(e=0;e<=max_label;e++) {
c696242001-07-18Henrik Grubbström (Grubba)  INT32 tmp2=labels[e];
2199ed1996-04-13Fredrik Hübinette (Hubbe)  while(jumps[e]!=-1) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(labels[e]==-1)
c6c6232002-08-30Henrik Grubbström (Grubba)  Pike_fatal("Hyperspace error: unknown jump point %ld(%ld) at %d (pc=%x).\n", PTRDIFF_T_TO_LONG(e), PTRDIFF_T_TO_LONG(max_label), labels[e], jumps[e]);
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
852c152001-07-23Fredrik Hübinette (Hubbe) #ifdef INS_F_JUMP if(jumps[e] < 0) {
2dea8f2001-08-16Marcus Comstedt  tmp = READ_F_JUMP(~jumps[e]);
852c152001-07-23Fredrik Hübinette (Hubbe)  UPDATE_F_JUMP(~jumps[e], tmp2); jumps[e]=tmp; continue; } #endif
dd6bca2001-07-20Henrik Grubbström (Grubba)  tmp = read_pointer(jumps[e]); upd_pointer(jumps[e], tmp2 - jumps[e]);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  jumps[e]=tmp; } } free((char *)labels); free((char *)jumps);
66d51c1997-03-04Fredrik Hübinette (Hubbe)  free((char *)uses);
4974fa2002-11-07Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (a_flag > 6) { size_t len = (Pike_compiler->new_program->num_program - fun_start)* sizeof(PIKE_OPCODE_T);
2abf522002-11-07Henrik Grubbström (Grubba)  fprintf(stderr, "Code at offset %d through %d:\n", fun_start, Pike_compiler->new_program->num_program-1);
4974fa2002-11-07Henrik Grubbström (Grubba) #ifdef DISASSEMBLE_CODE DISASSEMBLE_CODE(Pike_compiler->new_program->program + fun_start, len); #else /* !DISASSEMBLE_CODE */ { /* FIXME: Hexdump here. */ } #endif /* DISASSEMBLE_CODE */ } #endif /* PIKE_DEBUG */
2199ed1996-04-13Fredrik Hübinette (Hubbe)  exit_bytecode(); } /**** Peephole optimizer ****/
a7538d1998-05-12Fredrik Hübinette (Hubbe) int remove_clear_locals=0x7fffffff;
7a35a42000-08-14Henrik Grubbström (Grubba) static int fifo_len; static ptrdiff_t eye, len;
06983f1996-09-22Fredrik Hübinette (Hubbe) static p_instr *instructions;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
9cdf3f2000-12-02Henrik Grubbström (Grubba) static INLINE ptrdiff_t insopt2(int f, INT32 a, INT32 b, int cl, struct pike_string *cf)
419fab1997-03-09Fredrik Hübinette (Hubbe) { p_instr *p;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
a96ce92000-04-19Fredrik Hübinette (Hubbe)  if(!hasarg2(f) && b)
5aad932002-08-15Marcus Comstedt  Pike_fatal("hasarg2(%d /*%s */) is wrong!\n",f,get_f_name(f));
419fab1997-03-09Fredrik Hübinette (Hubbe) #endif p=(p_instr *)low_make_buf_space(sizeof(p_instr), &instrbuf); if(fifo_len) { MEMMOVE(p-fifo_len+1,p-fifo_len,fifo_len*sizeof(p_instr)); p-=fifo_len; }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
419fab1997-03-09Fredrik Hübinette (Hubbe)  if(!instrbuf.s.len)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Low make buf space failed!!!!!!\n");
419fab1997-03-09Fredrik Hübinette (Hubbe) #endif p->opcode=f;
e7df5b1997-03-17Fredrik Hübinette (Hubbe)  p->line=cl;
9cdf3f2000-12-02Henrik Grubbström (Grubba)  copy_shared_string(p->file, cf);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  p->arg=a; p->arg2=b;
419fab1997-03-09Fredrik Hübinette (Hubbe)  return p - (p_instr *)instrbuf.s.str; }
9cdf3f2000-12-02Henrik Grubbström (Grubba) static INLINE ptrdiff_t insopt1(int f, INT32 a, int cl, struct pike_string *cf)
a96ce92000-04-19Fredrik Hübinette (Hubbe) { #ifdef PIKE_DEBUG if(!hasarg(f) && a)
5aad932002-08-15Marcus Comstedt  Pike_fatal("hasarg(%d /* %s */) is wrong!\n",f,get_f_name(f));
a96ce92000-04-19Fredrik Hübinette (Hubbe) #endif return insopt2(f,a,0,cl, cf); }
8d553a2000-12-02Henrik Grubbström (Grubba) static INLINE ptrdiff_t insopt0(int f, int cl, struct pike_string *cf)
419fab1997-03-09Fredrik Hübinette (Hubbe) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
419fab1997-03-09Fredrik Hübinette (Hubbe)  if(hasarg(f))
5aad932002-08-15Marcus Comstedt  Pike_fatal("hasarg(%d /* %s */) is wrong!\n",f,get_f_name(f));
419fab1997-03-09Fredrik Hübinette (Hubbe) #endif
a96ce92000-04-19Fredrik Hübinette (Hubbe)  return insopt2(f,0,0,cl, cf);
419fab1997-03-09Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) static void debug(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
645e261996-04-23Fredrik Hübinette (Hubbe)  if(fifo_len > (long)instrbuf.s.len / (long)sizeof(p_instr))
66d51c1997-03-04Fredrik Hübinette (Hubbe)  fifo_len=(long)instrbuf.s.len / (long)sizeof(p_instr);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(eye < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Popped beyond start of code.\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(instrbuf.s.len) {
66d51c1997-03-04Fredrik Hübinette (Hubbe)  p_instr *p;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  p=(p_instr *)low_make_buf_space(0, &instrbuf); if(!p[-1].file)
5aad932002-08-15Marcus Comstedt  Pike_fatal("No file name on last instruction!\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } #endif
66d51c1997-03-04Fredrik Hübinette (Hubbe) }
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) static INLINE p_instr *instr(int offset)
2199ed1996-04-13Fredrik Hübinette (Hubbe) { p_instr *p; debug();
419fab1997-03-09Fredrik Hübinette (Hubbe)  if(offset < fifo_len)
2199ed1996-04-13Fredrik Hübinette (Hubbe)  {
419fab1997-03-09Fredrik Hübinette (Hubbe)  p=(p_instr *)low_make_buf_space(0, &instrbuf); p-=fifo_len; p+=offset; if(((char *)p)<instrbuf.s.str) return 0; return p;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }else{
419fab1997-03-09Fredrik Hübinette (Hubbe)  offset-=fifo_len; offset+=eye; if(offset >= len) return 0; return instructions+offset;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } }
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) static INLINE int opcode(int offset)
2199ed1996-04-13Fredrik Hübinette (Hubbe) { p_instr *a; a=instr(offset); if(a) return a->opcode; return -1; }
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) static INLINE int argument(int offset)
2199ed1996-04-13Fredrik Hübinette (Hubbe) { p_instr *a; a=instr(offset); if(a) return a->arg; return -1; }
a96ce92000-04-19Fredrik Hübinette (Hubbe) static INLINE int argument2(int offset) { p_instr *a; a=instr(offset); if(a) return a->arg2; return -1; }
be478c1997-08-30Henrik Grubbström (Grubba) static void advance(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) { if(fifo_len) { fifo_len--; }else{ p_instr *p;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((p=instr(0)))
a96ce92000-04-19Fredrik Hübinette (Hubbe)  insert_opcode2(p->opcode, p->arg, p->arg2, p->line, p->file);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  eye++; } debug(); } static void pop_n_opcodes(int n) {
66d51c1997-03-04Fredrik Hübinette (Hubbe)  int e,d; if(fifo_len)
2199ed1996-04-13Fredrik Hübinette (Hubbe)  {
66d51c1997-03-04Fredrik Hübinette (Hubbe)  p_instr *p;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
419fab1997-03-09Fredrik Hübinette (Hubbe)  d=n; if(d>fifo_len) d=fifo_len;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
66d51c1997-03-04Fredrik Hübinette (Hubbe)  if((long)d > (long)instrbuf.s.len / (long)sizeof(p_instr))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Popping out of instructions.\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
66d51c1997-03-04Fredrik Hübinette (Hubbe) 
b956702000-11-25Henrik Grubbström (Grubba)  /* FIXME: It looks like the fifo could be optimized. * /grubba 2000-11-21 (in Versailles) */
66d51c1997-03-04Fredrik Hübinette (Hubbe)  p=(p_instr *)low_make_buf_space(0, &instrbuf);
419fab1997-03-09Fredrik Hübinette (Hubbe)  p-=fifo_len;
66d51c1997-03-04Fredrik Hübinette (Hubbe)  for(e=0;e<d;e++) free_string(p[e].file); fifo_len-=d; if(fifo_len) MEMMOVE(p,p+d,fifo_len*sizeof(p_instr)); n-=d;
419fab1997-03-09Fredrik Hübinette (Hubbe)  low_make_buf_space(-((INT32)sizeof(p_instr))*d, &instrbuf);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }
66d51c1997-03-04Fredrik Hübinette (Hubbe)  eye+=n;
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
b956702000-11-25Henrik Grubbström (Grubba) #define DO_OPTIMIZATION_PREQUEL(topop) do { \ struct pike_string *cf; \ INT32 cl=instr(0)->line; \ \ DO_IF_DEBUG( \ if(a_flag>5) \ { \ int e; \ fprintf(stderr,"PEEP at %d:",cl); \ for(e=0;e<topop;e++) \ { \ fprintf(stderr," "); \ dump_instr(instr(e)); \ } \ fprintf(stderr," => "); \ } \ ) \ \ copy_shared_string(cf,instr(0)->file); \ pop_n_opcodes(topop) #define DO_OPTIMIZATION_POSTQUEL(q) \ fifo_len+=q; \ free_string(cf); \ debug(); \ \ DO_IF_DEBUG( \ if(a_flag>5) \ { \ int e; \ for(e=0;e<q;e++) \ { \ fprintf(stderr," "); \ dump_instr(instr(e)); \ } \ fprintf(stderr,"\n"); \ } \ ) \ \ fifo_len += q + 3; \ } while(0)
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) static void do_optimization(int topop, ...) { va_list arglist;
c6c6232002-08-30Henrik Grubbström (Grubba)  int q=0; int oplen;
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
b956702000-11-25Henrik Grubbström (Grubba)  DO_OPTIMIZATION_PREQUEL(topop);
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  va_start(arglist, topop);
c6c6232002-08-30Henrik Grubbström (Grubba)  while((oplen = va_arg(arglist, int)))
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  { q++;
c6c6232002-08-30Henrik Grubbström (Grubba)  switch(oplen)
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  {
c6c6232002-08-30Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG default: Pike_fatal("Unsupported argument number: %d\n", oplen);
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  break;
c6c6232002-08-30Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  case 1:
c6c6232002-08-30Henrik Grubbström (Grubba)  { int i=va_arg(arglist, int); insopt0(i,cl,cf); } break;
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  case 2:
c6c6232002-08-30Henrik Grubbström (Grubba)  { int i=va_arg(arglist, int); int j=va_arg(arglist, int); insopt1(i,j,cl,cf); } break;
a96ce92000-04-19Fredrik Hübinette (Hubbe)  case 3:
c6c6232002-08-30Henrik Grubbström (Grubba)  { int i=va_arg(arglist, int); int j=va_arg(arglist, int); int k=va_arg(arglist, int); insopt2(i,j,k,cl,cf); } break;
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  } } va_end(arglist);
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
b956702000-11-25Henrik Grubbström (Grubba)  DO_OPTIMIZATION_POSTQUEL(q);
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) }
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
66d51c1997-03-04Fredrik Hübinette (Hubbe) static void asm_opt(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(a_flag > 3) { p_instr *c;
7a35a42000-08-14Henrik Grubbström (Grubba)  ptrdiff_t e, length;
85f4f52001-01-31Martin Stjernholm  int synch_depth = 0;
7a35a42000-08-14Henrik Grubbström (Grubba) 
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr);
2814552003-10-10Martin Stjernholm  fprintf(stderr,"Before peep optimization:\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++,c++) {
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_POP_SYNCH_MARK) synch_depth--;
2814552003-10-10Martin Stjernholm  fprintf(stderr,"<<<%4d: %*s",c->line,synch_depth,"");
a96ce92000-04-19Fredrik Hübinette (Hubbe)  dump_instr(c); fprintf(stderr,"\n");
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_SYNCH_MARK) synch_depth++;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } } #endif #include "peep_engine.c"
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(a_flag > 4) { p_instr *c;
7a35a42000-08-14Henrik Grubbström (Grubba)  ptrdiff_t e, length;
2814552003-10-10Martin Stjernholm  int synch_depth = 0;
7a35a42000-08-14Henrik Grubbström (Grubba) 
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr);
2814552003-10-10Martin Stjernholm  fprintf(stderr,"After peep optimization:\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++,c++) {
2814552003-10-10Martin Stjernholm  if (c->opcode == F_POP_SYNCH_MARK) synch_depth--; fprintf(stderr,">>>%4d: %*s",c->line,synch_depth,"");
a96ce92000-04-19Fredrik Hübinette (Hubbe)  dump_instr(c); fprintf(stderr,"\n");
2814552003-10-10Martin Stjernholm  if (c->opcode == F_SYNCH_MARK) synch_depth++;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } } #endif }