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. */
1b10db2002-10-08Martin Nilsson 
2199ed1996-04-13Fredrik Hübinette (Hubbe) #include "global.h" #include "stralloc.h"
2d10fb2016-12-29Arne Goedeke #include "buffer.h"
2199ed1996-04-13Fredrik Hübinette (Hubbe) #include "program.h" #include "las.h" #include "docode.h"
1a26b22004-12-30Henrik Grubbström (Grubba) #include "pike_embed.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"
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"
9b4ac32014-11-26Henrik Grubbström (Grubba) #include "pike_compiler.h"
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
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,")"); } }
2383112006-09-16Henrik Grubbström (Grubba) static int asm_opt(void); /* Output buffer. The optimization eye is at the end of the buffer. */
2d10fb2016-12-29Arne Goedeke struct byte_buffer instrbuf;
2383112006-09-16Henrik Grubbström (Grubba) long num_instrs = 0;
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
be478c1997-08-30Henrik Grubbström (Grubba) void init_bytecode(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
7563742016-11-08Arne Goedeke  buffer_init(&instrbuf); buffer_ensure_space(&instrbuf, 512);
2383112006-09-16Henrik Grubbström (Grubba)  num_instrs = 0;
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;
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf); length=buffer_content_length(&instrbuf) / sizeof(p_instr);
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
65ca2f2006-09-05Henrik Grubbström (Grubba)  for(e=0;e<length;e++) { free_string(dmalloc_touch_named(struct pike_string *, c[e].file, "exit_bytecode")); #ifdef PIKE_DEBUG c[e].file = (void *)(ptrdiff_t)~0; #endif }
13670c2015-05-25Martin Nilsson 
2d10fb2016-12-29Arne Goedeke  buffer_free(&instrbuf);
2383112006-09-16Henrik Grubbström (Grubba) } /* insert_opcode{,0,1,2}() append an opcode to the instrbuf. */ ptrdiff_t insert_opcode(p_instr *opcode) { /* Note: Steals references from opcode. */
2d10fb2016-12-29Arne Goedeke  p_instr *p = (p_instr *)buffer_alloc(&instrbuf, sizeof(p_instr));
2383112006-09-16Henrik Grubbström (Grubba)  if (!p) Pike_fatal("Out of memory in peep.\n"); *p = *opcode; num_instrs++;
7563742016-11-08Arne Goedeke  return p - (p_instr *)buffer_ptr(&instrbuf);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
7a35a42000-08-14Henrik Grubbström (Grubba) ptrdiff_t insert_opcode2(unsigned int f, INT32 b, INT32 c,
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE current_line,
7a35a42000-08-14Henrik Grubbström (Grubba)  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
2d10fb2016-12-29Arne Goedeke  p=(p_instr *)buffer_alloc(&instrbuf, sizeof(p_instr));
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
7563742016-11-08Arne Goedeke  if(!buffer_content_length(&instrbuf))
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;
65ca2f2006-09-05Henrik Grubbström (Grubba)  copy_shared_string(p->file, dmalloc_touch_named(struct pike_string *, current_file, "insert_opcode"));
2199ed1996-04-13Fredrik Hübinette (Hubbe)  p->arg=b;
a96ce92000-04-19Fredrik Hübinette (Hubbe)  p->arg2=c;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
7563742016-11-08Arne Goedeke  return p - (p_instr *)buffer_ptr(&instrbuf);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
7a35a42000-08-14Henrik Grubbström (Grubba) ptrdiff_t insert_opcode1(unsigned int f, INT32 b,
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE current_line,
7a35a42000-08-14Henrik Grubbström (Grubba)  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); }
ef24a82012-01-12Henrik Grubbström (Grubba) ptrdiff_t insert_opcode0(int f, INT_TYPE 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
7563742016-11-08Arne Goedeke  if(instr > (long)buffer_content_length(&instrbuf) / (long)sizeof(p_instr) || instr < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("update_arg outside known space.\n");
13670c2015-05-25Martin Nilsson #endif
7563742016-11-08Arne Goedeke  p=(p_instr *)buffer_ptr(&instrbuf);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  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 *****/
ee6a782003-11-19Henrik Grubbström (Grubba) INT32 assemble(int store_linenumbers)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
ee6a782003-11-19Henrik Grubbström (Grubba)  INT32 entry_point;
bedc662003-09-26Henrik Grubbström (Grubba)  INT32 max_label=-1,tmp;
cbeb9b2006-02-27Martin Stjernholm  INT32 *labels, *jumps, *uses, *aliases;
7a35a42000-08-14Henrik Grubbström (Grubba)  ptrdiff_t e, length;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  p_instr *c;
5095a72016-07-18Martin Nilsson  struct pike_string *triples = NULL;
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
b9ca5f2004-08-25Henrik Grubbström (Grubba)  int relabel; int reoptimize = relabel = !(debug_options & NO_PEEP_OPTIMIZING);
9b4ac32014-11-26Henrik Grubbström (Grubba)  struct lex *lex; CHECK_COMPILER(); lex = &THIS_COMPILATION->lex;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf); length=buffer_content_length(&instrbuf) / sizeof(p_instr);
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
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--;
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr, "~~~%4ld %4lx %*s", (long)c[e].line,
bd67392015-10-14Martin Nilsson  (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
ee6a782003-11-19Henrik Grubbström (Grubba)  /* No need to do this for constant evaluations. */ if (store_linenumbers) {
7111992016-07-18Martin Nilsson  p_wchar2 *current_triple;
ee6a782003-11-19Henrik Grubbström (Grubba)  struct pike_string *previous_file = NULL;
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE previous_line = 0;
ee6a782003-11-19Henrik Grubbström (Grubba)  ptrdiff_t num_linedirectives = 0;
fcbe1f2003-11-19Henrik Grubbström (Grubba)  /* Count the number of F_FILENAME/F_LINE pseudo-ops we need to add. */
ee6a782003-11-19Henrik Grubbström (Grubba)  for (e=0; e < length; e++) { if (c[e].file != previous_file) {
65ca2f2006-09-05Henrik Grubbström (Grubba)  previous_file = dmalloc_touch_named(struct pike_string *, c[e].file, "prev_file");
ee6a782003-11-19Henrik Grubbström (Grubba)  num_linedirectives++; } if (c[e].line != previous_line) { previous_line = c[e].line; num_linedirectives++; } }
fcbe1f2003-11-19Henrik Grubbström (Grubba)  /* fprintf(stderr, "length:%d directives:%d\n", * length, num_linedirectives); */
13670c2015-05-25Martin Nilsson 
5095a72016-07-18Martin Nilsson  if (!(triples = begin_wide_shared_string(3*(length+num_linedirectives),
b5575f2003-11-24Henrik Grubbström (Grubba)  2))) { Pike_fatal("Failed to allocate wide string of length %d 3*(%d + %d).\n", 3*(length+num_linedirectives), length, num_linedirectives);
ee6a782003-11-19Henrik Grubbström (Grubba)  } previous_file = NULL; previous_line = 0;
7111992016-07-18Martin Nilsson  current_triple = STR2(triples);
ee6a782003-11-19Henrik Grubbström (Grubba)  for (e = 0; e < length; e++) { if (c[e].file != previous_file) {
7111992016-07-18Martin Nilsson  current_triple[0] = F_FILENAME; current_triple[1] =
65ca2f2006-09-05Henrik Grubbström (Grubba)  store_prog_string(dmalloc_touch_named(struct pike_string *, c[e].file, "store_prog_string"));
7111992016-07-18Martin Nilsson  current_triple[2] = 0; current_triple += 3;
65ca2f2006-09-05Henrik Grubbström (Grubba)  previous_file = dmalloc_touch_named(struct pike_string *, c[e].file, "prev_file");
ee6a782003-11-19Henrik Grubbström (Grubba)  } if (c[e].line != previous_line) {
7111992016-07-18Martin Nilsson  current_triple[0] = F_LINE; current_triple[1] = c[e].line;
0695b42014-11-05Martin Nilsson #if SIZEOF_INT_TYPE > 4
7111992016-07-18Martin Nilsson  current_triple[2] = c[e].line>>32;
0695b42014-11-05Martin Nilsson #else
7111992016-07-18Martin Nilsson  current_triple[2] = 0;
0695b42014-11-05Martin Nilsson #endif
7111992016-07-18Martin Nilsson  current_triple += 3;
ee6a782003-11-19Henrik Grubbström (Grubba)  previous_line = c[e].line; }
7111992016-07-18Martin Nilsson  current_triple[0] = c[e].opcode; current_triple[1] = c[e].arg; current_triple[2] = c[e].arg2; current_triple += 3;
ee6a782003-11-19Henrik Grubbström (Grubba)  } #ifdef PIKE_DEBUG
7111992016-07-18Martin Nilsson  if (current_triple != STR2(triples) + 3*(length + num_linedirectives)) { Pike_fatal("Triple length mismatch %d != %d 3*(%d + %d)\n", current_triple - STR2(triples),
b5575f2003-11-24Henrik Grubbström (Grubba)  3*(length + num_linedirectives),
ee6a782003-11-19Henrik Grubbström (Grubba)  length, num_linedirectives); } #endif /* PIKE_DEBUG */
5095a72016-07-18Martin Nilsson  triples = end_shared_string(triples);
ee6a782003-11-19Henrik Grubbström (Grubba)  }
13670c2015-05-25Martin Nilsson 
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);
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf);
bedc662003-09-26Henrik Grubbström (Grubba)  for(e=0;e<length;e++,c++) { if (c->opcode == F_POP_SYNCH_MARK) synch_depth--;
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr, " * %4ld %4lx ",
bd67392015-10-14Martin Nilsson  (long)c->line, (unsigned long)e);
bedc662003-09-26Henrik Grubbström (Grubba)  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++; }
13670c2015-05-25Martin Nilsson 
bedc662003-09-26Henrik Grubbström (Grubba)  Pike_fatal("Reference to undefined label %d > %d\n", max_pointer, max_label); } #endif /* PIKE_DEBUG */
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
cbeb9b2006-02-27Martin Stjernholm #ifndef INS_ENTRY /* Replace F_ENTRY with F_NOP if we have no entry prologue. */
7563742016-11-08Arne Goedeke  for (c = (p_instr *) buffer_ptr(&instrbuf), e = 0; e < length; e++, c++)
cbeb9b2006-02-27Martin Stjernholm  if (c->opcode == F_ENTRY) c->opcode = F_NOP; #endif
dc8d022014-04-27Martin Nilsson  labels=xalloc(sizeof(INT32) * 4 * (max_label+2));
9988422003-10-10Martin Stjernholm  jumps = labels + max_label + 2;
42ddc62016-03-24Henrik Grubbström (Grubba)  aliases = jumps + max_label + 2; uses = aliases + max_label + 2;
b6334d2004-08-25Henrik Grubbström (Grubba)  while(relabel)
66d51c1997-03-04Fredrik Hübinette (Hubbe)  {
b6334d2004-08-25Henrik Grubbström (Grubba)  /* First do the relabel pass. */
42ddc62016-03-24Henrik Grubbström (Grubba)  /* Set labels, jumps and aliases to all -1. */ memset(labels, 0xff, ((max_label + 2) * 3) * sizeof(INT32)); memset(uses, 0x00, (max_label + 2) * sizeof(INT32));
13670c2015-05-25Martin Nilsson 
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf); length=buffer_content_length(&instrbuf) / 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) {
cbeb9b2006-02-27Martin Stjernholm  INT32 l = c[e].arg;
bd67392015-10-14Martin Nilsson  labels[l]=(INT32)e;
cbeb9b2006-02-27Martin Stjernholm  while (e+1 < length && c[e+1].opcode == F_LABEL && c[e+1].arg >= 0) { /* aliases is used to compact several labels at the same * position to one label. That's necessary for some peep * optimizations to work well. */ e++;
bd67392015-10-14Martin Nilsson  labels[c[e].arg] = (INT32)e;
cbeb9b2006-02-27Martin Stjernholm  aliases[c[e].arg] = l; }
c6c6232002-08-30Henrik Grubbström (Grubba)  }
13670c2015-05-25Martin Nilsson 
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)  {
cbeb9b2006-02-27Martin Stjernholm  if (aliases[c[e].arg] >= 0) c[e].arg = aliases[c[e].arg];
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];
13670c2015-05-25Martin Nilsson 
928f952000-11-30Fredrik Hübinette (Hubbe)  while(tmp<length && (c[tmp].opcode == F_LABEL || c[tmp].opcode == F_NOP)) tmp++;
13670c2015-05-25Martin Nilsson 
928f952000-11-30Fredrik Hübinette (Hubbe)  if(tmp>=length) break;
13670c2015-05-25Martin Nilsson 
928f952000-11-30Fredrik Hübinette (Hubbe)  if(c[tmp].opcode==F_BRANCH) { c[e].arg=c[tmp].arg; continue; }
13670c2015-05-25Martin Nilsson 
419fab1997-03-09Fredrik Hübinette (Hubbe) #define TWOO(X,Y) (((X)<<8)+(Y))
13670c2015-05-25Martin Nilsson 
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;
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
928f952000-11-30Fredrik Hübinette (Hubbe)  case TWOO(F_LOR,F_LOR): c[e].arg=c[tmp].arg; continue;
13670c2015-05-25Martin Nilsson 
928f952000-11-30Fredrik Hübinette (Hubbe)  case TWOO(F_LAND,F_BRANCH_WHEN_ZERO): c[e].opcode=F_BRANCH_WHEN_ZERO;
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */
928f952000-11-30Fredrik Hübinette (Hubbe)  case TWOO(F_LAND,F_LAND): c[e].arg=c[tmp].arg; continue;
13670c2015-05-25Martin Nilsson 
928f952000-11-30Fredrik Hübinette (Hubbe)  case TWOO(F_LOR, F_RETURN): c[e].opcode=F_RETURN_IF_TRUE;
2814552003-10-10Martin Stjernholm  goto pointer_opcode_done;
13670c2015-05-25Martin Nilsson 
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):
65ca2f2006-09-05Henrik Grubbström (Grubba)  if(c[e].file) { free_string(dmalloc_touch_named(struct pike_string *, c[e].file, "branch_opt 1")); }
928f952000-11-30Fredrik Hübinette (Hubbe)  c[e]=c[tmp];
65ca2f2006-09-05Henrik Grubbström (Grubba)  if(c[e].file) { add_ref(dmalloc_touch_named(struct pike_string *, c[e].file, "branch_opt 2")); }
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)  }
13670c2015-05-25Martin Nilsson 
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;
b6334d2004-08-25Henrik Grubbström (Grubba)  reoptimize = 1;
928f952000-11-30Fredrik Hübinette (Hubbe)  } }
b6334d2004-08-25Henrik Grubbström (Grubba) 
cbeb9b2006-02-27Martin Stjernholm  if(!reoptimize) { #ifdef PIKE_DEBUG if (a_flag > 3) fprintf (stderr, "Optimizer done after relabel.\n"); #endif break; }
b6334d2004-08-25Henrik Grubbström (Grubba)  /* Then do the optimize pass. */
b9ca5f2004-08-25Henrik Grubbström (Grubba)  relabel = asm_opt();
b6334d2004-08-25Henrik Grubbström (Grubba)  reoptimize = 0;
cbeb9b2006-02-27Martin Stjernholm  if (!relabel) { #ifdef PIKE_DEBUG if (a_flag > 3) fprintf (stderr, "Optimizer done after asm_opt.\n"); #endif break; }
b6334d2004-08-25Henrik Grubbström (Grubba) 
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 */
b6334d2004-08-25Henrik Grubbström (Grubba)  relabel = 0;
3bc7a62002-09-24Henrik Grubbström (Grubba) #endif /* 1 */
66d51c1997-03-04Fredrik Hübinette (Hubbe)  }
ee6a782003-11-19Henrik Grubbström (Grubba)  /* Time to create the actual bytecode. */
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf); length=buffer_content_length(&instrbuf) / sizeof(p_instr);
66d51c1997-03-04Fredrik Hübinette (Hubbe)  for(e=0;e<=max_label;e++) labels[e]=jumps[e]=-1;
387ad32012-07-18Henrik Grubbström (Grubba)  #ifdef START_NEW_FUNCTION START_NEW_FUNCTION(store_linenumbers); #endif #ifdef ALIGN_PIKE_FUNCTION_BEGINNINGS while( ( (((INT32) PIKE_PC)+4) & (ALIGN_PIKE_JUMPS-1))) ins_byte(0); #endif
ee6a782003-11-19Henrik Grubbström (Grubba)  if (store_linenumbers) {
5095a72016-07-18Martin Nilsson  ins_data(store_prog_string(triples)); free_string(triples);
ee6a782003-11-19Henrik Grubbström (Grubba)  } else {
cad18a2004-08-27Martin Nilsson  ins_data(0);
ee6a782003-11-19Henrik Grubbström (Grubba)  }
a852ac2012-07-16Per Hedbor 
ee6a782003-11-19Henrik Grubbström (Grubba)  entry_point = PIKE_PC;
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++) {
fdde6b2017-01-16Henrik Grubbström (Grubba) #ifdef DISASSEMBLE_CODE
c056e82016-07-29Arne Goedeke  size_t opcode_start = PIKE_PC;
fdde6b2017-01-16Henrik Grubbström (Grubba) #endif #ifdef PIKE_DEBUG
7563742016-11-08Arne Goedeke  if (c != (((p_instr *)buffer_ptr(&instrbuf))+e)) {
2d76f22005-05-20Martin Stjernholm  Pike_fatal("Instruction loop deviates. " "0x%04"PRINTPTRDIFFT"x != 0x%04"PRINTPTRDIFFT"x\n",
7563742016-11-08Arne Goedeke  e, c - ((p_instr *)buffer_ptr(&instrbuf)));
c6c6232002-08-30Henrik Grubbström (Grubba)  }
fdde6b2017-01-16Henrik Grubbström (Grubba) #endif if( #ifdef PIKEDEBUG ((a_flag > 2) && store_linenumbers) ||
9b4ac32014-11-26Henrik Grubbström (Grubba)  (a_flag > 3) ||
fdde6b2017-01-16Henrik Grubbström (Grubba) #endif
9b4ac32014-11-26Henrik Grubbström (Grubba)  (lex->pragmas & ID_DISASSEMBLE))
2199ed1996-04-13Fredrik Hübinette (Hubbe)  {
fdde6b2017-01-16Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_POP_SYNCH_MARK) synch_depth--;
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr, "===%4ld %4lx %*s", (long)c->line,
bd67392015-10-14Martin Nilsson  (unsigned long)PIKE_PC, synch_depth, "");
fdde6b2017-01-16Henrik Grubbström (Grubba) #else fprintf(stderr, "===%4ld %4lx ", (long)c->line, (unsigned long)PIKE_PC); #endif
a96ce92000-04-19Fredrik Hübinette (Hubbe)  dump_instr(c); fprintf(stderr,"\n");
fdde6b2017-01-16Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
85f4f52001-01-31Martin Stjernholm  if (c->opcode == F_SYNCH_MARK) synch_depth++;
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
fdde6b2017-01-16Henrik Grubbström (Grubba)  }
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
ee6a782003-11-19Henrik Grubbström (Grubba)  if(store_linenumbers) {
65ca2f2006-09-05Henrik Grubbström (Grubba)  store_linenumber(c->line, dmalloc_touch_named(struct pike_string *, c->file, "store_line"));
ee6a782003-11-19Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (c->opcode < F_MAX_OPCODE) ADD_COMPILED(c->opcode); #endif /* PIKE_DEBUG */ }
2199ed1996-04-13Fredrik Hübinette (Hubbe)  switch(c->opcode) {
2cbc492017-02-21Martin Karlgren  case F_START_FUNCTION: #ifdef INS_START_FUNCTION INS_START_FUNCTION(); #endif break;
873ceb2000-04-30Fredrik Hübinette (Hubbe)  case F_NOP:
928f952000-11-30Fredrik Hübinette (Hubbe)  case F_NOTREACHED:
873ceb2000-04-30Fredrik Hübinette (Hubbe)  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();
cbeb9b2006-02-27Martin Stjernholm #else Pike_fatal ("F_ENTRY is supposed to be gone here.\n"); #endif
a468a02001-07-24Henrik Grubbström (Grubba)  break;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  case F_LABEL:
cbeb9b2006-02-27Martin Stjernholm  if(c->arg == -1) { #ifdef PIKE_DEBUG if (!(debug_options & NO_PEEP_OPTIMIZING)) Pike_fatal ("Failed to optimize away an unused label.\n"); #endif 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)
5179c52018-02-06Henrik Grubbström (Grubba)  Pike_fatal("Duplicate label %d!\n", c->arg);
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
80fe612001-07-21Fredrik Hübinette (Hubbe)  FLUSH_CODE_GENERATOR_STATE();
bd67392015-10-14Martin Nilsson  labels[c->arg] = (INT32)PIKE_PC;
9be5602002-11-12Henrik Grubbström (Grubba)  if ((e+1 < length) && (c[1].opcode != F_LABEL) && (c[1].opcode != F_BYTE) &&
45dda92012-06-10Henrik Grubbström (Grubba)  (c[1].opcode != F_ENTRY) &&
9be5602002-11-12Henrik Grubbström (Grubba)  (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
bd67392015-10-14Martin Nilsson  tmp = (INT32)PIKE_PC;
0420702002-11-02Henrik Grubbström (Grubba)  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
142b002003-11-25Martin Stjernholm  tmp=INS_F_JUMP(c->opcode, (labels[c->arg] != -1));
852c152001-07-23Fredrik Hübinette (Hubbe)  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
bd67392015-10-14Martin Nilsson  tmp = (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
142b002003-11-25Martin Stjernholm  tmp = INS_F_JUMP_WITH_TWO_ARGS(c->opcode, c->arg, c->arg2,
46b1bf2003-11-26Henrik Grubbström (Grubba)  (labels[c[1].arg] != -1));
b401532002-11-02Henrik Grubbström (Grubba)  if(tmp != -1) { /* 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 */
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */ /*
b401532002-11-02Henrik Grubbström (Grubba)  * 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
46b1bf2003-11-26Henrik Grubbström (Grubba)  tmp = INS_F_JUMP_WITH_ARG(c->opcode, c->arg, (labels[c[1].arg] != -1));
b401532002-11-02Henrik Grubbström (Grubba)  if(tmp != -1) { /* 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 */
5f50842018-02-12Marcus Comstedt  /* FALLTHRU */ /*
b401532002-11-02Henrik Grubbström (Grubba)  * 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) 
fdde6b2017-01-16Henrik Grubbström (Grubba) #ifdef DISASSEMBLE_CODE
c056e82016-07-29Arne Goedeke  if((lex->pragmas & ID_DISASSEMBLE) && PIKE_PC > opcode_start) { DISASSEMBLE_CODE(Pike_compiler->new_program->program + opcode_start, (PIKE_PC - opcode_start)*sizeof(PIKE_OPCODE_T)); } #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:
13670c2015-05-25Martin Nilsson 
852c152001-07-23Fredrik Hübinette (Hubbe) #define CALLS(X) \ case PIKE_CONCAT3(F_,X,_AND_RETURN): \ case PIKE_CONCAT3(F_MARK_,X,_AND_RETURN):
13670c2015-05-25Martin Nilsson 
852c152001-07-23Fredrik Hübinette (Hubbe)  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
13670c2015-05-25Martin Nilsson 
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",
6da27e2016-02-12Martin Nilsson  (long)e, (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; } }
0ec7522014-04-27Martin Nilsson  free(labels);
66d51c1997-03-04Fredrik Hübinette (Hubbe) 
a852ac2012-07-16Per Hedbor #ifdef END_FUNCTION END_FUNCTION(store_linenumbers); #endif
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);
2d76f22005-05-20Martin Stjernholm  fprintf(stderr, "Code at offset %"PRINTSIZET"d through %"PRINTSIZET"d:\n",
2abf522002-11-07Henrik Grubbström (Grubba)  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();
ee6a782003-11-19Henrik Grubbström (Grubba)  return entry_point;
2199ed1996-04-13Fredrik Hübinette (Hubbe) } /**** Peephole optimizer ****/
3327722006-09-17Henrik Grubbström (Grubba) static void do_optimization(int topop, int topush, ...);
01b9212016-01-12Per Hedbor static inline int opcode(int offset); static inline int argument(int offset); static inline int argument2(int offset);
2383112006-09-16Henrik Grubbström (Grubba)  #include "peep_engine.c"
3327722006-09-17Henrik Grubbström (Grubba) #ifndef PEEP_STACK_SIZE #define PEEP_STACK_SIZE 256 #endif /* Stack holding pending instructions. * Note that instructions must be pushed in reverse order. */ static long stack_depth = 0; static p_instr instrstack[PEEP_STACK_SIZE];
a7538d1998-05-12Fredrik Hübinette (Hubbe) int remove_clear_locals=0x7fffffff;
7a35a42000-08-14Henrik Grubbström (Grubba) static ptrdiff_t eye, len;
06983f1996-09-22Fredrik Hübinette (Hubbe) static p_instr *instructions;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
2383112006-09-16Henrik Grubbström (Grubba) /* insopt{0,1,2} push an instruction on instrstack. */
01b9212016-01-12Per Hedbor static inline p_instr *insopt2(int f, INT32 a, INT32 b,
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE 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
3327722006-09-17Henrik Grubbström (Grubba)  p = instrstack + stack_depth++;
419fab1997-03-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3327722006-09-17Henrik Grubbström (Grubba)  if(stack_depth > PEEP_STACK_SIZE) Pike_fatal("Instructions stacked too high!!!!!!\n");
419fab1997-03-09Fredrik Hübinette (Hubbe) #endif p->opcode=f;
e7df5b1997-03-17Fredrik Hübinette (Hubbe)  p->line=cl;
65ca2f2006-09-05Henrik Grubbström (Grubba)  copy_shared_string(p->file, dmalloc_touch_named(struct pike_string *, cf, "insopt2"));
a96ce92000-04-19Fredrik Hübinette (Hubbe)  p->arg=a; p->arg2=b;
419fab1997-03-09Fredrik Hübinette (Hubbe) 
2383112006-09-16Henrik Grubbström (Grubba)  return p;
419fab1997-03-09Fredrik Hübinette (Hubbe) }
01b9212016-01-12Per Hedbor static inline p_instr *insopt1(int f, INT32 a, INT_TYPE cl,
ef24a82012-01-12Henrik Grubbström (Grubba)  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); }
01b9212016-01-12Per Hedbor static inline p_instr *insopt0(int f, INT_TYPE 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) }
2383112006-09-16Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
be478c1997-08-30Henrik Grubbström (Grubba) static void debug(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
7563742016-11-08Arne Goedeke  if (num_instrs != (long)buffer_content_length(&instrbuf) / (long)sizeof(p_instr)) {
2383112006-09-16Henrik Grubbström (Grubba)  Pike_fatal("PEEP: instrbuf lost count (%d != %d)\n",
7563742016-11-08Arne Goedeke  num_instrs, (long)buffer_content_length(&instrbuf) / (long)sizeof(p_instr));
65ca2f2006-09-05Henrik Grubbström (Grubba)  }
7563742016-11-08Arne Goedeke  if(buffer_content_length(&instrbuf))
2199ed1996-04-13Fredrik Hübinette (Hubbe)  {
66d51c1997-03-04Fredrik Hübinette (Hubbe)  p_instr *p;
7563742016-11-08Arne Goedeke  p=(p_instr *)buffer_dst(&instrbuf);
2199ed1996-04-13Fredrik Hübinette (Hubbe)  if(!p[-1].file)
5aad932002-08-15Marcus Comstedt  Pike_fatal("No file name on last instruction!\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }
66d51c1997-03-04Fredrik Hübinette (Hubbe) }
2383112006-09-16Henrik Grubbström (Grubba) #else #define debug() #endif
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
2383112006-09-16Henrik Grubbström (Grubba) /* Offset from the end of instrbuf backwards. */
01b9212016-01-12Per Hedbor static inline p_instr *instr(int offset)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
2383112006-09-16Henrik Grubbström (Grubba)  if (offset >= num_instrs) return NULL;
7563742016-11-08Arne Goedeke  return ((p_instr *)buffer_dst(&instrbuf)) - (offset + 1);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
01b9212016-01-12Per Hedbor 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; }
01b9212016-01-12Per Hedbor 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; }
01b9212016-01-12Per Hedbor static inline int argument2(int offset)
a96ce92000-04-19Fredrik Hübinette (Hubbe) { p_instr *a; a=instr(offset); if(a) return a->arg2; return -1; }
2383112006-09-16Henrik Grubbström (Grubba) static int advance(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
2383112006-09-16Henrik Grubbström (Grubba)  p_instr *p; if(stack_depth)
2199ed1996-04-13Fredrik Hübinette (Hubbe)  {
3327722006-09-17Henrik Grubbström (Grubba)  p = instrstack + --stack_depth;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }else{
2383112006-09-16Henrik Grubbström (Grubba)  if (eye >= len) return 0; p = instructions + eye;
2199ed1996-04-13Fredrik Hübinette (Hubbe)  eye++; }
2383112006-09-16Henrik Grubbström (Grubba)  insert_opcode(p);
3327722006-09-17Henrik Grubbström (Grubba)  debug_malloc_touch_named(p->file, "advance");
2199ed1996-04-13Fredrik Hübinette (Hubbe)  debug();
2383112006-09-16Henrik Grubbström (Grubba)  return 1;
2199ed1996-04-13Fredrik Hübinette (Hubbe) } static void pop_n_opcodes(int n) {
2383112006-09-16Henrik Grubbström (Grubba)  int e;
cffe882007-04-19Martin Stjernholm  p_instr *p;
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2383112006-09-16Henrik Grubbström (Grubba)  if (n > num_instrs) Pike_fatal("Popping out of instructions.\n");
2199ed1996-04-13Fredrik Hübinette (Hubbe) #endif
66d51c1997-03-04Fredrik Hübinette (Hubbe) 
7563742016-11-08Arne Goedeke  p = ((p_instr *)buffer_dst(&instrbuf)) - n;
2383112006-09-16Henrik Grubbström (Grubba)  for (e = 0; e < n; e++) { free_string(dmalloc_touch_named(struct pike_string *, p[e].file, "pop_n_opcodes"));
2199ed1996-04-13Fredrik Hübinette (Hubbe)  }
2383112006-09-16Henrik Grubbström (Grubba)  num_instrs -= n;
2d10fb2016-12-29Arne Goedeke  buffer_remove(&instrbuf, sizeof(p_instr)*n);
2199ed1996-04-13Fredrik Hübinette (Hubbe) }
b956702000-11-25Henrik Grubbström (Grubba) 
2383112006-09-16Henrik Grubbström (Grubba) /* NOTE: Called with opcodes in reverse order! */
3327722006-09-17Henrik Grubbström (Grubba) static void do_optimization(int topop, int topush, ...)
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) { va_list arglist;
c6c6232002-08-30Henrik Grubbström (Grubba)  int q=0; int oplen;
65ca2f2006-09-05Henrik Grubbström (Grubba)  struct pike_string *cf;
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE cl=instr(0)->line;
a96ce92000-04-19Fredrik Hübinette (Hubbe) 
65ca2f2006-09-05Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if(a_flag>5) { int e;
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr, "PEEP at %ld:", cl);
2383112006-09-16Henrik Grubbström (Grubba)  for(e = topop; e--;)
65ca2f2006-09-05Henrik Grubbström (Grubba)  { fprintf(stderr," "); dump_instr(instr(e)); } fprintf(stderr," => "); } #endif
3327722006-09-17Henrik Grubbström (Grubba)  if (stack_depth + topush > PEEP_STACK_SIZE) { /* No place left on stack. Ignore the optimization. */ #ifdef PIKE_DEBUG if (a_flag) { fprintf(stderr, "PEEP stack full.\n"); } #endif return; }
65ca2f2006-09-05Henrik Grubbström (Grubba)  copy_shared_string(cf,dmalloc_touch_named(struct pike_string *, instr(0)->file, "do_optimization")); pop_n_opcodes(topop);
b956702000-11-25Henrik Grubbström (Grubba) 
3327722006-09-17Henrik Grubbström (Grubba)  va_start(arglist, topush);
13670c2015-05-25Martin Nilsson 
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) 
65ca2f2006-09-05Henrik Grubbström (Grubba)  /*fifo_len+=q;*/ free_string(dmalloc_touch_named(struct pike_string *, cf, "do_optimization")); debug(); #ifdef PIKE_DEBUG if(a_flag>5) {
3327722006-09-17Henrik Grubbström (Grubba)  p_instr *p = instrstack + stack_depth;
65ca2f2006-09-05Henrik Grubbström (Grubba)  int e; for(e=0;e<q;e++) { fprintf(stderr," ");
2383112006-09-16Henrik Grubbström (Grubba)  dump_instr(p-(e+1));
65ca2f2006-09-05Henrik Grubbström (Grubba)  } fprintf(stderr,"\n"); }
3327722006-09-17Henrik Grubbström (Grubba)  if (q != topush) { Pike_fatal("PEEP: Lost track of instructions to push (%d != %d)\n", q, topush); }
65ca2f2006-09-05Henrik Grubbström (Grubba) #endif /* Note: The 5 below is the longest * match prefix in the ruleset */ /*fifo_len += q + 5;*/
8ebb6a1998-04-27Fredrik Hübinette (Hubbe) }
b9ca5f2004-08-25Henrik Grubbström (Grubba) static int asm_opt(void)
2199ed1996-04-13Fredrik Hübinette (Hubbe) {
b9ca5f2004-08-25Henrik Grubbström (Grubba)  int relabel = 0;
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) 
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf); length=buffer_content_length(&instrbuf) / sizeof(p_instr);
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
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--;
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr,"<<<%4ld: %*s",(long)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
7563742016-11-08Arne Goedeke  len=buffer_content_length(&instrbuf)/sizeof(p_instr); instructions=(p_instr *)buffer_ptr(&instrbuf);
0c24572003-10-17Martin Nilsson  init_bytecode();
2383112006-09-16Henrik Grubbström (Grubba)  for(eye = 0; advance();)
0c24572003-10-17Martin Nilsson  { #ifdef PIKE_DEBUG if(a_flag>6) { int e;
bd67392015-10-14Martin Nilsson  fprintf(stderr, "#%ld,%ld:", (long)eye, stack_depth);
2383112006-09-16Henrik Grubbström (Grubba)  for(e = 4;e--;) {
0c24572003-10-17Martin Nilsson  fprintf(stderr," "); dump_instr(instr(e)); }
2383112006-09-16Henrik Grubbström (Grubba)  /* FIXME: Show instrstack too? */
0c24572003-10-17Martin Nilsson  fprintf(stderr,"\n"); } #endif
b9ca5f2004-08-25Henrik Grubbström (Grubba)  relabel |= low_asm_opt();
0c24572003-10-17Martin Nilsson  }
0ec7522014-04-27Martin Nilsson  free(instructions);
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;
2814552003-10-10Martin Stjernholm  int synch_depth = 0;
7a35a42000-08-14Henrik Grubbström (Grubba) 
7563742016-11-08Arne Goedeke  c=(p_instr *)buffer_ptr(&instrbuf); length=buffer_content_length(&instrbuf) / sizeof(p_instr);
2199ed1996-04-13Fredrik Hübinette (Hubbe) 
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--;
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr,">>>%4ld: %*s",(long)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
b9ca5f2004-08-25Henrik Grubbström (Grubba)  return relabel;
2199ed1996-04-13Fredrik Hübinette (Hubbe) }