pike.git / src / peep.c

version» Context lines:

pike.git/src/peep.c:1:   /*   || 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. - || $Id$ +    */      #include "global.h"   #include "stralloc.h"   #include "dynamic_buffer.h"   #include "program.h"   #include "las.h"   #include "docode.h"   #include "pike_embed.h"   #include "pike_error.h"   #include "lex.h"   #include "pike_memory.h"   #include "peep.h" - #include "dmalloc.h" +    #include "stuff.h"   #include "bignum.h"   #include "opcodes.h"   #include "builtin_functions.h"   #include "constants.h"   #include "interpret.h"   #include "pikecode.h" -  + #include "pike_compiler.h"      #ifdef PIKE_DEBUG   static int hasarg(int opcode)   {    return instrs[opcode-F_OFFSET].flags & I_HASARG;   }      static int hasarg2(int opcode)   {    return instrs[opcode-F_OFFSET].flags & I_HASARG2;
pike.git/src/peep.c:91:    p_instr *p = (p_instr *)low_make_buf_space(sizeof(p_instr), &instrbuf);    if (!p) Pike_fatal("Out of memory in peep.\n");    *p = *opcode;    num_instrs++;    return p - (p_instr *)instrbuf.s.str;   }      ptrdiff_t insert_opcode2(unsigned int f,    INT32 b,    INT32 c, -  INT32 current_line, +  INT_TYPE current_line,    struct pike_string *current_file)   {    p_instr *p;      #ifdef PIKE_DEBUG    if(!hasarg2(f) && c)    Pike_fatal("hasarg2(%d) is wrong!\n",f);   #endif       p=(p_instr *)low_make_buf_space(sizeof(p_instr), &instrbuf);
pike.git/src/peep.c:122:    current_file,    "insert_opcode"));    p->arg=b;    p->arg2=c;       return p - (p_instr *)instrbuf.s.str;   }      ptrdiff_t insert_opcode1(unsigned int f,    INT32 b, -  INT32 current_line, +  INT_TYPE current_line,    struct pike_string *current_file)   {   #ifdef PIKE_DEBUG    if(!hasarg(f) && b)    Pike_fatal("hasarg(%d) is wrong!\n",f);   #endif       return insert_opcode2(f,b,0,current_line,current_file);   }    - ptrdiff_t insert_opcode0(int f,int current_line, struct pike_string *current_file) + ptrdiff_t insert_opcode0(int f, INT_TYPE current_line, +  struct pike_string *current_file)   {   #ifdef PIKE_DEBUG    if(hasarg(f))    Pike_fatal("hasarg(%d) is wrong!\n",f);   #endif    return insert_opcode1(f,0,current_line, current_file);   }         void update_arg(int instr,INT32 arg)
pike.git/src/peep.c:167:      /**** Bytecode Generator *****/      INT32 assemble(int store_linenumbers)   {    INT32 entry_point;    INT32 max_label=-1,tmp;    INT32 *labels, *jumps, *uses, *aliases;    ptrdiff_t e, length;    p_instr *c; - #ifdef PIKE_PORTABLE_BYTECODE +     struct pike_string *tripples = NULL; - #endif /* PIKE_PORTABLE_BYTECODE */ +    #ifdef PIKE_DEBUG    INT32 max_pointer=-1;    int synch_depth = 0;    size_t fun_start = Pike_compiler->new_program->num_program;   #endif    int relabel;    int reoptimize = relabel = !(debug_options & NO_PEEP_OPTIMIZING); -  +  struct lex *lex; +  CHECK_COMPILER(); +  lex = &THIS_COMPILATION->lex;       c=(p_instr *)instrbuf.s.str;    length=instrbuf.s.len / sizeof(p_instr);      #ifdef PIKE_DEBUG    if((a_flag > 1 && store_linenumbers) || a_flag > 2)    {    for (e = 0; e < length; e++) {    if (c[e].opcode == F_POP_SYNCH_MARK) synch_depth--; -  fprintf(stderr, "~~~%4d %4lx %*s", c[e].line, -  DO_NOT_WARN((unsigned long)e), synch_depth, ""); +  fprintf(stderr, "~~~%4ld %4lx %*s", (long)c[e].line, +  (unsigned long)e, synch_depth, "");    dump_instr(c+e);    fprintf(stderr,"\n");    if (c[e].opcode == F_SYNCH_MARK) synch_depth++;    }    if (synch_depth) {    Pike_fatal("Unbalanced sync_mark/pop_sync_mark: %d\n", synch_depth);    }    }   #endif    - #ifdef PIKE_PORTABLE_BYTECODE +     /* No need to do this for constant evaluations. */    if (store_linenumbers) {    p_wchar2 *current_tripple;    struct pike_string *previous_file = NULL; -  int previous_line = 0; +  INT_TYPE previous_line = 0;    ptrdiff_t num_linedirectives = 0;       /* Count the number of F_FILENAME/F_LINE pseudo-ops we need to add. */    for (e=0; e < length; e++) {    if (c[e].file != previous_file) {    previous_file = dmalloc_touch_named(struct pike_string *,    c[e].file, "prev_file");    num_linedirectives++;    }    if (c[e].line != previous_line) {
pike.git/src/peep.c:246: Inside #if defined(PIKE_PORTABLE_BYTECODE)
   c[e].file,    "store_prog_string"));    current_tripple[2] = 0;    current_tripple += 3;    previous_file = dmalloc_touch_named(struct pike_string *,    c[e].file, "prev_file");    }    if (c[e].line != previous_line) {    current_tripple[0] = F_LINE;    current_tripple[1] = c[e].line; + #if SIZEOF_INT_TYPE > 4 +  current_tripple[2] = c[e].line>>32; + #else    current_tripple[2] = 0; -  + #endif    current_tripple += 3;    previous_line = c[e].line;    }    current_tripple[0] = c[e].opcode;    current_tripple[1] = c[e].arg;    current_tripple[2] = c[e].arg2;    current_tripple += 3;    }   #ifdef PIKE_DEBUG    if (current_tripple != STR2(tripples) + 3*(length + num_linedirectives)) {    Pike_fatal("Tripple length mismatch %d != %d 3*(%d + %d)\n",    current_tripple - STR2(tripples),    3*(length + num_linedirectives),    length, num_linedirectives);    }   #endif /* PIKE_DEBUG */    tripples = end_shared_string(tripples);    }    - #endif /* PIKE_PORTABLE_BYTECODE */ -  +     for(e=0;e<length;e++,c++) {    if(c->opcode == F_LABEL) {    if(c->arg > max_label)    max_label = c->arg;    }   #ifdef PIKE_DEBUG    else if (instrs[c->opcode - F_OFFSET].flags & I_POINTER) {    if (c->arg > max_pointer)    max_pointer = c->arg;    }
pike.git/src/peep.c:290: Inside #if defined(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)); +  fprintf(stderr, " * %4ld %4lx ", +  (long)c->line, (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.git/src/peep.c:313: Inside #if defined(PIKE_DEBUG)
   max_pointer, max_label);    }   #endif /* PIKE_DEBUG */      #ifndef INS_ENTRY    /* Replace F_ENTRY with F_NOP if we have no entry prologue. */    for (c = (p_instr *) instrbuf.s.str, e = 0; e < length; e++, c++)    if (c->opcode == F_ENTRY) c->opcode = F_NOP;   #endif    -  labels=(INT32 *)xalloc(sizeof(INT32) * 4 * (max_label+2)); +  labels=xalloc(sizeof(INT32) * 4 * (max_label+2));    jumps = labels + max_label + 2;    uses = jumps + max_label + 2;    aliases = uses + max_label + 2; -  +     while(relabel)    {    /* First do the relabel pass. */    for(e=0;e<=max_label;e++)    {    labels[e]=jumps[e]= aliases[e] = -1;    uses[e]=0;    }       c=(p_instr *)instrbuf.s.str;    length=instrbuf.s.len / sizeof(p_instr);    for(e=0;e<length;e++)    if(c[e].opcode == F_LABEL && c[e].arg>=0) {    INT32 l = c[e].arg; -  labels[l]=DO_NOT_WARN((INT32)e); +  labels[l]=(INT32)e;    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++; -  labels[c[e].arg] = DO_NOT_WARN((INT32)e); +  labels[c[e].arg] = (INT32)e;    aliases[c[e].arg] = l;    }    }       for(e=0;e<length;e++)    {    if(instrs[c[e].opcode-F_OFFSET].flags & I_POINTER)    {    if (aliases[c[e].arg] >= 0) c[e].arg = aliases[c[e].arg];   
