pike.git / src / docode.c

version» Context lines:

pike.git/src/docode.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: docode.c,v 1.196 2008/03/22 13:22:20 grubba Exp $ + || $Id: docode.c,v 1.197 2008/04/14 10:14:35 grubba Exp $   */      #include "global.h"   #include "las.h"   #include "program.h"   #include "pike_types.h"   #include "stralloc.h"   #include "interpret.h"   #include "constants.h"   #include "array.h"
pike.git/src/docode.c:20:   #include "pike_embed.h"   #include "builtin_functions.h"   #include "peep.h"   #include "docode.h"   #include "operators.h"   #include "object.h"   #include "opcodes.h"   #include "lex.h"   #include "mapping.h"   #include "multiset.h" + #include "pike_compiler.h"      static int do_docode2(node *n, int flags);      typedef void (*cleanup_func)(void *);      struct cleanup_frame   {    struct cleanup_frame *prev;    cleanup_func cleanup;    void *cleanup_arg;
pike.git/src/docode.c:180:   {    return EXTRACT_INT(Pike_compiler->new_program->program+offset);   }      static int label_no=0;      int alloc_label(void) { return ++label_no; }      int do_jump(int token,INT32 lbl)   { +  struct compilation *c = THIS_COMPILATION;    if(lbl==-1) lbl=alloc_label();    emit1(token, lbl);    return lbl;   }         #define LBLCACHESIZE 4711   #define CURRENT_INSTR ((long)instrbuf.s.len / (long)sizeof(p_instr))   #define MAX_UNWIND 100      static int lbl_cache[LBLCACHESIZE];      static int do_branch(INT32 lbl)   { -  +  struct compilation *c = THIS_COMPILATION;    if(lbl==-1)    {    lbl=alloc_label();    }else{    INT32 last,pos=lbl_cache[lbl % LBLCACHESIZE];    if(pos < (last=CURRENT_INSTR) && (CURRENT_INSTR - pos) < MAX_UNWIND)    {   #define BUF ((p_instr *)instrbuf.s.str)    if(BUF[pos].opcode == F_LABEL && BUF[pos].arg == lbl)    {
pike.git/src/docode.c:225:    }    }       }    emit1(F_BRANCH, lbl);    return lbl;   }      static void low_insert_label(int lbl)   { +  struct compilation *c = THIS_COMPILATION;    lbl_cache[ lbl % LBLCACHESIZE ] = CURRENT_INSTR;    emit1(F_LABEL, lbl);   }      static int ins_label(int lbl)   {    if(lbl==-1) lbl=alloc_label();    low_insert_label(lbl);    return lbl;   }      void do_pop(int x)   { -  +  struct compilation *c = THIS_COMPILATION;   #ifdef PIKE_DEBUG    if (x < 0) Pike_fatal("Cannot do pop of %d args.\n", x);   #endif    switch(x)    {    case 0: return;    case 1: emit0(F_POP_VALUE); break;    default: emit1(F_POP_N_ELEMS,x); break;    }    current_stack_depth -= x;   }      static void do_pop_mark(void *ignored)   { -  +  struct compilation *c = THIS_COMPILATION;    emit0(F_POP_MARK);   }      static void do_pop_to_mark(void *ignored)   { -  +  struct compilation *c = THIS_COMPILATION;    emit0(F_POP_TO_MARK);   }      static void do_cleanup_synch_mark(void)   { -  +  struct compilation *c = THIS_COMPILATION;    if (d_flag > 2)    emit0(F_CLEANUP_SYNCH_MARK);   }      static void do_escape_catch(void)   { -  +  struct compilation *c = THIS_COMPILATION;    emit0(F_ESCAPE_CATCH);   }      #define DO_CODE_BLOCK(X) do_pop(do_docode((X),DO_NOT_COPY | DO_POP ))      int do_docode(node *n, int flags)   {    int i;    int stack_depth_save = current_stack_depth; -  int save_current_line=lex.current_line; +  struct compilation *c = THIS_COMPILATION; +  int save_current_line = c->lex.current_line;    if(!n) return 0; -  lex.current_line=n->line_number; +  c->lex.current_line=n->line_number;   #ifdef PIKE_DEBUG    if (current_stack_depth == -4711) Pike_fatal("do_docode() used outside docode().\n");   #endif    i=do_docode2(n, flags);    current_stack_depth = stack_depth_save + i;    -  lex.current_line=save_current_line; +  c->lex.current_line=save_current_line;    return i;   }      static int is_efun(node *n, c_fun fun)   {    return n && n->token == F_CONSTANT &&    n->u.sval.subtype == FUNCTION_BUILTIN &&    n->u.sval.u.efun->function == fun;   }      static void code_expression(node *n, int flags, char *err)   {    switch(do_docode(n, flags & ~DO_POP))    {    case 0: my_yyerror("Void expression for %s",err);    case 1: return;    case 2:    Pike_fatal("Internal compiler error (%s), line %ld, file %s\n",    err, -  (long)lex.current_line, -  lex.current_file?lex.current_file->str:"Unknown"); +  (long)THIS_COMPILATION->lex.current_line, +  THIS_COMPILATION->lex.current_file->str);    }   }      void do_cond_jump(node *n, int label, int iftrue, int flags)   {    iftrue=!!iftrue;    if((flags & DO_POP) && node_is_tossable(n))    {    int t,f;    t=!!node_is_true(n);
pike.git/src/docode.c:405:    ret=0;    if(car_is_node(n)) ret += count_cases(CAR(n));    if(cdr_is_node(n)) ret += count_cases(CDR(n));    return ret;    }   }         int generate_call_function(node *n)   { +  struct compilation *c = THIS_COMPILATION;    emit0(F_MARK);    PUSH_CLEANUP_FRAME(do_pop_mark, 0);    do_docode(CDR(n),DO_NOT_COPY);    emit0(F_CALL_FUNCTION);    POP_AND_DONT_CLEANUP;    return 1;   }      static INLINE struct compiler_frame *find_local_frame(INT32 depth)   {
pike.git/src/docode.c:426:    while(--depth>=0) f=f->previous;    return f;   }      /* Emit code for a function call to the identifier reference #id,    * with the arguments specified by args.    */   static int do_lfun_call(int id, node *args)   {   #if 1 +  struct compilation *c = THIS_COMPILATION;    struct reference *ref =    Pike_compiler->new_program->identifier_references + id;       /* Test description:    *    * * Test if we have a valid current function.    *    * * Quick check if id is the current function.    *    * * Check if id is an alternate reference to the current function.
pike.git/src/docode.c:502:    return 1;   }      /*    * FIXME: this can be optimized, but is not really used    * enough to be worth it yet.    */   static void emit_apply_builtin(char *func)   {    INT32 tmp1; +  struct compilation *c = THIS_COMPILATION;    struct pike_string *n1=make_shared_string(func);    node *n=find_module_identifier(n1,0);    free_string(n1);       switch(n?n->token:0)    {    case F_CONSTANT:    tmp1=store_constant(&n->u.sval,    !(n->tree_info & OPT_EXTERNAL_DEPEND),    n->name);
pike.git/src/docode.c:528:       default:    my_yyerror("docode: Failed to make call to %s",func);    }    free_node(n);   }      static int do_encode_automap_arg_list(node *n,    int flags)   { +  struct compilation *c = THIS_COMPILATION;    int stack_depth_save = current_stack_depth;    if(!n) return 0;    switch(n->token)    {    default:    return do_docode(n, flags);       case F_ARG_LIST:    {    int ret;
pike.git/src/docode.c:565:    emit1(F_NUMBER, depth);    emit_apply_builtin("__builtin.automap_marker");    return 1;    }    }   }      static void emit_builtin_svalue(char *func)   {    INT32 tmp1; +  struct compilation *c = THIS_COMPILATION;    struct pike_string *n1=make_shared_string(func);    node *n=find_module_identifier(n1,0);    free_string(n1);       switch(n?n->token:0)    {    case F_CONSTANT:    tmp1=store_constant(&n->u.sval,    (!(n->tree_info & OPT_EXTERNAL_DEPEND)) &&    (n->u.sval.type != T_TYPE),
pike.git/src/docode.c:587:    break;       default:    my_yyerror("docode: Failed to make svalue for builtin %s",func);    }    free_node(n);   }      static void emit_range (node *n DO_IF_DEBUG (COMMA int num_args))   { +  struct compilation *c = THIS_COMPILATION;    node *low = CADR (n), *high = CDDR (n);    int bound_types;       switch (low->token) {    case F_RANGE_FROM_BEG: bound_types = RANGE_LOW_FROM_BEG; break;    case F_RANGE_FROM_END: bound_types = RANGE_LOW_FROM_END; break;    case F_RANGE_OPEN: bound_types = RANGE_LOW_OPEN; break;   #ifdef PIKE_DEBUG    default:    Pike_fatal ("Unexpected node %d as range lower bound.\n", low->token);
pike.git/src/docode.c:633: Inside #if defined(PIKE_DEBUG)
   Pike_fatal ("Wrong number of args to o_range opcode. Expected %d, got %d.\n",    expected_args, num_args);    }   #endif       emit1 (F_RANGE, bound_types);   }      static void emit_multi_assign(node *vals, node *vars, int no)   { +  struct compilation *c = THIS_COMPILATION;    node *var;    node *val;    node **valp = my_get_arg(&vals, no);       if (!vars && (!valp || !*valp)) return;    if (!(vars && valp && (val = *valp))) {    yyerror("Argument count mismatch for multi-assignment.\n");    return;    }   
pike.git/src/docode.c:755:    do_docode(var, DO_LVALUE);    if(do_docode(val, 0) != 1) yyerror("RHS is void!");    emit_multi_assign(vals, vars, no+1);    emit0(F_ASSIGN_AND_POP);    break;    }   }      static int do_docode2(node *n, int flags)   { +  struct compilation *c = THIS_COMPILATION;    ptrdiff_t tmp1,tmp2,tmp3;    int ret;       if(!n) return 0;       if(flags & DO_LVALUE)    {    switch(n->token)    {    default:
pike.git/src/docode.c:2121:       if (case_val) {    if(!is_const(case_val))    yyerror("Case label isn't constant.");       if (case_val->type && !TEST_COMPAT(0,6)) {    if (!pike_types_le(case_val->type, current_switch.type)) {    if (!match_types(case_val->type, current_switch.type)) {    yytype_error("Type mismatch in case.",    current_switch.type, case_val->type, 0); -  } else if (lex.pragmas & ID_STRICT_TYPES) { +  } else if (c->lex.pragmas & ID_STRICT_TYPES) {    yytype_error("Type mismatch in case.",    current_switch.type, case_val->type, YYTE_IS_WARNING);    }    }    }       if (!Pike_compiler->num_parse_error) {    tmp1=eval_low(case_val,1);    if(tmp1<1)    {
pike.git/src/docode.c:2254:    struct statement_label_name name;    BLOCK_BEGIN;    PUSH_STATEMENT_LABEL;    name.str = CAR(n)->u.sval.u.string;    name.line_number = n->line_number;       for (label = current_label; label; label = label->prev) {    struct statement_label_name *lbl_name;    for (lbl_name = label->name; lbl_name; lbl_name = lbl_name->next)    if (lbl_name->str == name.str) { -  INT32 save_line = lex.current_line; -  lex.current_line = name.line_number; +  INT32 save_line = c->lex.current_line; +  c->lex.current_line = name.line_number;    my_yyerror("Duplicate nested labels, previous one on line %d.",    lbl_name->line_number); -  lex.current_line = save_line; +  c->lex.current_line = save_line;    goto label_check_done;    }    }    label_check_done:       name.next = current_label->name;    current_label->name = &name;       if (!name.next) {    if (n->token == F_CUSTOM_STMT_LABEL)
pike.git/src/docode.c:2650:       default:    Pike_fatal("Infernal compiler error (unknown parse-tree-token %d).\n", n->token);    return 0; /* make gcc happy */    }   }      /* Used to generate code for functions. */   INT32 do_code_block(node *n)   { +  struct compilation *c = THIS_COMPILATION;    INT32 entry_point;   #ifdef PIKE_DEBUG    if (current_stack_depth != -4711) Pike_fatal("Reentrance in do_code_block().\n");    current_stack_depth = 0;   #endif       init_bytecode();    label_no=1;       /* NOTE: This is no ordinary label... */