pike.git
/
src
/
docode.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/docode.c:1:
/*\ ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. \*/ /**/ #include "global.h"
-
RCSID("$Id: docode.c,v 1.
90
2001/01/10
20
:
00
:
23
mast Exp $");
+
RCSID("$Id: docode.c,v 1.
91
2001/01/10
23
:
31
:
55
mast Exp $");
#include "las.h" #include "program.h" #include "pike_types.h" #include "stralloc.h" #include "interpret.h" #include "constants.h" #include "array.h" #include "pike_macros.h" #include "pike_error.h" #include "pike_memory.h"
pike.git/src/docode.c:35:
struct pike_string *str; unsigned INT16 line_number; }; struct statement_label { struct statement_label *prev; struct statement_label_name *name; INT16 emit_break_label; INT32 break_label, continue_label;
-
unsigned
catch
_
depth
;
+
void
(*cleanup)(void *);
+
void *cleanup
_
arg
;
}; static struct statement_label *current_label = 0;
-
static unsigned catch_depth = 0;
-
+
#define PUSH_STATEMENT_LABEL do { \ struct statement_label new_label__; \ new_label__.prev = current_label; \
-
+
new_label__.cleanup = 0; \
if (!current_label || current_label->break_label != -2) { \ /* Only cover the current label if it's in use by a statement. */ \ new_label__.name = 0; \ new_label__.break_label = new_label__.continue_label = -1; \
-
new_label__.catch_depth = catch_depth; \
+
current_label = &new_label__; \ } \
-
+
DO_IF_DEBUG( \
+
else if (current_label && current_label->cleanup) \
+
fatal("Cleanup callback taken in unused statement label.\n"); \
+
) \
do #define POP_STATEMENT_LABEL \ while (0); \ current_label = new_label__.prev; \
-
+
if (new_label__.cleanup) \
+
new_label__.cleanup(new_label__.cleanup_arg); \
} while (0) static INT32 current_switch_case; static INT32 current_switch_default; static INT32 current_switch_values_on_stack; static INT32 *current_switch_jumptable =0; static struct pike_string *current_switch_type = NULL; void upd_int(int offset, INT32 tmp) {
pike.git/src/docode.c:93:
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];
-
int do_branch(INT32 lbl
, int catch_escapes
)
+
int do_branch(INT32 lbl)
{ 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:120:
BUF[pos].arg, BUF[pos].arg2, BUF[pos].line, BUF[pos].file); } } } } }
-
while (catch_escapes--)
-
emit0(F_ESCAPE_CATCH);
+
emit1(F_BRANCH, lbl); return lbl; } void low_insert_label(int lbl) { lbl_cache[ lbl % LBLCACHESIZE ] = CURRENT_INSTR; emit1(F_LABEL, lbl); }
pike.git/src/docode.c:149:
void do_pop(int x) { switch(x) { case 0: return; case 1: emit0(F_POP_VALUE); break; default: emit1(F_POP_N_ELEMS,x); break; } }
+
void do_escape_catch()
+
{
+
emit0(F_ESCAPE_CATCH);
+
}
+
#define DO_CODE_BLOCK(X) do_pop(do_docode((X),DO_NOT_COPY | DO_POP | DO_DEFER_POP)) int do_docode(node *n, INT16 flags) { int i; int save_current_line=lex.current_line; if(!n) return 0; lex.current_line=n->line_number; i=do_docode2(check_node_hash(n), flags);
pike.git/src/docode.c:194:
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); f=!!node_is_false(n); if(t || f) {
-
if(t == iftrue) do_branch( label
, 0
);
+
if(t == iftrue) do_branch( label);
return; } } switch(n->token) { case F_LAND: case F_LOR: if(iftrue == (n->token==F_LAND)) {
pike.git/src/docode.c:461:
return 0; } tmp1=alloc_label(); do_jump_when_zero(CAR(n), DO_NOT_WARN((INT32)tmp1)); adroppings=do_docode(CADR(n), flags); tmp3=emit1(F_POP_N_ELEMS,0); /* Else */
-
tmp2=do_branch(-1
, 0
);
+
tmp2=do_branch(-1);
low_insert_label( DO_NOT_WARN((INT32)tmp1)); bdroppings=do_docode(CDDR(n), flags); if(adroppings < bdroppings) { do_pop(bdroppings - adroppings); } if(adroppings > bdroppings) {
pike.git/src/docode.c:753:
{ tmp2=do_docode(CAR(arr),DO_NOT_COPY); do_docode(*a1,DO_NOT_COPY); goto foreach_arg_pushed; } } tmp2=do_docode(CAR(n),DO_NOT_COPY); emit0(F_CONST0); foreach_arg_pushed:
+
current_label->cleanup = (void (*)(void *)) do_pop;
+
current_label->cleanup_arg = (void *) 4;
#ifdef PIKE_DEBUG /* This is really ugly because there is always a chance that the bug * will disappear when new instructions are added to the code, but * think it is worth it. */ if(d_flag) emit0(F_MARK); #endif
-
tmp3=do_branch(-1
, 0
);
+
tmp3=do_branch(-1);
tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_label->continue_label); low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(n->token, DO_NOT_WARN((INT32)tmp1)); ins_label(current_label->break_label); #ifdef PIKE_DEBUG if(d_flag) emit0(F_POP_MARK); #endif current_switch_jumptable = prev_switch_jumptable; } POP_STATEMENT_LABEL;
-
do_pop(4);
+
return 0; } case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_INC_LOOP: case F_DEC_LOOP: { INT32 *prev_switch_jumptable = current_switch_jumptable; PUSH_STATEMENT_LABEL { current_switch_jumptable=0; current_label->break_label=alloc_label(); current_label->continue_label=alloc_label(); tmp2=do_docode(CAR(n),0);
-
+
current_label->cleanup = (void (*)(void *)) do_pop;
+
current_label->cleanup_arg = (void *) 3;
#ifdef PIKE_DEBUG /* This is really ugly because there is always a chance that the bug * will disappear when new instructions are added to the code, but * think it is worth it. */ if(d_flag) emit0(F_MARK); #endif
-
tmp3=do_branch(-1
, 0
);
+
tmp3=do_branch(-1);
tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_label->continue_label); low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(n->token, DO_NOT_WARN((INT32)tmp1)); ins_label(current_label->break_label); #ifdef PIKE_DEBUG if(d_flag) emit0(F_POP_MARK); #endif current_switch_jumptable = prev_switch_jumptable; } POP_STATEMENT_LABEL;
-
do_pop(3);
+
return 0; } case F_DO: { INT32 *prev_switch_jumptable = current_switch_jumptable; PUSH_STATEMENT_LABEL { current_switch_jumptable=0; current_label->break_label=alloc_label();
pike.git/src/docode.c:1186:
{ yyerror("Default outside switch."); }else if(current_switch_default!=-1){ yyerror("Duplicate switch default."); }else{ current_switch_default = ins_label(-1); } return 0; case F_BREAK:
-
case F_CONTINUE:
+
case F_CONTINUE:
{
+
struct statement_label *label, *p;
+
if (CAR(n)) { struct pike_string *name = CAR(n)->u.sval.u.string;
-
struct statement_label *label;
+
struct statement_label_name *lbl_name; for (label = current_label; label; label = label->prev) for (lbl_name = label->name; lbl_name; lbl_name = lbl_name->next) if (lbl_name->str == name) goto label_found; my_yyerror("No surrounding statement labeled '%s'.", name->str); return 0; label_found:
-
if (n->token == F_
BREAK)
{
-
if (
label->
break
_label < 0)
label->emit_break_label = 1;
-
label->break_label =
-
do_branch(label->break_label, catch_depth - label->catch_depth);
-
}
-
else
{
-
if (label->continue_label < 0)
+
if (n->token == F_
CONTINUE
&&
label->
continue
_label < 0) {
my_yyerror("Cannot continue the non-loop statement on line %d.", lbl_name->line_number);
-
else
-
do_branch(label->continue_label, catch_depth - label->catch_depth)
;
+
return
0
;
} } else if (n->token == F_BREAK) {
-
if(!
current_
label ||
current_
label->break_label < 0)
+
label = current_label;
+
if(!label || label->break_label < 0)
{ yyerror("Break outside loop or switch.");
-
}else{
-
do_branch( current_label->break_label,
-
catch_depth - current_label->catch_depth)
;
+
return
0
;
} } else {
-
struct statement_label *label;
+
for (label = current_label; label; label = label->prev)
-
if (label->continue_label >= 0)
{
-
do_branch(
label->
continue_label
,
-
catch_depth - label->catch_depth
);
+
if (label->continue_label >= 0)
+
goto
continue_label
_found;
+
yyerror("Continue
outside
loop."
);
return 0;
-
+
continue_label_found:
}
-
yyerror
(
"Continue
outside
loop."
);
+
+
for
(p
=
current_label;
p != label; p = p->prev)
+
if
(
p->cleanup)
+
p->cleanup(p->cleanup_arg
);
+
+
if (n->token == F_BREAK) {
+
if (label->break_label < 0) label->emit_break_label = 1;
+
label->break_label = do_branch(label->break_label);
}
-
+
else
+
do_branch(label->continue_label);
+
return 0;
-
+
}
case F_NORMAL_STMT_LABEL: case F_CUSTOM_STMT_LABEL:
-
{
+
PUSH_STATEMENT_LABEL { struct statement_label *label; struct statement_label_name name; 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) {
pike.git/src/docode.c:1275:
* instead of covering it. */ current_label->break_label = -2; else current_label->break_label = -1; } DO_CODE_BLOCK(CDR(n)); if (!name.next && current_label->emit_break_label) low_insert_label(current_label->break_label); } POP_STATEMENT_LABEL; return 0;
-
}
+
case F_RETURN: do_docode(CAR(n),0); emit0(F_RETURN); return 0; case F_SSCANF: tmp1=do_docode(CAR(n),DO_NOT_COPY); tmp2=do_docode(CDR(n),DO_NOT_COPY | DO_LVALUE); emit1(F_SSCANF, DO_NOT_WARN((INT32)(tmp1+tmp2))); return 1; case F_CATCH:
-
{
+
PUSH_STATEMENT_LABEL { INT32 *prev_switch_jumptable = current_switch_jumptable; current_switch_jumptable=0; current_label->break_label=alloc_label(); if (TEST_COMPAT(7,0)) current_label->continue_label=alloc_label();
-
+
current_label->cleanup = (void (*)(void *)) do_escape_catch;
-
catch_depth++;
+
tmp1=do_jump(F_CATCH,-1); DO_CODE_BLOCK(CAR(n));
-
catch_depth--;
+
if (TEST_COMPAT(7,0)) ins_label(current_label->continue_label); ins_label(current_label->break_label); emit0(F_THROW_ZERO); ins_label(DO_NOT_WARN((INT32)tmp1)); current_switch_jumptable = prev_switch_jumptable;
-
+
current_label->cleanup = 0;
} POP_STATEMENT_LABEL; return 1;
-
}
+
case F_LVALUE_LIST: return do_docode(CAR(n),DO_LVALUE)+do_docode(CDR(n),DO_LVALUE); case F_ARRAY_LVALUE: tmp1=do_docode(CAR(n),DO_LVALUE); #ifdef PIKE_DEBUG if(tmp1 & 1) fatal("Very internal compiler error.\n"); #endif
pike.git/src/docode.c:1509:
emit1(F_GLOBAL,n->u.id.number); } } return 1; case F_VAL_LVAL: return do_docode(CAR(n),flags) + do_docode(CDR(n), (INT16)(flags | DO_LVALUE)); default:
-
fatal("Infernal compiler error (unknown parse-tree-token).\n");
+
fatal("Infernal compiler error (unknown parse-tree-token
%d
).\n"
, n->token
);
return 0; /* make gcc happy */ } } void do_code_block(node *n) { init_bytecode(); label_no=1; emit1(F_BYTE,Pike_compiler->compiler_frame->max_number_of_locals);