|
|
|
|
|
|
#include "global.h" |
#include "program.h" |
#include "object.h" |
#include "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 "main.h" |
#include "pike_memory.h" |
#include "gc.h" |
#include "threads.h" |
#include "constants.h" |
#include "operators.h" |
#include "builtin_functions.h" |
#include "mapping.h" |
#include "cyclic.h" |
#include "opcodes.h" |
#include "version.h" |
#include "block_allocator.h" |
#include "block_alloc.h" |
#include "pikecode.h" |
#include "pike_compiler.h" |
#include "module_support.h" |
#include "bitvector.h" |
#include "sprintf.h" |
|
#include <errno.h> |
#include <fcntl.h> |
|
static void exit_program_struct(struct program *); |
static size_t add_xstorage(size_t size, |
size_t alignment, |
ptrdiff_t modulo_orig); |
|
|
static struct mapping *reverse_symbol_table = NULL; |
|
static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4); |
|
ATTRIBUTE((malloc)) |
struct program * alloc_program(void) { |
return ba_alloc(&program_allocator); |
} |
|
void really_free_program(struct program * p) { |
exit_program_struct(p); |
ba_free(&program_allocator, p); |
} |
|
void count_memory_in_programs(size_t *num, size_t *_size) { |
size_t size; |
struct program *p; |
ba_count_all(&program_allocator, num, &size); |
for(p=first_program;p;p=p->next) { |
size+=p->total_size - sizeof (struct program); |
} |
*_size = size; |
} |
|
void free_all_program_blocks(void) { |
ba_destroy(&program_allocator); |
} |
|
|
|
|
#ifdef COMPILER_DEBUG |
#define CDFPRINTF(...) fprintf(stderr, __VA_ARGS__) |
#ifndef PIKE_THREADS |
|
static const int lock_depth = 1; |
#endif |
#else /* !COMPILER_DEBUG */ |
#define CDFPRINTF(...) |
#endif /* COMPILER_DEBUG */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define FIND_FUNCTION_HASHSIZE 16384 |
|
|
#define FIND_FUNCTION_HASH_TRESHOLD 0 |
|
|
#define DECLARE |
#include "compilation.h" |
|
struct pike_string *this_program_string, *this_string, *args_string; |
static struct pike_string *this_function_string; |
static struct pike_string *UNDEFINED_string; |
|
|
struct pike_string *parser_system_string; |
struct pike_string *type_check_system_string; |
|
struct pike_string *compat_lfun_destroy_string; |
|
|
|
|
|
|
|
const char *const lfun_names[] = { |
"__INIT", |
"create", |
"_destruct", |
"`+", |
"`-", |
"`&", |
"`|", |
"`^", |
"`<<", |
"`>>", |
"`*", |
"`/", |
"`%", |
"`~", |
"`==", |
"`<", |
"`>", |
"__hash", |
"cast", |
"`!", |
"`[]", |
"`[]=", |
"`->", |
"`->=", |
"_sizeof", |
"_indices", |
"_values", |
"`()", |
"``+", |
"``-", |
"``&", |
"``|", |
"``^", |
"``<<", |
"``>>", |
"``*", |
"``/", |
"``%", |
"`+=", |
"_is_type", |
"_sprintf", |
"_equal", |
"_m_delete", |
"_get_iterator", |
"`[..]", |
|
"_search", |
"_types", |
"_serialize", |
"_deserialize", |
"_size_object", |
"_random", |
"`**", |
"``**", |
"_sqrt", |
"_annotations", |
}; |
|
struct pike_string *lfun_strings[NELEM(lfun_names)]; |
|
static struct mapping *lfun_ids; |
|
|
static struct mapping *lfun_types; |
|
static const char *const raw_lfun_types[] = { |
tFuncV(tNone,tVoid,tVoid), |
tFuncV(tNone,tZero,tVoid), |
tFuncV(tOr(tVoid,tInt),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 tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tMix), |
tFuncV(tStr tSetvar(0,tZero) tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tVar(0)), |
tFuncV(tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tInt), |
tFuncV(tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tArray), |
tFuncV(tOr(tVoid,tObj) tOr(tVoid,tInt),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 tRangeBound tZero tRangeBound, tVoid, tMix), |
|
tFuncV(tZero tOr(tZero, tVoid), tZero, tMix), |
tFuncV(tNone,tVoid,tArray), |
tFuncV(tObj tZero, tVoid, tVoid), |
tFuncV(tObj tZero, tVoid, tVoid), |
tFuncV(tNone, tVoid, tInt), |
tFuncV(tFunction tFunction, tVoid, tMix), |
tFuncV(tOr3(tInt,tFloat,tObj),tVoid,tOr3(tObj,tInt,tFloat)), |
tFuncV(tOr3(tInt,tFloat,tObj),tVoid,tOr3(tObj,tInt,tFloat)), |
tFunc(tVoid,tMix), |
tFuncV(tNone,tVoid,tArray), |
}; |
|
|
static struct pike_type *lfun_getter_type_string = NULL; |
static struct pike_type *lfun_setter_type_string = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct program *first_program = 0; |
static int current_program_id = PROG_DYNAMIC_ID_START; |
|
struct program *gc_internal_program = 0; |
static struct program *gc_mark_program_pos = 0; |
|
#define CHECK_FILE_ENTRY(PROG, STRNO) \ |
do { \ |
if ((STRNO < 0) || (STRNO >= PROG->num_strings)) \ |
Pike_fatal ("Invalid file entry in linenumber info.\n"); \ |
} while (0) |
|
INT_TYPE get_small_number(char **q); |
|
PMOD_EXPORT void do_free_program (struct program *p) |
{ |
if (p) |
free_program(p); |
} |
|
|
|
#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_identifier_cache(ORIG,NEW) |
#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_annotations(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 |
|
#ifdef PIKE_USE_MACHINE_CODE |
|
* many OSes require us to use mmap to allocate memory for our |
* machine code. For decoding efficiency we also want a multi copy |
* variant to be used by decode(). |
*/ |
#define BAR(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 = mexec_realloc(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(low_add_many_to_,NAME) (struct program_state *state, \ |
TYPE *ARG, NUMTYPE cnt) { \ |
NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ |
CHECK_FOO(NUMTYPE,TYPE,NAME); \ |
if((m + cnt) > state->new_program->PIKE_CONCAT(num_,NAME)) { \ |
TYPE *tmp; \ |
NUMTYPE n = m; \ |
do { \ |
if(n==MAXVARS(NUMTYPE)) { \ |
yyerror("Too many " #NAME "."); \ |
return; \ |
} \ |
n = MINIMUM(n*2+1,MAXVARS(NUMTYPE)); \ |
} while (m + cnt > n); \ |
m = n; \ |
tmp = mexec_realloc(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; \ |
} \ |
memcpy(state->new_program->NAME + \ |
state->new_program->PIKE_CONCAT(num_,NAME), \ |
ARG, sizeof(TYPE) * cnt); \ |
state->new_program->PIKE_CONCAT(num_,NAME) += cnt; \ |
} \ |
void PIKE_CONCAT(add_to_,NAME) (ARGTYPE ARG) { \ |
PIKE_CONCAT(low_add_to_,NAME) ( Pike_compiler, ARG ); \ |
} |
#else /* !PIKE_USE_MACHINE_CODE */ |
#define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
void PIKE_CONCAT(low_add_many_to_,NAME) (struct program_state *state, \ |
TYPE *ARG, NUMTYPE cnt) { \ |
NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ |
CHECK_FOO(NUMTYPE,TYPE,NAME); \ |
if((m + cnt) > state->new_program->PIKE_CONCAT(num_,NAME)) { \ |
TYPE *tmp; \ |
NUMTYPE n = m; \ |
do { \ |
if(n==MAXVARS(NUMTYPE)) { \ |
yyerror("Too many " #NAME "."); \ |
return; \ |
} \ |
n = MINIMUM(n*2+1,MAXVARS(NUMTYPE)); \ |
} while (m + cnt > n); \ |
m = n; \ |
tmp = realloc(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; \ |
} \ |
memcpy(state->new_program->NAME + \ |
state->new_program->PIKE_CONCAT(num_,NAME), \ |
ARG, sizeof(TYPE) * cnt); \ |
state->new_program->PIKE_CONCAT(num_,NAME) += cnt; \ |
} |
#endif /* PIKE_USE_MACHINE_CODE */ |
|
|
|
#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(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 ); \ |
} |
|
|
|
#define PASS1ONLY(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); \ |
DO_IF_DEBUG(if (state->compiler_pass != COMPILER_PASS_FIRST) { \ |
Pike_fatal("Adding " TOSTR(NAME) " in pass %d.\n", \ |
state->compiler_pass); \ |
}); \ |
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(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]); |
} |
} |
|
|
#if 0 |
|
* before checking for duplicates in add_constant. */ |
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 %s:%d #%d.\n", |
Pike_compiler->new_program->identifiers[i].filename? |
Pike_compiler->new_program->identifiers[i].filename:"-", |
Pike_compiler->new_program->identifiers[i].linenumber, |
i); |
} |
} |
add_to_identifiers (id); |
} |
#else |
#define debug_add_to_identifiers(ARG) add_to_identifiers(ARG) |
#endif |
|
static int low_add_identifier(struct compilation *c, |
struct pike_type *type, |
struct pike_string *name, |
unsigned int identifier_flags, |
unsigned int opt_flags, |
union idptr func, |
int run_time_type) |
{ |
struct identifier dummy; |
int n = Pike_compiler->new_program->num_identifiers; |
|
copy_shared_string(dummy.name, name); |
copy_pike_type(dummy.type, type); |
dummy.filename_strno = store_prog_string(c->lex.current_file); |
dummy.linenumber = c->lex.current_line; |
dummy.identifier_flags = identifier_flags; |
dummy.run_time_type = run_time_type; |
dummy.func = func; |
dummy.opt_flags = opt_flags; |
#ifdef PROFILING |
dummy.self_time=0; |
dummy.num_calls=0; |
dummy.recur_depth=0; |
dummy.total_time=0; |
#endif |
debug_add_to_identifiers(dummy); |
|
if (Pike_compiler->current_annotations) { |
|
compiler_add_annotations(n, Pike_compiler->current_annotations); |
|
free_node(Pike_compiler->current_annotations); |
Pike_compiler->current_annotations = NULL; |
} |
|
return n; |
} |
|
static int add_identifier(struct compilation *c, |
struct pike_type *type, |
struct pike_string *name, |
unsigned int modifier_flags, |
unsigned int identifier_flags, |
unsigned int opt_flags, |
union idptr func, |
int run_time_type) |
{ |
struct reference ref; |
struct identifier dummy; |
int n; |
|
if (modifier_flags & ID_PRIVATE) modifier_flags |= ID_LOCAL|ID_PROTECTED; |
|
if (((identifier_flags & (IDENTIFIER_VARIABLE|IDENTIFIER_ALIAS)) == |
IDENTIFIER_VARIABLE) && |
(modifier_flags & ID_WEAK)) { |
identifier_flags |= IDENTIFIER_WEAK; |
} |
|
ref.id_flags = modifier_flags; |
ref.identifier_offset = |
low_add_identifier(c, type, name, |
identifier_flags, opt_flags, |
func, run_time_type); |
ref.inherit_offset = 0; |
ref.run_time_type = PIKE_T_UNKNOWN; |
|
if ((identifier_flags & (IDENTIFIER_VARIABLE|IDENTIFIER_ALIAS)) == |
IDENTIFIER_VARIABLE) { |
add_to_variable_index(ref.identifier_offset); |
} |
|
n = Pike_compiler->new_program->num_identifier_references; |
add_to_identifier_references(ref); |
|
return n; |
} |
|
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) |
{ |
struct compilation *c = THIS_COMPILATION; |
if( (1<<TYPEOF(*s)) & (BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM)) |
{ |
c->num_used_modules++; |
Pike_compiler->num_used_modules++; |
assign_svalue_no_free((struct svalue *) |
buffer_alloc(&c->used_modules, sizeof(struct svalue)), s); |
if(Pike_compiler->module_index_cache) |
{ |
free_mapping(Pike_compiler->module_index_cache); |
Pike_compiler->module_index_cache=0; |
} |
if(c->resolve_cache) |
{ |
free_mapping(c->resolve_cache); |
c->resolve_cache=0; |
} |
}else{ |
yyerror("Module is neither mapping nor object"); |
} |
} |
|
void unuse_modules(INT32 howmany) |
{ |
struct compilation *c = THIS_COMPILATION; |
struct svalue *s = buffer_dst(&c->used_modules); |
if(!howmany) return; |
s -= howmany; |
#ifdef PIKE_DEBUG |
if(howmany *sizeof(struct svalue) > buffer_content_length(&c->used_modules)) |
Pike_fatal("Unusing too many modules.\n"); |
#endif |
c->num_used_modules -= howmany; |
Pike_compiler->num_used_modules-=howmany; |
free_svalues(s, howmany, BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM); |
buffer_remove(&c->used_modules, howmany*sizeof(struct svalue)); |
#ifdef PIKE_DEBUG |
if (s != buffer_dst(&c->used_modules)) |
Pike_fatal("buffer_remove is broken.\n"); |
#endif |
if(Pike_compiler->module_index_cache) |
{ |
free_mapping(Pike_compiler->module_index_cache); |
Pike_compiler->module_index_cache=0; |
} |
} |
|
static struct node_s *index_modules(struct pike_string *ident, |
struct mapping **module_index_cache, |
const 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) && SUBTYPEOF(*tmp)==1)) |
return mksvaluenode(tmp); |
return 0; |
} |
} |
|
|
|
{ |
JMP_BUF tmp; |
|
if(SETJMP(tmp)) |
handle_compile_exception ("Couldn't index a module with %S.", ident); |
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 == COMPILER_PASS_LAST && |
((TYPEOF(Pike_sp[-1]) == T_OBJECT && |
Pike_sp[-1].u.object == placeholder_object) || |
(TYPEOF(Pike_sp[-1]) == 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 (TYPEOF(Pike_sp[-1])), 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 compilation *c = THIS_COMPILATION; |
struct node_s *ret; |
|
struct svalue *modules=(struct svalue *)buffer_dst(&c->used_modules); |
|
{ |
struct program_state *p=Pike_compiler; |
int n; |
for(n=0;n<=c->compilation_depth;n++,p=p->previous) |
{ |
int i; |
if(see_inherit) |
{ |
i=really_low_find_shared_string_identifier(ident, |
p->new_program, |
SEE_PROTECTED|SEE_PRIVATE); |
if(i!=-1) |
{ |
if ((p->flags & COMPILATION_FORCE_RESOLVE) && |
(p->compiler_pass == COMPILER_PASS_LAST) && |
((p->num_inherits + 1) < p->new_program->num_inherits) && |
(PTR_FROM_INT(p->new_program, i)->inherit_offset > |
p->num_inherits)) { |
|
|
|
continue; |
} |
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 ) < (char*)buffer_ptr(&c->used_modules)) |
Pike_fatal("Modules out of whack!\n"); |
#endif |
} |
} |
|
return resolve_identifier(ident); |
} |
|
|
struct node_s *find_predef_identifier(struct pike_string *ident) |
{ |
struct compilation *c = THIS_COMPILATION; |
node *tmp = mkconstantsvaluenode(&c->default_module); |
node *ret = index_node(tmp, "predef", ident); |
if(ret && !ret->name) |
add_ref(ret->name = ident); |
free_node(tmp); |
return ret; |
} |
|
|
|
|
|
|
int low_resolve_identifier(struct pike_string *ident) |
{ |
struct compilation *c = THIS_COMPILATION; |
node *ret = NULL; |
|
|
if (ident == UNDEFINED_string) { |
push_undefined(); |
return 1; |
} |
|
if(c->resolve_cache) |
{ |
struct svalue *tmp=low_mapping_string_lookup(c->resolve_cache,ident); |
if(tmp) |
{ |
if(IS_UNDEFINED (tmp)) { |
return 0; |
} |
|
push_svalue(tmp); |
return 1; |
} |
} |
|
CHECK_COMPILER(); |
|
ref_push_string(ident); |
if (!safe_apply_current2(PC_RESOLV_FUN_NUM, 1, NULL)) |
handle_compile_exception ("Error resolving '%S'.", ident); |
|
if (Pike_compiler->compiler_pass != COMPILER_PASS_LAST) { |
|
|
|
|
struct program *p = NULL; |
if (TYPEOF(Pike_sp[-1]) == T_PROGRAM) |
p = Pike_sp[-1].u.program; |
else if (TYPEOF(Pike_sp[-1]) == T_OBJECT || |
(TYPEOF(Pike_sp[-1]) == T_FUNCTION && |
SUBTYPEOF(Pike_sp[-1]) != FUNCTION_BUILTIN)) |
p = Pike_sp[-1].u.object->prog; |
if (p && !(p->flags & PROGRAM_PASS_1_DONE)) |
report_compiler_dependency (p); |
} |
|
if (Pike_compiler->compiler_pass == COMPILER_PASS_LAST && |
((TYPEOF(Pike_sp[-1]) == T_OBJECT && |
|