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$
+
*/
#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:38:
struct cleanup_frame *prev;
cleanup_func cleanup;
void *cleanup_arg;
int stack_depth;
};
struct statement_label_name
{
struct statement_label_name *next;
struct pike_string *str;
- unsigned int line_number;
+ INT_TYPE line_number;
+ int used;
};
struct statement_label
{
struct statement_label *prev;
struct statement_label_name *name;
/* -2 in break_label is used to flag "open" statement_label entries.
* If an open entry is on top of the stack, it's used instead of a
* new one. That's used to associate statement labels to the
* following statement. */
pike.git/src/docode.c:167:
INT32 less_label, greater_label, default_label;
INT32 values_on_stack;
INT32 *jumptable;
struct pike_type *type;
};
static struct switch_data current_switch = {0, 0, 0, 0, 0, NULL, NULL};
void upd_int(int offset, INT32 tmp)
{
- MEMCPY(Pike_compiler->new_program->program+offset, (char *)&tmp,sizeof(tmp));
+ memcpy(Pike_compiler->new_program->program+offset, &tmp, sizeof(tmp));
}
INT32 read_int(int offset)
{
return EXTRACT_INT(Pike_compiler->new_program->program+offset);
}
static int label_no=0;
int alloc_label(void) { return ++label_no; }
pike.git/src/docode.c:265:
#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)
+ static void do_pop_mark(void *UNUSED(ignored))
{
struct compilation *c = THIS_COMPILATION;
emit0(F_POP_MARK);
}
- static void do_pop_to_mark(void *ignored)
+ static void do_pop_to_mark(void *UNUSED(ignored))
{
struct compilation *c = THIS_COMPILATION;
emit0(F_POP_TO_MARK);
}
#ifdef PIKE_DEBUG
static void do_cleanup_synch_mark(void)
{
struct compilation *c = THIS_COMPILATION;
if (d_flag > 2)
pike.git/src/docode.c:299:
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;
struct compilation *c = THIS_COMPILATION;
- int save_current_line = c->lex.current_line;
+ INT_TYPE save_current_line = c->lex.current_line;
if(!n) return 0;
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;
c->lex.current_line=save_current_line;
return i;
pike.git/src/docode.c:333:
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)THIS_COMPILATION->lex.current_line,
THIS_COMPILATION->lex.current_file->str);
}
}
- void do_cond_jump(node *n, int label, int iftrue, int flags)
+ static 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);
pike.git/src/docode.c:424:
return !!CAR(n)+!!CDR(n);
default:
ret=0;
if(car_is_node(n)) ret += count_cases(CAR(n));
if(cdr_is_node(n)) ret += count_cases(CDR(n));
return ret;
}
}
+ static int has_automap(node *n)
+ {
+ if(!n) return 0;
+ switch(n->token)
+ {
+ case F_AUTO_MAP_MARKER:
+ case F_AUTO_MAP:
+ return 1;
-
+ default:
+ if(car_is_node(n) && has_automap(CAR(n)) )
+ return 1;
+ if( cdr_is_node(n) && has_automap(CDR(n)) )
+ return 1;
+ }
+ return 0;
+ }
+
+
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)
+ static struct compiler_frame *find_local_frame(INT32 depth)
{
struct compiler_frame *f=Pike_compiler->compiler_frame;
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.
- *
- * * Check that the function isn't varargs or contains scoped functions.
- *
- * * Check that the current function doesn't contain scoped functions.
- */
+
if((Pike_compiler->compiler_frame->current_function_number >= 0) &&
((id == Pike_compiler->compiler_frame->current_function_number) ||
((!ref->inherit_offset) &&
(ref->identifier_offset ==
Pike_compiler->new_program->
identifier_references[Pike_compiler->compiler_frame->
current_function_number].identifier_offset))) &&
!(Pike_compiler->new_program->
identifiers[ref->identifier_offset].identifier_flags &
(IDENTIFIER_VARARGS|IDENTIFIER_SCOPE_USED)) &&
!(Pike_compiler->compiler_frame->lexical_scope & SCOPE_SCOPE_USED))
{
- int n=count_args(args);
- if(n == Pike_compiler->compiler_frame->num_args)
- {
+ PUSH_CLEANUP_FRAME(do_pop_mark, 0);
+ emit0(F_MARK);
do_docode(args,0);
- if(Pike_compiler->compiler_frame->is_inline ||
- (ref->id_flags & ID_INLINE))
+
+ /* 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.
+ *
+ * * Check that the function isn't varargs or contains scoped functions.
+ *
+ * * Check that the current function doesn't contain scoped functions.
+ */
+ if(Pike_compiler->compiler_frame->is_inline || (ref->id_flags & (ID_INLINE|ID_PRIVATE)))
{
/* Identifier is declared inline/local
* or in inlining pass.
*/
- if ((ref->id_flags & ID_INLINE) &&
+ if ((ref->id_flags & (ID_INLINE|ID_PRIVATE)) &&
(!Pike_compiler->compiler_frame->is_inline)) {
/* Explicit local:: reference in first pass.
*
* RECUR directly to label 0.
*
* Note that we in this case don't know if we are overloaded or
* not, and thus can't RECUR to the recur_label.
*/
do_jump(F_RECUR, 0);
} else {
- Pike_compiler->compiler_frame->
- recur_label=do_jump(F_RECUR,
- Pike_compiler->compiler_frame->recur_label);
+ Pike_compiler->compiler_frame->recur_label =
+ do_jump(F_RECUR, Pike_compiler->compiler_frame->recur_label);
}
} else {
/* Recur if not overloaded. */
emit1(F_COND_RECUR,id);
- Pike_compiler->compiler_frame->
- recur_label=do_jump(F_POINTER,
- Pike_compiler->compiler_frame->recur_label);
+ Pike_compiler->compiler_frame->recur_label =
+ do_jump(F_POINTER, Pike_compiler->compiler_frame->recur_label);
}
-
+ POP_AND_DONT_CLEANUP;
return 1;
}
- }
+ else {
+ #ifdef USE_APPLY_N
+ int nargs = count_args(args);
+ if( nargs == -1 )
+ {
#endif
-
- emit0(F_MARK);
+
PUSH_CLEANUP_FRAME(do_pop_mark, 0);
-
+ emit0(F_MARK);
do_docode(args,0);
emit1(F_CALL_LFUN, id);
POP_AND_DONT_CLEANUP;
return 1;
-
+ #ifdef USE_APPLY_N
}
-
+ else
+ {
+ do_docode(args,0);
+ emit2(F_CALL_LFUN_N, id, nargs);
+ }
+ #endif
+ }
+ 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);
pike.git/src/docode.c:542:
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);
if(TYPEOF(n->u.sval) == T_FUNCTION &&
SUBTYPEOF(n->u.sval) == FUNCTION_BUILTIN)
- emit1(F_CALL_BUILTIN, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CALL_BUILTIN, (INT32)tmp1);
else
- emit1(F_APPLY, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_APPLY, (INT32)tmp1);
break;
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)
pike.git/src/docode.c:606:
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)) &&
(TYPEOF(n->u.sval) != T_TYPE),
n->name);
- emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CONSTANT, (INT32)tmp1);
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; /* Got bogus gcc warning here. */
+ int bound_types = 0; /* Got bogus gcc warning here. */
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);
#endif
}
pike.git/src/docode.c:662: Inside #if defined(PIKE_DEBUG)
}
if (num_args != expected_args)
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_global( int n )
+ {
+ struct compilation *c = THIS_COMPILATION;
+ struct reference *ref = PTR_FROM_INT(Pike_compiler->new_program, n);
+ struct identifier *id = ID_FROM_PTR(Pike_compiler->new_program, ref);
+
+ if(!(id->identifier_flags & IDENTIFIER_NO_THIS_REF)
+ && !ref->inherit_offset
+ && !IDENTIFIER_IS_ALIAS(id->identifier_flags)
+ && IDENTIFIER_IS_VARIABLE(id->identifier_flags))
+ {
+ /* fprintf( stderr, "private global %d\n", (INT32)id->func.offset ); */
+ if( ref->id_flags & (ID_PRIVATE|ID_FINAL) )
+ {
+ if( id->run_time_type == PIKE_T_MIXED )
+ emit1(F_PRIVATE_GLOBAL, id->func.offset);
+ else
+ emit2(F_PRIVATE_TYPED_GLOBAL, id->func.offset, id->run_time_type);
+ return;
+ }
+
+ if( id->run_time_type == PIKE_T_MIXED )
+ {
+ emit2(F_PRIVATE_IF_DIRECT_GLOBAL, id->func.offset, n);
+ return;
+ }
+ /* else if( (id->func.offset < 65536) && (n<65536) ) */
+ /* { */
+ /* INT32 mix = id->func.offset | (n<<16); */
+ /* emit2(F_PRIVATE_IF_DIRECT_TYPED_GLOBAL, mix, id->run_time_type); */
+ /* } */
+ }
+ emit1(F_GLOBAL, n);
+ }
+
+ static void emit_assign_global( int n, int and_pop )
+ {
+ struct compilation *c = THIS_COMPILATION;
+ struct reference *ref = PTR_FROM_INT(Pike_compiler->new_program, n);
+ struct identifier *id = ID_FROM_PTR(Pike_compiler->new_program, ref);
+
+ if( !(id->identifier_flags & IDENTIFIER_NO_THIS_REF)
+ && !ref->inherit_offset
+ && !IDENTIFIER_IS_ALIAS(id->identifier_flags)
+ && IDENTIFIER_IS_VARIABLE(id->identifier_flags))
+ {
+ if( (ref->id_flags & (ID_PRIVATE|ID_FINAL)) )
+ {
+ if( id->run_time_type == PIKE_T_MIXED )
+ emit1((and_pop?F_ASSIGN_PRIVATE_GLOBAL_AND_POP:F_ASSIGN_PRIVATE_GLOBAL),
+ id->func.offset);
+ else
+ emit2((and_pop?F_ASSIGN_PRIVATE_TYPED_GLOBAL_AND_POP:F_ASSIGN_PRIVATE_TYPED_GLOBAL),
+ id->func.offset, id->run_time_type);
+ return;
+ }
+ if( id->run_time_type == PIKE_T_MIXED )
+ {
+ emit2(F_ASSIGN_PRIVATE_IF_DIRECT_GLOBAL, id->func.offset, n );
+ if( and_pop )
+ emit0(F_POP_VALUE);
+ return;
+ }
+ }
+ emit1((and_pop?F_ASSIGN_GLOBAL_AND_POP:F_ASSIGN_GLOBAL), n);
+ }
+
+ static int emit_ltosval_call_and_assign( node *lval, node *func, node *args )
+ {
+ struct compilation *c = THIS_COMPILATION;
+ node **arg;
+ int no = 0;
+ int tmp1=store_constant(&func->u.sval,
+ !(func->tree_info & OPT_EXTERNAL_DEPEND),
+ func->name);
+
+
+ #ifdef PIKE_DEBUG
+ arg = my_get_arg(&args,0);
+ if( !node_is_eq(*arg,lval) )
+ Pike_fatal("lval should be the same as arg1, or this will not work.\n");
+ #endif
+ do_docode(lval, DO_LVALUE);
+ emit0(F_MARK);
+ emit0(F_CONST0);
+ PUSH_CLEANUP_FRAME(do_pop_mark, 0);
+ while ((arg = my_get_arg(&args, ++no)) && *arg) {
+ do_docode(*arg, 0);
+ }
+ emit1(F_LTOSVAL_CALL_BUILTIN_AND_ASSIGN, (INT32)tmp1);
+ POP_AND_DONT_CLEANUP;
+ return 1;
+ }
+
+ static int is_apply_constant_function_arg0( node *n, node *target )
+ {
+ if (/*n->token == F_APPLY &&*/
+ (CAR(n)->token == F_CONSTANT) &&
+ (TYPEOF(CAR(n)->u.sval) == T_FUNCTION) &&
+ (SUBTYPEOF(CAR(n)->u.sval) == FUNCTION_BUILTIN) &&
+ (CAR(n)->u.sval.u.efun->function != f_map) &&
+ (CAR(n)->u.sval.u.efun->function != f_filter)) {
+ /* efuns typically don't access object variables. */
+ node *args = CDR(n), **arg;
+ if (args)
+ {
+ arg = my_get_arg(&args, 0);
+ if (arg && node_is_eq(target, *arg) &&
+ !(args->tree_info & OPT_ASSIGNMENT))
+ {
+ if(match_types(target->type, array_type_string) ||
+ match_types(target->type, string_type_string) ||
+ match_types(target->type, object_type_string) ||
+ match_types(target->type, multiset_type_string) ||
+ match_types(target->type, mapping_type_string))
+ {
+ return emit_ltosval_call_and_assign(target,CAR(n),args);
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
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");
pike.git/src/docode.c:701:
if (var->node_info & OPT_ASSIGNMENT) {
/* Initialize. */
emit0(F_CONST0);
emit1(F_ASSIGN_LOCAL_AND_POP, var->u.integer.a);
}
code_expression(val, 0, "RHS");
emit_multi_assign(vals, vars, no+1);
emit1(F_ASSIGN_LOCAL_AND_POP, var->u.integer.a );
break;
- /* FIXME: Make special case for F_EXTERNAL */
- case F_IDENTIFIER:
- if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(Pike_compiler->new_program,
- var->u.id.number)->identifier_flags))
- {
- yyerror("Cannot assign functions or constants.\n");
- }else{
- code_expression(val, 0, "RHS");
- emit_multi_assign(vals, vars, no+1);
- emit1(F_ASSIGN_GLOBAL_AND_POP, var->u.id.number);
- }
- break;
-
+
case F_GET_SET:
{
/* Check for the setter function. */
struct program_state *state = Pike_compiler;
int program_id = var->u.integer.a;
int level = 0;
while (state && (state->new_program->id != program_id)) {
state = state->previous;
level++;
}
pike.git/src/docode.c:769:
case F_EXTERNAL:
/* Check that it is in this context */
if(Pike_compiler ->new_program->id == var->u.integer.a)
{
/* Check that it is a variable */
if(var->u.integer.b != IDREF_MAGIC_THIS &&
IDENTIFIER_IS_VARIABLE( ID_FROM_INT(Pike_compiler->new_program, var->u.integer.b)->identifier_flags))
{
code_expression(val, 0, "RHS");
emit_multi_assign(vals, vars, no+1);
- emit1(F_ASSIGN_GLOBAL_AND_POP, var->u.integer.b);
+ emit_assign_global( var->u.integer.b, 1 );
break;
}
}
/* fall through */
default:
normal_assign:
do_docode(var, DO_LVALUE);
if(do_docode(val, 0) != 1) yyerror("RHS is void!");
emit_multi_assign(vals, vars, no+1);
pike.git/src/docode.c:807:
default:
yyerror("Illegal lvalue.");
emit1(F_NUMBER,0);
emit1(F_NUMBER,0);
return 2;
case F_ARRAY_LVALUE:
case F_LVALUE_LIST:
case F_LOCAL:
case F_GLOBAL:
- case F_IDENTIFIER:
+
case F_INDEX:
case F_ARROW:
case F_ARG_LIST:
case F_COMMA_EXPR:
case F_EXTERNAL:
case F_GET_SET:
case F_AUTO_MAP_MARKER:
break;
}
}
pike.git/src/docode.c:922:
} else {
/* FIXME: Support inlining for the parent case.
*
* do_call_external(n->u.integer.a, f + inh->identifier_level,
* NULL);
*/
emit2(F_EXTERNAL, n->u.integer.b, level);
}
} else if (level) {
if (IDENTIFIER_IS_CONSTANT(id->identifier_flags) &&
- (ref->id_flags & ID_INLINE) && !ref->inherit_offset &&
+ (ref->id_flags & ID_INLINE) &&
(id->func.const_info.offset >= 0)) {
/* An inline, local or final constant identifier in
* a lexically surrounding (aka parent) class.
* Avoid vtable traversal during runtime by moving
* the constant to this class.
*/
struct svalue *s = &state->new_program->
-
+ inherits[ref->inherit_offset].prog->
constants[id->func.const_info.offset].sval;
if (TYPEOF(*s) == T_PROGRAM &&
s->u.program->flags & PROGRAM_USES_PARENT) {
/* An external reference is required. */
emit2(F_EXTERNAL, n->u.integer.b, level);
} else {
int tmp1 = store_constant(s, 1, NULL);
emit1(F_CONSTANT, tmp1);
}
} else {
-
+ struct program_state *state = Pike_compiler;
+ int e;
+ for (e = level; e; e--) {
+ state->new_program->flags |=
+ PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT;
+ state = state->previous;
+ }
emit2(F_EXTERNAL, n->u.integer.b, level);
}
} else if (n->u.integer.b == IDREF_MAGIC_THIS) {
emit1(F_THIS_OBJECT, 0);
} else if(IDENTIFIER_IS_FUNCTION(id->identifier_flags) &&
id->identifier_flags & IDENTIFIER_HAS_BODY)
{
/* Only use this opcode when it's certain that the result
* can't zero, i.e. when we know the function isn't just a
* prototype. */
emit1(F_LFUN, n->u.integer.b);
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags) &&
- (ref->id_flags & ID_INLINE) && !ref->inherit_offset &&
+ (ref->id_flags & (ID_INLINE|ID_PRIVATE)) && !ref->inherit_offset &&
(id->func.const_info.offset >= 0)) {
/* An inline, local or final constant identifier.
* No need for vtable traversal during runtime.
*/
struct svalue *s = &state->new_program->
constants[id->func.const_info.offset].sval;
if (TYPEOF(*s) == T_PROGRAM &&
s->u.program->flags & PROGRAM_USES_PARENT) {
/* Program using parent. Convert to an LFUN. */
emit1(F_LFUN, n->u.integer.b);
} else {
emit1(F_CONSTANT, id->func.const_info.offset);
}
}else{
- emit1(F_GLOBAL, n->u.integer.b);
+ emit_global( n->u.integer.b );
}
}
}
return 1;
case F_THIS:
{
int level = 0;
struct program_state *state = Pike_compiler;
int inh = n->u.integer.b;
pike.git/src/docode.c:1027:
emit0(F_MARK);
PUSH_CLEANUP_FRAME(do_pop_mark, 0);
do_docode(CAR(n),DO_LVALUE);
emit0(F_CONST0); /* Reserved for svalue. */
do_docode(CDR(n),0);
emit0(F_APPEND_ARRAY);
POP_AND_DONT_CLEANUP;
return 1;
}
+ case F_APPEND_MAPPING: {
+ emit0(F_MARK);
+ PUSH_CLEANUP_FRAME(do_pop_mark, 0);
+ do_docode(CAR(n),DO_LVALUE);
+ emit0(F_CONST0); /* Reserved for svalue. */
+ do_docode(CDR(n),0);
+ emit0(F_APPEND_MAPPING);
+ POP_AND_DONT_CLEANUP;
+ return 1;
+ }
+
case '?':
{
INT32 *prev_switch_jumptable = current_switch.jumptable;
int adroppings , bdroppings;
current_switch.jumptable=0;
if(!CDDR(n))
{
tmp1=alloc_label();
- do_jump_when_zero(CAR(n), DO_NOT_WARN((INT32)tmp1));
+ do_jump_when_zero(CAR(n), (INT32)tmp1);
DO_CODE_BLOCK(CADR(n));
- low_insert_label( DO_NOT_WARN((INT32)tmp1));
+ low_insert_label( (INT32)tmp1 );
current_switch.jumptable = prev_switch_jumptable;
return 0;
}
if(!CADR(n))
{
tmp1=alloc_label();
- do_jump_when_non_zero(CAR(n), DO_NOT_WARN((INT32)tmp1));
+ do_jump_when_non_zero(CAR(n), (INT32)tmp1);
DO_CODE_BLOCK(CDDR(n));
- low_insert_label( DO_NOT_WARN((INT32)tmp1));
+ low_insert_label( (INT32)tmp1 );
current_switch.jumptable = prev_switch_jumptable;
return 0;
}
tmp1=alloc_label();
- do_jump_when_zero(CAR(n), DO_NOT_WARN((INT32)tmp1));
+ do_jump_when_zero(CAR(n), (INT32)tmp1);
adroppings=do_docode(CADR(n), flags);
tmp3=emit1(F_POP_N_ELEMS,0);
/* Else */
tmp2=do_branch(-1);
- low_insert_label( DO_NOT_WARN((INT32)tmp1));
+ low_insert_label( (INT32)tmp1 );
bdroppings=do_docode(CDDR(n), flags);
if(adroppings < bdroppings)
{
do_pop(bdroppings - adroppings);
}
if(adroppings > bdroppings)
{
- update_arg(DO_NOT_WARN((INT32)tmp3),
- adroppings - bdroppings);
+ update_arg((INT32)tmp3, adroppings - bdroppings);
adroppings=bdroppings;
}
- low_insert_label( DO_NOT_WARN((INT32)tmp2));
+ low_insert_label( (INT32)tmp2 );
current_switch.jumptable = prev_switch_jumptable;
return adroppings;
}
- case F_AND_EQ:
- case F_OR_EQ:
- case F_XOR_EQ:
- case F_LSH_EQ:
- case F_RSH_EQ:
- case F_ADD_EQ:
- case F_SUB_EQ:
- case F_MULT_EQ:
- case F_MOD_EQ:
- case F_DIV_EQ:
- if((CAR(n) && CAR(n)->token == F_AUTO_MAP_MARKER) ||
- (CDR(n) && CDR(n)->token == F_AUTO_MAP_MARKER))
- {
- char *opname;
-
- if(CAR(n)->token == F_AUTO_MAP_MARKER)
- {
- int depth=0;
- node *tmp=CAR(n);
- while(tmp->token == F_AUTO_MAP_MARKER)
- {
- depth++;
- tmp=CAR(tmp);
- }
- tmp1=do_docode(tmp,DO_LVALUE);
- emit0(F_MARK);
- emit0(F_MARK);
- emit0(F_LTOSVAL);
- emit1(F_NUMBER,depth);
- emit_apply_builtin("__builtin.automap_marker");
- }else{
- tmp1=do_docode(CAR(n),DO_LVALUE);
- emit0(F_LTOSVAL);
- }
-
- switch(n->token)
- {
- case F_ADD_EQ: opname="`+"; break;
- case F_AND_EQ: opname="`&"; break;
- case F_OR_EQ: opname="`|"; break;
- case F_XOR_EQ: opname="`^"; break;
- case F_LSH_EQ: opname="`<<"; break;
- case F_RSH_EQ: opname="`>>"; break;
- case F_SUB_EQ: opname="`-"; break;
- case F_MULT_EQ:opname="`*"; break;
- case F_MOD_EQ: opname="`%"; break;
- case F_DIV_EQ: opname="`/"; break;
- default:
- Pike_fatal("Really???\n");
- opname="`make gcc happy";
- }
-
- emit_builtin_svalue(opname);
- emit2(F_REARRANGE,1,1);
-
- if(CDR(n)->token == F_AUTO_MAP)
- {
- do_encode_automap_arg_list(CDR(n), 0);
- }else{
- code_expression(CDR(n), 0, "assignment");
- }
- emit_apply_builtin("__automap__");
- }else{
- tmp1=do_docode(CAR(n),DO_LVALUE);
- #ifdef PIKE_DEBUG
- if(tmp1 != 2)
- Pike_fatal("HELP! FATAL INTERNAL COMPILER ERROR (7)\n");
- #endif
-
- if(n->token == F_ADD_EQ && (flags & DO_POP))
- {
- code_expression(CDR(n), 0, "assignment");
- emit0(F_ADD_TO_AND_POP);
- return 0;
- }
-
- if(CAR(n)->token != F_AUTO_MAP &&
- (match_types(CAR(n)->type, array_type_string) ||
- match_types(CAR(n)->type, string_type_string) ||
- match_types(CAR(n)->type, mapping_type_string) ||
- match_types(CAR(n)->type, object_type_string)))
- {
- code_expression(CDR(n), 0, "assignment");
- emit0(F_LTOSVAL2_AND_FREE);
- }else{
- emit0(F_LTOSVAL);
- code_expression(CDR(n), 0, "assignment");
- }
-
-
- switch(n->token)
- {
- case F_ADD_EQ:
- if(CAR(n)->type == int_type_string &&
- CDR(n)->type == int_type_string)
- {
- emit0(F_ADD_INTS);
- }
- else if(CAR(n)->type == float_type_string &&
- CDR(n)->type == float_type_string)
- {
- emit0(F_ADD_FLOATS);
- }else{
- emit0(F_ADD);
- }
- break;
- case F_AND_EQ: emit0(F_AND); break;
- case F_OR_EQ: emit0(F_OR); break;
- case F_XOR_EQ: emit0(F_XOR); break;
- case F_LSH_EQ: emit0(F_LSH); break;
- case F_RSH_EQ: emit0(F_RSH); break;
- case F_SUB_EQ: emit0(F_SUBTRACT); break;
- case F_MULT_EQ:emit0(F_MULTIPLY);break;
- case F_MOD_EQ: emit0(F_MOD); break;
- case F_DIV_EQ: emit0(F_DIVIDE); break;
- }
- }
-
- if(flags & DO_POP)
- {
- emit0(F_ASSIGN_AND_POP);
- return 0;
- }else{
- emit0(F_ASSIGN);
- return 1;
- }
-
+
case F_MULTI_ASSIGN:
if (flags & DO_POP) {
emit_multi_assign(CAR(n), CDR(n), 0);
return 0;
} else {
/* Fall back to the normal assign case. */
tmp1=do_docode(CDR(n),DO_LVALUE);
#ifdef PIKE_DEBUG
if(tmp1 & 1)
Pike_fatal("Very internal compiler error.\n");
#endif
- emit1(F_ARRAY_LVALUE, DO_NOT_WARN((INT32)(tmp1>>1)));
+ emit1(F_ARRAY_LVALUE, (INT32)(tmp1>>1) );
emit0(F_MARK);
PUSH_CLEANUP_FRAME(do_pop_mark, 0);
do_docode(CAR(n), 0);
emit_apply_builtin("aggregate");
POP_AND_DONT_CLEANUP;
emit0(F_ASSIGN);
return 1;
}
-
+ case F_ASSIGN_SELF:
+ /* in assign self we know this:
+ *
+ * car(n) = lvalue
+ * cdr(n)= softcast(apply(efun, arglist(car(n),one more arg)))
+ *
+ * The first argument of the arglist is equal to the lvalue.
+ *
+ * We only want to evaluate car(n) once.
+ */
+ if( CDR(n)->token == F_AUTO_MAP_MARKER )
+ yyerror("[*] is not yet supported here\n");
+ return emit_ltosval_call_and_assign( CDR(n), CAAAR(n), CDAAR(n) );
+
case F_ASSIGN:
-
+
+ if( CDR(n)->token == F_AUTO_MAP_MARKER )
+ {
+ int depth = 0;
+ node *lval = CDR(n);
+ while( lval->token == F_AUTO_MAP_MARKER )
+ {
+ lval = CAR(lval);
+ depth++;
+ }
+ do_docode(lval,0); /* note: not lvalue */
+ if(do_docode(CAR(n),0)!=1)
+ yyerror("RHS is void!");
+
+ if( CAR(n)->token == F_AUTO_MAP_MARKER ||
+ CAR(n)->token == F_AUTO_MAP ||
+ /* Well, hello there... ;) */
+ /* This is what is generated by a[*] += 10 and such. */
+ (CAR(n)->token == F_SOFT_CAST &&
+ has_automap(CAR(n))))
+ {
+ emit1(F_ASSIGN_INDICES,depth);
+ }
+ else
+ {
+ emit1(F_ASSIGN_ALL_INDICES,depth);
+ }
+ if( flags & DO_POP )
+ emit0( F_POP_VALUE );
+ return !(flags&DO_POP);
+ }
+
switch(CAR(n)->token)
{
case F_RANGE:
- case F_AND:
- case F_OR:
- case F_XOR:
- case F_LSH:
- case F_RSH:
- case F_ADD:
- case F_MOD:
- case F_SUBTRACT:
- case F_DIVIDE:
- case F_MULTIPLY:
+
if(node_is_eq(CDR(n),CAAR(n)))
{
int num_args;
- tmp1=do_docode(CDR(n),DO_LVALUE);
+ /* tmp1=do_docode(CDR(n),DO_LVALUE); */
if(match_types(CDR(n)->type, array_type_string) ||
match_types(CDR(n)->type, string_type_string) ||
match_types(CDR(n)->type, object_type_string) ||
match_types(CDR(n)->type, multiset_type_string) ||
match_types(CDR(n)->type, mapping_type_string))
{
-
+ do_docode(CDR(n),DO_LVALUE);
num_args = do_docode(CDAR(n), 0);
switch (num_args)
{
case 0: emit0(F_LTOSVAL_AND_FREE); break;
case 1: emit0(F_LTOSVAL2_AND_FREE); break;
case 2: emit0(F_LTOSVAL3_AND_FREE); break;
#ifdef PIKE_DEBUG
default:
Pike_fatal("Arglebargle glop-glyf?\n");
#endif
}
}else{
-
+ goto do_not_suboptimize_assign;
emit0(F_LTOSVAL);
num_args = do_docode(CDAR(n), 0);
}
if (CAR (n)->token == F_RANGE)
emit_range (CAR (n) DO_IF_DEBUG (COMMA num_args));
else
emit0(CAR(n)->token);
emit0(n->token);
return n->token==F_ASSIGN; /* So when is this false? /mast */
}
-
+ case F_SOFT_CAST:
+ /* a = [type]`oper(a,*) */
+ if( CAAR(n)->token == F_APPLY &&
+ is_apply_constant_function_arg0( CAAR(n), CDR(n) ))
+ return 1;
+ goto do_not_suboptimize_assign;
case F_APPLY:
- if ((CAAR(n)->token == F_CONSTANT) &&
- (TYPEOF(CAAR(n)->u.sval) == T_FUNCTION) &&
- (SUBTYPEOF(CAAR(n)->u.sval) == FUNCTION_BUILTIN) &&
- (CAAR(n)->u.sval.u.efun->function != f_map) &&
- (CAAR(n)->u.sval.u.efun->function != f_filter)) {
- /* efuns typically don't access object variables. */
- node *args = CDAR(n);
- if (args) {
- node **arg = my_get_arg(&args, 0);
- if (arg && node_is_eq(CDR(n), *arg) &&
- !(args->tree_info & OPT_ASSIGNMENT)) {
- /* First arg is the lvalue.
- *
- * We optimize this to allow for destructive operations.
- */
- int no = 0;
- tmp1 = do_docode(CDR(n), DO_LVALUE);
- emit0(F_MARK_AND_CONST0);
- PUSH_CLEANUP_FRAME(do_pop_mark, 0);
- while ((arg = my_get_arg(&args, ++no)) && *arg) {
- do_docode(*arg, 0);
- }
- tmp1=store_constant(&CAAR(n)->u.sval,
- !(CAAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
- CAAR(n)->name);
- emit1(F_LTOSVAL_CALL_BUILTIN_AND_ASSIGN, DO_NOT_WARN((INT32)tmp1));
- POP_AND_DONT_CLEANUP;
+ /* a = `oper(a,*) */
+ if (is_apply_constant_function_arg0( CAR(n), CDR(n) ))
return 1;
- }
- }
- }
+
/* FALL_THROUGH */
default:
-
+ do_not_suboptimize_assign:
switch(CDR(n)->token)
{
-
+ case F_GLOBAL:
+ if(CDR(n)->u.integer.b) goto normal_assign;
+ code_expression(CAR(n), 0, "RHS");
+ emit_assign_global( CDR(n)->u.integer.a, flags & DO_POP );
+ break;
case F_LOCAL:
if(CDR(n)->u.integer.a >=
find_local_frame(CDR(n)->u.integer.b)->max_number_of_locals)
yyerror("Illegal to use local variable here.");
if(CDR(n)->u.integer.b) goto normal_assign;
if (CDR(n)->node_info & OPT_ASSIGNMENT) {
/* Initialize. */
emit0(F_CONST0);
emit1(F_ASSIGN_LOCAL_AND_POP, CDR(n)->u.integer.a);
}
code_expression(CAR(n), 0, "RHS");
emit1(flags & DO_POP ? F_ASSIGN_LOCAL_AND_POP:F_ASSIGN_LOCAL,
CDR(n)->u.integer.a );
break;
- /* FIXME: Make special case for F_EXTERNAL */
- case F_IDENTIFIER:
- if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(Pike_compiler->new_program, CDR(n)->u.id.number)->identifier_flags))
- {
- yyerror("Cannot assign functions or constants.\n");
- }else{
- code_expression(CAR(n), 0, "RHS");
- emit1(flags & DO_POP ? F_ASSIGN_GLOBAL_AND_POP:F_ASSIGN_GLOBAL,
- CDR(n)->u.id.number);
- }
- break;
-
+
case F_GET_SET:
{
/* Check for the setter function. */
struct program_state *state = Pike_compiler;
int program_id = CDR(n)->u.integer.a;
int level = 0;
while (state && (state->new_program->id != program_id)) {
state = state->previous;
level++;
}
pike.git/src/docode.c:1380: Inside #if defined(PIKE_DEBUG)
get_name_of_type(id->run_time_type),
id->run_time_type);
}
#endif /* PIKE_DEBUG */
f = id->func.gs_info.setter;
if (f == -1) {
yywarning("Variable %S lacks a setter.", id->name);
} else if (!level) {
f += inh->identifier_level;
if (flags & DO_POP) {
+ #ifndef USE_APPLY_N
emit0(F_MARK);
-
+ #endif
code_expression(CAR(n), 0, "RHS");
} else {
code_expression(CAR(n), 0, "RHS");
-
+ #ifndef USE_APPLY_N
emit0(F_MARK);
-
+ #endif
emit0(F_DUP);
}
-
+ #ifdef USE_APPLY_N
+ emit2(F_CALL_LFUN_N, f, 1);
+ #else
emit1(F_CALL_LFUN, f);
-
+ #endif
emit0(F_POP_VALUE);
return !(flags & DO_POP);
}
}
}
/* FALL_THROUGH */
case F_EXTERNAL:
/* Check that it is in this context */
if(Pike_compiler ->new_program->id == CDR(n)->u.integer.a)
{
/* Check that it is a variable */
if(CDR(n)->u.integer.b != IDREF_MAGIC_THIS &&
IDENTIFIER_IS_VARIABLE( ID_FROM_INT(Pike_compiler->new_program, CDR(n)->u.integer.b)->identifier_flags))
{
code_expression(CAR(n), 0, "RHS");
- emit1(flags & DO_POP ? F_ASSIGN_GLOBAL_AND_POP:F_ASSIGN_GLOBAL,
- CDR(n)->u.integer.b);
+ emit_assign_global(CDR(n)->u.integer.b, flags & DO_POP );
break;
}
}
/* fall through */
default:
normal_assign:
tmp1=do_docode(CDR(n),DO_LVALUE);
if(do_docode(CAR(n),0)!=1) yyerror("RHS is void!");
emit0(flags & DO_POP ? F_ASSIGN_AND_POP:F_ASSIGN);
break;
}
return flags & DO_POP ? 0 : 1;
}
case F_LAND:
case F_LOR:
tmp1=alloc_label();
if(flags & DO_POP)
{
- do_cond_jump(CAR(n), DO_NOT_WARN((INT32)tmp1), n->token == F_LOR, DO_POP);
+ do_cond_jump(CAR(n), (INT32)tmp1, n->token == F_LOR, DO_POP);
DO_CODE_BLOCK(CDR(n));
- low_insert_label( DO_NOT_WARN((INT32)tmp1));
+ low_insert_label( (INT32)tmp1 );
return 0;
}else{
- do_cond_jump(CAR(n), DO_NOT_WARN((INT32)tmp1), n->token == F_LOR, 0);
+ do_cond_jump(CAR(n), (INT32)tmp1, n->token == F_LOR, 0);
code_expression(CDR(n), flags, n->token == F_LOR ? "||" : "&&");
- low_insert_label( DO_NOT_WARN((INT32)tmp1));
+ low_insert_label( (INT32)tmp1 );
return 1;
}
- case F_EQ:
- case F_NE:
- case F_ADD:
- case F_LT:
- case F_LE:
- case F_GT:
- case F_GE:
- case F_SUBTRACT:
- case F_MULTIPLY:
- case F_DIVIDE:
- case F_MOD:
- case F_LSH:
- case F_RSH:
- case F_XOR:
- case F_OR:
- case F_AND:
- case F_NOT:
- case F_COMPL:
- case F_NEGATE:
- Pike_fatal("Optimizer error.\n");
-
+
case F_RANGE:
tmp1=do_docode(CAR(n),DO_NOT_COPY_TOPLEVEL);
{
#ifdef PIKE_DEBUG
int num_args =
#endif
do_docode (CDR (n), DO_NOT_COPY);
emit_range (n DO_IF_DEBUG (COMMA num_args));
- return DO_NOT_WARN((INT32)tmp1);
+ return (INT32)tmp1;
}
/* The special bound type nodes are simply ignored when the
* arglist to the range operator is coded. emit_range looks at
* them later on instead. */
case F_RANGE_FROM_BEG:
case F_RANGE_FROM_END:
return do_docode (CAR (n), flags);
case F_RANGE_OPEN:
return 0;
pike.git/src/docode.c:1620:
if(CDR(n))
{
do_jump_when_zero(CAR(n),current_label->break_label);
tmp2=ins_label(-1);
DO_CODE_BLOCK(CADR(n));
ins_label(current_label->continue_label);
DO_CODE_BLOCK(CDDR(n));
}else{
tmp2=ins_label(-1);
}
- do_jump_when_non_zero(CAR(n), DO_NOT_WARN((INT32)tmp2));
+ do_jump_when_non_zero(CAR(n), (INT32)tmp2);
ins_label(current_label->break_label);
current_switch.jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL;
BLOCK_END;
return 0;
}
case ' ':
ret = do_docode(CAR(n),0);
pike.git/src/docode.c:1674:
PUSH_CLEANUP_FRAME(do_pop, 5);
PUSH_STATEMENT_LABEL;
current_switch.jumptable=0;
current_label->break_label=alloc_label();
current_label->continue_label=alloc_label();
/* Doubt it's necessary to use a label separate from
* current_label->break_label, but I'm playing safe. /mast */
tmp3 = alloc_label();
- do_jump(F_FOREACH_START, DO_NOT_WARN((INT32) tmp3));
+ do_jump(F_FOREACH_START, (INT32) tmp3);
tmp1=ins_label(-1);
DO_CODE_BLOCK(CDR(n));
ins_label(current_label->continue_label);
- do_jump(F_FOREACH_LOOP, DO_NOT_WARN((INT32)tmp1));
+ do_jump(F_FOREACH_LOOP, (INT32)tmp1);
ins_label(current_label->break_label);
- low_insert_label( DO_NOT_WARN((INT32)tmp3));
+ low_insert_label( (INT32)tmp3 );
current_switch.jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL;
POP_AND_DO_CLEANUP;
BLOCK_END;
return 0;
}
BLOCK_BEGIN;
pike.git/src/docode.c:1704:
node *range = CAR(arr);
node *low = CADR(range);
node *high = CDDR(range);
if(high->token == F_RANGE_OPEN &&
low->token == F_RANGE_FROM_BEG &&
match_types (low->type, int_type_string))
{
/* Optimize foreach(x[start..],y). */
do_docode (CAR(range), DO_NOT_COPY_TOPLEVEL);
do_docode (CDR(arr), DO_NOT_COPY|DO_LVALUE);
+ if ((low->token == F_CONSTANT) && (TYPEOF(low->u.sval) == PIKE_T_INT)) {
+ if (low->u.sval.u.integer < 0) {
+ emit0(F_CONST0);
+ goto foreach_arg_pushed;
+ }
do_docode (CAR(low), DO_NOT_COPY);
goto foreach_arg_pushed;
}
-
+ do_docode (CAR(low), DO_NOT_COPY);
+ tmp1 = alloc_label();
+ emit0(F_DUP);
+ emit0(F_CONST0);
+ do_jump(F_BRANCH_WHEN_GE, tmp1);
+ /* The value is negative. replace it with zero. */
+ emit0(F_POP_VALUE);
+ emit0(F_CONST0);
+ low_insert_label((INT32)tmp1);
+ goto foreach_arg_pushed;
}
-
+ }
do_docode(arr,DO_NOT_COPY);
emit0(F_CONST0);
current_stack_depth++;
foreach_arg_pushed:
PUSH_CLEANUP_FRAME(do_pop, 4);
PUSH_STATEMENT_LABEL;
current_switch.jumptable=0;
current_label->break_label=alloc_label();
current_label->continue_label=alloc_label();
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));
+ low_insert_label( (INT32)tmp3 );
+ do_jump(n->token, (INT32)tmp1);
ins_label(current_label->break_label);
current_switch.jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL;
POP_AND_DO_CLEANUP;
BLOCK_END;
return 0;
}
case F_INC_NEQ_LOOP:
pike.git/src/docode.c:1754:
PUSH_STATEMENT_LABEL;
current_switch.jumptable=0;
current_label->break_label=alloc_label();
current_label->continue_label=alloc_label();
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));
+ low_insert_label( (INT32)tmp3 );
+ do_jump(n->token, (INT32)tmp1);
ins_label(current_label->break_label);
current_switch.jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL;
POP_AND_DO_CLEANUP;
BLOCK_END;
return 0;
}
case F_LOOP:
pike.git/src/docode.c:1795:
BLOCK_BEGIN;
PUSH_STATEMENT_LABEL;
current_switch.jumptable=0;
current_label->break_label=alloc_label();
current_label->continue_label=alloc_label();
tmp2=ins_label(-1);
DO_CODE_BLOCK(CAR(n));
ins_label(current_label->continue_label);
- do_jump_when_non_zero(CDR(n), DO_NOT_WARN((INT32)tmp2));
+ do_jump_when_non_zero(CDR(n), (INT32)tmp2);
ins_label(current_label->break_label);
current_switch.jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL;
BLOCK_END;
return 0;
}
case F_POP_VALUE:
{
pike.git/src/docode.c:1824:
case T_VOID:
DO_CODE_BLOCK(CAR(n));
return 0;
case T_INT:
/* FIXME: Integer range? */
tmp1 = do_docode(CAR(n), 0);
if(!tmp1)
emit0(F_CONST0);
else {
if(tmp1>1)
- do_pop(DO_NOT_WARN((INT32)(tmp1-1)));
+ do_pop((INT32)(tmp1-1));
emit0(F_CAST_TO_INT);
}
return 1;
case T_STRING:
/* FIXME: String width? */
tmp1 = do_docode(CAR(n), 0);
if(!tmp1)
emit0(F_CONST0);
else if(tmp1>1)
- do_pop(DO_NOT_WARN((INT32)(tmp1-1)));
+ do_pop((INT32)(tmp1-1));
emit0(F_CAST_TO_STRING);
return 1;
default:
if (compile_type_to_runtime_type(n->type) == PIKE_T_MIXED) {
tmp1 = do_docode(CAR(n), 0);
if(!tmp1)
emit0(F_CONST0);
else if(tmp1>1)
- do_pop(DO_NOT_WARN((INT32)(tmp1-1)));
+ do_pop((INT32)(tmp1-1));
return 1;
}
}
{
struct svalue sv;
SET_SVAL(sv, T_TYPE, 0, type, n->type);
tmp1 = store_constant(&sv, 0, n->name);
- emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CONSTANT, (INT32)tmp1);
}
tmp1=do_docode(CAR(n),0);
if(!tmp1) { emit0(F_CONST0); tmp1=1; }
- if(tmp1>1) do_pop(DO_NOT_WARN((INT32)(tmp1-1)));
+ if(tmp1>1) do_pop((INT32)(tmp1-1));
emit0(F_CAST);
return 1;
case F_SOFT_CAST:
if (runtime_options & RUNTIME_CHECK_TYPES) {
{
struct svalue sv;
SET_SVAL(sv, T_TYPE, 0, type, n->type);
tmp1 = store_constant(&sv, 0, n->name);
- emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CONSTANT, (INT32)tmp1);
}
tmp1 = do_docode(CAR(n), 0);
if (!tmp1) { emit0(F_CONST0); tmp1 = 1; }
- if (tmp1 > 1) do_pop(DO_NOT_WARN((INT32)(tmp1 - 1)));
+ if (tmp1 > 1) do_pop((INT32)(tmp1 - 1));
emit0(F_SOFT_CAST);
return 1;
}
tmp1 = do_docode(CAR(n), flags);
- if (tmp1 > 1) do_pop(DO_NOT_WARN((INT32)(tmp1 - 1)));
+ if (tmp1 > 1) do_pop((INT32)(tmp1 - 1));
return !!tmp1;
case F_APPLY:
if(CAR(n)->token == F_CONSTANT)
{
-
+ int args = count_args(CDR(n));
if(TYPEOF(CAR(n)->u.sval) == T_FUNCTION)
{
if(SUBTYPEOF(CAR(n)->u.sval) == FUNCTION_BUILTIN) /* driver fun? */
{
if(!CAR(n)->u.sval.u.efun->docode ||
!CAR(n)->u.sval.u.efun->docode(n))
{
- if(count_args(CDR(n))==1)
+ if(args==1)
{
do_docode(CDR(n),0);
tmp1=store_constant(& CAR(n)->u.sval,
!(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
CAR(n)->name);
- emit1(F_CALL_BUILTIN1, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CALL_BUILTIN1, (INT32)tmp1);
+ #ifdef USE_APPLY_N
+ }else if(args>0){
+ do_docode(CDR(n),0);
+ tmp1=store_constant(& CAR(n)->u.sval,
+ !(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
+ CAR(n)->name);
+ emit2(F_CALL_BUILTIN_N, (INT32)tmp1, args);
+ #endif
}else{
emit0(F_MARK);
PUSH_CLEANUP_FRAME(do_pop_mark, 0);
do_docode(CDR(n),0);
tmp1=store_constant(& CAR(n)->u.sval,
!(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
CAR(n)->name);
- emit1(F_CALL_BUILTIN, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CALL_BUILTIN, (INT32)tmp1);
POP_AND_DONT_CLEANUP;
}
}
if(n->type == void_type_string)
return 0;
-
+
return 1;
}else{
if(CAR(n)->u.sval.u.object == Pike_compiler->fake_object)
return do_lfun_call(SUBTYPEOF(CAR(n)->u.sval), CDR(n));
}
}
-
+ #ifdef USE_APPLY_N
+ if( args <= 1 )
+ #endif
+ {
emit0(F_MARK);
PUSH_CLEANUP_FRAME(do_pop_mark, 0);
do_docode(CDR(n),0);
tmp1=store_constant(& CAR(n)->u.sval,
!(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
CAR(n)->name);
- emit1(F_APPLY, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_APPLY, (INT32)tmp1);
POP_AND_DONT_CLEANUP;
-
- return 1;
+
}
- else if(CAR(n)->token == F_IDENTIFIER)
+ #ifdef USE_APPLY_N
+ else
{
- return do_lfun_call(CAR(n)->u.id.number, CDR(n));
+ do_docode(CDR(n),0);
+ tmp1=store_constant(& CAR(n)->u.sval,
+ !(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
+ CAR(n)->name);
+ emit2(F_APPLY_N, (INT32)tmp1, args);
}
-
+ #endif
+ return 1;
+ }
else if(CAR(n)->token == F_EXTERNAL &&
CAR(n)->u.integer.a == Pike_compiler->new_program->id &&
CAR(n)->u.integer.b != IDREF_MAGIC_THIS)
{
return do_lfun_call(CAR(n)->u.integer.b, CDR(n));
}
else if(CAR(n)->token == F_GET_SET &&
CAR(n)->u.integer.a == Pike_compiler->new_program->id &&
CAR(n)->u.integer.b != IDREF_MAGIC_THIS)
{
pike.git/src/docode.c:1979:
yyerror("No call_function efun.");
}else{
if(TYPEOF(foo->u.sval) == T_FUNCTION &&
SUBTYPEOF(foo->u.sval) == FUNCTION_BUILTIN &&
foo->u.sval.u.efun->function == f_call_function)
{
emit0(F_CALL_FUNCTION);
}else{
/* We might want to put "predef::"+foo->name here /Hubbe */
tmp1=store_constant(& foo->u.sval, 1, foo->name);
- emit1(F_APPLY, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_APPLY, (INT32)tmp1);
}
}
free_node(foo);
POP_AND_DONT_CLEANUP;
return 1;
}
case F_ARG_LIST:
case F_COMMA_EXPR:
case ':':
pike.git/src/docode.c:2035:
/* Retrace */
/* Note: n->parent is always a visited CAR node on the
* way to the root.
*/
n = n->parent;
} while (n);
/* Restore root->parent. */
root->parent = parent;
}
- return DO_NOT_WARN((INT32)tmp1);
+ return (INT32)tmp1;
/* Switch:
* So far all switches are implemented with a binsearch lookup.
* It stores the case values in the programs area for constants.
* It also has a jump-table in the program itself, for every index in
* the array of cases, there is 2 indexes in the jumptable, and one extra.
* The first entry in the jumptable is used if you call switch with
* a value that is ranked lower than all the indexes in the array of
* cases. (Ranked by the binsearch that is) The second is used if it
pike.git/src/docode.c:2082:
tmp1=emit1(F_SWITCH,0);
current_stack_depth--;
emit1(F_ALIGN,sizeof(INT32));
current_switch.values_on_stack=0;
current_switch.index=2;
current_switch.less_label=-1;
current_switch.greater_label=-1;
current_switch.default_label=-1;
- current_switch.jumptable=(INT32 *)xalloc(sizeof(INT32)*(cases*2+2));
- jumptable=(INT32 *)xalloc(sizeof(INT32)*(cases*2+2));
+ current_switch.jumptable=xalloc(sizeof(INT32)*(cases*2+2));
+ jumptable=xalloc(sizeof(INT32)*(cases*2+2));
for(e=1; e<cases*2+2; e++)
{
- jumptable[e] = DO_NOT_WARN((INT32)emit1(F_POINTER, 0));
+ jumptable[e] = (INT32)emit1(F_POINTER, 0);
current_switch.jumptable[e]=-1;
}
emit0(F_NOTREACHED);
DO_CODE_BLOCK(CDR(n));
#ifdef PIKE_DEBUG
if(Pike_sp-save_sp != cases)
Pike_fatal("Count cases is wrong!\n");
#endif
pike.git/src/docode.c:2135:
yyerror("Case inside range.");
e++;
}
}
}
}
order_array(Pike_sp[-1].u.array,order);
reorder((void *)(current_switch.jumptable+2),cases,sizeof(INT32)*2,order);
- free((char *)order);
+ free(order);
current_switch.jumptable[1] = current_switch.less_label;
current_switch.jumptable[current_switch.index - 1] = current_switch.greater_label;
if(current_switch.default_label < 0)
current_switch.default_label = ins_label(-1);
for(e=1;e<cases*2+2;e++)
if(current_switch.jumptable[e]==-1)
current_switch.jumptable[e]=current_switch.default_label;
for(e=1; e<cases*2+2; e++)
update_arg(jumptable[e], current_switch.jumptable[e]);
- update_arg(DO_NOT_WARN((INT32)tmp1),
- store_constant(Pike_sp-1,1,0));
+ update_arg((INT32)tmp1, store_constant(Pike_sp-1,1,0));
pop_stack();
- free((char *)jumptable);
- free((char *)current_switch.jumptable);
+ free(jumptable);
+ free(current_switch.jumptable);
current_switch = prev_switch;
low_insert_label( current_label->break_label);
POP_STATEMENT_LABEL;
BLOCK_END;
#ifdef PIKE_DEBUG
if(Pike_interpreter.recoveries && Pike_sp-Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer)
Pike_fatal("Stack error after F_SWITCH (underflow)\n");
pike.git/src/docode.c:2187:
INT32 label = ins_label(-1);
int i;
for (i = 0; i < 2; i++) {
node *case_val = i == 0 ? CAR(n) : CDR(n);
if (case_val) {
if(!is_const(case_val))
yyerror("Case label isn't constant.");
- if (case_val->type && !TEST_COMPAT(0,6)) {
+ if (case_val->type) {
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 (c->lex.pragmas & ID_STRICT_TYPES) {
yytype_error("Type mismatch in case.",
current_switch.type, case_val->type, YYTE_IS_WARNING);
}
}
}
pike.git/src/docode.c:2261:
case F_BREAK:
case F_CONTINUE: {
struct statement_label *label, *p;
if (CAR(n)) {
struct pike_string *name = CAR(n)->u.sval.u.string;
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)
+ if (lbl_name->str == name) {
+ lbl_name->used = 1;
goto label_found_1;
-
+ }
my_yyerror("No surrounding statement labeled %S.", name);
return 0;
label_found_1:
if (n->token == F_CONTINUE && label->continue_label < 0) {
- my_yyerror("Cannot continue the non-loop statement on line %d.",
- lbl_name->line_number);
+ my_yyerror("Cannot continue the non-loop statement on line %ld.",
+ (long)lbl_name->line_number);
return 0;
}
}
else {
if (n->token == F_BREAK) {
for (label = current_label; label; label = label->prev)
if (label->break_label >= 0 && !label->emit_break_label)
goto label_found_2;
yyerror("Break outside loop or switch.");
pike.git/src/docode.c:2320:
}
case F_NORMAL_STMT_LABEL:
case F_CUSTOM_STMT_LABEL: {
struct statement_label *label;
struct statement_label_name name;
BLOCK_BEGIN;
PUSH_STATEMENT_LABEL;
name.str = CAR(n)->u.sval.u.string;
name.line_number = n->line_number;
+ name.used = 0;
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 = c->lex.current_line;
+ INT_TYPE 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);
c->lex.current_line = save_line;
goto label_check_done;
}
}
label_check_done:
name.next = current_label->name;
pike.git/src/docode.c:2350:
/* The statement we precede has custom label handling; leave
* the statement_label "open" so the statement will use it
* 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);
+ if (!name.used) {
+ low_yyreport(REPORT_WARNING, n->current_file, n->line_number,
+ parser_system_string, 0,
+ "Label %S not used.", name.str);
+ }
POP_STATEMENT_LABEL;
BLOCK_END;
return 0;
}
case F_RETURN: {
struct statement_label *p;
int in_catch = 0;
do_docode(CAR(n),0);
pike.git/src/docode.c:2391:
}
#endif
}
}
emit0(in_catch ? F_VOLATILE_RETURN : F_RETURN);
return 0;
}
case F_SSCANF:
- tmp1=do_docode(CDAR(n),DO_NOT_COPY);
+ tmp1=do_docode(CAR(n),DO_NOT_COPY);
tmp2=do_docode(CDR(n),DO_NOT_COPY | DO_LVALUE);
- emit2(F_SSCANF, DO_NOT_WARN((INT32)(tmp1+tmp2)), CAAR(n)->u.sval.u.integer);
+ emit1(F_SSCANF, (INT32)(tmp1+tmp2));
return 1;
case F_CATCH: {
INT32 *prev_switch_jumptable = current_switch.jumptable;
tmp1=do_jump(F_CATCH,-1);
PUSH_CLEANUP_FRAME(do_escape_catch, 0);
/* Entry point called via catching_eval_instruction(). */
emit0(F_ENTRY);
PUSH_STATEMENT_LABEL;
current_switch.jumptable=0;
current_label->break_label=alloc_label();
- if (TEST_COMPAT(7,0))
- current_label->continue_label = current_label->break_label;
+
DO_CODE_BLOCK(CAR(n));
ins_label(current_label->break_label);
emit0(F_EXIT_CATCH);
POP_STATEMENT_LABEL;
current_switch.jumptable = prev_switch_jumptable;
do_branch (tmp1);
current_stack_depth++;
/* Entry point called via catching_eval_instruction() after
* catching an error.
*
* NB: This is reached by subtracting ENTRY_PROLOGUE_SIZE
* from the label below.
* NB: The label must be after the entry, since it may expand to code
* that requires the entry code to have run.
*/
emit0(F_ENTRY);
- ins_label(DO_NOT_WARN((INT32)tmp1));
+ ins_label((INT32)tmp1);
POP_AND_DONT_CLEANUP;
return 1;
}
case F_LVALUE_LIST:
ret = do_docode(CAR(n),DO_LVALUE);
return ret + do_docode(CDR(n),DO_LVALUE);
case F_ARRAY_LVALUE:
tmp1=do_docode(CAR(n),DO_LVALUE);
#ifdef PIKE_DEBUG
if(tmp1 & 1)
Pike_fatal("Very internal compiler error.\n");
#endif
- emit1(F_ARRAY_LVALUE, DO_NOT_WARN((INT32)(tmp1>>1)));
+ emit1(F_ARRAY_LVALUE, (INT32)(tmp1>>1));
return 2;
case F_ARROW:
if(CDR(n)->token != F_CONSTANT || TYPEOF(CDR(n)->u.sval) != T_STRING)
Pike_fatal("Bugg in F_ARROW, index not string.\n");
if(flags & WANT_LVALUE)
{
/* FIXME!!!! ??? I wonder what needs fixing... /Hubbe */
tmp1=do_docode(CAR(n), 0);
emit1(F_ARROW_STRING, store_prog_string(CDR(n)->u.sval.u.string));
return 2;
}else{
tmp1 = do_docode(CAR(n), DO_NOT_COPY);
- if ((tmp2 = lfun_lookup_id(CDR(n)->u.sval.u.string)) != -1) {
+ if ((tmp2 = lfun_lookup_id(CDR(n)->u.sval.u.string)) != -1 ) {
emit1(F_LOOKUP_LFUN, tmp2);
} else {
emit1(F_ARROW, store_prog_string(CDR(n)->u.sval.u.string));
}
if(!(flags & DO_NOT_COPY))
{
while(n && (n->token==F_INDEX || n->token==F_ARROW)) n=CAR(n);
- if(n->token==F_CONSTANT && !(n->node_info & OPT_EXTERNAL_DEPEND))
+ if(n && n->token==F_CONSTANT && !(n->node_info & OPT_EXTERNAL_DEPEND))
emit0(F_COPY_VALUE);
}
}
- return DO_NOT_WARN((INT32)tmp1);
+ return (INT32)tmp1;
case F_INDEX:
if(flags & WANT_LVALUE)
{
int mklval=CAR(n) && match_types(CAR(n)->type, string_type_string);
tmp1 = do_docode(CAR(n),
mklval ? DO_LVALUE_IF_POSSIBLE : 0);
if(tmp1==2)
{
#ifdef PIKE_DEBUG
pike.git/src/docode.c:2507:
code_expression(CDR(n), DO_NOT_COPY, "index");
if(CDR(n)->token != F_CONSTANT &&
match_types(CDR(n)->type, string_type_string))
emit0(F_CLEAR_STRING_SUBTYPE);
emit0(F_INDEX);
if(!(flags & DO_NOT_COPY))
{
while(n && (n->token==F_INDEX || n->token==F_ARROW)) n=CAR(n);
- if(n->token==F_CONSTANT && !(n->node_info & OPT_EXTERNAL_DEPEND))
+ if(n && (n->token==F_CONSTANT) && !(n->node_info & OPT_EXTERNAL_DEPEND))
emit0(F_COPY_VALUE);
}
}
- return DO_NOT_WARN((INT32)tmp1);
+ return (INT32)tmp1;
case F_CONSTANT:
switch(TYPEOF(n->u.sval))
{
case T_INT:
if(!n->u.sval.u.integer && SUBTYPEOF(n->u.sval) == NUMBER_UNDEFINED)
{
emit0(F_UNDEFINED);
}else{
#if SIZEOF_INT_TYPE > 4
pike.git/src/docode.c:2541: Inside #if SIZEOF_INT_TYPE > 4
else
emit1(F_NUMBER,i);
#else
emit1(F_NUMBER,n->u.sval.u.integer);
#endif
}
return 1;
case T_STRING:
tmp1=store_prog_string(n->u.sval.u.string);
- emit1(F_STRING, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_STRING, (INT32)tmp1);
return 1;
case T_FUNCTION:
if(SUBTYPEOF(n->u.sval) != FUNCTION_BUILTIN)
{
if(n->u.sval.u.object == Pike_compiler->fake_object)
{
/* When does this occur? /mast */
emit1(F_GLOBAL, SUBTYPEOF(n->u.sval));
return 1;
pike.git/src/docode.c:2589:
/* FALL_THROUGH */
default:
#ifdef PIKE_DEBUG
if((TYPEOF(n->u.sval) == T_OBJECT) &&
(n->u.sval.u.object->next == n->u.sval.u.object))
Pike_fatal("Internal error: Pointer to parent cannot be a compile time constant!\n");
#endif
tmp1=store_constant(&(n->u.sval),
!(n->tree_info & OPT_EXTERNAL_DEPEND),
n->name);
- emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CONSTANT, (INT32)tmp1);
return 1;
case T_TYPE:
tmp1 = store_constant(&(n->u.sval), 0, n->name);
- emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CONSTANT, (INT32)tmp1);
return 1;
case T_ARRAY:
case T_MAPPING:
case T_MULTISET:
tmp1=store_constant(&(n->u.sval),
!(n->tree_info & OPT_EXTERNAL_DEPEND),
n->name);
- emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+ emit1(F_CONSTANT, (INT32)tmp1);
/* copy now or later ? */
if(!(flags & DO_NOT_COPY) && !(n->tree_info & OPT_EXTERNAL_DEPEND))
{
if(flags & DO_NOT_COPY_TOPLEVEL)
{
switch(TYPEOF(n->u.sval))
{
case T_ARRAY:
if(array_fix_type_field(n->u.sval.u.array) & BIT_COMPLEX)
pike.git/src/docode.c:2687:
struct compiler_frame *f;
int depth=0;
for(f=Pike_compiler->compiler_frame;
f!=n->u.trampoline.frame;f=f->previous)
depth++;
emit2(F_TRAMPOLINE,n->u.trampoline.ident,depth);
return 1;
}
- case F_IDENTIFIER: {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, n->u.id.number);
- if(IDENTIFIER_IS_FUNCTION(id->identifier_flags))
- {
- if(flags & WANT_LVALUE)
- {
- yyerror("Cannot assign functions.\n");
- }else{
- if (id->identifier_flags & IDENTIFIER_HAS_BODY)
- /* Only use this opcode when it's certain that the result
- * can't zero, i.e. when we know the function isn't just a
- * prototype. */
- emit1(F_LFUN,n->u.id.number);
- else
- emit1(F_GLOBAL,n->u.id.number);
- }
- }else{
- if(flags & WANT_LVALUE)
- {
- emit1(F_GLOBAL_LVALUE,n->u.id.number);
- return 2;
- }else{
- emit1(F_GLOBAL,n->u.id.number);
- }
- }
- return 1;
- }
-
+
case F_VAL_LVAL:
ret = do_docode(CAR(n),flags);
return ret + do_docode(CDR(n), flags | DO_LVALUE);
case F_AUTO_MAP:
emit0(F_MARK);
code_expression(CAR(n), 0, "automap function");
do_encode_automap_arg_list(CDR(n),0);
emit_apply_builtin("__automap__");
return 1;
case F_AUTO_MAP_MARKER:
-
+ if( flags & DO_LVALUE )
+ {
+ do_docode(CAR(n),DO_LVALUE);
+ }
+ else
+ {
yyerror("[*] not supported here.\n");
emit0(F_CONST0);
-
+ }
return 1;
default:
Pike_fatal("Infernal compiler error (unknown parse-tree-token %d).\n", n->token);
- return 0; /* make gcc happy */
+ UNREACHABLE(return 0);
}
}
/* Used to generate code for functions. */
INT32 do_code_block(node *n)
{
struct compilation *c = THIS_COMPILATION;
-
+ struct reference *id = NULL;
+ struct identifier *i = NULL;
INT32 entry_point;
-
+ int aggregate_cnum = -1;
#ifdef PIKE_DEBUG
if (current_stack_depth != -4711) Pike_fatal("Reentrance in do_code_block().\n");
current_stack_depth = 0;
#endif
-
+ if (Pike_compiler->compiler_frame->current_function_number >= 0) {
+ id = Pike_compiler->new_program->identifier_references +
+ Pike_compiler->compiler_frame->current_function_number;
+ i = ID_FROM_PTR(Pike_compiler->new_program, id);
+ }
+
init_bytecode();
label_no=1;
/* NOTE: This is no ordinary label... */
low_insert_label(0);
- emit1(F_BYTE,Pike_compiler->compiler_frame->max_number_of_locals);
- emit1(F_BYTE,Pike_compiler->compiler_frame->num_args);
+
emit0(F_ENTRY);
emit0(F_START_FUNCTION);
- if(Pike_compiler->compiler_frame->current_function_number >= 0 &&
- (Pike_compiler->new_program->identifier_references[
- Pike_compiler->compiler_frame->current_function_number].id_flags &
- ID_INLINE))
+ if (Pike_compiler->compiler_frame->num_args) {
+ emit2(F_FILL_STACK, Pike_compiler->compiler_frame->num_args, 1);
+ }
+ emit1(F_MARK_AT, Pike_compiler->compiler_frame->num_args);
+ if (i && i->identifier_flags & IDENTIFIER_VARARGS) {
+ struct svalue *sval =
+ simple_mapping_string_lookup(get_builtin_constants(), "aggregate");
+ if (!sval) {
+ yyerror("predef::aggregate() is missing.\n");
+ Pike_fatal("No aggregate!\n");
+ UNREACHABLE(return 0);
+ }
+ aggregate_cnum = store_constant(sval, 0, NULL);
+ emit1(F_CALL_BUILTIN, aggregate_cnum);
+ if (Pike_compiler->compiler_frame->max_number_of_locals !=
+ Pike_compiler->compiler_frame->num_args+1) {
+ emit2(F_FILL_STACK,
+ Pike_compiler->compiler_frame->max_number_of_locals, 0);
+ }
+ } else {
+ emit0(F_POP_TO_MARK);
+ if (Pike_compiler->compiler_frame->max_number_of_locals !=
+ Pike_compiler->compiler_frame->num_args) {
+ emit2(F_FILL_STACK,
+ Pike_compiler->compiler_frame->max_number_of_locals, 0);
+ }
+ }
+ emit2(F_INIT_FRAME, Pike_compiler->compiler_frame->num_args,
+ Pike_compiler->compiler_frame->max_number_of_locals);
+ if (Pike_compiler->compiler_frame->lexical_scope & SCOPE_SCOPE_USED) {
+ emit1(F_PROTECT_STACK, Pike_compiler->compiler_frame->max_number_of_locals);
+ }
+
+ if(id && (id->id_flags & ID_INLINE))
{
Pike_compiler->compiler_frame->recur_label=0;
Pike_compiler->compiler_frame->is_inline=1;
}
DO_CODE_BLOCK(n);
if(Pike_compiler->compiler_frame->recur_label > 0)
{
#ifdef PIKE_DEBUG
if(l_flag)
{
fprintf(stderr,"Generating inline recursive function.\n");
}
#endif
/* generate code again, but this time it is inline */
Pike_compiler->compiler_frame->is_inline=1;
/* NOTE: This is no ordinary label... */
low_insert_label(Pike_compiler->compiler_frame->recur_label);
- emit1(F_BYTE,Pike_compiler->compiler_frame->max_number_of_locals);
- emit1(F_BYTE,Pike_compiler->compiler_frame->num_args);
+
emit0(F_ENTRY);
emit0(F_START_FUNCTION);
-
+
+ if (Pike_compiler->compiler_frame->num_args) {
+ emit2(F_FILL_STACK, Pike_compiler->compiler_frame->num_args, 1);
+ }
+ emit1(F_MARK_AT, Pike_compiler->compiler_frame->num_args);
+ if (i && i->identifier_flags & IDENTIFIER_VARARGS) {
+ emit1(F_CALL_BUILTIN, aggregate_cnum);
+ if (Pike_compiler->compiler_frame->max_number_of_locals !=
+ Pike_compiler->compiler_frame->num_args+1) {
+ emit2(F_FILL_STACK,
+ Pike_compiler->compiler_frame->max_number_of_locals, 0);
+ }
+ emit2(F_INIT_FRAME, Pike_compiler->compiler_frame->num_args+1,
+ Pike_compiler->compiler_frame->max_number_of_locals);
+ } else {
+ emit0(F_POP_TO_MARK);
+ if (Pike_compiler->compiler_frame->max_number_of_locals !=
+ Pike_compiler->compiler_frame->num_args) {
+ emit2(F_FILL_STACK,
+ Pike_compiler->compiler_frame->max_number_of_locals, 0);
+ }
+ emit2(F_INIT_FRAME, Pike_compiler->compiler_frame->num_args,
+ Pike_compiler->compiler_frame->max_number_of_locals);
+ }
+ if (Pike_compiler->compiler_frame->lexical_scope & SCOPE_SCOPE_USED) {
+ emit1(F_PROTECT_STACK,
+ Pike_compiler->compiler_frame->max_number_of_locals);
+ }
+
DO_CODE_BLOCK(n);
}
entry_point = assemble(1);
#ifdef PIKE_DEBUG
current_stack_depth = -4711;
#endif
return entry_point;
}