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"
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
d242722001-07-17Henrik Grubbström (Grubba) RCSID("$Id: peep.c,v 1.58 2001/07/17 20:16:40 grubba 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;
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; } #ifdef PIKE_DEBUG 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) {
e43ca21996-11-15Fredrik Hübinette (Hubbe)  low_reinit_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) 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) fatal("Low make buf space failed!!!!!!\n"); #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) fatal("hasarg(%d) is wrong!\n",f); #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))
596e361998-03-31Fredrik Hübinette (Hubbe)  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)
2199ed1996-04-13Fredrik Hübinette (Hubbe)  fatal("update_arg outside known space.\n"); #endif p=(p_instr *)instrbuf.s.str; p[instr].arg=arg; } /**** Bytecode Generator *****/
0996a92001-07-17Henrik Grubbström (Grubba) #ifdef PIKE_USE_MACHINE_CODE
1524392001-07-16Fredrik Hübinette (Hubbe) /* FIXME: Move this to pike_cpulib.h */
0996a92001-07-17Henrik Grubbström (Grubba) #ifdef __GNUC__
f822262001-07-16Fredrik Hübinette (Hubbe)  #define PUSH_INT(X) ins_int((INT32)(X), add_to_program) #define PUSH_ADDR(X) PUSH_INT((X))
1524392001-07-16Fredrik Hübinette (Hubbe) 
0996a92001-07-17Henrik Grubbström (Grubba) #ifdef __i386__
1524392001-07-16Fredrik Hübinette (Hubbe) /* This is ugly, but since the code may be moved we cannot use * relative addressing :( */ #define CALL_ABSOLUTE(X) do{ \ add_to_program(0xb8); /* mov $xxx,%eax */ \ PUSH_INT(X); \ add_to_program(0xff); /* jsr *(%eax) */ \ add_to_program(0xd0); \ }while(0)
6a21702001-07-17Fredrik Hübinette (Hubbe) #define UPDATE_PC() do { \ INT32 tmp=PC; \ add_to_program(0xa1 /* mov $xxxxx, %eax */); \ ins_int((INT32)(&Pike_interpreter.frame_pointer), add_to_program); \ \ add_to_program(0xc7); /* movl $xxxxx, yy%(eax) */ \ add_to_program(0x40); \ add_to_program(OFFSETOF(pike_frame, pc)); \ ins_int((INT32)tmp, add_to_program); \ }while(0)
f822262001-07-16Fredrik Hübinette (Hubbe) 
0996a92001-07-17Henrik Grubbström (Grubba) #elif defined(sparc) #define REG_O0 8 #define REG_O1 9 #define REG_O2 10 #define REG_O3 11 #define REG_O4 12 #define REG_O5 13 #define REG_O6 14 #define REG_O7 15 #define SET_REG(REG, X) do { \ INT32 val_ = X; \ INT32 reg_ = REG; \ if ((-4096 <= val_) && (val_ <= 4095)) { \ /* or %g0, val_, reg */ \ PUSH_INT(0x80102000|(reg_<<25)|(val_ & 0x1fff)); \ } else { \ /* sethi %hi(val_), reg */ \ PUSH_INT(0x01000000|(reg_<<25)|((val_ >> 10)&0x3fffff)); \ if (val_ & 0x3ff) { \ /* or reg, %lo(val_), reg */ \ PUSH_INT(0x80102000|(reg_<<25)|(reg_<<14)|(val_ & 0x0fff)); \ } \ if (val_ < 0) { \ /* sra reg, %g0, reg */ \ PUSH_INT(0x81380000|(reg_<<25)|(reg_<<14)); \ } \ } \ } while(0) #define CALL_ABSOLUTE(X) do { \ SET_REG(REG_O2, (INT32)(X)); \ /* jmpl %o2, %o7 */ \
d242722001-07-17Henrik Grubbström (Grubba)  PUSH_INT(0x81c00000|(REG_O7<<25)|(REG_O2<<14)); \
0996a92001-07-17Henrik Grubbström (Grubba)  /* noop */ \ PUSH_INT(0x01000000); \ } while(0) #define UPDATE_PC() do { \ INT32 tmp = PC; \ SET_REG(REG_O3, ((INT32)(&Pike_interpreter.frame_pointer))); \ /* lduw %o3, %o3 */ \ PUSH_INT(0xc0000000|(REG_O3<<25)|(REG_O3<<14)); \ SET_REG(REG_O4, tmp); \ /* stw %o4, yy(%o3) */ \ PUSH_INT(0xc0202000|(REG_O4<<25)|(REG_O3<<14)|OFFSETOF(pike_frame, pc)); \ } while(0) #endif /* __i386__ || sparc */ #endif /* __GNUC__ */ #else /* !PIKE_USE_MACHINE_CODE */
6a21702001-07-17Fredrik Hübinette (Hubbe) #undef UPDATE_PC #define UPDATE_PC()
0996a92001-07-17Henrik Grubbström (Grubba) #endif /* PIKE_USE_MACHINE_CODE */
f822262001-07-16Fredrik Hübinette (Hubbe) 
2199ed1996-04-13Fredrik Hübinette (Hubbe) void ins_f_byte(unsigned int b) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(store_linenumbers && b<F_MAX_OPCODE) ADD_COMPILED(b);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
06983f1996-09-22Fredrik Hübinette (Hubbe) 
2199ed1996-04-13Fredrik Hübinette (Hubbe)  b-=F_OFFSET;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(b>255)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Instruction too big %d\n",b);
e82b301997-01-29Fredrik Hübinette (Hubbe) #endif
6a21702001-07-17Fredrik Hübinette (Hubbe) 
f822262001-07-16Fredrik Hübinette (Hubbe) #ifdef PIKE_USE_MACHINE_CODE
6a21702001-07-17Fredrik Hübinette (Hubbe)  do{ static int last_prog_id=-1; static int last_num_linenumbers=-1; if(last_prog_id != Pike_compiler->new_program->id || last_num_linenumbers != Pike_compiler->new_program->num_linenumbers) { last_prog_id=Pike_compiler->new_program->id; last_num_linenumbers = Pike_compiler->new_program->num_linenumbers; UPDATE_PC(); } }while(0);
f822262001-07-16Fredrik Hübinette (Hubbe)  CALL_ABSOLUTE(instrs[b].address);
1524392001-07-16Fredrik Hübinette (Hubbe)  return;
f822262001-07-16Fredrik Hübinette (Hubbe) #endif
fe19fd2001-07-08Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO
c9745c2001-07-09Henrik Grubbström (Grubba)  add_to_program(fcode_to_opcode[b]);
fe19fd2001-07-08Henrik Grubbström (Grubba) #else /* !HAVE_COMPUTED_GOTO */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  add_to_program((unsigned char)b);
fe19fd2001-07-08Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */
2199ed1996-04-13Fredrik Hübinette (Hubbe) } static void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b) {
f822262001-07-16Fredrik Hübinette (Hubbe) #ifdef PIKE_USE_MACHINE_CODE
0996a92001-07-17Henrik Grubbström (Grubba) #ifdef __GNUC__ #ifdef __i386__
f822262001-07-16Fredrik Hübinette (Hubbe)  add_to_program(0xc7); /* movl $xxxx, (%esp) */ add_to_program(0x04); add_to_program(0x24); PUSH_INT(b);
0996a92001-07-17Henrik Grubbström (Grubba) #elif defined(sparc) SET_REG(REG_O0, b); #endif /* __i386__ || sparc */
f822262001-07-16Fredrik Hübinette (Hubbe)  ins_f_byte(a); return;
0996a92001-07-17Henrik Grubbström (Grubba) #endif /* __GNUC__ */
f822262001-07-16Fredrik Hübinette (Hubbe) #endif
fe19fd2001-07-08Henrik Grubbström (Grubba) #ifndef HAVE_COMPUTED_GOTO
2199ed1996-04-13Fredrik Hübinette (Hubbe)  switch(b >> 8) { case 0 : break; case 1 : ins_f_byte(F_PREFIX_256); break; case 2 : ins_f_byte(F_PREFIX_512); break; case 3 : ins_f_byte(F_PREFIX_768); break; case 4 : ins_f_byte(F_PREFIX_1024); break; default: if( b < 256*256) { ins_f_byte(F_PREFIX_CHARX256);
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(b>>8));
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }else if(b < 256*256*256) { ins_f_byte(F_PREFIX_WORDX256);
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(b>>16)); add_to_program((unsigned char)(b>>8));
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }else{ ins_f_byte(F_PREFIX_24BITX256);
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(b>>24)); add_to_program((unsigned char)(b>>16)); add_to_program((unsigned char)(b>>8));
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } }
fe19fd2001-07-08Henrik Grubbström (Grubba) #endif /* !HAVE_COMPUTED_GOTO */
2199ed1996-04-13Fredrik Hübinette (Hubbe)  ins_f_byte(a);
fe19fd2001-07-08Henrik Grubbström (Grubba)  add_to_program((PIKE_OPCODE_T)b);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
a96ce92000-04-19Fredrik Hübinette (Hubbe) static void ins_f_byte_with_2_args(unsigned int a, unsigned INT32 c, unsigned INT32 b) {
f822262001-07-16Fredrik Hübinette (Hubbe) #ifdef PIKE_USE_MACHINE_CODE
0996a92001-07-17Henrik Grubbström (Grubba) #ifdef __GNUC__ #ifdef __i386__
6a21702001-07-17Fredrik Hübinette (Hubbe)  add_to_program(0xc7); /* movl $xxxx, (%esp) */ add_to_program(0x04); add_to_program(0x24); PUSH_INT(c);
f822262001-07-16Fredrik Hübinette (Hubbe)  add_to_program(0xc7); /* movl $xxxx, 4(%esp) */ add_to_program(0x44); add_to_program(0x24); add_to_program(0x04);
6a21702001-07-17Fredrik Hübinette (Hubbe)  PUSH_INT(b);
0996a92001-07-17Henrik Grubbström (Grubba) #elif defined(sparc) SET_REG(REG_O0, c); SET_REG(REG_O1, b); #endif /* __i386__ || sparc */
6a21702001-07-17Fredrik Hübinette (Hubbe)  ins_f_byte(a); return;
0996a92001-07-17Henrik Grubbström (Grubba) #endif /* __GNUC__ */
f822262001-07-16Fredrik Hübinette (Hubbe) #endif #ifdef HAVE_COMPUTED_GOTO
a96ce92000-04-19Fredrik Hübinette (Hubbe)  switch(b >> 8) { case 0 : break; case 1 : ins_f_byte(F_PREFIX2_256); break; case 2 : ins_f_byte(F_PREFIX2_512); break; case 3 : ins_f_byte(F_PREFIX2_768); break; case 4 : ins_f_byte(F_PREFIX2_1024); break; default: if( b < 256*256) { ins_f_byte(F_PREFIX2_CHARX256);
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(b>>8));
a96ce92000-04-19Fredrik Hübinette (Hubbe)  }else if(b < 256*256*256) { ins_f_byte(F_PREFIX2_WORDX256);
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(b>>16)); add_to_program((unsigned char)(b>>8));
a96ce92000-04-19Fredrik Hübinette (Hubbe)  }else{ ins_f_byte(F_PREFIX2_24BITX256);
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(b>>24)); add_to_program((unsigned char)(b>>16)); add_to_program((unsigned char)(b>>8));
a96ce92000-04-19Fredrik Hübinette (Hubbe)  } }
fe19fd2001-07-08Henrik Grubbström (Grubba) #endif /* !HAVE_COMPUTED_GOTO */
a96ce92000-04-19Fredrik Hübinette (Hubbe)  ins_f_byte_with_arg(a,c);
fe19fd2001-07-08Henrik Grubbström (Grubba)  add_to_program((PIKE_OPCODE_T)b);
a96ce92000-04-19Fredrik Hübinette (Hubbe) }
66d51c1997-03-04Fredrik Hübinette (Hubbe) void assemble(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
7a35a42000-08-14Henrik Grubbström (Grubba)  INT32 d,max_label,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 int synch_depth; #endif
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr);
66d51c1997-03-04Fredrik Hübinette (Hubbe)  max_label=-1;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++,c++) if(c->opcode == F_LABEL) if(c->arg > max_label) max_label = c->arg;
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; for(e=0;e<length;e++) if(c[e].opcode == F_LABEL && c[e].arg>=0) labels[c[e].arg]=DO_NOT_WARN((INT32)e); 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)  {
928f952000-11-30Fredrik Hübinette (Hubbe)  int tmp,tmp2; 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; break; 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); break; }
71c5b92000-11-27Fredrik Hübinette (Hubbe)  break;
419fab1997-03-09Fredrik Hübinette (Hubbe)  }
928f952000-11-30Fredrik Hübinette (Hubbe)  uses[c[e].arg]++;
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(); reoptimize=0;
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;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c=(p_instr *)instrbuf.s.str;
85f4f52001-01-31Martin Stjernholm #ifdef PIKE_DEBUG synch_depth = 0; #endif
2199ed1996-04-13Fredrik Hübinette (Hubbe)  for(e=0;e<length;e++) {
6a21702001-07-17Fredrik Hübinette (Hubbe)  int linenumbers_stored=0;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
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, DO_NOT_WARN((unsigned long)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:
afa1c62001-07-09Henrik Grubbström (Grubba) #ifndef HAVE_COMPUTED_GOTO
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  while(PC % c->arg) add_to_program(0);
afa1c62001-07-09Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */
2199ed1996-04-13Fredrik Hübinette (Hubbe)  break;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  case F_BYTE:
fe19fd2001-07-08Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO add_to_program((void *)(ptrdiff_t)(unsigned char)(c->arg)); #else /* !HAVE_COMPUTED_GOTO */
3a1bb12000-09-22Henrik Grubbström (Grubba)  add_to_program((unsigned char)(c->arg));
fe19fd2001-07-08Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */
873ceb2000-04-30Fredrik Hübinette (Hubbe)  break;
9b08a21998-03-31Fredrik Hübinette (Hubbe)  case F_DATA:
fe19fd2001-07-08Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO add_to_program((void *)(ptrdiff_t)c->arg); #else /* !HAVE_COMPUTED_GOTO */
9b08a21998-03-31Fredrik Hübinette (Hubbe)  ins_int(c->arg, (void(*)(char))add_to_program);
fe19fd2001-07-08Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */
9b08a21998-03-31Fredrik Hübinette (Hubbe)  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) fatal("max_label calculation failed!\n"); if(labels[c->arg] != -1) fatal("Duplicate label!\n"); #endif
393a592000-08-16Henrik Grubbström (Grubba)  labels[c->arg] = DO_NOT_WARN((INT32)PC);
6a21702001-07-17Fredrik Hübinette (Hubbe)  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;
2d12341997-03-10Fredrik Hübinette (Hubbe)  default: switch(instrs[c->opcode - F_OFFSET].flags) { case I_ISJUMP: ins_f_byte(c->opcode);
7951942000-04-20Fredrik Hübinette (Hubbe) 
2d12341997-03-10Fredrik Hübinette (Hubbe)  case I_ISPOINTER:
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2d12341997-03-10Fredrik Hübinette (Hubbe)  if(c->arg > max_label || c->arg < 0) fatal("Jump to unknown label?\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
393a592000-08-16Henrik Grubbström (Grubba)  tmp = DO_NOT_WARN((INT32)PC);
b8237a2001-07-08Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO
fe19fd2001-07-08Henrik Grubbström (Grubba)  add_to_program(jumps[c->arg]); #else /* !HAVE_COMPUTED_GOTO */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  ins_int(jumps[c->arg], (void(*)(char))add_to_program);
fe19fd2001-07-08Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */
2d12341997-03-10Fredrik Hübinette (Hubbe)  jumps[c->arg]=tmp; break;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
87c7592000-04-18Fredrik Hübinette (Hubbe)  case I_TWO_ARGS:
fe19fd2001-07-08Henrik Grubbström (Grubba)  ins_f_byte_with_2_args(c->opcode, c->arg, c->arg2);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  break;
9b08a21998-03-31Fredrik Hübinette (Hubbe)  case I_HASARG: ins_f_byte_with_arg(c->opcode, c->arg); break;
2d12341997-03-10Fredrik Hübinette (Hubbe)  case 0:
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: fatal("Unknown instruction type.\n"); #endif }
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } c++; } for(e=0;e<=max_label;e++) {
66d51c1997-03-04Fredrik Hübinette (Hubbe)  int 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)
a4a1722000-12-05Per Hedbor  fatal("Hyperspace error: unknown jump point %ld at %d (pc=%x).\n",
69bb402000-08-17Henrik Grubbström (Grubba)  PTRDIFF_T_TO_LONG(e), labels[e], jumps[e]);
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
afa1c62001-07-09Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO tmp = (int)(ptrdiff_t)(Pike_compiler->new_program->program[jumps[e]]); Pike_compiler->new_program->program[jumps[e]] = (PIKE_OPCODE_T)(ptrdiff_t)(tmp2 - jumps[e]); jumps[e] = tmp; #else /* !HAVE_COMPUTED_GOTO */
2199ed1996-04-13Fredrik Hübinette (Hubbe)  tmp=read_int(jumps[e]); upd_int(jumps[e], tmp2 - jumps[e]); jumps[e]=tmp;
afa1c62001-07-09Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } } free((char *)labels); free((char *)jumps);
66d51c1997-03-04Fredrik Hübinette (Hubbe)  free((char *)uses);
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)
d9a93b2001-07-01Fredrik Hübinette (Hubbe)  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) fatal("Low make buf space failed!!!!!!\n"); #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)
d9a93b2001-07-01Fredrik Hübinette (Hubbe)  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))
d9a93b2001-07-01Fredrik Hübinette (Hubbe)  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) fatal("Popped beyond start of code.\n"); 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) fatal("No file name on last instruction!\n"); } #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)) 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; int q=-1;
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); while(1) { q++; switch(va_arg(arglist, int)) { case 0: break; case 1: { int i=va_arg(arglist, int);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  insopt0(i,cl,cf);
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  continue; } case 2: { int i=va_arg(arglist, int); int j=va_arg(arglist, int);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  insopt1(i,j,cl,cf); continue; } case 3: { int i=va_arg(arglist, int); int j=va_arg(arglist, int); int k=va_arg(arglist, int); insopt2(i,j,k,cl,cf);
8ebb6a1998-04-27Fredrik Hübinette (Hubbe)  continue; } } break; } 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); fprintf(stderr,"Optimization begins: \n"); for(e=0;e<length;e++,c++) {
85f4f52001-01-31Martin 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");
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_SYNCH_MARK) synch_depth++;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } } #endif
7018811999-11-08Henrik Grubbström (Grubba) #ifndef IN_TPIKE
2199ed1996-04-13Fredrik Hübinette (Hubbe) #include "peep_engine.c"
7018811999-11-08Henrik Grubbström (Grubba) #endif /* IN_TPIKE */
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
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;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr); fprintf(stderr,"Optimization begins: \n"); for(e=0;e<length;e++,c++) {
a96ce92000-04-19Fredrik Hübinette (Hubbe)  fprintf(stderr,">>>%3d: ",c->line); dump_instr(c); fprintf(stderr,"\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  } } #endif }