2008-04-14
2008-04-14 10:14:41 by Henrik Grubbström (Grubba) <grubba@grubba.org>
-
e021fe12b6e37a84a53c1b5c72150b62422307b8
(806 lines)
(+644/-162)
[
Show
| Annotate
]
Branch: 7.9
Pike compiler mega patch.
Added predef::CompilerEnvironment, which is a wrapper for struct compilation.
Moved the definition of struct compilation to the new header file "pike_compiler.h".
The compilation struct is now contained in the current context in the current_object during compilation.
The global variable lex is no more, it has moved into the compilation struct.
Added enter_compiler() and exit_compiler().
predef::compile() is now shorthand for predef::CompilerContext()->compile().
Rev: src/builtin_functions.c:1.652
Rev: src/compilation.h:1.35
Rev: src/docode.c:1.197
Rev: src/docode.h:1.20
Rev: src/dynamic_load.c:1.90
Rev: src/encode.c:1.263
Rev: src/language.yacc:1.411
Rev: src/las.c:1.406
Rev: src/lex.c:1.121
Rev: src/lex.h:1.36
Rev: src/lexer.h:1.66
Rev: src/module.c:1.52
Rev: src/object.c:1.284
Rev: src/operators.c:1.230
Rev: src/pike_compiler.h:1.1
Rev: src/pike_types.c:1.321
Rev: src/program.c:1.660
Rev: src/program.h:1.237
2:
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
- || $Id: program.c,v 1.659 2008/04/07 01:45:53 mbaehr Exp $
+ || $Id: program.c,v 1.660 2008/04/14 10:14:41 grubba Exp $
*/
#include "global.h"
35:
#include "version.h"
#include "block_alloc.h"
#include "pikecode.h"
+ #include "pike_compiler.h"
#include <errno.h>
#include <fcntl.h>
44:
#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,
1218:
struct program *compilation_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;
1616:
if(get_master())
{
+ struct compilation *c = THIS_COMPILATION;
DECLARE_CYCLIC();
node *ret=0;
- if(BEGIN_CYCLIC(ident, lex.current_file))
+ if(BEGIN_CYCLIC(ident, c->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);
+ ref_push_string(c->lex.current_file);
+ if (c->handler) {
+ ref_push_object(c->handler);
} else {
push_int(0);
}
- if (safe_apply_handler("resolv", error_handler, compat_handler, 3, 0)) {
+ if (safe_apply_handler("resolv", c->handler, c->compat_handler, 3, 0)) {
if (Pike_compiler->compiler_pass == 2 &&
((Pike_sp[-1].type == T_OBJECT &&
Pike_sp[-1].u.object == placeholder_object) ||
1977:
int override_identifier (struct reference *new_ref, struct pike_string *name)
{
+ struct compilation *c = THIS_COMPILATION;
int id = -1, cur_id = 0, is_used = 0;
int new_is_variable =
1989:
* /Hubbe
*/
+ CHECK_COMPILER();
+
for(;cur_id<Pike_compiler->new_program->num_identifier_references;cur_id++)
{
struct reference *ref =
2040:
sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level);
/* Check if the symbol was used before it was inherited. */
- if ((lex.pragmas & ID_STRICT_TYPES) &&
+ if ((c->lex.pragmas & ID_STRICT_TYPES) &&
(sub_ref->id_flags & ID_USED)) {
struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref);
if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {
2085:
void fixate_program(void)
{
+ struct compilation *c = THIS_COMPILATION;
INT32 i,e,t;
struct program *p=Pike_compiler->new_program;
-
+ CHECK_COMPILER();
+
if(p->flags & PROGRAM_FIXED) return;
#ifdef PIKE_DEBUG
if(p->flags & PROGRAM_OPTIMIZED)
2161:
if(funa_is_prototype && (funb->func.offset != -1) &&
!(funp->id_flags & ID_INLINE))
{
- if ((lex.pragmas & ID_STRICT_TYPES) &&
+ if ((c->lex.pragmas & ID_STRICT_TYPES) &&
(funp->id_flags & ID_USED)) {
/* Verify that the types are compatible. */
if (!pike_types_le(funb->type, fun->type)) {
2175:
}
if(!funa_is_prototype && funb->func.offset == -1)
{
- if ((lex.pragmas & ID_STRICT_TYPES) &&
+ if ((c->lex.pragmas & ID_STRICT_TYPES) &&
(funpb->id_flags & ID_USED)) {
/* Verify that the types are compatible. */
if (!pike_types_le(fun->type, funb->type)) {
2267:
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,"-"))
+ if(c->lex.current_file &&
+ c->lex.current_file->str &&
+ c->lex.current_file->len &&
+ !strcmp(c->lex.current_file->str,"-"))
{
- m=dmalloc_alloc_mmap( DBSTR(lex.current_file), lex.current_line);
+ m=dmalloc_alloc_mmap( DBSTR(c->lex.current_file), c->lex.current_line);
}
else if( (tmp=find_program_name(Pike_compiler->new_program, &line)) )
{
2353:
int flags,
int *idp)
{
+ struct compilation *c = THIS_COMPILATION;
int id=0;
struct svalue tmp;
-
+ CHECK_COMPILER();
+
#ifdef WITH_FACETS
if(Pike_compiler->compiler_pass == 1 && p) {
p->facet_class = 0;
2387: Inside #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 : "-",
+ c->lex.current_file ? c->lex.current_file->str : "-",
compilation_depth);
#endif
}
2499:
#endif
if (compilation_depth >= 1) {
- if(TEST_COMPAT(7,2) || (lex.pragmas & ID_SAVE_PARENT))
+ if(TEST_COMPAT(7,2) || (c->lex.pragmas & ID_SAVE_PARENT))
{
p->flags |= PROGRAM_USES_PARENT;
- }else if (!(lex.pragmas & ID_DONT_SAVE_PARENT)) {
+ }else if (!(c->lex.pragmas & ID_DONT_SAVE_PARENT)) {
struct pike_string *tmp=findstring("__pragma_save_parent__");
if(tmp)
{
2613:
PMOD_EXPORT void debug_start_new_program(int line, const char *file)
{
- struct pike_string *save_file =
- dmalloc_touch(struct pike_string *, lex.current_file);
- int save_line = lex.current_line;
+ struct pike_string *save_file;
+ int save_line;
+ struct compilation *c;
-
+ CHECK_COMPILER();
+ c = THIS_COMPILATION;
+
+ save_file = dmalloc_touch(struct pike_string *, c->lex.current_file);
+ save_line = c->lex.current_line;
+
{ /* Trim off the leading path of the compilation environment. */
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;
+ c->lex.current_file = make_shared_string(f);
+ c->lex.current_line = line;
}
CDFPRINTF((stderr,
2632:
(long)th_self(), line, file, threads_disabled, compilation_depth));
low_start_new_program(0,1,0,0,0);
- store_linenumber(line,lex.current_file);
+ store_linenumber(line,c->lex.current_file);
debug_malloc_name(Pike_compiler->new_program, file, line);
- free_string(lex.current_file);
- lex.current_file = dmalloc_touch(struct pike_string *, save_file);
- lex.current_line = save_line;
+ free_string(c->lex.current_file);
+ c->lex.current_file = dmalloc_touch(struct pike_string *, save_file);
+ c->lex.current_line = save_line;
}
3045:
}
fprintf(stderr, "\n"
+ "%*sLFUN table:\n"
+ "%*s LFUN Ref# Name\n",
+ indent, "", indent, "");
+ for (d = 0; d < NUM_LFUNS; d++) {
+ if (p->lfuns[d] != -1) {
+ fprintf(stderr, "%*s %4d: %04d %s\n",
+ indent, "", d, p->lfuns[d], lfun_names[d]);
+ }
+ }
+
+ fprintf(stderr, "\n"
"%*sLinenumber table:\n",
indent, "");
{
4445:
int call_handle_inherit(struct pike_string *s)
{
+ struct compilation *c = THIS_COMPILATION;
int args;
-
+ CHECK_COMPILER();
+
reference_shared_string(s);
push_string(s);
if (!TEST_COMPAT(7,6)) {
4455:
*/
f_string_to_utf8(1);
}
- ref_push_string(lex.current_file);
- if (error_handler && error_handler->prog) {
- ref_push_object(error_handler);
+ ref_push_string(c->lex.current_file);
+ if (c->handler && c->handler->prog) {
+ ref_push_object(c->handler);
args = 3;
}
else args = 2;
- if (safe_apply_handler("handle_inherit", error_handler, compat_handler,
+ if (safe_apply_handler("handle_inherit", c->handler, c->compat_handler,
args, BIT_PROGRAM|BIT_FUNCTION|BIT_ZERO))
if (Pike_sp[-1].type != T_INT)
return 1;
5314:
union idptr *func,
unsigned opt_flags)
{
+ struct compilation *c = THIS_COMPILATION;
struct identifier *funp,fun;
struct reference ref;
struct svalue *lfun_type;
5321:
INT32 i;
INT32 getter_setter_offset = -1;
+ CHECK_COMPILER();
+
#ifdef PROGRAM_BUILD_DEBUG
{
struct pike_string *d = describe_type (type);
5351:
my_yyerror("Type mismatch for callback function %S:", name);
yytype_error(NULL, lfun_type->u.type, type, 0);
Pike_fatal("Type mismatch!\n");
- } else if (lex.pragmas & ID_STRICT_TYPES) {
+ } else if (c->lex.pragmas & ID_STRICT_TYPES) {
yywarning("Type mismatch for callback function %S:", name);
yytype_error(NULL, lfun_type->u.type, type,
YYTE_IS_WARNING);
5396:
if (!match_types(type, gs_type)) {
my_yyerror("Type mismatch for callback function %S:", name);
yytype_error(NULL, gs_type, type, 0);
- } else if (lex.pragmas & ID_STRICT_TYPES) {
+ } else if (c->lex.pragmas & ID_STRICT_TYPES) {
yywarning("Type mismatch for callback function %S:", name);
yytype_error(NULL, gs_type, type, YYTE_IS_WARNING);
}
6791:
void handle_compile_exception (const char *yyerror_fmt, ...)
{
struct svalue thrown;
+ struct compilation *c = THIS_COMPILATION;
+
+ CHECK_COMPILER();
+
move_svalue (&thrown, &throw_value);
mark_free_svalue (&throw_value);
6802:
}
push_svalue(&thrown);
- low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+ low_safe_apply_handler("compile_exception", c->handler, c->compat_handler, 1);
if (SAFE_IS_ZERO(sp-1)) {
struct pike_string *s = format_exception_for_error_msg (&thrown);
6960:
supporter_callback *fun,
void *data)
{
+ CDFPRINTF((stderr, "th(%ld) init_supporter() supporter=%p data=%p.\n",
+ (long) th_self(), s, data));
verify_supporters();
#ifdef PIKE_DEBUG
s->magic = 0x500b0127;
6995:
ret++;
c->next_dependant = c->depends_on->dependants;
c->depends_on->dependants=c;
+ add_ref(c->self);
+ CDFPRINTF((stderr, "th(%ld) unlink_current_supporter() supporter=%p depends on %p.\n",
+ (long) th_self(), c, c->depends_on));
}
current_supporter=c->previous;
verify_supporters();
7017:
{
int ok = 1;
struct Supporter *tmp;
+ CDFPRINTF((stderr, "th(%ld) call_dependants() supporter=%p finish=%d.\n",
+ (long) th_self(), s, finish));
verify_supporters();
while((tmp=s->dependants))
{
-
+ CDFPRINTF((stderr, "th(%ld) dependant: %p (data:%p).\n",
+ (long) th_self(), tmp, tmp->data));
s->dependants=tmp->next_dependant;
#ifdef PIKE_DEBUG
tmp->next_dependant=0;
7027:
verify_supporters();
if (!tmp->fun(tmp->data, finish)) ok = 0;
verify_supporters();
+ free_object(tmp->self);
}
return ok;
}
7040:
/* Depends on self... */
return 0;
}
+
+ CDFPRINTF((stderr, "th(%ld) %p depends on %p\n",
+ (long)th_self(), Pike_compiler->new_program, p));
+
verify_supporters();
if (Pike_compiler->flags & COMPILATION_FORCE_RESOLVE)
return 0;
7066:
}
- /*! @class PikeCompiler
+ /*! @class CompilerEnviroment
*!
- *! The Pike compiler.
+ *! The compiler environment.
*/
- struct compilation
- {
- struct Supporter supporter;
- struct pike_string *prog;
- struct object *handler;
- int major, minor;
- struct program *target;
- struct object *placeholder;
-
- struct program *p;
- struct lex save_lex;
- int save_depth;
- int saved_threads_disabled;
- struct object *saved_handler;
- struct object *saved_compat_handler;
- dynamic_buffer used_modules_save;
- INT32 num_used_modules_save;
- struct mapping *resolve_cache_save;
-
- struct svalue default_module;
- };
-
+
static void free_compilation(struct compilation *c)
{
debug_malloc_touch(c);
- free_string(c->prog);
+ if (c->prog) free_string(c->prog);
if(c->handler) free_object(c->handler);
-
+ if(c->compat_handler) free_object(c->compat_handler);
if(c->target) free_program(c->target);
if(c->placeholder) free_object(c->placeholder);
-
+ if(c->lex.current_file) free_string(c->lex.current_file);
free_svalue(& c->default_module);
free_supporter(&c->supporter);
verify_supporters();
7111:
c->save_depth=compilation_depth;
compilation_depth=-1;
- c->saved_handler = error_handler;
- if((error_handler = c->handler))
- add_ref(error_handler);
+ if (c->compat_handler) free_object(c->compat_handler);
+ c->compat_handler=0;
- c->saved_compat_handler = compat_handler;
- compat_handler=0;
-
+
c->used_modules_save = used_modules;
c->num_used_modules_save = Pike_compiler->num_used_modules;
Pike_compiler->num_used_modules=0;
7125:
c->resolve_cache_save = resolve_cache;
resolve_cache = 0;
- c->save_lex=lex;
+ c->lex.current_line=1;
+ free_string(c->lex.current_file);
+ c->lex.current_file=make_shared_string("-");
- lex.current_line=1;
- lex.current_file=make_shared_string("-");
-
+
if (runtime_options & RUNTIME_STRICT_TYPES)
{
- lex.pragmas = ID_STRICT_TYPES;
+ c->lex.pragmas = ID_STRICT_TYPES;
} else {
- lex.pragmas = 0;
+ c->lex.pragmas = 0;
}
- lex.end = c->prog->str + (c->prog->len << c->prog->size_shift);
+ c->lex.end = c->prog->str + (c->prog->len << c->prog->size_shift);
switch(c->prog->size_shift)
{
- case 0: lex.current_lexer = yylex0; break;
- case 1: lex.current_lexer = yylex1; break;
- case 2: lex.current_lexer = yylex2; break;
+ case 0: c->lex.current_lexer = yylex0; break;
+ case 1: c->lex.current_lexer = yylex1; break;
+ case 2: c->lex.current_lexer = yylex2; break;
default:
Pike_fatal("Program has bad shift %d!\n", c->prog->size_shift);
break;
}
- lex.pos=c->prog->str;
+ c->lex.pos=c->prog->str;
}
static void run_init2(struct compilation *c)
7191:
free_mapping(resolve_cache);
resolve_cache = c->resolve_cache_save;
- if (error_handler) free_object(error_handler);
- error_handler = c->saved_handler;
-
- if (compat_handler) free_object(compat_handler);
- compat_handler = c->saved_compat_handler;
-
- free_string(lex.current_file);
- lex=c->save_lex;
+
verify_supporters();
}
7286:
if (!Pike_compiler->new_program->num_linenumbers) {
/* The lexer didn't write an initial entry. */
- store_linenumber(0, lex.current_file);
+ store_linenumber(0, c->lex.current_file);
#ifdef DEBUG_MALLOC
- if(strcmp(lex.current_file->str,"-"))
- debug_malloc_name(Pike_compiler->new_program, lex.current_file->str, 0);
+ if(strcmp(c->lex.current_file->str,"-"))
+ debug_malloc_name(Pike_compiler->new_program, c->lex.current_file->str, 0);
#endif
}
CDFPRINTF((stderr, "th(%ld) %p run_pass1() done for %s\n",
- (long)th_self(), Pike_compiler->new_program, lex.current_file->str));
+ (long)th_self(), Pike_compiler->new_program,
+ c->lex.current_file->str));
ret=unlink_current_supporter(& c->supporter);
7343:
(long)th_self(), Pike_compiler->new_program,
threads_disabled, compilation_depth));
+ CDFPRINTF((stderr,
+ "th(%ld) %p:\n"
+ "%s\n"
+ "---\n"
+ "%s\n", (long)th_self(), Pike_compiler->new_program,
+ c->prog->str, c->lex.pos));
+
verify_supporters();
do_yyparse(); /* Parse da program */
CDFPRINTF((stderr, "th(%ld) %p run_pass2() done for %s\n",
- (long)th_self(), Pike_compiler->new_program, lex.current_file->str));
+ (long)th_self(), Pike_compiler->new_program,
+ c->lex.current_file->str));
verify_supporters();
7458:
int ok = 0;
debug_malloc_touch(cc);
+ debug_malloc_touch(cc->p);
+
CDFPRINTF((stderr, "th(%ld) %p %s delayed compile.\n",
(long) th_self(), cc->p, finish ? "continuing" : "cleaning up"));
-
+ /* Reenter the delayed compilation. */
+ add_ref(cc->supporter.self);
+ low_enter_compiler(cc->supporter.self, cc->compilation_inherit);
+
if(finish && cc->p) run_pass2(cc);
run_cleanup(cc,1);
-
+ exit_compiler();
+
debug_malloc_touch(cc);
#ifdef PIKE_DEBUG
7478:
CDFPRINTF((stderr, "th(%ld) %p delayed compile %s.\n",
(long) th_self(), cc->target, ok ? "done" : "failed"));
- free_compilation(cc);
- free(cc);
+
verify_supporters();
return ok;
}
- #define THIS_COMPILATION ((struct compilation *)(Pike_fp->current_storage))
-
+
static void compilation_event_handler(int e)
{
struct compilation *c = THIS_COMPILATION;
-
+
switch (e) {
case PROG_EVENT_INIT:
-
+ CDFPRINTF((stderr, "th(%ld) compilation: INIT(%p).\n",
+ (long) th_self(), c));
+ MEMSET(c, 0, sizeof(*c));
+ c->supporter.self = Pike_fp->current_object; /* NOTE: Not ref-counted! */
+ c->compilation_inherit =
+ Pike_fp->context - Pike_fp->current_object->prog->inherits;
c->default_module.type = T_INT;
c->default_module.subtype = NUMBER_NUMBER;
-
+ c->lex.current_line = 1;
+ c->lex.current_file = make_shared_string("-");
break;
case PROG_EVENT_EXIT:
-
+ CDFPRINTF((stderr, "th(%ld) compilation: EXIT(%p).\n",
+ (long) th_self(), c));
free_compilation(c);
break;
}
}
- /*! @decl void compile(string code)
- *!
- *! Compile a segment of Pike code.
- */
- static void f_compilation_compile(INT32 args)
- {
- pop_n_elems(args);
- push_int(0);
- }
-
+
/*! @decl void report(SeverityLevel severity, @
- *! string filename, int linenumber, @
- *! string subsystem, @
- *! string message, mixed ... extra_args)
+ *! string filename, int linenumber, @
+ *! string subsystem, @
+ *! string message, mixed ... extra_args)
*!
*! Report a diagnostic from the compiler.
*/
static void f_compilation_report(INT32 args)
{
-
+ struct compilation *c = THIS_COMPILATION;
int level;
struct pike_string *filename;
INT_TYPE linenumber;
7529:
f_sprintf(args - 4);
args = 5;
}
- get_all_args("report", args, "%d%S%i%S%S",
+ get_all_args("report", args, "%d%W%i%W%W",
&level, &filename, &linenumber, &subsystem, &message);
- fprintf(stderr, "%s:%ld: %s\n", filename->str, linenumber, message->str);
+
+ /* Ignore informational level messages */
+ if (level) {
+ if ((c->handler && c->handler->prog) ||
+ (c->compat_handler && c->compat_handler->prog) ||
+ get_master()) {
+ ref_push_string(filename);
+ push_int(linenumber);
+ ref_push_string(message);
+ if (level >= 2) {
+ low_safe_apply_handler("compile_error",
+ c->handler, c->compat_handler, 3);
+ args++;
+ } else {
+ low_safe_apply_handler("compile_warning",
+ c->handler, c->compat_handler, 3);
+ args++;
+ }
+ } else {
+ if (level >= 2) {
+ fprintf(stderr, "%s:%ld: %s\n",
+ filename->str, linenumber, message->str);
+ } else {
+ fprintf(stderr, "%s:%ld: Warning: %s\n",
+ filename->str, linenumber, message->str);
+ }
+ fflush(stderr);
+ }
+ }
pop_n_elems(args);
push_int(0);
}
-
+ /*! @decl program compile(string source, CompilationHandler|void handler, @
+ *! int|void major, int|void minor,@
+ *! program|void target, object|void placeholder)
+ *!
+ *! Compile a string to a program.
+ *!
+ *! This function takes a piece of Pike code as a string and
+ *! compiles it into a clonable program.
+ *!
+ *! The optional argument @[handler] is used to specify an alternative
+ *! error handler. If it is not specified the current master object will
+ *! be used.
+ *!
+ *! The optional arguments @[major] and @[minor] are used to tell the
+ *! compiler to attempt to be compatible with Pike @[major].@[minor].
+ *!
+ *! @note
+ *! Note that @[source] must contain the complete source for a program.
+ *! It is not possible to compile a single expression or statement.
+ *!
+ *! Also note that @[compile()] does not preprocess the program.
+ *! To preprocess the program you can use @[compile_string()] or
+ *! call the preprocessor manually by calling @[cpp()].
+ *!
+ *! @seealso
+ *! @[compile_string()], @[compile_file()], @[cpp()], @[master()],
+ *! @[CompilationHandler]
+ */
+ static void f_compilation_compile(INT32 args)
+ {
+ struct pike_string *aprog;
+ struct object *ahandler = NULL;/* error handler */
+ int amajor = -1;
+ int aminor = -1;
+ struct program *atarget = NULL;
+ struct object *aplaceholder = NULL;
+ int delay, dependants_ok = 1;
+ struct program *ret;
+ #ifdef PIKE_DEBUG
+ ONERROR tmp;
+ #endif
+ struct compilation *c = THIS_COMPILATION;
+
+ if (c->target) {
+ Pike_error("CompilationEnvironment in use.\n");
+ }
+
+ STACK_LEVEL_START(args);
+
+ get_all_args("compile", args, "%W.%O%d%d%P%O",
+ &aprog, &ahandler,
+ &amajor, &aminor,
+ &atarget, &aplaceholder);
+
+ if (args == 3) {
+ SIMPLE_BAD_ARG_ERROR("compile", 4, "int");
+ }
+
+ check_c_stack(65536);
+
+ CDFPRINTF((stderr, "th(%ld) %p compile() enter, placeholder=%p\n",
+ (long) th_self(), atarget, aplaceholder));
+
+ debug_malloc_touch(c);
+
+ verify_supporters();
+
+ if (c->p) free_program(c->p);
+ c->p = NULL;
+ if (c->prog) free_string(c->prog);
+ add_ref(c->prog=aprog);
+ if (ahandler) {
+ if (c->handler) free_object(c->handler);
+ add_ref(c->handler = ahandler);
+ }
+ c->major=amajor;
+ c->minor=aminor;
+
+ if((c->target=atarget)) add_ref(atarget);
+ else c->target = low_allocate_program();
+
+ if (c->placeholder) free_object(c->placeholder);
+ if ((c->placeholder=aplaceholder)) add_ref(aplaceholder);
+
+ if (c->handler)
+ {
+ if (safe_apply_handler ("get_default_module", c->handler, NULL,
+ 0, BIT_MAPPING|BIT_OBJECT|BIT_ZERO)) {
+ if(SAFE_IS_ZERO(Pike_sp-1))
+ {
+ pop_stack();
+ ref_push_mapping(get_builtin_constants());
+ }
+ } else {
+ ref_push_mapping(get_builtin_constants());
+ }
+ }else{
+ ref_push_mapping(get_builtin_constants());
+ }
+ free_svalue(& c->default_module);
+ c->default_module=Pike_sp[-1];
+ dmalloc_touch_svalue(Pike_sp-1);
+ Pike_sp--;
+
+ #ifdef PIKE_DEBUG
+ SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");
+ #endif
+
+ low_init_threads_disable();
+ c->saved_threads_disabled = threads_disabled;
+
+ init_supporter(& c->supporter,
+ (supporter_callback *) call_delayed_pass2,
+ (void *)c);
+
+ delay=run_pass1(c) && c->p;
+ dependants_ok = call_dependants(& c->supporter, !!c->p );
+ #ifdef PIKE_DEBUG
+ /* FIXME */
+ UNSET_ONERROR(tmp);
+ #endif
+
+ if(delay)
+ {
+ CDFPRINTF((stderr, "th(%ld) %p compile() finish later, placeholder=%p.\n",
+ (long) th_self(), c->target, c->placeholder));
+ /* finish later */
+ add_ref(c->p);
+ verify_supporters();
+ /* We're hanging in the supporter. */
+ ret = c->p;
+ }else{
+ /* finish now */
+ if(c->p) run_pass2(c);
+ debug_malloc_touch(c);
+ run_cleanup(c,0);
+
+ ret=c->p;
+ c->p = NULL;
+
+ debug_malloc_touch(c);
+
+ if (!dependants_ok) {
+ CDFPRINTF((stderr, "th(%ld) %p compile() reporting failure "
+ "since a dependant failed.\n",
+ (long) th_self(), c->target));
+ if (ret) free_program(ret);
+ throw_error_object(low_clone(compilation_error_program), 0, 0, 0,
+ "Compilation failed.\n");
+ }
+ if(!ret) {
+ CDFPRINTF((stderr, "th(%ld) %p compile() failed.\n",
+ (long) th_self(), c->target));
+ throw_error_object(low_clone(compilation_error_program), 0, 0, 0,
+ "Compilation failed.\n");
+ }
+ debug_malloc_touch(ret);
+ #ifdef PIKE_DEBUG
+ if (a_flag > 2) {
+ dump_program_tables(ret, 0);
+ }
+ #endif /* PIKE_DEBUG */
+ verify_supporters();
+ }
+ STACK_LEVEL_DONE(args);
+ pop_n_elems(args);
+ if (ret)
+ push_program(ret);
+ else
+ push_int(0);
+ }
+
+ /* Fake being called via CompilationEnvironment()->compile()
+ *
+ * This function is used to set up the environment for
+ * compiling C efuns and modules.
+ *
+ * Note: Since this is a stack frame, it will be cleaned up
+ * automatically on error, so no need to use ONERROR().
+ *
+ * Note: Steals a reference from ce.
+ */
+ static void low_enter_compiler(struct object *ce, int inherit)
+ {
+ struct pike_frame *new_frame = alloc_pike_frame();
+ #ifdef PROFILING
+ new_frame->children_base = Pike_interpreter.accounted_time;
+ new_frame->start_time = get_cpu_time() - Pike_interpreter.unlocked_time;
+ new_frame->ident = CE_COMPILE_FUN_NUM; /* Fake call of compile(). */
+ #endif /* PROFILING */
+ new_frame->next = Pike_fp;
+ new_frame->current_object = ce;
+ /* Note: The compilation environment object hangs on this frame,
+ * so that it will be freed when the frame dies.
+ */
+ new_frame->current_program = ce->prog;
+ add_ref(new_frame->current_program);
+ new_frame->context = compilation_program->inherits + inherit;
+ new_frame->current_storage = ce->storage + new_frame->context->storage_offset;
+ #ifdef PIKE_DEBUG
+ if (new_frame->context->prog != compilation_program) {
+ Pike_fatal("Invalid inherit for compilation context (%p != %p).\n",
+ new_frame->context->prog, compilation_program);
+ }
+ #endif /* PIKE_DEBUG */
+ new_frame->fun = new_frame->context->identifier_level + CE_COMPILE_FUN_NUM;
+ new_frame->expendible = Pike_sp;
+ new_frame->locals = Pike_sp;
+ new_frame->save_sp = Pike_sp;
+ new_frame->save_mark_sp = Pike_mark_sp;
+ new_frame->mark_sp_base = Pike_mark_sp;
+ new_frame->args = 0;
+ new_frame->num_locals = 0;
+ new_frame->pc = 0;
+ new_frame->return_addr = 0;
+ new_frame->scope = 0;
+ new_frame->save_sp = Pike_sp;
+ Pike_fp = new_frame;
+ }
+
+ void enter_compiler(struct pike_string *filename, int linenumber)
+ {
+ struct object *ce = clone_object(compilation_program, 0);
+ struct compilation *c;
+
+ low_enter_compiler(ce, 0);
+
+ c = THIS_COMPILATION;
+ if (filename) {
+ free_string(c->lex.current_file);
+ copy_shared_string(c->lex.current_file, filename);
+ }
+ if (linenumber) {
+ c->lex.current_line = linenumber;
+ }
+ }
+
+ /* Reverse the effect of enter_compiler().
+ */
+ void exit_compiler(void)
+ {
+ #ifdef PIKE_DEBUG
+ if ((Pike_fp->current_program != compilation_program) ||
+ (Pike_fp->fun != 2)) {
+ Pike_fatal("exit_compiler(): Frame stack out of whack!\n");
+ }
+ #endif /* PIKE_DEBUG */
+ POP_PIKE_FRAME();
+ }
+
+ /*! @class PikeCompiler
+ *!
+ *! The Pike compiler.
+ */
+
+ /*! @decl void report(SeverityLevel severity, @
+ *! string filename, int linenumber, @
+ *! string subsystem, @
+ *! string message, mixed ... extra_args)
+ *!
+ *! Report a diagnostic from the compiler.
+ *!
+ *! The default implementation calls @[CompilerEnvironment::report()]
+ *! with the same arguments.
+ */
+
+ #define THIS_PROGRAM_STATE ((struct program_state *)(Pike_fp->current_storage))
+
+ static void program_state_event_handler(int event)
+ {
+ #if 0
+ struct program_state *c = THIS_PROGRAM_STATE;
+ switch (event) {
+ case PROG_EVENT_INIT:
+ #define INIT
+ #include "compilation.h"
+ break;
+ case PROG_EVENT_EXIT:
+ #define EXIT
+ #include "compilation.h"
+ break;
+ }
+ #endif /* 0 */
+
+ fprintf(stderr, "program_state_event_handler(%d) obj:%p prog:%p\n",
+ event, Pike_fp->current_object, Pike_fp->current_program);
+ }
+
+ /*! @endclass
+ */
+
+ /*! @endclass
+ */
+
/* Strap the compiler by creating the compilation program by hand. */
static void compile_compiler(void)
{
- struct program *p = compilation_program = low_allocate_program();
- struct reference *ref;
- struct identifier *i;
- struct inherit *inh;
- unsigned INT16 *ix;
+ struct program *p = compilation_program = low_allocate_program(), *p2;
+ struct program_constant *pc;
+ struct reference *ref, *ref2;
+ struct identifier *i, *i2;
+ struct inherit *inh, *inh2;
+ unsigned INT16 *ix, *ix2;
+ int e;
p->parent_info_storage = -1;
p->event_handler = compilation_event_handler;
p->flags |= PROGRAM_HAS_C_METHODS;
- p->inherits = inh = malloc(sizeof(struct inherit));
- p->identifier_references = ref = malloc(sizeof(struct reference) * 2);
- p->identifiers = i = malloc(sizeof(struct identifier) * 2);
- p->identifier_index = ix = malloc(sizeof(unsigned INT16) * 2);
+ p->inherits = inh = xalloc(sizeof(struct inherit));
+ p->identifier_references = ref = xalloc(sizeof(struct reference) * 3);
+ p->identifiers = i = xalloc(sizeof(struct identifier) * 3);
+ p->identifier_index = ix = xalloc(sizeof(unsigned INT16) * 3);
+ p->constants = pc = xalloc(sizeof(struct program_constant) * 1);
inh->prog = p;
inh->inherit_level = 0;
7570:
p->inherits->storage_offset = 0;
p->storage_needed = sizeof(struct compilation);
- /* ADD_FUNCTION("compile", f_compilation_compile, ...); */
- i->name = make_shared_string("compile");
- i->type = make_pike_type(tFunc(tStr, tPrg(tObj)));
+ /* ADD_FUNCTION("report", f_compilation_report, ...); */
+ i->name = make_shared_string("report");
+ i->type = make_pike_type(tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos
+ tStr tStr, tMix, tVoid));
i->run_time_type = T_FUNCTION;
i->identifier_flags = IDENTIFIER_C_FUNCTION;
- i->func.c_fun = f_compilation_compile;
+ i->func.c_fun = f_compilation_report;
i->opt_flags = 0;
-
+ #ifdef PROFILING
+ i->self_time = 0;
+ i->num_calls = 0;
+ i->total_time = 0;
+ #endif
i++;
*(ix++) = ref->identifier_offset = compilation_program->num_identifiers++;
p->num_identifier_index++;
7585:
ref++;
p->num_identifier_references++;
- /* ADD_FUNCTION("report", f_compilation_report, ...); */
- i->name = make_shared_string("report");
- i->type = make_pike_type(tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos
+ p2 = low_allocate_program();
+
+ pc->sval.u.program = p2;
+ pc->sval.type = T_PROGRAM;
+ pc->sval.subtype = 0;
+ pc->offset = -1;
+ i->name = make_shared_string("PikeCompiler");
+ i->type = get_type_of_svalue(&pc->sval);
+ i->run_time_type = T_PROGRAM;
+ i->identifier_flags = IDENTIFIER_CONSTANT;
+ i->func.offset = p->num_constants++;
+ pc++;
+ i->opt_flags = 0;
+ #ifdef PROFILING
+ i->self_time = 0;
+ i->num_calls = 0;
+ i->total_time = 0;
+ #endif
+ i++;
+ *(ix++) = ref->identifier_offset = compilation_program->num_identifiers++;
+ p->num_identifier_index++;
+ ref->id_flags = 0;
+ ref->inherit_offset = 0;
+ ref++;
+ p->num_identifier_references++;
+
+ /* FIXME: Parent info. */
+ p2->event_handler = program_state_event_handler;
+ p2->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT|PROGRAM_HAS_C_METHODS;
+ p2->parent_info_storage = 0;
+ p2->xstorage = sizeof(struct parent_info);
+
+ p2->inherits = inh2 = malloc(sizeof(struct inherit));
+ p2->identifier_references = ref2 = malloc(sizeof(struct reference) * 2);
+ p2->identifiers = i2 = malloc(sizeof(struct identifier) * 2);
+ p2->identifier_index = ix2 = malloc(sizeof(unsigned INT16) * 2);
+
+ inh2->prog = p2;
+ inh2->inherit_level = 0;
+ inh2->identifier_level = 0;
+ inh2->parent_identifier = -1;
+ inh2->parent_offset = OBJECT_PARENT;
+ inh2->identifier_ref_offset = 0;
+ inh2->storage_offset = p2->xstorage;
+ inh2->parent = NULL;
+ inh2->name = NULL;
+ p2->num_inherits = 1;
+
+ /* ADD_STORAGE(struct program_state); */
+ p2->alignment_needed = ALIGNOF(struct program_state);
+ p2->inherits->storage_offset = p2->xstorage;
+ p2->storage_needed = p2->xstorage + sizeof(struct program_state);
+
+ /* low_define_alias(NULL, NULL, 0, 1, 0); */
+ i2->name = make_shared_string("report");
+ i2->type = make_pike_type(tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos
tStr tStr, tMix, tVoid));
-
+ i2->run_time_type = T_FUNCTION;
+ i2->identifier_flags = IDENTIFIER_C_FUNCTION | IDENTIFIER_ALIAS;
+ i2->func.ext_ref.depth = 1;
+ i2->func.ext_ref.id = 0;
+ i2->opt_flags = 0;
+ #ifdef PROFILING
+ i2->self_time = 0;
+ i2->num_calls = 0;
+ i2->total_time = 0;
+ #endif
+ i2++;
+ *(ix2++) = ref2->identifier_offset = p2->num_identifiers++;
+ p2->num_identifier_index++;
+ ref2->id_flags = 0;
+ ref2->inherit_offset = 0;
+ ref2++;
+ p2->num_identifier_references++;
+
+
+ p2->flags |= PROGRAM_PASS_1_DONE;
+
+ fsort_program_identifier_index(p2->identifier_index, ix2-1, p2);
+ p2->flags |= PROGRAM_FIXED;
+
+ /* Yes, it is supposed to start at 0 /Grubba */
+ for(e=0;e<NUM_LFUNS;e++) {
+ int id = p2->lfuns[e] = low_find_lfun(p2, e);
+ }
+
+ optimize_program(p2);
+ p2->flags |= PROGRAM_FINISHED;
+
+
+ /* ADD_FUNCTION("compile", f_compilation_compile, ...); */
+ i->name = make_shared_string("compile");
+ i->type = make_pike_type(tFunc(tStr, tPrg(tObj)));
i->run_time_type = T_FUNCTION;
i->identifier_flags = IDENTIFIER_C_FUNCTION;
- i->func.c_fun = f_compilation_report;
+ i->func.c_fun = f_compilation_compile;
i->opt_flags = 0;
-
+ #ifdef PROFILING
+ i->self_time = 0;
+ i->num_calls = 0;
+ i->total_time = 0;
+ #endif
i++;
*(ix++) = ref->identifier_offset = compilation_program->num_identifiers++;
p->num_identifier_index++;
7606:
fsort_program_identifier_index(p->identifier_index, ix-1, p);
p->flags |= PROGRAM_FIXED;
+ /* Yes, it is supposed to start at 0 /Grubba */
+ for(e=0;e<NUM_LFUNS;e++) {
+ int id = p->lfuns[e] = low_find_lfun(p, e);
+ }
+
optimize_program(p);
p->flags |= PROGRAM_FINISHED;
-
+
+ add_global_program("CompilerEnvironment", p);
}
- /*! @endclass
- */
-
+
struct program *compile(struct pike_string *aprog,
struct object *ahandler,/* error handler */
int amajor, int aminor,
7624: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
ONERROR tmp;
#endif
- struct compilation *c=ALLOC_STRUCT(compilation);
+ struct object *ce;
+ struct compilation *c;
- verify_supporters();
+ /* FIXME! */
-
+ Pike_fatal("Old C-level compile() function called!\n");
+
CDFPRINTF((stderr, "th(%ld) %p compile() enter, placeholder=%p\n",
(long) th_self(), atarget, aplaceholder));
-
+ ce = clone_object(compilation_program, 0);
+ c = (struct compilation *)ce->storage;
+
debug_malloc_touch(c);
-
+
+ verify_supporters();
+
c->p = NULL;
add_ref(c->prog=aprog);
if((c->handler=ahandler)) add_ref(ahandler);
7697:
ret=c->p;
debug_malloc_touch(c);
- free_compilation(c);
- free(c);
+ free_object(ce);
if (!dependants_ok) {
CDFPRINTF((stderr, "th(%ld) %p compile() reporting failure "
7955:
compile_compiler();
+ enter_compiler(NULL, 0);
+
MAKE_CONST_STRING(this_program_string,"this_program");
MAKE_CONST_STRING(this_string,"this");
MAKE_CONST_STRING(UNDEFINED_string,"UNDEFINED");
8036:
low_add_constant("__placeholder_object",&s);
debug_malloc_touch(placeholder_object);
}
+
+ exit_compiler();
}
void cleanup_program(void)
8395:
void low_pop_local_variables(int level)
{
+ struct compilation *c = THIS_COMPILATION;
while(Pike_compiler->compiler_frame->current_number_of_locals > level)
{
int e;
8402:
if ((Pike_compiler->compiler_pass == 2) &&
!(Pike_compiler->compiler_frame->variable[e].flags &
LOCAL_VAR_IS_USED)) {
- struct pike_string *save_file = lex.current_file;
- int save_line = lex.current_line;
- lex.current_file = Pike_compiler->compiler_frame->variable[e].file;
- lex.current_line = Pike_compiler->compiler_frame->variable[e].line;
+ struct pike_string *save_file = c->lex.current_file;
+ int save_line = c->lex.current_line;
+ c->lex.current_file = Pike_compiler->compiler_frame->variable[e].file;
+ c->lex.current_line = Pike_compiler->compiler_frame->variable[e].line;
yywarning("Unused local variable %S.",
Pike_compiler->compiler_frame->variable[e].name);
- lex.current_file = save_file;
- lex.current_line = save_line;
+ c->lex.current_file = save_file;
+ c->lex.current_line = save_line;
}
free_string(Pike_compiler->compiler_frame->variable[e].name);
free_type(Pike_compiler->compiler_frame->variable[e].type);
8423:
void pop_local_variables(int level)
{
#if 1
+ struct compilation *c = THIS_COMPILATION;
/* We need to save the variables Kuppo (but not their names) */
if(level < Pike_compiler->compiler_frame->min_number_of_locals)
{
8433: Inside #if 1
if ((Pike_compiler->compiler_pass == 2) &&
!(Pike_compiler->compiler_frame->variable[level].flags &
LOCAL_VAR_IS_USED)) {
- struct pike_string *save_file = lex.current_file;
- int save_line = lex.current_line;
- lex.current_file = Pike_compiler->compiler_frame->variable[level].file;
- lex.current_line = Pike_compiler->compiler_frame->variable[level].line;
+ struct pike_string *save_file = c->lex.current_file;
+ int save_line = c->lex.current_line;
+ c->lex.current_file =
+ Pike_compiler->compiler_frame->variable[level].file;
+ c->lex.current_line =
+ Pike_compiler->compiler_frame->variable[level].line;
yywarning("Unused local variable %S.",
Pike_compiler->compiler_frame->variable[level].name);
- lex.current_file = save_file;
- lex.current_line = save_line;
+ c->lex.current_file = save_file;
+ c->lex.current_line = save_line;
/* Make sure we only warn once... */
Pike_compiler->compiler_frame->variable[level].flags |=
LOCAL_VAR_IS_USED;
8649:
void yywarning(char *fmt, ...)
{
+ struct compilation *c = THIS_COMPILATION;
struct string_builder s;
struct pike_string *msg;
va_list args;
-
+ CHECK_COMPILER();
+
/* If we have parse errors we might get erroneous warnings,
* so don't print them.
* This has the additional benefit of making it easier to
8667:
msg = finish_string_builder(&s);
if (master_object) {
- if (lex.current_file) {
- ref_push_string(lex.current_file);
- } else {
- push_empty_string();
- }
- push_int(lex.current_line);
+ ref_push_string(c->lex.current_file);
+ push_int(c->lex.current_line);
push_string(msg);
low_safe_apply_handler("compile_warning",
- error_handler, compat_handler, 3);
+ c->handler, c->compat_handler, 3);
pop_stack();
} else {
if (!msg->size_shift) {
fprintf(stderr, "%s:%d: Warning: %s\n",
- lex.current_file->str, lex.current_line, msg->str);
+ c->lex.current_file->str, c->lex.current_line, msg->str);
}
free_string(msg);
}
9001:
PMOD_EXPORT void change_compiler_compatibility(int major, int minor)
{
+ struct compilation *c = THIS_COMPILATION;
+
+ CHECK_COMPILER();
+
STACK_LEVEL_START(0);
if(major == PIKE_MAJOR_VERSION && minor == PIKE_MINOR_VERSION)
9010:
if(major == Pike_compiler->compat_major &&
minor == Pike_compiler->compat_minor) {
/* Optimization -- reuse the current compat handler. */
- if (compat_handler) {
- ref_push_object(compat_handler);
+ if (c->compat_handler) {
+ ref_push_object(c->compat_handler);
} else {
push_int(0);
}
9024:
STACK_LEVEL_CHECK(1);
- if(compat_handler)
+ if(c->compat_handler)
{
- free_object(compat_handler);
- compat_handler = NULL;
+ free_object(c->compat_handler);
+ c->compat_handler = NULL;
}
if((Pike_sp[-1].type == T_OBJECT) && (Pike_sp[-1].u.object->prog))
9036:
/* FIXME: */
Pike_error("Subtyped compat handlers are not supported yet.\n");
}
- compat_handler = dmalloc_touch(struct object *, Pike_sp[-1].u.object);
+ c->compat_handler = dmalloc_touch(struct object *, Pike_sp[-1].u.object);
dmalloc_touch_svalue(Pike_sp-1);
Pike_sp--;
} else {
pop_stack();
}
- if (safe_apply_handler ("get_default_module", error_handler, compat_handler,
+ if (safe_apply_handler ("get_default_module",
+ c->handler, c->compat_handler,
0, BIT_MAPPING|BIT_OBJECT|BIT_ZERO)) {
if(Pike_sp[-1].type == T_INT)
{