pike.git/src/peep.c:373:    c[e].arg=c[tmp].arg;    continue;    }      #define TWOO(X,Y) (((X)<<8)+(Y))       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; +  /* FALL_THROUGH */    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; -  +  /* FALL_THROUGH */    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;    goto pointer_opcode_done;       case TWOO(F_BRANCH, F_RETURN):    case TWOO(F_BRANCH, F_RETURN_0):
pike.git/src/peep.c:453: Inside #if 1 and #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (a_flag > 3)    fprintf(stderr, "Rerunning optimizer.\n");   #endif   #else /* !1 */    relabel = 0;   #endif /* 1 */    }       /* Time to create the actual bytecode. */ -  +     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;    -  +  + #ifdef START_NEW_FUNCTION +  START_NEW_FUNCTION(store_linenumbers); + #endif +    #ifdef ALIGN_PIKE_FUNCTION_BEGINNINGS -  while( ( (((INT32) PIKE_PC)+2) & (ALIGN_PIKE_JUMPS-1))) +  while( ( (((INT32) PIKE_PC)+4) & (ALIGN_PIKE_JUMPS-1)))    ins_byte(0);   #endif    - #ifdef PIKE_PORTABLE_BYTECODE +     if (store_linenumbers) {    ins_data(store_prog_string(tripples));    free_string(tripples);    } else {    ins_data(0);    } - #endif /* PIKE_PORTABLE_BYTECODE */ +        entry_point = PIKE_PC;      #ifdef PIKE_DEBUG    synch_depth = 0;   #endif    FLUSH_CODE_GENERATOR_STATE();    for(e=0;e<length;e++)    {   #ifdef PIKE_DEBUG    if (c != (((p_instr *)instrbuf.s.str)+e)) {    Pike_fatal("Instruction loop deviates. "    "0x%04"PRINTPTRDIFFT"x != 0x%04"PRINTPTRDIFFT"x\n",    e, c - ((p_instr *)instrbuf.s.str));    } -  if((a_flag > 2 && store_linenumbers) || a_flag > 3) +  if(((a_flag > 2) && store_linenumbers) || +  (a_flag > 3) || +  (lex->pragmas & ID_DISASSEMBLE))    {    if (c->opcode == F_POP_SYNCH_MARK) synch_depth--; -  fprintf(stderr, "===%4d %4lx %*s", c->line, -  DO_NOT_WARN((unsigned long)PIKE_PC), synch_depth, ""); +  fprintf(stderr, "===%4ld %4lx %*s", (long)c->line, +  (unsigned long)PIKE_PC, synch_depth, "");    dump_instr(c);    fprintf(stderr,"\n");    if (c->opcode == F_SYNCH_MARK) synch_depth++;    }   #endif       if(store_linenumbers) {    store_linenumber(c->line, dmalloc_touch_named(struct pike_string *,    c->file,    "store_line"));
pike.git/src/peep.c:550:    break;    }   #ifdef PIKE_DEBUG    if(c->arg > max_label || c->arg < 0)    Pike_fatal("max_label calculation failed!\n");       if(labels[c->arg] != -1)    Pike_fatal("Duplicate label!\n");   #endif    FLUSH_CODE_GENERATOR_STATE(); -  labels[c->arg] = DO_NOT_WARN((INT32)PIKE_PC); +  labels[c->arg] = (INT32)PIKE_PC;    if ((e+1 < length) &&    (c[1].opcode != F_LABEL) &&    (c[1].opcode != F_BYTE) && -  +  (c[1].opcode != F_ENTRY) &&    (c[1].opcode != F_DATA)) {    /* Don't add redundant code before labels or raw data. */    UPDATE_PC();    }       break;       case F_VOLATILE_RETURN:    ins_f_byte(F_RETURN);    break;       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); +  tmp = (INT32)PIKE_PC;    ins_pointer(jumps[c->arg]);    jumps[c->arg]=tmp;    break;       default:    switch(instrs[c->opcode - F_OFFSET].flags & I_IS_MASK)    {    case I_ISPTRJUMP:   #ifdef INS_F_JUMP    tmp=INS_F_JUMP(c->opcode, (labels[c->arg] != -1));
pike.git/src/peep.c:595: Inside #if defined(INS_F_JUMP)
   break;    }   #endif       ins_f_byte(c->opcode);      #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); +  tmp = (INT32)PIKE_PC;    ins_pointer(jumps[c->arg]);    jumps[c->arg]=tmp;    break;       case I_ISPTRJUMPARGS:   #ifdef INS_F_JUMP_WITH_TWO_ARGS    tmp = INS_F_JUMP_WITH_TWO_ARGS(c->opcode, c->arg, c->arg2,    (labels[c[1].arg] != -1));    if(tmp != -1)    {
