|
|
|
|
|
|
|
#include "global.h" |
#include "program.h" |
#include "object.h" |
#include "dynamic_buffer.h" |
#include "pike_types.h" |
#include "stralloc.h" |
#include "las.h" |
#include "lex.h" |
#include "pike_macros.h" |
#include "fsort.h" |
#include "pike_error.h" |
#include "docode.h" |
#include "interpret.h" |
#include "hashtable.h" |
#include "main.h" |
#include "pike_memory.h" |
#include "gc.h" |
#include "threads.h" |
#include "constants.h" |
#include "operators.h" |
#include "builtin_functions.h" |
#include "stuff.h" |
#include "mapping.h" |
#include "cyclic.h" |
#include "pike_security.h" |
#include "pike_types.h" |
#include "opcodes.h" |
#include "version.h" |
#include "block_alloc.h" |
#include "pikecode.h" |
|
#include <errno.h> |
#include <fcntl.h> |
|
#define sp Pike_sp |
|
#undef ATTRIBUTE |
#define ATTRIBUTE(X) |
|
static void exit_program_struct(struct program *); |
static size_t add_xstorage(size_t size, |
size_t alignment, |
ptrdiff_t modulo_orig); |
|
#undef EXIT_BLOCK |
#define EXIT_BLOCK(P) exit_program_struct( (P) ) |
|
#undef COUNT_OTHER |
#define COUNT_OTHER() do{ \ |
struct program *p; \ |
for(p=first_program;p;p=p->next) \ |
{ \ |
size+=p->total_size; \ |
} \ |
}while(0) |
|
BLOCK_ALLOC_FILL_PAGES(program, 4) |
|
|
|
|
|
#ifdef COMPILER_DEBUG |
#define CDFPRINTF(X) fprintf X |
#else /* !COMPILER_DEBUG */ |
#define CDFPRINTF(X) |
#endif /* COMPILER_DEBUG */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define FIND_FUNCTION_HASHSIZE 15013 |
|
|
#define FIND_FUNCTION_HASH_TRESHOLD 9 |
|
|
#define DECLARE |
#include "compilation.h" |
|
struct pike_string *this_program_string, *this_string; |
static struct pike_string *UNDEFINED_string; |
|
const char *const lfun_names[] = { |
"__INIT", |
"create", |
"destroy", |
"`+", |
"`-", |
"`&", |
"`|", |
"`^", |
"`<<", |
"`>>", |
"`*", |
"`/", |
"`%", |
"`~", |
"`==", |
"`<", |
"`>", |
"__hash", |
"cast", |
"`!", |
"`[]", |
"`[]=", |
"`->", |
"`->=", |
"_sizeof", |
"_indices", |
"_values", |
"`()", |
"``+", |
"``-", |
"``&", |
"``|", |
"``^", |
"``<<", |
"``>>", |
"``*", |
"``/", |
"``%", |
"`+=", |
"_is_type", |
"_sprintf", |
"_equal", |
"_m_delete", |
"_get_iterator", |
|
"_search", |
}; |
|
struct pike_string *lfun_strings[NELEM(lfun_names)]; |
|
static struct mapping *lfun_ids; |
|
|
static struct mapping *lfun_types; |
|
static char *raw_lfun_types[] = { |
tFuncV(tNone,tVoid,tVoid), |
tFuncV(tNone,tZero,tVoid), |
tFuncV(tNone,tVoid,tVoid), |
tFuncV(tZero,tZero,tMix), |
tFunc(tOr(tVoid,tZero),tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tVoid,tMix), |
tFuncV(tMix,tVoid,tInt), |
tFuncV(tMix,tVoid,tInt), |
tFuncV(tMix,tVoid,tInt), |
tFuncV(tNone,tVoid,tInt), |
tFuncV(tString,tVoid,tMix), |
tFuncV(tNone,tVoid,tInt), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tZero tSetvar(0,tZero),tVoid,tVar(0)), |
tFuncV(tStr,tVoid,tMix), |
tFuncV(tStr tSetvar(0,tZero),tVoid,tVar(0)), |
tFuncV(tNone,tVoid,tInt), |
tFuncV(tNone,tVoid,tArray), |
tFuncV(tNone,tVoid,tArray), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tZero,tZero,tMix), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tNone,tZero,tMix), |
tFuncV(tZero,tZero,tMix), |
tFuncV(tStr,tVoid,tInt), |
tFuncV(tInt tOr(tMap(tStr,tInt),tVoid),tVoid,tStr), |
tFuncV(tMix,tVoid,tInt), |
tFuncV(tZero,tVoid,tMix), |
tFuncV(tNone,tVoid,tObj), |
|
tFuncV(tZero tOr(tZero, tVoid), tVoid, tMix), |
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct program *first_program = 0; |
static int current_program_id = PROG_DYNAMIC_ID_START; |
|
struct program *null_program=0; |
|
struct object *error_handler=0; |
struct object *compat_handler=0; |
|
struct program *gc_internal_program = 0; |
static struct program *gc_mark_program_pos = 0; |
|
int compilation_depth=-1; |
dynamic_buffer used_modules; |
static struct mapping *resolve_cache=0; |
|
#ifdef PIKE_DEBUG |
#define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) \ |
do { \ |
if (SHIFT < 0 || SHIFT > 2 || \ |
POS + (LEN << SHIFT) > PROG->linenumbers + PROG->num_linenumbers) \ |
Pike_fatal ("Invalid file entry in linenumber info.\n"); \ |
} while (0) |
#else |
#define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) do {} while (0) |
#endif |
|
int get_small_number(char **q); |
|
|
|
#ifdef PIKE_DEBUG |
#define CHECK_FOO(NUMTYPE,TYPE,NAME) \ |
if(Pike_compiler->malloc_size_program-> PIKE_CONCAT(num_,NAME) < \ |
Pike_compiler->new_program-> PIKE_CONCAT(num_,NAME)) \ |
Pike_fatal("Pike_compiler->new_program->num_" #NAME " is out of order\n");\ |
if(Pike_compiler->new_program->flags & PROGRAM_OPTIMIZED) \ |
Pike_fatal("Tried to reallocate fixed program.\n") |
|
#else |
#define CHECK_FOO(NUMTYPE,TYPE,NAME) |
#endif |
|
#ifndef RELOCATE_program |
#define RELOCATE_program(ORIG, NEW) |
#endif /* !RELOCATE_program */ |
#define RELOCATE_linenumbers(ORIG,NEW) |
#define RELOCATE_identifier_index(ORIG,NEW) |
#define RELOCATE_variable_index(ORIG,NEW) |
#define RELOCATE_identifier_references(ORIG,NEW) |
#define RELOCATE_strings(ORIG,NEW) |
#define RELOCATE_inherits(ORIG,NEW) |
#define RELOCATE_identifiers(ORIG,NEW) |
#define RELOCATE_constants(ORIG,NEW) |
#define RELOCATE_relocations(ORIG,NEW) |
|
#if SIZEOF_LONG_LONG == 8 |
|
#define MAXVARS(NUMTYPE) \ |
(NUMTYPE)(sizeof(NUMTYPE)==1?254: \ |
(sizeof(NUMTYPE)==2?65534: \ |
(sizeof(NUMTYPE)==4?4294967294U:18446744073709551614ULL))) |
#else |
#define MAXVARS(NUMTYPE) \ |
(NUMTYPE)(sizeof(NUMTYPE)==1?254: (sizeof(NUMTYPE)==2?65534:4294967294U)) |
#endif |
|
|
|
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
void PIKE_CONCAT(low_add_to_,NAME) (struct program_state *state, \ |
TYPE ARG) { \ |
NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ |
CHECK_FOO(NUMTYPE,TYPE,NAME); \ |
if(m == state->new_program->PIKE_CONCAT(num_,NAME)) { \ |
TYPE *tmp; \ |
if(m==MAXVARS(NUMTYPE)) { \ |
yyerror("Too many " #NAME "."); \ |
return; \ |
} \ |
m = MINIMUM(m*2+1,MAXVARS(NUMTYPE)); \ |
tmp = realloc((void *)state->new_program->NAME, \ |
sizeof(TYPE) * m); \ |
if(!tmp) Pike_fatal("Out of memory.\n"); \ |
PIKE_CONCAT(RELOCATE_,NAME)(state->new_program, tmp); \ |
state->malloc_size_program->PIKE_CONCAT(num_,NAME)=m; \ |
state->new_program->NAME=tmp; \ |
} \ |
state->new_program-> \ |
NAME[state->new_program->PIKE_CONCAT(num_,NAME)++]=(ARG); \ |
} \ |
void PIKE_CONCAT(add_to_,NAME) (ARGTYPE ARG) { \ |
PIKE_CONCAT(low_add_to_,NAME) ( Pike_compiler, ARG ); \ |
} |
|
|
#include "program_areas.h" |
|
|
#define add_to_program(ARG) do { \ |
debug_malloc_touch(Pike_compiler->new_program->program); \ |
add_to_program(ARG); \ |
} while(0) |
|
void ins_int(INT32 i, void (*func)(char tmp)) |
{ |
int e; |
unsigned char *p = (unsigned char *)&i; |
for(e=0;e<(long)sizeof(i);e++) { |
func(p[e]); |
} |
} |
|
void ins_short(int i, void (*func)(char tmp)) |
{ |
int e; |
unsigned char *p = (unsigned char *)&i; |
for(e=0;e<(long)sizeof(i);e++) { |
func(p[e]); |
} |
} |
|
#ifdef PIKE_DEBUG |
static void debug_add_to_identifiers (struct identifier id) |
{ |
if (d_flag) { |
int i; |
for (i = 0; i < Pike_compiler->new_program->num_identifiers; i++) |
if (Pike_compiler->new_program->identifiers[i].name == id.name) { |
dump_program_tables (Pike_compiler->new_program, 0); |
Pike_fatal ("Adding identifier twice, old at %d.\n", i); |
} |
} |
add_to_identifiers (id); |
} |
#else |
#define debug_add_to_identifiers(ARG) add_to_identifiers(ARG) |
#endif |
|
void add_relocated_int_to_program(INT32 i) |
{ |
add_to_relocations(Pike_compiler->new_program->num_program); |
ins_int(i, (void (*)(char))add_to_program); |
} |
|
void use_module(struct svalue *s) |
{ |
if( (1<<s->type) & (BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM)) |
{ |
Pike_compiler->num_used_modules++; |
assign_svalue_no_free((struct svalue *) |
low_make_buf_space(sizeof(struct svalue), |
&used_modules), s); |
if(Pike_compiler->module_index_cache) |
{ |
free_mapping(Pike_compiler->module_index_cache); |
Pike_compiler->module_index_cache=0; |
} |
}else{ |
yyerror("Module is neither mapping nor object"); |
} |
} |
|
void unuse_modules(INT32 howmany) |
{ |
if(!howmany) return; |
#ifdef PIKE_DEBUG |
if(howmany *sizeof(struct svalue) > used_modules.s.len) |
Pike_fatal("Unusing too many modules.\n"); |
#endif |
Pike_compiler->num_used_modules-=howmany; |
low_make_buf_space(-sizeof(struct svalue)*howmany, &used_modules); |
free_svalues((struct svalue *)low_make_buf_space(0, &used_modules), |
howmany, |
BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM); |
if(Pike_compiler->module_index_cache) |
{ |
free_mapping(Pike_compiler->module_index_cache); |
Pike_compiler->module_index_cache=0; |
} |
} |
|
int low_find_shared_string_identifier(struct pike_string *name, |
struct program *prog); |
|
|
|
static struct node_s *index_modules(struct pike_string *ident, |
struct mapping **module_index_cache, |
int num_used_modules, |
struct svalue *modules) |
{ |
if(*module_index_cache) |
{ |
struct svalue *tmp=low_mapping_string_lookup(*module_index_cache,ident); |
if(tmp) |
{ |
if(!(SAFE_IS_ZERO(tmp) && tmp->subtype==1)) |
return mksvaluenode(tmp); |
return 0; |
} |
} |
|
|
|
{ |
JMP_BUF tmp; |
|
if(SETJMP(tmp)) |
{ |
if (!ident->size_shift) { |
handle_compile_exception ("Couldn't index a module with '%s'.", ident->str); |
} else { |
handle_compile_exception ("Couldn't index a module."); |
} |
} else { |
int e = num_used_modules; |
struct svalue *m = modules - num_used_modules; |
|
while(--e>=0) |
{ |
push_svalue(m+e); |
ref_push_string(ident); |
f_index(2); |
|
if(!IS_UNDEFINED(Pike_sp-1)) |
{ |
struct node_s *ret; |
UNSETJMP(tmp); |
|
if (Pike_compiler->compiler_pass == 2 && |
((Pike_sp[-1].type == T_OBJECT && |
Pike_sp[-1].u.object == placeholder_object) || |
(Pike_sp[-1].type == T_PROGRAM && |
Pike_sp[-1].u.program == placeholder_program))) { |
my_yyerror("Got placeholder %s (resolver problem) " |
"when indexing a module with %S.", |
get_name_of_type (Pike_sp[-1].type), ident); |
ret = 0; |
} |
else { |
if(!*module_index_cache) |
*module_index_cache = allocate_mapping(10); |
mapping_string_insert(*module_index_cache, ident, Pike_sp-1); |
ret = mksvaluenode(Pike_sp-1); |
} |
pop_stack(); |
return ret; |
} |
pop_stack(); |
} |
} |
UNSETJMP(tmp); |
} |
|
|
|
return 0; |
} |
|
|
|
|
|
|
struct node_s *resolve_identifier(struct pike_string *ident); |
|
struct node_s *find_module_identifier(struct pike_string *ident, |
int see_inherit) |
{ |
struct node_s *ret; |
|
struct svalue *modules=(struct svalue *) |
(used_modules.s.str + used_modules.s.len); |
|
{ |
struct program_state *p=Pike_compiler; |
int n; |
for(n=0;n<=compilation_depth;n++,p=p->previous) |
{ |
int i; |
if(see_inherit) |
{ |
i=really_low_find_shared_string_identifier(ident, |
p->new_program, |
SEE_STATIC|SEE_PRIVATE); |
if(i!=-1) |
{ |
return p == Pike_compiler ? |
mkidentifiernode(i) : |
mkexternalnode(p->new_program, i); |
} |
} |
|
if((ret=index_modules(ident, |
&p->module_index_cache, |
p->num_used_modules, |
modules))) return ret; |
modules-=p->num_used_modules; |
#ifdef PIKE_DEBUG |
if( ((char *)modules ) < used_modules.s.str) |
Pike_fatal("Modules out of whack!\n"); |
#endif |
} |
} |
|
|
if (ident == UNDEFINED_string) { |
struct svalue s; |
s.type = T_INT; |
s.subtype = NUMBER_UNDEFINED; |
s.u.integer = 0; |
return mkconstantsvaluenode(&s); |
} |
|
return resolve_identifier(ident); |
} |
|
struct node_s *resolve_identifier(struct pike_string *ident) |
{ |
if(resolve_cache) |
{ |
struct svalue *tmp=low_mapping_string_lookup(resolve_cache,ident); |
if(tmp) |
{ |
if(!(SAFE_IS_ZERO(tmp) && tmp->subtype==1)) |
return mkconstantsvaluenode(tmp); |
|
return 0; |
} |
} |
|
if(get_master()) |
{ |
DECLARE_CYCLIC(); |
node *ret=0; |
if(BEGIN_CYCLIC(ident, lex.current_file)) |
{ |
my_yyerror("Recursive module dependency in %S.", ident); |
}else{ |
SET_CYCLIC_RET(1); |
|
ref_push_string(ident); |
ref_push_string(lex.current_file); |
if (error_handler) { |
ref_push_object(error_handler); |
} else { |
push_int(0); |
} |
|
if (safe_apply_handler("resolv", error_handler, compat_handler, 3, 0)) { |
if (Pike_compiler->compiler_pass == 2 && |
((Pike_sp[-1].type == T_OBJECT && |
Pike_sp[-1].u.object == placeholder_object) || |
(Pike_sp[-1].type == T_PROGRAM && |
Pike_sp[-1].u.program == placeholder_program))) { |
my_yyerror("Got placeholder %s (resolver problem) " |
"when resolving %S.", |
get_name_of_type (Pike_sp[-1].type), ident->str); |
} |
else { |
if(!resolve_cache) |
resolve_cache=dmalloc_touch(struct mapping *, allocate_mapping(10)); |
mapping_string_insert(resolve_cache,ident,Pike_sp-1); |
|
if(!(SAFE_IS_ZERO(Pike_sp-1) && Pike_sp[-1].subtype==1)) |
{ |
ret=mkconstantsvaluenode(Pike_sp-1); |
} |
} |
pop_stack(); |
} |
else |
if(Pike_compiler->compiler_pass==2) { |
if (throw_value.type == T_STRING) { |
my_yyerror("%O", throw_value); |
free_svalue(&throw_value); |
throw_value.type = T_INT; |
} |
else { |
handle_compile_exception ("Error resolving %S.", ident); |
} |
} |
} |
END_CYCLIC(); |
|
return ret; |
} |
|
return 0; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct node_s *program_magic_identifier (struct program_state *state, |
int state_depth, int inherit_num, |
struct pike_string *ident, |
int colon_colon_ref) |
{ |
#if 0 |
fprintf (stderr, "magic_identifier (state, %d, %d, %s, %d)\n", |
state_depth, inherit_num, ident->str, colon_colon_ref); |
#endif |
|
if (!inherit_num) { |
|
|
|
|
if (ident == this_string) { |
if (state_depth > 0) |
return mkexternalnode (state->new_program, IDREF_MAGIC_THIS); |
else |
return mkidentifiernode (IDREF_MAGIC_THIS); |
} |
|
|
if (ident == this_program_string) { |
node *n = mkefuncallnode ("object_program", |
state_depth > 0 ? |
mkexternalnode (state->new_program, IDREF_MAGIC_THIS) : |
mkidentifiernode (IDREF_MAGIC_THIS)); |
|
n->node_info &= ~OPT_NOT_CONST; |
n->tree_info &= ~OPT_NOT_CONST; |
return n; |
} |
} |
|
if (colon_colon_ref) { |
|
|
if (inherit_num < 0) inherit_num = 0; |
if(ident == lfun_strings[LFUN_ARROW] || |
ident == lfun_strings[LFUN_INDEX]) { |
return mknode(F_MAGIC_INDEX, mknewintnode(inherit_num), |
mknewintnode(state_depth)); |
} else if(ident == lfun_strings[LFUN_ASSIGN_ARROW] || |
ident == lfun_strings[LFUN_ASSIGN_INDEX]) { |
return mknode(F_MAGIC_SET_INDEX, mknewintnode(inherit_num), |
mknewintnode(state_depth)); |
} else if(ident == lfun_strings[LFUN__INDICES]) { |
return mknode(F_MAGIC_INDICES, mknewintnode(inherit_num), |
mknewintnode(state_depth)); |
} else if(ident == lfun_strings[LFUN__VALUES]) { |
return mknode(F_MAGIC_VALUES, mknewintnode(inherit_num), |
mknewintnode(state_depth)); |
} |
} |
|
return NULL; |
} |
|
|
struct program *parent_compilation(int level) |
{ |
int n; |
struct program_state *p=Pike_compiler->previous; |
for(n=0;n<level;n++) |
{ |
if(n>=compilation_depth) return 0; |
p=p->previous; |
if(!p) return 0; |
} |
return p->new_program; |
} |
|
#define ID_TO_PROGRAM_CACHE_SIZE 512 |
struct program *id_to_program_cache[ID_TO_PROGRAM_CACHE_SIZE]; |
|
struct program *id_to_program(INT32 id) |
{ |
struct program *p; |
INT32 h; |
if(!id) return 0; |
h=id & (ID_TO_PROGRAM_CACHE_SIZE-1); |
|
if((p=id_to_program_cache[h])) |
if(p->id==id) |
return p; |
|
for(p=first_program;p;p=p->next) |
{ |
if(id==p->id) |
{ |
id_to_program_cache[h]=p; |
return p; |
} |
} |
|
if ((id > 0) && (id < PROG_DYNAMIC_ID_START)) { |
|
|
|
char *module = NULL; |
|
switch(id) { |
case PROG_PARSER_HTML_ID: |
module = "Parser._parser"; |
break; |
case PROG_GMP_MPZ_ID: |
module = "Gmp"; |
break; |
case PROG_MODULE_MIME_ID: |
module = "___MIME"; |
break; |
default: |
if ((id >= 100) && (id <= 300)) { |
module = "Image"; |
} else if ((id >= 1000) && (id <= 2000)) { |
module = "___GTK"; |
} |
break; |
} |
if (module) { |
push_text(module); |
SAFE_APPLY_MASTER("resolv", 1); |
pop_stack(); |
|
|
for(p=first_program;p;p=p->next) |
{ |
if(id==p->id) |
{ |
id_to_program_cache[h]=p; |
return p; |
} |
} |
} |
} |
return 0; |
} |
|
|
|
|
|
|
|
|
void optimize_program(struct program *p) |
{ |
size_t size=0; |
char *data; |
|
|
if(p->flags & PROGRAM_OPTIMIZED) return; |
|
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
size=DO_ALIGN(size, ALIGNOF(TYPE)); \ |
size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]); |
#include "program_areas.h" |
|
data=malloc(size); |
if(!data) |
{ |
make_program_executable(p); |
return; |
} |
|
size=0; |
|
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
size=DO_ALIGN(size, ALIGNOF(TYPE)); \ |
if (p->PIKE_CONCAT (num_, NAME)) \ |
MEMCPY(data+size,p->NAME,p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); \ |
PIKE_CONCAT(RELOCATE_,NAME)(p, (TYPE *)(data+size)); \ |
dmfree(p->NAME); \ |
p->NAME=(TYPE *)(data+size); \ |
size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]); |
#include "program_areas.h" |
|
p->total_size=size + sizeof(struct program); |
|
p->flags |= PROGRAM_OPTIMIZED; |
make_program_executable(p); |
} |
|
|
static int program_identifier_index_compare(int a, int b, |
const struct program *p) |
{ |
size_t val_a = PTR_TO_INT (ID_FROM_INT(p, a)->name); |
size_t val_b = PTR_TO_INT (ID_FROM_INT(p, b)->name); |
return val_a < val_b ? -1 : (val_a == val_b ? 0 : 1); |
} |
|
#define CMP(X,Y) program_identifier_index_compare(*(X), *(Y), prog) |
#define EXTRA_ARGS , struct program *prog |
#define XARGS , prog |
#define ID fsort_program_identifier_index |
#define TYPE unsigned short |
#include "fsort_template.h" |
#undef TYPE |
#undef ID |
#undef XARGS |
#undef EXTRA_ARGS |
#undef CMP |
|
#ifdef PIKE_DEBUG |
struct pike_string *find_program_name(struct program *p, INT32 *line) |
{ |
INT32 l; |
if(!line) line=&l; |
|
#ifdef DEBUG_MALLOC |
{ |
char *tmp=dmalloc_find_name(p); |
if (tmp) { |
char *p = STRCHR (tmp, ':'); |
if (p) { |
char *pp; |
while ((pp = STRCHR (p + 1, ':'))) p = pp; |
*line = atoi (p + 1); |
return make_shared_binary_string (tmp, p - tmp); |
} |
else { |
*line=0; |
return make_shared_string(tmp); |
} |
} |
} |
#endif |
|
return get_program_line(p, line); |
} |
#endif |
|
int override_identifier (struct reference *ref, struct pike_string *name) |
{ |
int id = -1, cur_id = 0; |
|
int new_is_variable = |
IDENTIFIER_IS_VARIABLE(ID_FROM_PTR(Pike_compiler->new_program, |
ref)->identifier_flags); |
|
|
|
|
|
|
|
for(;cur_id<Pike_compiler->new_program->num_identifier_references;cur_id++) |
{ |
|
if(Pike_compiler->new_program->identifier_references[cur_id].id_flags & ID_HIDDEN) |
continue; |
|
|
if((Pike_compiler->new_program->identifier_references[cur_id].id_flags & |
(ID_INLINE|ID_INHERITED)) == (ID_INLINE|ID_INHERITED)) |
continue; |
|
|
if(ID_FROM_INT(Pike_compiler->new_program, cur_id)->name != name) |
continue; |
|
#ifdef PROGRAM_BUILD_DEBUG |
fprintf(stderr, "%.*soverloaded reference %d (id_flags:0x%04x)\n", |
compilation_depth, " ", cur_id, |
Pike_compiler->new_program->identifier_references[cur_id].id_flags); |
#endif |
|
if (!new_is_variable && |
IDENTIFIER_IS_VARIABLE(ID_FROM_INT(Pike_compiler->new_program, |
cur_id)->identifier_flags)) { |
|
|
|
Pike_compiler->new_program->identifier_references[cur_id].id_flags |= |
ID_INLINE|ID_HIDDEN; |
yywarning("Attempt to override a non local variable %S " |
"with a non variable.", name); |
continue; |
} |
|
Pike_compiler->new_program->identifier_references[cur_id]=*ref; |
id = cur_id; |
} |
|
return id; |
} |
|
void fixate_program(void) |
{ |
INT32 i,e,t; |
struct program *p=Pike_compiler->new_program; |
|
if(p->flags & PROGRAM_FIXED) return; |
#ifdef PIKE_DEBUG |
if(p->flags & PROGRAM_OPTIMIZED) |
Pike_fatal("Cannot fixate optimized program\n"); |
#endif |
|
|
for (i=0; i < p->num_identifiers; i++) { |
if (IDENTIFIER_IS_FUNCTION(p->identifiers[i].identifier_flags) == |
IDENTIFIER_FUNCTION) { |
|
p->identifiers[i].identifier_flags &= ~IDENTIFIER_C_FUNCTION; |
} |
} |
|
|
for (i = 0; i < p->num_identifier_references; i++) { |
struct reference *ref = p->identifier_references + i; |
if (ref->id_flags & ID_HIDDEN) continue; |
if (ref->inherit_offset != 0) continue; |
override_identifier (ref, ID_FROM_PTR (p, ref)->name); |
} |
|
|
for(e=i=0;i<(int)p->num_identifier_references;i++) |
{ |
struct reference *funp; |
struct identifier *fun; |
funp=p->identifier_references+i; |
if(funp->id_flags & (ID_HIDDEN|ID_STATIC)) continue; |
fun=ID_FROM_PTR(p, funp); |
if(funp->id_flags & ID_INHERITED) |
{ |
int found_better=-1; |
int funa_is_prototype; |
|
if(funp->id_flags & ID_PRIVATE) continue; |
funa_is_prototype = fun->func.offset == -1; |
|
|
|
for(t=i+1;t<(int)p->num_identifier_references;t++) |
{ |
struct reference *funpb; |
struct identifier *funb; |
|
funpb=p->identifier_references+t; |
if(funpb->id_flags & (ID_HIDDEN|ID_STATIC)) continue; |
funb=ID_FROM_PTR(p,funpb); |
|
|
if(fun->name==funb->name) |
{ |
found_better=t; |
|
|
|
|
if(funa_is_prototype && (funb->func.offset != -1) && |
!(funp->id_flags & ID_INLINE)) |
{ |
funp->inherit_offset = funpb->inherit_offset; |
funp->identifier_offset = funpb->identifier_offset; |
} |
if(!funa_is_prototype && funb->func.offset == -1) |
{ |
funpb->inherit_offset = funp->inherit_offset; |
funpb->identifier_offset = funp->identifier_offset; |
} |
} |
} |
if(found_better!=-1) |
continue; |
} |
if ((fun->func.offset == -1) && (funp->id_flags & ID_INLINE) && |
IDENTIFIER_IS_PIKE_FUNCTION(fun->identifier_flags)) { |
if (fun->name->len < 900) { |
my_yyerror("Missing definition for local function %S.", |
fun->name); |
} else { |
yyerror("Missing definition for local function."); |
} |
} |
add_to_identifier_index(i); |
} |
fsort_program_identifier_index(p->identifier_index, |
p->identifier_index + |
p->num_identifier_index - 1, |
p); |
|
|
p->flags |= PROGRAM_FIXED; |
|
|
for(i=1;i<NUM_LFUNS;i++) { |
p->lfuns[i] = low_find_lfun(p, i); |
} |
|
if(Pike_compiler->flags & COMPILATION_CHECK_FINAL) |
{ |
for(i=0;i<(int)p->num_identifier_references;i++) |
{ |
if((p->identifier_references[i].id_flags & (ID_NOMASK|ID_HIDDEN)) == |
ID_NOMASK) |
{ |
struct pike_string *name=ID_FROM_INT(p, i)->name; |
|
e=find_shared_string_identifier(name,p); |
if(e == -1) |
e=really_low_find_shared_string_identifier(name, p, |
SEE_STATIC|SEE_PRIVATE); |
|
if((e != i) && (e != -1)) |
{ |
if(name->len < 1024) |
my_yyerror("Illegal to redefine final identifier %S", name); |
else |
my_yyerror("Illegal to redefine final identifier (name too large to print)."); |
} |
} |
} |
} |
|
#ifdef DEBUG_MALLOC |
{ |
#define DBSTR(X) ((X)?(X)->str:"") |
int e,v; |
INT32 line; |
struct pike_string *tmp; |
struct memory_map *m=0;; |
if(lex.current_file && |
lex.current_file->str && |
lex.current_file->len && |
!strcmp(lex.current_file->str,"-")) |
{ |
m=dmalloc_alloc_mmap( DBSTR(lex.current_file), lex.current_line); |
} |
else if( (tmp=find_program_name(Pike_compiler->new_program, &line)) ) |
{ |
m=dmalloc_alloc_mmap( tmp->str, line); |
free_string(tmp); |
}else{ |
m=dmalloc_alloc_mmap( "program id", Pike_compiler->new_program->id); |
} |
|
for(e=0;e<Pike_compiler->new_program->num_inherits;e++) |
{ |
struct inherit *i=Pike_compiler->new_program->inherits+e; |
char *tmp; |
struct pike_string *tmp2 = NULL; |
char buffer[50]; |
|
for(v=0;v<i->prog->num_variable_index;v++) |
{ |
int d=i->prog->variable_index[v]; |
struct identifier *id=i->prog->identifiers+d; |
|
dmalloc_add_mmap_entry(m, |
id->name->str, |
i->storage_offset + id->func.offset, |
sizeof_variable(id->run_time_type), |
1, |
0,0); |
} |
|
if(i->name) |
{ |
tmp=i->name->str; |
} |
else if(!(tmp2 = find_program_name(i->prog, &line))) |
{ |
sprintf(buffer,"inherit[%d]",e); |
tmp=buffer; |
} else { |
tmp = tmp2->str; |
} |
dmalloc_add_mmap_entry(m, |
tmp, |
i->storage_offset, |
i->prog->storage_needed - i->prog->inherits[0].storage_offset, |
1, |
0,0); |
if (tmp2) { |
free_string(tmp2); |
} |
} |
dmalloc_set_mmap_template(Pike_compiler->new_program, m); |
} |
#endif |
} |
|
struct program *low_allocate_program(void) |
{ |
struct program *p=alloc_program(); |
MEMSET(p, 0, sizeof(struct program)); |
p->flags|=PROGRAM_VIRGIN; |
p->alignment_needed=1; |
|
GC_ALLOC(p); |
p->id=++current_program_id; |
INIT_PIKE_MEMOBJ(p); |
|
DOUBLELINK(first_program, p); |
GETTIMEOFDAY(& p->timestamp); |
return p; |
} |
|
|
|
|
void low_start_new_program(struct program *p, |
int pass, |
struct pike_string *name, |
int flags, |
int *idp) |
{ |
int id=0; |
struct svalue tmp; |
|
#if 0 |
#ifdef SHARED_NODES |
if (!node_hash.table) { |
node_hash.table = malloc(sizeof(node *)*32831); |
if (!node_hash.table) { |
Pike_fatal("Out of memory!\n"); |
} |
MEMSET(node_hash.table, 0, sizeof(node *)*32831); |
node_hash.size = 32831; |
} |
#endif /* SHARED_NODES */ |
#endif /* 0 */ |
|
|
|
|
low_init_threads_disable(); |
|
compilation_depth++; |
|
tmp.type=T_PROGRAM; |
if(!p) |
{ |
p=low_allocate_program(); |
if(name) |
{ |
tmp.u.program=p; |
id=add_constant(name, &tmp, flags & ~ID_EXTERN); |
#if 0 |
fprintf(stderr,"Compiling class %s, depth=%d\n",name->str,compilation_depth); |
}else{ |
fprintf(stderr,"Compiling file %s, depth=%d\n", |
lex.current_file ? lex.current_file->str : "-", |
compilation_depth); |
#endif |
} |
}else{ |
tmp.u.program=p; |
add_ref(p); |
if((pass == 2) && name) |
{ |
struct identifier *i; |
id=isidentifier(name); |
if (id < 0) |
Pike_fatal("Program constant disappeared in second pass.\n"); |
i=ID_FROM_INT(Pike_compiler->new_program, id); |
free_type(i->type); |
i->type=get_type_of_svalue(&tmp); |
} |
} |
if (pass == 1) { |
if(compilation_depth >= 1) |
add_ref(p->parent = Pike_compiler->new_program); |
} |
p->flags &=~ PROGRAM_VIRGIN; |
Pike_compiler->parent_identifier=id; |
if(idp) *idp=id; |
|
CDFPRINTF((stderr, "th(%ld) %p low_start_new_program() %s " |
"pass=%d: threads_disabled:%d, compilation_depth:%d\n", |
(long)th_self(), p, name ? name->str : "-", |
Pike_compiler->compiler_pass, |
threads_disabled, compilation_depth)); |
|
init_type_stack(); |
|
#define PUSH |
#include "compilation.h" |
|
Pike_compiler->compiler_pass = pass; |
|
Pike_compiler->num_used_modules=0; |
|
if(p && (p->flags & PROGRAM_FINISHED)) |
{ |
yyerror("Pass2: Program already done"); |
p=0; |
} |
|
Pike_compiler->malloc_size_program = ALLOC_STRUCT(program); |
Pike_compiler->fake_object=alloc_object(); |
|
#ifdef PIKE_DEBUG |
Pike_compiler->fake_object->storage=(char *)xalloc(256 * sizeof(struct svalue)); |
|
MEMSET(Pike_compiler->fake_object->storage,0x55,256*sizeof(struct svalue)); |
#else |
Pike_compiler->fake_object->storage=(char *)malloc(sizeof(struct parent_info)); |
#endif |
|
* that they never take over a stale gc marker. */ |
if (Pike_in_gc) remove_marker(Pike_compiler->fake_object); |
|
Pike_compiler->fake_object->next=Pike_compiler->fake_object; |
Pike_compiler->fake_object->prev=Pike_compiler->fake_object; |
Pike_compiler->fake_object->refs=0; |
add_ref(Pike_compiler->fake_object); |
Pike_compiler->fake_object->prog=p; |
add_ref(p); |
|
#ifdef PIKE_DEBUG |
Pike_compiler->fake_object->program_id=p->id; |
#endif |
|
#ifdef PIKE_SECURITY |
Pike_compiler->fake_object->prot=0; |
#endif |
|
debug_malloc_touch(Pike_compiler->fake_object); |
debug_malloc_touch(Pike_compiler->fake_object->storage); |
|
if(name) |
{ |
|
if((((struct parent_info *)Pike_compiler->fake_object->storage)->parent=Pike_compiler->previous->fake_object)) |
add_ref(Pike_compiler->previous->fake_object); |
((struct parent_info *)Pike_compiler->fake_object->storage)->parent_identifier=id; |
}else{ |
((struct parent_info *)Pike_compiler->fake_object->storage)->parent=0; |
((struct parent_info *)Pike_compiler->fake_object->storage)->parent_identifier=0; |
} |
|
Pike_compiler->new_program=p; |
|
#ifdef PROGRAM_BUILD_DEBUG |
if (name) { |
fprintf (stderr, "%.*sstarting program %d (pass=%d): ", |
compilation_depth, " ", Pike_compiler->new_program->id, Pike_compiler->compiler_pass); |
push_string (name); |
print_svalue (stderr, --Pike_sp); |
putc ('\n', stderr); |
} |
else |
fprintf (stderr, "%.*sstarting program %d (pass=%d)\n", |
compilation_depth, " ", Pike_compiler->new_program->id, Pike_compiler->compiler_pass); |
#endif |
|
if (compilation_depth >= 1) { |
if(TEST_COMPAT(7,2) || (lex.pragmas & ID_SAVE_PARENT)) |
{ |
p->flags |= PROGRAM_USES_PARENT; |
}else if (!(lex.pragmas & ID_DONT_SAVE_PARENT)) { |
struct pike_string *tmp=findstring("__pragma_save_parent__"); |
if(tmp) |
{ |
struct node_s *n=find_module_identifier(tmp, 0); |
if(n) |
{ |
int do_save_parent = !node_is_false(n); |
free_node(n); |
if (do_save_parent) p->flags |= PROGRAM_USES_PARENT; |
} |
} |
} |
} |
|
debug_malloc_touch(Pike_compiler->fake_object); |
debug_malloc_touch(Pike_compiler->fake_object->storage); |
|
if(Pike_compiler->new_program->program) |
{ |
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME)=Pike_compiler->new_program->PIKE_CONCAT(num_,NAME); |
#include "program_areas.h" |
|
|
{ |
INT32 line=0, off=0; |
size_t len = 0; |
INT32 shift = 0; |
char *file=0; |
char *cnt=Pike_compiler->new_program->linenumbers; |
|
while(cnt < Pike_compiler->new_program->linenumbers + |
Pike_compiler->new_program->num_linenumbers) |
{ |
if(*cnt == 127) |
{ |
cnt++; |
len = get_small_number(&cnt); |
shift = *cnt; |
file = ++cnt; |
CHECK_FILE_ENTRY (Pike_compiler->new_program, cnt, len, shift); |
cnt += len<<shift; |
} |
off+=get_small_number(&cnt); |
line+=get_small_number(&cnt); |
} |
Pike_compiler->last_line=line; |
Pike_compiler->last_pc=off; |
if(file) |
{ |
struct pike_string *str = begin_wide_shared_string(len, shift); |
if(Pike_compiler->last_file) free_string(Pike_compiler->last_file); |
memcpy(str->str, file, len<<shift); |
Pike_compiler->last_file = end_shared_string(str); |
} |
} |
|
}else{ |
static struct pike_string *s; |
struct inherit i; |
|
#define START_SIZE 64 |
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
if (Pike_compiler->new_program->NAME) { \ |
free (Pike_compiler->new_program->NAME); \ |
Pike_compiler->new_program->PIKE_CONCAT(num_,NAME) = 0; \ |
} \ |
Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME)=START_SIZE; \ |
Pike_compiler->new_program->NAME=(TYPE *)xalloc(sizeof(TYPE) * START_SIZE); |
#include "program_areas.h" |
|
i.prog=Pike_compiler->new_program; |
i.identifier_level=0; |
i.storage_offset=0; |
i.inherit_level=0; |
i.identifier_ref_offset=0; |
i.parent=0; |
i.parent_identifier=-1; |
i.parent_offset=OBJECT_PARENT; |
i.name=0; |
add_to_inherits(i); |
} |
|
Pike_compiler->init_node=0; |
Pike_compiler->num_parse_error=0; |
|
push_compiler_frame(0); |
copy_pike_type(Pike_compiler->compiler_frame->current_return_type, |
void_type_string); |
|
debug_malloc_touch(Pike_compiler->fake_object); |
debug_malloc_touch(Pike_compiler->fake_object->storage); |
} |
|
PMOD_EXPORT void debug_start_new_program(int line, const char *file) |
{ |
struct pike_string *save_file = lex.current_file; |
int save_line = lex.current_line; |
|
{ |
const char *p = DEFINETOSTR(PIKE_SRC_ROOT), *f = file; |
while (*p && *p == *f) p++, f++; |
while (*f == '/' || *f == '\\') f++; |
|
lex.current_file = make_shared_string(f); |
lex.current_line = line; |
} |
|
CDFPRINTF((stderr, |
"th(%ld) start_new_program(%d, %s): " |
"threads_disabled:%d, compilation_depth:%d\n", |
(long)th_self(), line, file, threads_disabled, compilation_depth)); |
|
low_start_new_program(0,1,0,0,0); |
store_linenumber(line,lex.current_file); |
debug_malloc_name(Pike_compiler->new_program, file, line); |
|
free_string(lex.current_file); |
lex.current_file = save_file; |
lex.current_line = save_line; |
} |
|
|
static void exit_program_struct(struct program *p) |
{ |
unsigned e; |
|
#ifdef PIKE_DEBUG |
if (p->refs) { |
#ifdef DEBUG_MALLOC |
fprintf (stderr, "Program to be freed still got %d references:\n", p->refs); |
describe_something(p, T_PROGRAM, 0,2,0, NULL); |
#endif |
Pike_fatal("Program to be freed still got %d references.\n", p->refs); |
} |
#endif |
|
if(p->parent) |
{ |
|
struct program *parent = p->parent; |
p->parent = NULL; |
free_program(parent); |
} |
|
|
if(id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]==p) |
id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]=0; |
|
if(p->strings) |
for(e=0; e<p->num_strings; e++) |
if(p->strings[e]) |
free_string(p->strings[e]); |
|
if(p->identifiers) |
{ |
for(e=0; e<p->num_identifiers; e++) |
{ |
if(p->identifiers[e].name) |
free_string(p->identifiers[e].name); |
if(p->identifiers[e].type) |
free_type(p->identifiers[e].type); |
} |
} |
|
if(p->constants) |
{ |
for(e=0;e<p->num_constants;e++) |
{ |
free_svalue(& p->constants[e].sval); |
#if 0 |
if(p->constants[e].name) free_string(p->constants[e].name); |
#endif /* 0 */ |
} |
} |
|
if(p->inherits) |
for(e=0; e<p->num_inherits; e++) |
{ |
if(p->inherits[e].name) |
free_string(p->inherits[e].name); |
if(e) |
{ |
if(p->inherits[e].prog) |
free_program(p->inherits[e].prog); |
} |
if(p->inherits[e].parent) |
free_object(p->inherits[e].parent); |
} |
|
DOUBLEUNLINK(first_program, p); |
|
if(p->flags & PROGRAM_OPTIMIZED) |
{ |
if(p->program) { |
#ifdef PIKE_USE_MACHINE_CODE |
#ifdef VALGRIND_DISCARD_TRANSLATIONS |
VALGRIND_DISCARD_TRANSLATIONS(p->program, |
p->num_program*sizeof(p->program[0])); |
#endif /* VALGRIND_DISCARD_TRANSLATIONS */ |
#endif /* PIKE_USE_MACHINE_CODE */ |
dmfree(p->program); |
} |
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) p->NAME=0; |
#include "program_areas.h" |
}else{ |
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
if(p->NAME) { dmfree((char *)p->NAME); p->NAME=0; } |
#include "program_areas.h" |
} |
|
EXIT_PIKE_MEMOBJ(p); |
|
GC_FREE(p); |
} |
|
#ifdef PIKE_DEBUG |
void dump_program_desc(struct program *p) |
{ |
int e,d,q; |
|
|
fprintf(stderr,"$$$$$ dump_program_desc for %p\n", p); |
|
fprintf(stderr,"All inherits:\n"); |
for(e=0;e<p->num_inherits;e++) |
{ |
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"%3d:\n",e); |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"inherited program: %d\n",p->inherits[e].prog->id); |
|
if(p->inherits[e].name) |
{ |
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"name : %s\n",p->inherits[e].name->str); |
} |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"inherit_level: %d\n",p->inherits[e].inherit_level); |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"identifier_level: %d\n",p->inherits[e].identifier_level); |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"parent_identifier: %d\n",p->inherits[e].parent_identifier); |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"parent_offset: %d\n",p->inherits[e].parent_offset); |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"storage_offset: %ld\n", |
DO_NOT_WARN((long)p->inherits[e].storage_offset)); |
|
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"parent: %p\n",p->inherits[e].parent); |
|
if(p->inherits[e].parent && |
p->inherits[e].parent->prog && |
p->inherits[e].parent->prog->num_linenumbers>1) |
{ |
for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"parent: %s\n",p->inherits[e].parent->prog->linenumbers+1); |
} |
} |
|
fprintf(stderr,"All identifier references:\n"); |
for(e=0;e<(int)p->num_identifier_references;e++) |
{ |
struct inherit *inh = INHERIT_FROM_INT(p,e); |
fprintf(stderr,"%3d: ",e); |
for(d=0;d<inh->inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"%-40s flags 0x%x",ID_FROM_INT(p,e)->name->str, |
p->identifier_references[e].id_flags); |
for (q = 0; q < p->num_inherits; q++) |
if (p->inherits + q == inh) { |
fprintf (stderr, " inherit %d\n", q); |
goto inherit_found; |
} |
fprintf (stderr, " inherit not found!\n"); |
inherit_found:; |
} |
fprintf(stderr,"All sorted identifiers:\n"); |
for(q=0;q<(int)p->num_identifier_index;q++) |
{ |
e=p->identifier_index[q]; |
fprintf(stderr,"%3d (%3d):",e,q); |
for(d=0;d<INHERIT_FROM_INT(p,e)->inherit_level;d++) fprintf(stderr," "); |
fprintf(stderr,"%s;\n", ID_FROM_INT(p,e)->name->str); |
} |
|
fprintf(stderr,"$$$$$ dump_program_desc for %p done\n", p); |
} |
#endif |
|
static void toss_compilation_resources(void) |
{ |
if(Pike_compiler->fake_object) |
{ |
if( ((struct parent_info *)Pike_compiler->fake_object->storage)->parent ) |
{ |
free_object(((struct parent_info *)Pike_compiler->fake_object->storage)->parent); |
|
((struct parent_info *)Pike_compiler->fake_object->storage)->parent=0; |
} |
|
free_program(Pike_compiler->fake_object->prog); |
Pike_compiler->fake_object->prog=0; |
free_object(Pike_compiler->fake_object); |
Pike_compiler->fake_object=0; |
} |
|
free_program(Pike_compiler->new_program); |
Pike_compiler->new_program=0; |
|
if(Pike_compiler->malloc_size_program) |
{ |
dmfree((char *)Pike_compiler->malloc_size_program); |
Pike_compiler->malloc_size_program=0; |
} |
|
if(Pike_compiler->module_index_cache) |
{ |
free_mapping(Pike_compiler->module_index_cache); |
Pike_compiler->module_index_cache=0; |
} |
|
while(Pike_compiler->compiler_frame) |
pop_compiler_frame(); |
|
if(Pike_compiler->last_identifier) |
{ |
free_string(Pike_compiler->last_identifier); |
Pike_compiler->last_identifier=0; |
} |
|
if(Pike_compiler->last_file) |
{ |
free_string(Pike_compiler->last_file); |
Pike_compiler->last_file=0; |
} |
|
unuse_modules(Pike_compiler->num_used_modules); |
} |
|
int sizeof_variable(int run_time_type) |
{ |
switch(run_time_type) |
{ |
case T_FUNCTION: |
case T_MIXED: return sizeof(struct svalue); |
case T_FLOAT: return sizeof(FLOAT_TYPE); |
case T_INT: return sizeof(INT_TYPE); |
default: return sizeof(void *); |
} |
} |
|
static ptrdiff_t alignof_variable(int run_time_type) |
{ |
switch(run_time_type) |
{ |
case T_FUNCTION: |
case T_MIXED: return ALIGNOF(struct svalue); |
case T_FLOAT: return ALIGNOF(FLOAT_TYPE); |
case T_INT: return ALIGNOF(INT_TYPE); |
default: return ALIGNOF(void *); |
} |
} |
|
#ifdef PIKE_DEBUG |
|
void dump_program_tables (struct program *p, int indent) |
{ |
int d; |
|
if (!p) { |
fprintf(stderr, "%*sProgram: NULL\n\n", indent, ""); |
return; |
} |
|
fprintf(stderr, |
"%*sProgram flags: 0x%04x\n\n", |
indent, "", p->flags); |
|
fprintf(stderr, |
"%*sReference table:\n" |
"%*s ####: Flags Inherit Identifier\n", |
indent, "", indent, ""); |
for (d=0; d < p->num_identifier_references; d++) { |
struct reference *ref = p->identifier_references + d; |
|
fprintf(stderr, "%*s %4d: %5x %7d %10d %s\n", |
indent, "", |
d, ref->id_flags, ref->inherit_offset, |
ref->identifier_offset, |
ID_FROM_PTR(p,ref)->name->size_shift ? "(wide)" : |
ID_FROM_PTR(p,ref)->name->str); |
if (IDENTIFIER_IS_PIKE_FUNCTION(ID_FROM_PTR(p,ref)->identifier_flags)) { |
INT32 line; |
struct program *inh_p = INHERIT_FROM_PTR(p,ref)->prog; |
struct pike_string *file = |
get_line (ID_FROM_PTR(p,ref)->func.offset + inh_p->program, inh_p, &line); |
if (!file->size_shift) |
fprintf (stderr, "%*s %s:%d\n", |
indent, "", file->str, line); |
free_string (file); |
} |
} |
|
fprintf(stderr, "\n" |
"%*sIdentifier index table:\n" |
"%*s ####: Index\n", |
indent, "", indent, ""); |
for (d = 0; d < p->num_identifier_index; d++) { |
fprintf(stderr, "%*s %4d: %5d\n", |
indent, "", |
d, p->identifier_index[d]); |
} |
|
fprintf(stderr, "\n" |
"%*sInherit table:\n" |
"%*s ####: Level prog_id id_level storage_offs " |
"par_id par_offs par_obj_id id_ref_offs\n", |
indent, "", indent, ""); |
for (d=0; d < p->num_inherits; d++) { |
struct inherit *inh = p->inherits + d; |
|
fprintf(stderr, "%*s %4d: %5d %7d %8d %12d %6d %8d %10d %11d\n", |
indent, "", |
d, inh->inherit_level, |
inh->prog ? inh->prog->id : -1, |
inh->identifier_level, inh->storage_offset, |
inh->parent_identifier, inh->parent_offset, |
inh->parent ? inh->parent->program_id : -1, |
inh->identifier_ref_offset); |
} |
fprintf(stderr, "\n" |
"%*sIdentifier table:\n" |
"%*s ####: Flags Offset Type Name\n", |
indent, "", indent, ""); |
for (d=0; d < p->num_identifiers; d++) { |
struct identifier *id = p->identifiers + d; |
|
fprintf(stderr, "%*s %4d: %5x %6d %4d \"%s\"\n", |
indent, "", |
d, id->identifier_flags, id->func.offset, |
id->run_time_type, id->name->str); |
} |
|
fprintf(stderr, "\n" |
"%*sVariable table:\n" |
"%*s ####: Index\n", |
indent, "", indent, ""); |
for (d = 0; d < p->num_variable_index; d++) { |
fprintf(stderr, "%*s %4d: %5d\n", |
indent, "", |
d, p->variable_index[d]); |
} |
fprintf(stderr, "\n" |
"%*sConstant table:\n" |
"%*s ####: Type Name\n", |
indent, "", indent, ""); |
for (d = 0; d < p->num_constants; d++) { |
struct program_constant *c = p->constants + d; |
#if 0 |
fprintf(stderr, "%*s %4d: %-15s %s%s%s\n", |
indent, "", |
d, get_name_of_type (c->sval.type), |
c->name?"\"":"",c->name?c->name->str:"NULL",c->name?"\"":""); |
#else /* !0 */ |
fprintf(stderr, "%*s %4d: %-15s %d\n", |
indent, "", |
d, get_name_of_type (c->sval.type), |
c->offset); |
#endif /* 0 */ |
} |
|
fprintf(stderr, "\n" |
"%*sLinenumber table:\n", |
indent, ""); |
{ |
INT32 off = 0, line = 0; |
char *cnt = p->linenumbers; |
|
while (cnt < p->linenumbers + p->num_linenumbers) { |
if (*cnt == 127) { |
int len, shift; |
char *file; |
cnt++; |
len = get_small_number(&cnt); |
shift = *cnt; |
file = ++cnt; |
CHECK_FILE_ENTRY (p, cnt, len, shift); |
cnt += len << shift; |
if (!shift) { |
fprintf(stderr, "%*s Filename: \"%s\"\n", indent, "", file); |
} else { |
fprintf(stderr, "%*s Filename: len:%d, shift:%d\n", indent, "", len, shift); |
} |
} |
off += get_small_number(&cnt); |
line += get_small_number(&cnt); |
fprintf(stderr, "%*s %8d:%8d\n", indent, "", off, line); |
} |
} |
|
fprintf(stderr, "\n"); |
} |
|
void check_program(struct program *p) |
{ |
INT32 size; |
unsigned INT32 checksum, e; |
int variable_positions[1024]; |
|
if(p->flags & PROGRAM_AVOID_CHECK) return; |
|
for(e=0;e<NELEM(variable_positions);e++) |
variable_positions[e]=-1; |
|
if(p->id > current_program_id) |
Pike_fatal("Program id is out of sync! (p->id=%d, current_program_id=%d)\n",p->id,current_program_id); |
|
if(p->refs <=0) |
Pike_fatal("Program has zero refs.\n"); |
|
if(p->next && p->next->prev != p) |
Pike_fatal("Program ->next->prev != program.\n"); |
|
if(p->prev) |
{ |
if(p->prev->next != p) |
Pike_fatal("Program ->prev->next != program.\n"); |
}else{ |
if(first_program != p) |
Pike_fatal("Program ->prev == 0 but first_program != program.\n"); |
} |
|
if(p->id > current_program_id || p->id <= 0) |
Pike_fatal("Program id is wrong.\n"); |
|
if(p->storage_needed < 0) |
Pike_fatal("Program->storage_needed < 0.\n"); |
|
if(p->num_identifier_index > p->num_identifier_references) |
Pike_fatal("Too many identifier index entries in program!\n"); |
|
for(e=0;e<p->num_constants;e++) |
{ |
struct svalue *s = & p->constants[e].sval; |
check_svalue(s); |
if (p->flags & PROGRAM_FINISHED && s->type == T_OBJECT && |
s->u.object->next == s->u.object) |
Pike_fatal ("Got fake object in constant in finished program.\n"); |
#if 0 |
if(p->constants[e].name) check_string(p->constants[e].name); |
#else /* ! 0 */ |
if (p->constants[e].offset >= p->num_identifiers) { |
Pike_fatal("Constant initializer outside num_identifiers (%d >= %d).\n", |
p->constants[e].offset, p->num_identifiers); |
} |
#endif /* 0 */ |
} |
|
for(e=0;e<p->num_strings;e++) |
check_string(p->strings[e]); |
|
for(e=0;e<p->num_inherits;e++) |
{ |
if(!p->inherits[e].prog) |
{ |
|
return; |
} |
|
if(p->inherits[e].storage_offset < 0) |
Pike_fatal("Inherit->storage_offset is wrong.\n"); |
|
if(p->inherits[e].prog && |
p->inherits[e].storage_offset + STORAGE_NEEDED(p->inherits[e].prog) > |
p->storage_needed) |
Pike_fatal("Not enough room allocated by inherit!\n"); |
|
if (p->inherits[e].inherit_level == 1 && |
p->inherits[e].identifier_level != (INT32) p->inherits[e].identifier_ref_offset) { |
dump_program_tables (p, 0); |
Pike_fatal ("Unexpected difference between identifier_level " |
"and identifier_ref_offset in inherit %d.\n", e); |
} |
|
if(e) |
{ |
if(p->inherits[e-1].storage_offset > |
p->inherits[e].storage_offset) |
Pike_fatal("Overlapping inherits! (1)\n"); |
|
if(p->inherits[e-1].prog && |
p->inherits[e-1].inherit_level >= p->inherits[e].inherit_level && |
( p->inherits[e-1].storage_offset + |
STORAGE_NEEDED(p->inherits[e-1].prog)) > |
p->inherits[e].storage_offset) |
Pike_fatal("Overlapping inherits! (3)\n"); |
} |
} |
|
|
if(p->flags & PROGRAM_FINISHED) |
for(e=0;e<p->num_identifiers;e++) |
{ |
check_string(p->identifiers[e].name); |
check_type_string(p->identifiers[e].type); |
|
switch (p->identifiers[e].identifier_flags & IDENTIFIER_TYPE_MASK) { |
case IDENTIFIER_VARIABLE: |
case IDENTIFIER_PIKE_FUNCTION: |
case IDENTIFIER_C_FUNCTION: |
case IDENTIFIER_CONSTANT: |
break; |
|
default: |
Pike_fatal("Invalid identifier type.\n"); |
} |
|
if(p->identifiers[e].identifier_flags & ~IDENTIFIER_MASK) |
Pike_fatal("Unknown flags in identifier flag field.\n"); |
|
if(p->identifiers[e].run_time_type!=T_MIXED) |
check_type(p->identifiers[e].run_time_type); |
|
if(IDENTIFIER_IS_VARIABLE(p->identifiers[e].identifier_flags)) |
{ |
if( (p->identifiers[e].func.offset ) & |
(alignof_variable(p->identifiers[e].run_time_type)-1)) |
{ |
Pike_fatal("Variable %s offset is not properly aligned (%ld).\n", |
p->identifiers[e].name->str, |
PTRDIFF_T_TO_LONG(p->identifiers[e].func.offset)); |
} |
} |
} |
|
for(e=0;e<p->num_identifier_references;e++) |
{ |
struct identifier *i; |
if(p->identifier_references[e].inherit_offset > p->num_inherits) |
Pike_fatal("Inherit offset is wrong!\n"); |
|
if(!p->inherits[p->identifier_references[e].inherit_offset].prog) |
{ |
if(!(p->flags & PROGRAM_FINISHED)) |
continue; |
|
Pike_fatal("p->inherit[%d].prog = NULL!\n",p->identifier_references[e].inherit_offset); |
} |
|
if(p->identifier_references[e].identifier_offset > |
p->inherits[p->identifier_references[e].inherit_offset].prog->num_identifiers) |
Pike_fatal("Identifier offset %d is wrong! %d > %d\n", |
e, |
p->identifier_references[e].identifier_offset, |
p->inherits[p->identifier_references[e].inherit_offset].prog->num_identifiers); |
|
i=ID_FROM_INT(p, e); |
|
if(IDENTIFIER_IS_VARIABLE(i->identifier_flags)) |
{ |
size_t q, size; |
|
ptrdiff_t offset = INHERIT_FROM_INT(p, e)->storage_offset+i->func.offset; |
size=sizeof_variable(i->run_time_type); |
|
if((offset+size > (size_t)p->storage_needed) || offset<0) |
Pike_fatal("Variable outside storage! (%s)\n",i->name->str); |
|
for(q=0;q<size;q++) |
{ |
if(offset+q >= NELEM(variable_positions)) break; |
|
if(variable_positions[offset+q] != -1) |
{ |
if(ID_FROM_INT(p,variable_positions[offset+q])->run_time_type != |
i->run_time_type) |
{ |
fprintf(stderr, "Storage offset: 0x%08x vs 0x%08x\n" |
"Func offset: 0x%08x vs 0x%08x\n" |
"Type: %s vs %s\n", |
INHERIT_FROM_INT(p, variable_positions[offset+q])-> |
storage_offset, |
INHERIT_FROM_INT(p, e)->storage_offset, |
ID_FROM_INT(p, variable_positions[offset+q])->func.offset, |
i->func.offset, |
get_name_of_type(ID_FROM_INT(p,variable_positions[offset+q] |
)->run_time_type), |
get_name_of_type(i->run_time_type)); |
if (i->name) { |
Pike_fatal("Variable '%s' and '%s' overlap\n" |
"Offset 0x%08x - 0x%08x overlaps with 0x%08x - 0x%08x\n", |
ID_FROM_INT(p, variable_positions[offset+q])->name->str, |
i->name->str, |
INHERIT_FROM_INT(p, variable_positions[offset+q])-> |
storage_offset + |
ID_FROM_INT(p, variable_positions[offset+q])->func.offset, |
INHERIT_FROM_INT(p, variable_positions[offset+q])-> |
storage_offset + |
ID_FROM_INT(p, variable_positions[offset+q])->func.offset + |
sizeof_variable(ID_FROM_INT(p, variable_positions[offset+q] |
)->run_time_type)-1, |
offset, offset+size-1); |
} else { |
Pike_fatal("Variable '%s' and anonymous variable (%d) overlap\n" |
"Offset 0x%08x - 0x%08x overlaps with 0x%08x - 0x%08x\n", |
ID_FROM_INT(p, variable_positions[offset+q])->name->str, |
e, |
INHERIT_FROM_INT(p, variable_positions[offset+q])-> |
storage_offset + |
ID_FROM_INT(p, variable_positions[offset+q])->func.offset, |
INHERIT_FROM_INT(p, variable_positions[offset+q])-> |
storage_offset + |
ID_FROM_INT(p, variable_positions[offset+q])->func.offset + |
sizeof_variable(ID_FROM_INT(p, variable_positions[offset+q] |
)->run_time_type)-1, |
offset, offset+size-1); |
} |
} |
} |
variable_positions[offset+q]=e; |
} |
} |
} |
|
for(e=0;e<p->num_identifier_index;e++) |
{ |
if(p->identifier_index[e] > p->num_identifier_references) |
Pike_fatal("Program->identifier_indexes[%ld] is wrong\n",(long)e); |
if (e && (program_identifier_index_compare(p->identifier_index[e-1], |
p->identifier_index[e], |
p) > 0)) { |
Pike_fatal("Program->identifier_index[%ld] > " |
"Program->identifier_index[%ld]\n", |
(long)(e-1), (long)e); |
} |
} |
|
} |
#endif |
|
|
|
|
|
|
|
|
struct program *end_first_pass(int finish) |
{ |
int e; |
struct program *prog; |
struct pike_string *s; |
|
debug_malloc_touch(Pike_compiler->fake_object); |
debug_malloc_touch(Pike_compiler->fake_object->storage); |
|
MAKE_CONST_STRING(s,"__INIT"); |
|
|
|
if (!(Pike_compiler->new_program->flags & PROGRAM_AVOID_CHECK)) { |
for(e=Pike_compiler->new_program->num_inherits-1;e;e--) |
{ |
int id; |
if(Pike_compiler->new_program->inherits[e].inherit_level!=1) continue; |
id=low_reference_inherited_identifier(0, e, s, SEE_STATIC); |
if(id!=-1) |
{ |
Pike_compiler->init_node=mknode(F_COMMA_EXPR, |
mkcastnode(void_type_string, |
mkapplynode(mkidentifiernode(id),0)), |
Pike_compiler->init_node); |
} |
} |
} |
|
|
|
|
|
|
if(Pike_compiler->init_node) |
{ |
Pike_compiler->compiler_frame->current_function_number = -2; |
e=dooptcode(s, |
mknode(F_COMMA_EXPR, |
Pike_compiler->init_node, |
mknode(F_RETURN,mkintnode(0),0)), |
function_type_string, |
ID_STATIC); |
Pike_compiler->init_node=0; |
} else if (finish == 2) { |
|
e = low_find_lfun(Pike_compiler->new_program, LFUN___INIT); |
}else{ |
e=-1; |
} |
Pike_compiler->new_program->lfuns[LFUN___INIT]=e; |
|
pop_compiler_frame(); |
|
if(Pike_compiler->num_parse_error > 0) |
{ |
CDFPRINTF((stderr, "th(%ld) Compilation errors (%d).\n", |
(long)th_self(), Pike_compiler->num_parse_error)); |
prog=0; |
}else{ |
prog=Pike_compiler->new_program; |
add_ref(prog); |
|
Pike_compiler->new_program->flags |= PROGRAM_PASS_1_DONE; |
|
if(finish) |
{ |
if(Pike_compiler->new_program->flags & PROGRAM_USES_PARENT) |
{ |
Pike_compiler->new_program->parent_info_storage = |
add_xstorage(sizeof(struct parent_info), |
ALIGNOF(struct parent_info), |
0); |
}else{ |
|
Pike_compiler->new_program->parent_info_storage=-1; |
} |
|
fixate_program(); |
if(Pike_compiler->num_parse_error) |
{ |
free_program(prog); |
prog=0; |
}else{ |
optimize_program(Pike_compiler->new_program); |
Pike_compiler->new_program->flags |= PROGRAM_FINISHED; |
} |
} |
|
#ifdef PIKE_DEBUG |
check_program(prog); |
if(l_flag) |
dump_program_desc(prog); |
#endif |
} |
|
#ifdef PROGRAM_BUILD_DEBUG |
fprintf (stderr, "%.*sfinishing program %d (pass=%d)\n", |
compilation_depth, " ", Pike_compiler->new_program->id, Pike_compiler->compiler_pass); |
#endif |
|
toss_compilation_resources(); |
|
#if 0 |
CDFPRINTF((stderr, |
"th(%ld) end_first_pass(): " |
"compilation_depth:%d, Pike_compiler->compiler_pass:%d\n", |
(long)th_self(), compilation_depth, Pike_compiler->compiler_pass)); |
#endif |
|
if(!Pike_compiler->compiler_frame && (Pike_compiler->compiler_pass==2 || !prog) && resolve_cache) |
{ |
free_mapping(dmalloc_touch(struct mapping *, resolve_cache)); |
resolve_cache=0; |
} |
|
#ifdef SHARED_NODES |
|
#endif /* SHARED_NODES */ |
|
#define POP |
#include "compilation.h" |
|
exit_type_stack(); |
|
free_all_nodes(); |
|
CDFPRINTF((stderr, |
"th(%ld) %p end_first_pass(%d): " |
"threads_disabled:%d, compilation_depth:%d\n", |
(long)th_self(), prog, finish, |
threads_disabled, compilation_depth)); |
|
compilation_depth--; |
|
exit_threads_disable(NULL); |
|
return prog; |
} |
|
|
|
|
PMOD_EXPORT struct program *debug_end_program(void) |
{ |
Pike_compiler->compiler_pass = 2; |
return end_first_pass(1); |
} |
|
|
|
|
|
|
PMOD_EXPORT size_t low_add_storage(size_t size, size_t alignment, |
ptrdiff_t modulo_orig) |
{ |
ptrdiff_t offset; |
ptrdiff_t modulo; |
|
if(!size) return Pike_compiler->new_program->storage_needed; |
|
#ifdef PIKE_DEBUG |
if(alignment <=0 || (alignment & (alignment-1)) || alignment > 256) |
Pike_fatal("Alignment must be 1,2,4,8,16,32,64,128 or 256 not %ld\n", |
PTRDIFF_T_TO_LONG(alignment)); |
#endif |
modulo=( modulo_orig ) % alignment; |
|
offset=DO_ALIGN(Pike_compiler->new_program->storage_needed-modulo,alignment)+modulo; |
|
if(!Pike_compiler->new_program->storage_needed) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pike_compiler->new_program->inherits[0].storage_offset=offset; |
} |
|
if(Pike_compiler->new_program->alignment_needed<alignment) |
Pike_compiler->new_program->alignment_needed = |
DO_NOT_WARN((unsigned INT8)alignment); |
|
#ifdef PIKE_DEBUG |
if(offset < Pike_compiler->new_program->storage_needed) |
Pike_fatal("add_storage failed horribly!\n"); |
|
if( (offset - modulo_orig ) % alignment ) |
Pike_fatal("add_storage failed horribly(2) %ld %ld %ld %ld!\n", |
DO_NOT_WARN((long)offset), |
(long)0 , |
DO_NOT_WARN((long)modulo_orig), |
DO_NOT_WARN((long)alignment)); |
|
#endif |
|
Pike_compiler->new_program->storage_needed = offset + size; |
|
return (size_t) offset; |
} |
|
|
|
|
|
static size_t add_xstorage(size_t size, |
size_t alignment, |
ptrdiff_t modulo_orig) |
{ |
ptrdiff_t offset, modulo, available; |
int e; |
|
if(!size) return Pike_compiler->new_program->xstorage; |
|
modulo=( modulo_orig ) % alignment; |
|
offset=DO_ALIGN(Pike_compiler->new_program->xstorage-modulo,alignment)+modulo; |
|
Pike_compiler->new_program->xstorage = offset + size; |
|
|
available = Pike_compiler->new_program->inherits[0].storage_offset; |
if(available < (ptrdiff_t)(offset+size)) |
{ |
available= |
DO_ALIGN( ((offset + size) - available), |
Pike_compiler->new_program->alignment_needed); |
|
for(e=0;e<Pike_compiler->new_program->num_inherits;e++) |
Pike_compiler->new_program->inherits[e].storage_offset+=available; |
|
Pike_compiler->new_program->storage_needed+=available; |
} |
|
return (size_t) offset; |
} |
|
typedef void (*oldhandlertype)(struct object *); |
static void compat_event_handler(int e) |
{ |
oldhandlertype handler; |
debug_malloc_touch(Pike_fp->current_object); |
handler=((oldhandlertype *)Pike_fp->context.prog->program)[e]; |
if(handler) handler(Pike_fp->current_object); |
debug_malloc_touch(Pike_fp->current_object); |
} |
|
static void add_compat_event_handler(void) |
{ |
if(Pike_compiler->new_program->event_handler != compat_event_handler) |
{ |
unsigned int e,d; |
unsigned char *tmp=(unsigned char *)&Pike_compiler->new_program->event_handler; |
|
for(d=0;d<NUM_PROG_EVENTS;d++) { |
|
|
#ifdef HAVE_COMPUTED_GOTO |
add_to_program(Pike_compiler->new_program->event_handler); |
#else /* !HAVE_COMPUTED_GOTO */ |
for(e=0;e<sizeof(Pike_compiler->new_program->event_handler);e++) |
add_to_program(tmp[e]); |
#endif /* HAVE_COMPUTED_GOTO */ |
} |
Pike_compiler->new_program->event_handler=compat_event_handler; |
} |
} |
|
|
|
|
|
|
PMOD_EXPORT void set_init_callback(void (*init)(struct object *)) |
{ |
add_compat_event_handler(); |
((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_INIT]=init; |
} |
|
|
|
|
|
|
PMOD_EXPORT void set_exit_callback(void (*exit)(struct object *)) |
{ |
add_compat_event_handler(); |
((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_EXIT]=exit; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void set_gc_recurse_callback(void (*m)(struct object *)) |
{ |
add_compat_event_handler(); |
((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_GC_RECURSE]=m; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void set_gc_check_callback(void (*m)(struct object *)) |
{ |
add_compat_event_handler(); |
((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_GC_CHECK]=m; |
} |
|
void pike_set_prog_event_callback(void (*cb)(int)) |
{ |
#ifdef PIKE_DEBUG |
if(Pike_compiler->new_program->event_handler) |
Pike_fatal("Program already has an event handler!\n"); |
#endif |
Pike_compiler->new_program->event_handler=cb; |
} |
|
void pike_set_prog_optimize_callback(node *(*opt)(node *)) |
{ |
#ifdef PIKE_DEBUG |
if(Pike_compiler->new_program->optimize) |
Pike_fatal("Program already has an optimize handler!\n"); |
#endif |
Pike_compiler->new_program->optimize = opt; |
} |
|
int really_low_reference_inherited_identifier(struct program_state *q, |
int e, |
int i) |
{ |
struct program *np=(q?q:Pike_compiler)->new_program; |
struct reference funp; |
struct program *p; |
int d, num_id_refs; |
|
if(i==-1) return -1; |
|
p = np->inherits[e].prog; |
|
funp = p->identifier_references[i]; |
funp.inherit_offset += e; |
funp.id_flags = (funp.id_flags & ~ID_INHERITED) | ID_INLINE|ID_HIDDEN; |
|
num_id_refs = np->num_identifier_references; |
|
for(d = 0; d < num_id_refs; d++) |
{ |
struct reference *refp; |
refp = np->identifier_references + d; |
|
if(!MEMCMP((char *)refp,(char *)&funp,sizeof funp)) return d; |
} |
|
if(q) |
low_add_to_identifier_references(q,funp); |
else |
add_to_identifier_references(funp); |
|
|
|
#ifdef PIKE_DEBUG |
if (num_id_refs != np->num_identifier_references-1) { |
fatal("Unexpected number of identifier references: %d != %d\n", |
num_id_refs, np->num_identifier_references-1); |
} |
#endif /* PIKE_DEBUG */ |
return num_id_refs; |
} |
|
int low_reference_inherited_identifier(struct program_state *q, |
int e, |
struct pike_string *name, |
int flags) |
{ |
struct program *np=(q?q:Pike_compiler)->new_program; |
struct reference funp; |
struct program *p; |
int i,d,refs; |
|
p=np->inherits[e].prog; |
i=find_shared_string_identifier(name,p); |
if(i==-1) |
{ |
i=really_low_find_shared_string_identifier(name,p, flags); |
if(i==-1) return -1; |
} |
|
if(p->identifier_references[i].id_flags & ID_HIDDEN) |
return -1; |
|
if(p->identifier_references[i].id_flags & ID_PRIVATE) |
if(!(flags & SEE_PRIVATE)) |
return -1; |
|
return really_low_reference_inherited_identifier(q, e, i); |
} |
|
int find_inherit(struct program *p, struct pike_string *name) |
{ |
int e; |
|
#if 0 |
fprintf(stderr, "find_inherit(0x%08lx, \"%s\")...\n", |
(unsigned long)p, name->str); |
#endif /* 0 */ |
for(e = p->num_inherits-1; e>0; e--) { |
#if 0 |
fprintf(stderr, " %04d: %04d %s\n", |
e, p->inherits[e].inherit_level, |
p->inherits[e].name?p->inherits[e].name->str:"NULL"); |
#endif /* 0 */ |
if (p->inherits[e].inherit_level > 1) continue; |
if (name == p->inherits[e].name) return e; |
} |
return 0; |
} |
|
node *reference_inherited_identifier(struct pike_string *super_name, |
struct pike_string *function_name) |
{ |
int n,e,id; |
struct program_state *state=Pike_compiler->previous; |
|
struct program *p; |
|
|
#ifdef PIKE_DEBUG |
if(function_name!=debug_findstring(function_name)) |
Pike_fatal("reference_inherited_function on nonshared string.\n"); |
#endif |
|
p=Pike_compiler->new_program; |
|
for(e=p->num_inherits-1;e>0;e--) |
{ |
if(p->inherits[e].inherit_level!=1) continue; |
if(!p->inherits[e].name) continue; |
|
if(super_name) |
if(super_name != p->inherits[e].name) |
continue; |
|
id=low_reference_inherited_identifier(0, |
e, |
function_name, |
SEE_STATIC); |
|
if(id!=-1) |
return mkidentifiernode(id); |
|
if(ISCONSTSTR(function_name,"`->") || |
ISCONSTSTR(function_name,"`[]")) |
{ |
return mknode(F_MAGIC_INDEX,mknewintnode(e),mknewintnode(0)); |
} |
|
if(ISCONSTSTR(function_name,"`->=") || |
ISCONSTSTR(function_name,"`[]=")) |
{ |
return mknode(F_MAGIC_SET_INDEX,mknewintnode(e),mknewintnode(0)); |
} |
|
if(ISCONSTSTR(function_name,"_indices")) |
{ |
return mknode(F_MAGIC_INDICES,mknewintnode(e),mknewintnode(0)); |
} |
|
if(ISCONSTSTR(function_name,"_values")) |
{ |
return mknode(F_MAGIC_VALUES,mknewintnode(e),mknewintnode(0)); |
} |
} |
|
|
for(n=0;n<compilation_depth;n++,state=state->previous) |
{ |
struct program *p=state->new_program; |
|
for(e=p->num_inherits-1;e>0;e--) |
{ |
if(p->inherits[e].inherit_level!=1) continue; |
if(!p->inherits[e].name) continue; |
|
if(super_name) |
if(super_name != p->inherits[e].name) |
continue; |
|
id=low_reference_inherited_identifier(state,e,function_name,SEE_STATIC); |
|
if(id!=-1) |
return mkexternalnode(p, id); |
|
if(ISCONSTSTR(function_name,"`->") || |
ISCONSTSTR(function_name,"`[]")) |
{ |
return mknode(F_MAGIC_INDEX, |
mknewintnode(e),mknewintnode(n+1)); |
} |
|
if(ISCONSTSTR(function_name,"`->=") || |
ISCONSTSTR(function_name,"`[]=")) |
{ |
return mknode(F_MAGIC_SET_INDEX, |
mknewintnode(e),mknewintnode(n+1)); |
} |
|
if(ISCONSTSTR(function_name,"_indices")) |
{ |
return mknode(F_MAGIC_INDICES, |
mknewintnode(e),mknewintnode(n+1)); |
} |
|
if(ISCONSTSTR(function_name,"_values")) |
{ |
return mknode(F_MAGIC_VALUES, |
mknewintnode(e),mknewintnode(n+1)); |
} |
} |
} |
|
return 0; |
} |
|
void rename_last_inherit(struct pike_string *n) |
{ |
if(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name) |
free_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name); |
copy_shared_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name, |
n); |
} |
|
#if 0 |
static int locate_parent_state(struct program_state **state, |
struct inherit **i, |
int *parent_identifier, |
int depth) |
{ |
int result=1; |
if(depth<=0) return depth; |
while(depth-->0) |
{ |
if( (*i)->parent_offset != INHERIT_PARENT) |
{ |
int tmp=(*i)->parent_identifier; |
if( (*i)->parent_offset > 0) |
{ |
int po=(*i)->parent_offset; |
*parent_identifier = (*state)->parent_identifier; |
*state = (*state)->previous; |
result++; |
fprintf(stderr,"INHERIT: state=state->previous (po=%d)\n",po); |
|
if(po>1) |
{ |
*i=INHERIT_FROM_INT( (*state)->new_program, |
*parent_identifier); |
|
result+=locate_parent_state(state,i,parent_identifier, po-1); |
} |
} |
|
if(tmp != -1) |
{ |
if( *parent_identifier == -4711) |
{ |
*parent_identifier = tmp; |
}else{ |
*parent_identifier = tmp + INHERIT_FROM_INT( (*state)->new_program, |
*parent_identifier)->identifier_level; |
} |
} |
}else{ |
fprintf(stderr,"INHERIT: Bailout!\n"); |
return result+depth+1; |
} |
*i = INHERIT_FROM_INT( (*state)->new_program, *parent_identifier); |
} |
return result; |
} |
|
|
static int find_depth(struct program_state *state, |
struct inherit *i, |
int parent_identifier, |
int depth) |
{ |
#if 0 |
int e; |
struct inherit *oi; |
for(e=0;e<=parent_offset;e++) state=state->previous; |
oi=INHERIT_FROM_INT(state->new_program, parent_identifier); |
parent_offset+=i->parent_offset; |
#endif |
|
return locate_parent_state(&state, |
&i, |
&parent_identifier, |
depth); |
} |
#endif |
|
|
|
|
void low_inherit(struct program *p, |
struct object *parent, |
int parent_identifier, |
int parent_offset, |
INT32 flags, |
struct pike_string *name) |
{ |
int e; |
ptrdiff_t inherit_offset, storage_offset; |
struct inherit inherit; |
|
#if 0 |
fprintf(stderr,"%p low_inherit(pid=%d, parent=%p, parid=%d, " |
"paroff=%d, flags=0x%x, name=%s);\n", |
Pike_compiler->new_program, |
p ? p->id : 0, |
parent, |
parent_identifier, |
parent_offset, |
flags, |
name? name->str : ""); |
#endif |
CDFPRINTF((stderr, "th(%ld) %p inherit %p\n", |
(long) th_self(), Pike_compiler->new_program, p)); |
|
if(!p) |
{ |
yyerror("Illegal program pointer."); |
return; |
} |
|
if (p == placeholder_program) { |
yyerror("Trying to inherit placeholder program (resolver problem)."); |
return; |
} |
|
if(p->flags & PROGRAM_NEEDS_PARENT) |
{ |
struct program_state *state=Pike_compiler; |
|
if(!parent && !parent_offset) |
{ |
yyerror("Parent pointer lost, cannot inherit!"); |
|
} |
|
#if 0 |
|
* previous compilations, but I'm too lazy to figure out |
* exactly how deep down we need to go... |
*/ |
for(e=0;e<compilation_depth;e++,state=state->previous) |
state->new_program->flags |= PROGRAM_USES_PARENT; |
#endif |
} |
|
|
if(parent_offset) |
parent_offset-=42; |
|
|
if(!(p->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) |
{ |
yyerror("Cannot inherit program which is not fully compiled yet."); |
return; |
} |
|
inherit_offset = Pike_compiler->new_program->num_inherits; |
|
|
storage_offset=p->inherits[0].storage_offset % p->alignment_needed; |
storage_offset=low_add_storage(STORAGE_NEEDED(p), |
p->alignment_needed, |
storage_offset); |
|
|
storage_offset-=p->inherits[0].storage_offset; |
|
for(e=0; e<(int)p->num_inherits; e++) |
{ |
inherit=p->inherits[e]; |
add_ref(inherit.prog); |
inherit.identifier_level += Pike_compiler->new_program->num_identifier_references; |
inherit.storage_offset += storage_offset; |
inherit.inherit_level ++; |
|
|
if(!e) |
{ |
if(parent) |
{ |
if(parent->next == parent) |
{ |
#if 0 |
struct object *o; |
inherit.parent_offset=0; |
for(o=Pike_compiler->fake_object;o!=parent;o=o->parent) |
{ |
#ifdef PIKE_DEBUG |
if(!o) Pike_fatal("low_inherit with odd Pike_compiler->fake_object as parent!\n"); |
#endif |
inherit.parent_offset++; |
} |
#else |
struct program_state *state=Pike_compiler; |
inherit.parent_offset=0; |
for(;state->fake_object!=parent;state=state->previous) |
{ |
#ifdef PIKE_DEBUG |
if(!state->fake_object) |
Pike_fatal("low_inherit with odd Pike_compiler->fake_object as parent!\n"); |
#endif |
inherit.parent_offset++; |
} |
#endif |
}else{ |
inherit.parent=parent; |
inherit.parent_identifier=parent_identifier; |
inherit.parent_offset=INHERIT_PARENT; |
} |
}else{ |
inherit.parent_offset=parent_offset; |
inherit.parent_identifier=parent_identifier; |
} |
}else{ |
if(!inherit.parent) |
{ |
if(parent && parent->next != parent && inherit.parent_offset) |
{ |
struct object *par=parent; |
int e,pid=parent_identifier; |
|
for(e=1;e<inherit.parent_offset;e++) |
{ |
struct inherit *in; |
if(!par->prog) |
{ |
par=0; |
pid=-1; |
break; |
} |
|
in=INHERIT_FROM_INT(par->prog, pid); |
switch(in->parent_offset) |
{ |
default: |
{ |
struct external_variable_context tmp; |
struct inherit *in2=in; |
while(in2->inherit_level >= in->inherit_level) in2--; |
tmp.o=par; |
tmp.inherit=in2; |
tmp.parent_identifier=pid; |
find_external_context(&tmp, in->parent_offset); |
par = tmp.o; |
pid = tmp.parent_identifier; |
} |
break; |
|
case INHERIT_PARENT: |
pid = in->parent_identifier; |
par = in->parent; |
break; |
|
case OBJECT_PARENT: |
|
|
if(par->prog->flags & PROGRAM_USES_PARENT) |
{ |
pid = PARENT_INFO(par)->parent_identifier; |
par = PARENT_INFO(par)->parent; |
}else{ |
pid=-1; |
par=0; |
} |
} |
} |
|
inherit.parent=par; |
inherit.parent_offset=INHERIT_PARENT; |
} |
} |
} |
if(inherit.parent) add_ref(inherit.parent); |
|
if(name) |
{ |
if(e==0) |
{ |
copy_shared_string(inherit.name,name); |
} |
else if(inherit.name) |
{ |
|
struct pike_string *s; |
s=begin_shared_string(inherit.name->len + name->len + 2); |
MEMCPY(s->str,name->str,name->len); |
MEMCPY(s->str+name->len,"::",2); |
MEMCPY(s->str+name->len+2,inherit.name->str,inherit.name->len); |
inherit.name=end_shared_string(s); |
} |
else |
{ |
inherit.name=0; |
} |
}else{ |
inherit.name=0; |
} |
add_to_inherits(inherit); |
} |
|
|
Pike_compiler->new_program->inherits[inherit_offset].identifier_ref_offset = |
Pike_compiler->new_program->num_identifier_references; |
|
for (e=0; e < (int)p->num_identifier_references; e++) |
{ |
struct reference fun; |
struct pike_string *name; |
|
fun = p->identifier_references[e]; |
|
name=ID_FROM_PTR(p,&fun)->name; |
fun.inherit_offset += inherit_offset; |
|
if (fun.id_flags & ID_NOMASK) |
{ |
Pike_compiler->flags |= COMPILATION_CHECK_FINAL; |
} |
|
if(fun.id_flags & ID_PRIVATE) fun.id_flags|=ID_HIDDEN; |
|
if (fun.id_flags & ID_PUBLIC) |
fun.id_flags |= flags & ~ID_PRIVATE; |
else |
fun.id_flags |= flags; |
|
fun.id_flags |= ID_INHERITED; |
add_to_identifier_references(fun); |
} |
} |
|
PMOD_EXPORT void do_inherit(struct svalue *s, |
INT32 flags, |
struct pike_string *name) |
{ |
struct program *p=program_from_svalue(s); |
low_inherit(p, |
s->type == T_FUNCTION ? s->u.object : 0, |
s->type == T_FUNCTION ? s->subtype : -1, |
0, |
flags, |
name); |
} |
|
void compiler_do_inherit(node *n, |
INT32 flags, |
struct pike_string *name) |
{ |
struct program *p; |
struct identifier *i; |
INT32 numid=-1, offset=0; |
|
if(!n) |
{ |
yyerror("Unable to inherit"); |
return; |
} |
|
switch(n->token) |
{ |
case F_IDENTIFIER: |
p=Pike_compiler->new_program; |
offset=0; |