|
|
|
|
|
|
|
#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 "pike_compiler.h" |
#include "module_support.h" |
|
#include <errno.h> |
#include <fcntl.h> |
|
#define sp Pike_sp |
|
#undef ATTRIBUTE |
#define ATTRIBUTE(X) |
|
static void low_enter_compiler(struct object *ce, int inherit); |
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 - sizeof (struct program); \ |
} \ |
}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; |
static struct pike_string *this_string, *this_function_string; |
static struct pike_string *UNDEFINED_string; |
|
|
struct pike_string *parser_system_string; |
struct pike_string *type_check_system_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 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,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 tRangeBound tZero tRangeBound, tVoid, tMix), |
|
tFuncV(tZero tOr(tZero, tVoid), tVoid, tMix), |
}; |
|
|
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 *null_program=0; |
|
struct program *compilation_program = 0; |
struct program *compilation_env_program = 0; |
struct object *compilation_environment = NULL; |
|
struct program *gc_internal_program = 0; |
static struct program *gc_mark_program_pos = 0; |
|
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); |
|
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_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((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(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((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; \ |
} \ |
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((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; \ |
} \ |
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((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); \ |
|