pike.git/src/peep.c:750: Inside #if defined(INS_F_JUMP)
   continue;    }   #endif       tmp = read_pointer(jumps[e]);    upd_pointer(jumps[e], tmp2 - jumps[e]);    jumps[e]=tmp;    }    }    -  free((char *)labels); +  free(labels);    -  + #ifdef END_FUNCTION +  END_FUNCTION(store_linenumbers); + #endif +    #ifdef PIKE_DEBUG    if (a_flag > 6) {    size_t len = (Pike_compiler->new_program->num_program - fun_start)*    sizeof(PIKE_OPCODE_T);    fprintf(stderr, "Code at offset %"PRINTSIZET"d through %"PRINTSIZET"d:\n",    fun_start, Pike_compiler->new_program->num_program-1);   #ifdef DISASSEMBLE_CODE    DISASSEMBLE_CODE(Pike_compiler->new_program->program + fun_start, len);   #else /* !DISASSEMBLE_CODE */    {
pike.git/src/peep.c:799:   static long stack_depth = 0;   static p_instr instrstack[PEEP_STACK_SIZE];      int remove_clear_locals=0x7fffffff;   static ptrdiff_t eye, len;   static p_instr *instructions;      /* insopt{0,1,2} push an instruction on instrstack. */      static INLINE p_instr *insopt2(int f, INT32 a, INT32 b, -  int cl, struct pike_string *cf) +  INT_TYPE cl, struct pike_string *cf)   {    p_instr *p;      #ifdef PIKE_DEBUG    if(!hasarg2(f) && b)    Pike_fatal("hasarg2(%d /*%s */) is wrong!\n",f,get_f_name(f));   #endif       p = instrstack + stack_depth++;   
pike.git/src/peep.c:825:    p->opcode=f;    p->line=cl;    copy_shared_string(p->file, dmalloc_touch_named(struct pike_string *,    cf, "insopt2"));    p->arg=a;    p->arg2=b;       return p;   }    - static INLINE p_instr *insopt1(int f, INT32 a, int cl, struct pike_string *cf) + static INLINE p_instr *insopt1(int f, INT32 a, INT_TYPE cl, +  struct pike_string *cf)   {   #ifdef PIKE_DEBUG    if(!hasarg(f) && a)    Pike_fatal("hasarg(%d /* %s */) is wrong!\n",f,get_f_name(f));   #endif       return insopt2(f,a,0,cl, cf);   }    - static INLINE p_instr *insopt0(int f, int cl, struct pike_string *cf) + static INLINE p_instr *insopt0(int f, INT_TYPE cl, struct pike_string *cf)   {   #ifdef PIKE_DEBUG    if(hasarg(f))    Pike_fatal("hasarg(%d /* %s */) is wrong!\n",f,get_f_name(f));   #endif    return insopt2(f,0,0,cl, cf);   }      #ifdef PIKE_DEBUG   static void debug(void)
pike.git/src/peep.c:939:   }         /* NOTE: Called with opcodes in reverse order! */   static void do_optimization(int topop, int topush, ...)   {    va_list arglist;    int q=0;    int oplen;    struct pike_string *cf; -  INT32 cl=instr(0)->line; +  INT_TYPE cl=instr(0)->line;      #ifdef PIKE_DEBUG    if(a_flag>5)    {    int e; -  fprintf(stderr,"PEEP at %d:",cl); +  fprintf(stderr, "PEEP at %ld:", cl);    for(e = topop; e--;)    {    fprintf(stderr," ");    dump_instr(instr(e));    }    fprintf(stderr," => ");    }   #endif       if (stack_depth + topush > PEEP_STACK_SIZE) {
pike.git/src/peep.c:1058: Inside #if defined(PIKE_DEBUG)
   ptrdiff_t e, length;    int synch_depth = 0;       c=(p_instr *)instrbuf.s.str;    length=instrbuf.s.len / sizeof(p_instr);       fprintf(stderr,"Before peep optimization:\n");    for(e=0;e<length;e++,c++)    {    if (c->opcode == F_POP_SYNCH_MARK) synch_depth--; -  fprintf(stderr,"<<<%4d: %*s",c->line,synch_depth,""); +  fprintf(stderr,"<<<%4ld: %*s",(long)c->line,synch_depth,"");    dump_instr(c);    fprintf(stderr,"\n");    if (c->opcode == F_SYNCH_MARK) synch_depth++;    }    }   #endif       len=instrbuf.s.len/sizeof(p_instr);    instructions=(p_instr *)instrbuf.s.str;    instrbuf.s.str=0;    init_bytecode();       for(eye = 0; advance();)    {   #ifdef PIKE_DEBUG    if(a_flag>6) {    int e; -  fprintf(stderr, "#%ld,%ld:", -  DO_NOT_WARN((long)eye), -  stack_depth); +  fprintf(stderr, "#%ld,%ld:", (long)eye, stack_depth);    for(e = 4;e--;) {    fprintf(stderr," ");    dump_instr(instr(e));    }    /* FIXME: Show instrstack too? */    fprintf(stderr,"\n");    }   #endif       relabel |= low_asm_opt();    }    -  free((char *)instructions); +  free(instructions);      #ifdef PIKE_DEBUG    if(a_flag > 4)    {    p_instr *c;    ptrdiff_t e, length;    int synch_depth = 0;       c=(p_instr *)instrbuf.s.str;    length=instrbuf.s.len / sizeof(p_instr);       fprintf(stderr,"After peep optimization:\n");    for(e=0;e<length;e++,c++)    {    if (c->opcode == F_POP_SYNCH_MARK) synch_depth--; -  fprintf(stderr,">>>%4d: %*s",c->line,synch_depth,""); +  fprintf(stderr,">>>%4ld: %*s",(long)c->line,synch_depth,"");    dump_instr(c);    fprintf(stderr,"\n");    if (c->opcode == F_SYNCH_MARK) synch_depth++;    }    }   #endif       return relabel;   }