diff --git a/src/lex.c b/src/lex.c index f35e9004d32f15a20b1070a2e3f5f9326cf0d4bb..5143deb4279c0e2aadd22ba30356ecc8984e8242 100644 --- a/src/lex.c +++ b/src/lex.c @@ -2,497 +2,19 @@ || 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: lex.c,v 1.116 2003/11/13 00:24:08 mast Exp $ +|| $Id: lex.c,v 1.117 2003/11/14 10:12:29 mast Exp $ */ #include "global.h" -RCSID("$Id: lex.c,v 1.116 2003/11/13 00:24:08 mast Exp $"); +RCSID("$Id: lex.c,v 1.117 2003/11/14 10:12:29 mast Exp $"); #include "language.h" -#include "array.h" #include "lex.h" -#include "stralloc.h" -#include "dynamic_buffer.h" -#include "constants.h" #include "stuff.h" -#include "pike_memory.h" -#include "interpret.h" -#include "pike_error.h" -#include "object.h" -#include "las.h" -#include "operators.h" -#include "opcodes.h" -#include "builtin_functions.h" -#include "main.h" -#include "mapping.h" -#include "pikecode.h" - -#include "pike_macros.h" - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif #include <ctype.h> -#include <math.h> -#include <fcntl.h> -#include <errno.h> -#include "time_stuff.h" #define LEXDEBUG 0 -#ifdef INSTR_PROFILING - -/* - * If you have a 64 bit machine and 15+ Gb memory, this - * routine should handle -p4 nicely. -Hubbe - * (-p3 only requires ~38Mb on a 32bit machine) - */ - -struct instr_counter -{ - long runned; - struct instr_counter* next[256]; -}; - -int last_instruction[256]; -struct instr_counter *instr_counter_storage; - -struct instr_counter *init_instr_storage_pointers(int depth) -{ - int e; - struct instr_counter *d; - if(!depth) return 0; - d=ALLOC_STRUCT(instr_counter); - if(!d) - { - fprintf(stderr,"-p%d: out of memory.\n",p_flag); - exit(2); - } - dmalloc_accept_leak(d); - d->runned=0; - for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) - d->next[e]=init_instr_storage_pointers(depth-1); - return d; -} - -void add_runned(PIKE_INSTR_T instr) -{ - int e; - struct instr_counter **tmp=&instr_counter_storage; - - for(e=0;e<p_flag;e++) - { - tmp[0]->runned++; - tmp=tmp[0]->next + last_instruction[e]; - last_instruction[e]=last_instruction[e+1]; - } -#ifndef HAVE_COMPUTED_GOTO - ((char **)(tmp))[0]++; -#endif /* !HAVE_COMPUTED_GOTO */ - last_instruction[e]=instr; -} - -void present_runned(struct instr_counter *d, int depth, int maxdepth) -{ - int e; - if(depth == maxdepth) - { - long runned = depth < p_flag ? d->runned : (long)d; - if(!runned) return; - fprintf(stderr,"%010ld @%d@: ",runned,maxdepth); - for(e=0;e<depth;e++) - { - if(e) fprintf(stderr," :: "); - fprintf(stderr,"%s", - low_get_f_name(last_instruction[e] + F_OFFSET,0)); - } - fprintf(stderr,"\n"); - }else{ - for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) - { - last_instruction[depth]=e; - present_runned(d->next[e],depth+1, maxdepth); - } - } -} - -#endif - -void exit_lex(void) -{ -#ifdef PIKE_DEBUG - if(p_flag) - { - extern void present_constant_profiling(void); - int e; - present_constant_profiling(); - - fprintf(stderr,"Opcode compiles: (opcode, compiled)\n"); - for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) - { - fprintf(stderr,"%08ld;;%-30s\n", - (long)instrs[e].compiles, - low_get_f_name(e+F_OFFSET,0)); - } - -#ifdef INSTR_PROFILING - for(e=0;e<=p_flag;e++) - { - fprintf(stderr,"Opcode x %d usage:\n",e); - present_runned(instr_counter_storage, 0, e); - } - } -#endif -#endif -} - -#ifdef PIKE_USE_MACHINE_CODE -#define ADDR(X) , (void *)PIKE_CONCAT(opcode_,X) -#define NULLADDR , 0 -#define ALIASADDR(X) , (void *)(X) - -#define OPCODE0(OP,DESC,FLAGS) void PIKE_CONCAT(opcode_,OP)(void); -#define OPCODE1(OP,DESC,FLAGS) void PIKE_CONCAT(opcode_,OP)(INT32); -#define OPCODE2(OP,DESC,FLAGS) void PIKE_CONCAT(opcode_,OP)(INT32,INT32); - -#ifdef OPCODE_RETURN_JUMPADDR -#define OPCODE0_JUMP(OP,DESC,FLAGS) void *PIKE_CONCAT(jump_opcode_,OP)(void); -#define OPCODE1_JUMP(OP,DESC,FLAGS) void *PIKE_CONCAT(jump_opcode_,OP)(INT32); -#define OPCODE2_JUMP(OP,DESC,FLAGS) void *PIKE_CONCAT(jump_opcode_,OP)(INT32,INT32); -#define JUMPADDR(X) , (void *)PIKE_CONCAT(jump_opcode_,X) -#else /* !OPCODE_RETURN_JUMPADDR */ -#define OPCODE0_JUMP(OP, DESC, FLAGS) OPCODE0(OP, DESC, FLAGS) -#define OPCODE1_JUMP(OP, DESC, FLAGS) OPCODE1(OP, DESC, FLAGS) -#define OPCODE2_JUMP(OP, DESC, FLAGS) OPCODE2(OP, DESC, FLAGS) -#define JUMPADDR(X) ADDR(X) -#endif /* !OPCODE_RETURN_JUMPADDR */ - -#define OPCODE0_PTRJUMP(OP,DESC,FLAGS) OPCODE0_JUMP(OP, DESC, FLAGS) -#define OPCODE1_PTRJUMP(OP,DESC,FLAGS) OPCODE1_JUMP(OP, DESC, FLAGS) -#define OPCODE2_PTRJUMP(OP,DESC,FLAGS) OPCODE2_JUMP(OP, DESC, FLAGS) - -#define OPCODE0_RETURN(OP,DESC,FLAGS) OPCODE0_JUMP(OP, DESC, FLAGS) -#define OPCODE1_RETURN(OP,DESC,FLAGS) OPCODE1_JUMP(OP, DESC, FLAGS) -#define OPCODE2_RETURN(OP,DESC,FLAGS) OPCODE2_JUMP(OP, DESC, FLAGS) - -#define OPCODE0_ALIAS(OP, DESC, FLAGS, ADDR) -#define OPCODE1_ALIAS(OP, DESC, FLAGS, ADDR) -#define OPCODE2_ALIAS(OP, DESC, FLAGS, ADDR) - -#ifdef OPCODE_INLINE_BRANCH -#define OPCODE0_BRANCH(OP,DESC,FLAGS) int PIKE_CONCAT(test_opcode_,OP)(void); -#define OPCODE1_BRANCH(OP,DESC,FLAGS) int PIKE_CONCAT(test_opcode_,OP)(INT32); -#define OPCODE2_BRANCH(OP,DESC,FLAGS) int PIKE_CONCAT(test_opcode_,OP)(INT32,INT32); -#define BRANCHADDR(X) , (void *)PIKE_CONCAT(test_opcode_,X) -#else /* !OPCODE_INLINE_BRANCH */ -#define OPCODE0_BRANCH OPCODE0_PTRJUMP -#define OPCODE1_BRANCH OPCODE1_PTRJUMP -#define OPCODE2_BRANCH OPCODE2_PTRJUMP -#define BRANCHADDR(X) JUMPADDR(X) -#endif /* OPCODE_INLINE_BRANCH */ - -#define OPCODE0_TAIL(OP,DESC,FLAGS) OPCODE0(OP,DESC,FLAGS) -#define OPCODE1_TAIL(OP,DESC,FLAGS) OPCODE1(OP,DESC,FLAGS) -#define OPCODE2_TAIL(OP,DESC,FLAGS) OPCODE2(OP,DESC,FLAGS) -#define OPCODE0_TAILJUMP(OP,DESC,FLAGS) OPCODE0_JUMP(OP,DESC,FLAGS) -#define OPCODE1_TAILJUMP(OP,DESC,FLAGS) OPCODE1_JUMP(OP,DESC,FLAGS) -#define OPCODE2_TAILJUMP(OP,DESC,FLAGS) OPCODE2_JUMP(OP,DESC,FLAGS) -#define OPCODE0_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE0_PTRJUMP(OP, DESC, FLAGS) -#define OPCODE1_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE1_PTRJUMP(OP, DESC, FLAGS) -#define OPCODE2_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE2_PTRJUMP(OP, DESC, FLAGS) -#define OPCODE0_TAILRETURN(OP,DESC,FLAGS) OPCODE0_RETURN(OP, DESC, FLAGS) -#define OPCODE1_TAILRETURN(OP,DESC,FLAGS) OPCODE1_RETURN(OP, DESC, FLAGS) -#define OPCODE2_TAILRETURN(OP,DESC,FLAGS) OPCODE2_RETURN(OP, DESC, FLAGS) -#define OPCODE0_TAILBRANCH(OP,DESC,FLAGS) OPCODE0_BRANCH(OP,DESC,FLAGS) -#define OPCODE1_TAILBRANCH(OP,DESC,FLAGS) OPCODE1_BRANCH(OP,DESC,FLAGS) -#define OPCODE2_TAILBRANCH(OP,DESC,FLAGS) OPCODE2_BRANCH(OP,DESC,FLAGS) - -#include "interpret_protos.h" - -#undef OPCODE0 -#undef OPCODE1 -#undef OPCODE2 -#undef OPCODE0_TAIL -#undef OPCODE1_TAIL -#undef OPCODE2_TAIL - -#undef OPCODE0_JUMP -#undef OPCODE1_JUMP -#undef OPCODE2_JUMP -#undef OPCODE0_TAILJUMP -#undef OPCODE1_TAILJUMP -#undef OPCODE2_TAILJUMP - -#undef OPCODE0_PTRJUMP -#undef OPCODE1_PTRJUMP -#undef OPCODE2_PTRJUMP -#undef OPCODE0_TAILPTRJUMP -#undef OPCODE1_TAILPTRJUMP -#undef OPCODE2_TAILPTRJUMP - -#undef OPCODE0_RETURN -#undef OPCODE1_RETURN -#undef OPCODE2_RETURN -#undef OPCODE0_TAILRETURN -#undef OPCODE1_TAILRETURN -#undef OPCODE2_TAILRETURN - -#undef OPCODE0_ALIAS -#undef OPCODE1_ALIAS -#undef OPCODE2_ALIAS - -#undef OPCODE0_BRANCH -#undef OPCODE1_BRANCH -#undef OPCODE2_BRANCH -#undef OPCODE0_TAILBRANCH -#undef OPCODE1_TAILBRANCH -#undef OPCODE2_TAILBRANCH - -#else -#define ADDR(X) -#define BRANCHADDR(X) -#define JUMPADDR(X) -#define NULLADDR -#define ALIASADDR(X) -#endif - -#define OPCODE0(OP,DESC,FLAGS) { DESC, OP, FLAGS ADDR(OP) }, -#define OPCODE1(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_HASARG ADDR(OP) }, -#define OPCODE2(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_TWO_ARGS ADDR(OP) }, -#define OPCODE0_TAIL(OP,DESC,FLAGS) OPCODE0(OP,DESC,FLAGS) -#define OPCODE1_TAIL(OP,DESC,FLAGS) OPCODE1(OP,DESC,FLAGS) -#define OPCODE2_TAIL(OP,DESC,FLAGS) OPCODE2(OP,DESC,FLAGS) - -#define OPCODE0_PTRJUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISPTRJUMP JUMPADDR(OP) }, -#define OPCODE1_PTRJUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISPTRJUMPARG JUMPADDR(OP) }, -#define OPCODE2_PTRJUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISPTRJUMPARGS JUMPADDR(OP) }, -#define OPCODE0_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE0_PTRJUMP(OP,DESC,FLAGS) -#define OPCODE1_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE1_PTRJUMP(OP,DESC,FLAGS) -#define OPCODE2_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE2_PTRJUMP(OP,DESC,FLAGS) - -#define OPCODE0_JUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISJUMP JUMPADDR(OP) }, -#define OPCODE1_JUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISJUMPARG JUMPADDR(OP) }, -#define OPCODE2_JUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISJUMPARGS JUMPADDR(OP) }, -#define OPCODE0_TAILJUMP(OP, DESC, FLAGS) OPCODE0_JUMP(OP,DESC,FLAGS) -#define OPCODE1_TAILJUMP(OP, DESC, FLAGS) OPCODE1_JUMP(OP,DESC,FLAGS) -#define OPCODE2_TAILJUMP(OP, DESC, FLAGS) OPCODE2_JUMP(OP,DESC,FLAGS) - -#define OPCODE0_RETURN(OP, DESC, FLAGS) OPCODE0_JUMP(OP,DESC,FLAGS) -#define OPCODE1_RETURN(OP, DESC, FLAGS) OPCODE1_JUMP(OP,DESC,FLAGS) -#define OPCODE2_RETURN(OP, DESC, FLAGS) OPCODE2_JUMP(OP,DESC,FLAGS) -#define OPCODE0_TAILRETURN(OP, DESC, FLAGS) OPCODE0_RETURN(OP,DESC,FLAGS) -#define OPCODE1_TAILRETURN(OP, DESC, FLAGS) OPCODE1_RETURN(OP,DESC,FLAGS) -#define OPCODE2_TAILRETURN(OP, DESC, FLAGS) OPCODE2_RETURN(OP,DESC,FLAGS) - -#define OPCODE0_ALIAS(OP, DESC, FLAGS, A) { DESC, OP, FLAGS ALIASADDR(A) }, -#define OPCODE1_ALIAS(OP, DESC, FLAGS, A) { DESC, OP, FLAGS | I_HASARG ALIASADDR(A) }, -#define OPCODE2_ALIAS(OP, DESC, FLAGS, A) { DESC, OP, FLAGS | I_TWO_ARGS ALIASADDR(A) }, - -#define OPCODE0_BRANCH(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISBRANCH BRANCHADDR(OP) }, -#define OPCODE1_BRANCH(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISBRANCHARG BRANCHADDR(OP) }, -#define OPCODE2_BRANCH(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISBRANCHARGS BRANCHADDR(OP) }, -#define OPCODE0_TAILBRANCH(OP,DESC,FLAGS) OPCODE0_BRANCH(OP,DESC,FLAGS) -#define OPCODE1_TAILBRANCH(OP,DESC,FLAGS) OPCODE1_BRANCH(OP,DESC,FLAGS) -#define OPCODE2_TAILBRANCH(OP,DESC,FLAGS) OPCODE2_BRANCH(OP,DESC,FLAGS) - -#define LEXER - -struct keyword instr_names[]= -{ -#ifndef PIKE_PRECOMPILER -#include "interpret_protos.h" -#endif /* !PIKE_PRECOMPILER */ -{ "%=", F_MOD_EQ,0 NULLADDR }, -{ "&=", F_AND_EQ,0 NULLADDR }, -{ "|=", F_OR_EQ,0 NULLADDR }, -{ "*=", F_MULT_EQ,0 NULLADDR }, -{ "+=", F_ADD_EQ,0 NULLADDR }, -{ "-=", F_SUB_EQ,0 NULLADDR }, -{ "/=", F_DIV_EQ,0 NULLADDR }, -{ "<<=", F_LSH_EQ,0 NULLADDR }, -{ ">>=", F_RSH_EQ,0 NULLADDR }, -{ "^=", F_XOR_EQ,0 NULLADDR }, -{ "arg+=1024", F_PREFIX_1024,0 NULLADDR }, -{ "arg+=256", F_PREFIX_256,0 NULLADDR }, -{ "arg+=256*X", F_PREFIX_CHARX256,0 NULLADDR }, -{ "arg+=256*XX", F_PREFIX_WORDX256,0 NULLADDR }, -{ "arg+=256*XXX", F_PREFIX_24BITX256,0 NULLADDR }, -{ "arg+=512", F_PREFIX_512,0 NULLADDR }, -{ "arg+=768", F_PREFIX_768,0 NULLADDR }, - -{ "arg+=1024", F_PREFIX2_1024,0 NULLADDR }, -{ "arg+=256", F_PREFIX2_256,0 NULLADDR }, -{ "arg+=256*X", F_PREFIX2_CHARX256,0 NULLADDR }, -{ "arg+=256*XX", F_PREFIX2_WORDX256,0 NULLADDR }, -{ "arg+=256*XXX", F_PREFIX2_24BITX256,0 NULLADDR }, -{ "arg+=512", F_PREFIX2_512,0 NULLADDR }, -{ "arg+=768", F_PREFIX2_768,0 NULLADDR }, - -{ "break", F_BREAK,0 NULLADDR }, -{ "case", F_CASE,0 NULLADDR }, -{ "continue", F_CONTINUE,0 NULLADDR }, -{ "default", F_DEFAULT,0 NULLADDR }, -{ "do-while", F_DO,0 NULLADDR }, -{ "for", F_FOR,0 NULLADDR }, - -{ "pointer", F_POINTER, I_ISPOINTER NULLADDR }, -{ "data", F_DATA, I_DATA NULLADDR }, -{ "byte", F_BYTE, I_DATA NULLADDR }, -{ "lvalue_list", F_LVALUE_LIST,0 NULLADDR }, -{ "label", F_LABEL,I_HASARG NULLADDR }, -{ "align", F_ALIGN, I_HASARG NULLADDR }, -{ "nop", F_NOP,0 NULLADDR }, -{ "entry", F_ENTRY,0 NULLADDR }, -{ "function start", F_START_FUNCTION,0 NULLADDR }, -{ "notreached!", F_NOTREACHED, 0 NULLADDR }, -}; - -struct instr instrs[F_MAX_INSTR - F_OFFSET]; - -struct reserved -{ - struct hash_entry link; - int token; -}; - -void init_lex() -{ - unsigned int i; -#ifdef PIKE_DEBUG - int fatal_later=0; -#ifdef INSTR_PROFILING - instr_counter_storage=init_instr_storage_pointers(p_flag); -#endif -#endif - - for(i=0; i<NELEM(instr_names);i++) - { -#ifdef PIKE_DEBUG - if(instr_names[i].token >= F_MAX_INSTR) - { - fprintf(stderr,"Error in instr_names[%u]\n\n",i); - fatal_later++; - } - - if(instrs[instr_names[i].token - F_OFFSET].name) - { - fprintf(stderr,"Duplicate name for %s\n",instr_names[i].word); - fatal_later++; - } -#endif - - instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word; - instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags; -#ifdef PIKE_USE_MACHINE_CODE - instrs[instr_names[i].token - F_OFFSET].address=instr_names[i].address; -#endif - } - -#ifdef PIKE_DEBUG - for(i=1; i<F_MAX_OPCODE-F_OFFSET;i++) - { - if(!instrs[i].name) - { - fprintf(stderr,"Opcode %d does not have a name.\n",i); - fatal_later++; - } - } - if(fatal_later) - Pike_fatal("Found %d errors in instrs.\n",fatal_later); - -#endif - -} - -char *low_get_f_name(int n,struct program *p) -{ - static char buf[30]; - - if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name) - { - return instrs[n-F_OFFSET].name; - }else if(n >= F_MAX_OPCODE) { - if(p && - (int)p->num_constants > (int)(n-F_MAX_OPCODE) && - p->constants[n-F_MAX_OPCODE].sval.type==T_FUNCTION && - (p->constants[n-F_MAX_OPCODE].sval.subtype == FUNCTION_BUILTIN) && - p->constants[n-F_MAX_OPCODE].sval.u.efun) - { - return p->constants[n-F_MAX_OPCODE].sval.u.efun->name->str; - }else{ - sprintf(buf, "Call efun %d", n - F_MAX_OPCODE); - return buf; - } - }else{ - sprintf(buf, "<OTHER %d>", n); - return buf; - } -} - -char *get_f_name(int n) -{ - static char buf[30]; - if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name) - { - return instrs[n-F_OFFSET].name; - }else if(n >= F_MAX_OPCODE) { - if(Pike_fp && Pike_fp->context.prog && - (int)Pike_fp->context.prog->num_constants > (int)(n-F_MAX_OPCODE) && - Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.type==T_FUNCTION && - Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.subtype == FUNCTION_BUILTIN && - Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.u.efun) - { - return Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.u.efun->name->str; - }else{ - sprintf(buf, "Call efun %d", n - F_MAX_OPCODE); - return buf; - } - }else{ - sprintf(buf, "<OTHER %d>", n); - return buf; - } -} - -#ifdef HAVE_COMPUTED_GOTO -char *get_opcode_name(PIKE_INSTR_T n) -{ - int fcode; - int low = 0; - int high = F_MAX_OPCODE - F_OFFSET; - static char buf[64]; - - if (!n) { - return "<NULL opcode!>"; - } - - while (low < high) { - int mid = (low+high)/2; - if (opcode_to_fcode[mid].opcode < n) { - low = mid + 1; - } else if (opcode_to_fcode[mid].opcode > n) { - high = mid; - } else { - return get_f_name(opcode_to_fcode[mid].fcode); - } - } - - sprintf(buf, "<Unknown opcode 0x%p>", n); - return buf; -} -#endif /* HAVE_COMPUTED_GOTO */ - -char *get_token_name(int n) -{ - static char buf[30]; - if (n<F_MAX_INSTR && instrs[n-F_OFFSET].name) - { - return instrs[n-F_OFFSET].name; - }else{ - sprintf(buf, "<OTHER %d>", n); - return buf; - } -} - struct lex lex; /* Make lexers for shifts 0, 1 and 2. */ diff --git a/src/lex.h b/src/lex.h index f35a39314d1b9fc61fca7aac91589de449e62431..d2b17584d1a3e5691d365201853ac0a69b94c3e7 100644 --- a/src/lex.h +++ b/src/lex.h @@ -2,125 +2,14 @@ || 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: lex.h,v 1.30 2003/09/23 17:35:33 grubba Exp $ +|| $Id: lex.h,v 1.31 2003/11/14 10:12:29 mast Exp $ */ #ifndef LEX_H #define LEX_H -#include <stdio.h> - #include "program.h" -struct keyword -{ - char *word; - int token; - int flags; -#ifdef PIKE_USE_MACHINE_CODE - void *address; -#endif -}; - -/* - * Instruction flags - * - * Flags used to classify the instructions. - * - * Note that branches that take arguments use an immediately - * following F_POINTER instruction to hold the destination - * address. - */ -#define I_HASARG 1 /* Instruction has a parameter. */ -#define I_POINTER 2 /* arg is a label number. */ -#define I_JUMP 4 /* Instruction performs a jump. */ -#define I__DATA 8 /* Instruction is raw data (data, byte)*/ -#define I_HASARG2 16 /* Instruction has a second parameter. */ -#define I_HASPOINTER 32 /* Instruction is followed by a F_POINTER. */ -#define I_PC_AT_NEXT 64 /* Opcode has updated Pike_fp->pc. */ -#define I_BRANCH 128 /* Opcode either jumps to the address - * given by I_POINTER/I_HASPOINTER or - * continues. */ -/* The following are useful for the code generator. - * Note that they apply to the change of state as seen - * by the immediately following instruction. - */ -#define I_UPDATE_SP 256 /* Opcode modifies Pike_sp */ -#define I_UPDATE_FP 512 /* Opcode modifies Pike_fp */ -#define I_UPDATE_M_SP 1024 /* Opcode modifies Pike_mark_sp */ - -/* Convenience variants */ -#define I_TWO_ARGS (I_HASARG | I_HASARG2) -#define I_DATA (I_HASARG | I__DATA) -#define I_ISPOINTER (I_HASARG | I_POINTER) /* Only F_POINTER */ -#define I_ISJUMP (I_JUMP) -#define I_ISJUMPARG (I_HASARG | I_JUMP) -#define I_ISJUMPARGS (I_TWO_ARGS | I_JUMP) -#define I_ISPTRJUMP (I_HASARG | I_POINTER | I_JUMP) -#define I_ISPTRJUMPARG (I_HASARG | I_HASPOINTER | I_JUMP) -#define I_ISPTRJUMPARGS (I_TWO_ARGS | I_HASPOINTER | I_JUMP) -#define I_ISBRANCH (I_HASARG | I_POINTER | I_JUMP | I_BRANCH) -#define I_ISBRANCHARG (I_HASARG | I_HASPOINTER | I_JUMP | I_BRANCH) -#define I_ISBRANCHARGS (I_TWO_ARGS | I_HASPOINTER | I_JUMP | I_BRANCH) -#define I_IS_MASK (I_TWO_ARGS | I_POINTER | I_HASPOINTER | I_JUMP) - -#define I_UPDATE_ALL (I_UPDATE_SP | I_UPDATE_FP | I_UPDATE_M_SP) - -/* Valid masked flags: - * - * 0 Generic instruction without immediate arguments. - * I_HAS_ARG Generic instruction with one argument. - * I_TWO_ARGS Generic instruction with two arguments. - * I_DATA Raw data (F_BYTE or F_DATA). - * I_ISPOINTER Raw jump address (F_POINTER). - * I_ISJUMP Jump instruction without immediate arguments. - * I_ISJUMPARG Jump instruction with one argument. - * I_ISJUMPARGS Jump instruction with two arguments. - * I_ISPTRJUMP Jump instruction with pointer. - * I_ISPTRJUMPARG Jump instruction with pointer and one argument. - * I_ISPTRJUMPARGS Jump instruction with pointer and two arguments. - */ - -#ifdef PIKE_DEBUG -#define INSTR_PROFILING -#endif - - -struct instr -{ -#ifdef PIKE_DEBUG - long compiles; -#endif - int flags; - char *name; -#ifdef PIKE_USE_MACHINE_CODE - void *address; -#endif -}; - -#ifdef PIKE_DEBUG -#define ADD_COMPILED(X) instrs[(X)-F_OFFSET].compiles++ -#ifdef INSTR_PROFILING -extern void add_runned(PIKE_INSTR_T); -#define ADD_RUNNED(X) add_runned(X) -#else -#define ADD_RUNNED(X) -#endif -#else -#define ADD_COMPILED(X) -#define ADD_RUNNED(X) -#endif - -#ifndef STRUCT_HASH_ENTRY_DECLARED -#define STRUCT_HASH_ENTRY_DECLARED -struct hash_entry; -#endif - -#ifndef STRUCT_HASH_TABLE_DECLARED -#define STRUCT_HASH_TABLE_DECLARED -struct hash_table; -#endif - #define NEW_LEX struct lex @@ -134,20 +23,8 @@ struct lex }; extern struct lex lex; -extern struct instr instrs[]; /* Prototypes begin here */ -void exit_lex(void); -struct reserved; -void init_lex(void); -char *low_get_f_name(int n,struct program *p); -char *get_f_name(int n); -#ifdef HAVE_COMPUTED_GOTO -char *get_opcode_name(PIKE_INSTR_T n); -#else /* !HAVE_COMPUTED_GOTO */ -#define get_opcode_name(n) get_f_name(n + F_OFFSET) -#endif /* HAVE_COMPUTED_GOTO */ -char *get_token_name(int n); int yylex0(YYSTYPE *); int yylex1(YYSTYPE *); @@ -155,4 +32,4 @@ int yylex2(YYSTYPE *); /* Prototypes end here */ -#endif +#endif /* !LEX_H */ diff --git a/src/opcodes.c b/src/opcodes.c index 0152bfc9ae310acc37abb75c4f9747ffe0809481..e26ab3967c0cb59932a0566099025ebe77e80792 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -2,9 +2,466 @@ || 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: opcodes.c,v 1.156 2003/11/14 09:27:29 mast Exp $ +|| $Id: opcodes.c,v 1.157 2003/11/14 10:12:29 mast Exp $ */ #include "global.h" +RCSID("$Id: opcodes.c,v 1.157 2003/11/14 10:12:29 mast Exp $"); +#include "constants.h" +#include "interpret.h" +#include "opcodes.h" +#include "main.h" -RCSID("$Id: opcodes.c,v 1.156 2003/11/14 09:27:29 mast Exp $"); +#ifdef INSTR_PROFILING + +/* + * If you have a 64 bit machine and 15+ Gb memory, this + * routine should handle -p4 nicely. -Hubbe + * (-p3 only requires ~38Mb on a 32bit machine) + */ + +struct instr_counter +{ + long runned; + struct instr_counter* next[256]; +}; + +int last_instruction[256]; +struct instr_counter *instr_counter_storage; + +struct instr_counter *init_instr_storage_pointers(int depth) +{ + int e; + struct instr_counter *d; + if(!depth) return 0; + d=ALLOC_STRUCT(instr_counter); + if(!d) + { + fprintf(stderr,"-p%d: out of memory.\n",p_flag); + exit(2); + } + dmalloc_accept_leak(d); + d->runned=0; + for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) + d->next[e]=init_instr_storage_pointers(depth-1); + return d; +} + +void add_runned(PIKE_INSTR_T instr) +{ + int e; + struct instr_counter **tmp=&instr_counter_storage; + + for(e=0;e<p_flag;e++) + { + tmp[0]->runned++; + tmp=tmp[0]->next + last_instruction[e]; + last_instruction[e]=last_instruction[e+1]; + } +#ifndef HAVE_COMPUTED_GOTO + ((char **)(tmp))[0]++; +#endif /* !HAVE_COMPUTED_GOTO */ + last_instruction[e]=instr; +} + +void present_runned(struct instr_counter *d, int depth, int maxdepth) +{ + int e; + if(depth == maxdepth) + { + long runned = depth < p_flag ? d->runned : (long)d; + if(!runned) return; + fprintf(stderr,"%010ld @%d@: ",runned,maxdepth); + for(e=0;e<depth;e++) + { + if(e) fprintf(stderr," :: "); + fprintf(stderr,"%s", + low_get_f_name(last_instruction[e] + F_OFFSET,0)); + } + fprintf(stderr,"\n"); + }else{ + for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) + { + last_instruction[depth]=e; + present_runned(d->next[e],depth+1, maxdepth); + } + } +} + +#endif + +#ifdef PIKE_USE_MACHINE_CODE +#define ADDR(X) , (void *)PIKE_CONCAT(opcode_,X) +#define NULLADDR , 0 +#define ALIASADDR(X) , (void *)(X) + +#define OPCODE0(OP,DESC,FLAGS) void PIKE_CONCAT(opcode_,OP)(void); +#define OPCODE1(OP,DESC,FLAGS) void PIKE_CONCAT(opcode_,OP)(INT32); +#define OPCODE2(OP,DESC,FLAGS) void PIKE_CONCAT(opcode_,OP)(INT32,INT32); + +#ifdef OPCODE_RETURN_JUMPADDR +#define OPCODE0_JUMP(OP,DESC,FLAGS) void *PIKE_CONCAT(jump_opcode_,OP)(void); +#define OPCODE1_JUMP(OP,DESC,FLAGS) void *PIKE_CONCAT(jump_opcode_,OP)(INT32); +#define OPCODE2_JUMP(OP,DESC,FLAGS) void *PIKE_CONCAT(jump_opcode_,OP)(INT32,INT32); +#define JUMPADDR(X) , (void *)PIKE_CONCAT(jump_opcode_,X) +#else /* !OPCODE_RETURN_JUMPADDR */ +#define OPCODE0_JUMP(OP, DESC, FLAGS) OPCODE0(OP, DESC, FLAGS) +#define OPCODE1_JUMP(OP, DESC, FLAGS) OPCODE1(OP, DESC, FLAGS) +#define OPCODE2_JUMP(OP, DESC, FLAGS) OPCODE2(OP, DESC, FLAGS) +#define JUMPADDR(X) ADDR(X) +#endif /* !OPCODE_RETURN_JUMPADDR */ + +#define OPCODE0_PTRJUMP(OP,DESC,FLAGS) OPCODE0_JUMP(OP, DESC, FLAGS) +#define OPCODE1_PTRJUMP(OP,DESC,FLAGS) OPCODE1_JUMP(OP, DESC, FLAGS) +#define OPCODE2_PTRJUMP(OP,DESC,FLAGS) OPCODE2_JUMP(OP, DESC, FLAGS) + +#define OPCODE0_RETURN(OP,DESC,FLAGS) OPCODE0_JUMP(OP, DESC, FLAGS) +#define OPCODE1_RETURN(OP,DESC,FLAGS) OPCODE1_JUMP(OP, DESC, FLAGS) +#define OPCODE2_RETURN(OP,DESC,FLAGS) OPCODE2_JUMP(OP, DESC, FLAGS) + +#define OPCODE0_ALIAS(OP, DESC, FLAGS, ADDR) +#define OPCODE1_ALIAS(OP, DESC, FLAGS, ADDR) +#define OPCODE2_ALIAS(OP, DESC, FLAGS, ADDR) + +#ifdef OPCODE_INLINE_BRANCH +#define OPCODE0_BRANCH(OP,DESC,FLAGS) int PIKE_CONCAT(test_opcode_,OP)(void); +#define OPCODE1_BRANCH(OP,DESC,FLAGS) int PIKE_CONCAT(test_opcode_,OP)(INT32); +#define OPCODE2_BRANCH(OP,DESC,FLAGS) int PIKE_CONCAT(test_opcode_,OP)(INT32,INT32); +#define BRANCHADDR(X) , (void *)PIKE_CONCAT(test_opcode_,X) +#else /* !OPCODE_INLINE_BRANCH */ +#define OPCODE0_BRANCH OPCODE0_PTRJUMP +#define OPCODE1_BRANCH OPCODE1_PTRJUMP +#define OPCODE2_BRANCH OPCODE2_PTRJUMP +#define BRANCHADDR(X) JUMPADDR(X) +#endif /* OPCODE_INLINE_BRANCH */ + +#define OPCODE0_TAIL(OP,DESC,FLAGS) OPCODE0(OP,DESC,FLAGS) +#define OPCODE1_TAIL(OP,DESC,FLAGS) OPCODE1(OP,DESC,FLAGS) +#define OPCODE2_TAIL(OP,DESC,FLAGS) OPCODE2(OP,DESC,FLAGS) +#define OPCODE0_TAILJUMP(OP,DESC,FLAGS) OPCODE0_JUMP(OP,DESC,FLAGS) +#define OPCODE1_TAILJUMP(OP,DESC,FLAGS) OPCODE1_JUMP(OP,DESC,FLAGS) +#define OPCODE2_TAILJUMP(OP,DESC,FLAGS) OPCODE2_JUMP(OP,DESC,FLAGS) +#define OPCODE0_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE0_PTRJUMP(OP, DESC, FLAGS) +#define OPCODE1_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE1_PTRJUMP(OP, DESC, FLAGS) +#define OPCODE2_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE2_PTRJUMP(OP, DESC, FLAGS) +#define OPCODE0_TAILRETURN(OP,DESC,FLAGS) OPCODE0_RETURN(OP, DESC, FLAGS) +#define OPCODE1_TAILRETURN(OP,DESC,FLAGS) OPCODE1_RETURN(OP, DESC, FLAGS) +#define OPCODE2_TAILRETURN(OP,DESC,FLAGS) OPCODE2_RETURN(OP, DESC, FLAGS) +#define OPCODE0_TAILBRANCH(OP,DESC,FLAGS) OPCODE0_BRANCH(OP,DESC,FLAGS) +#define OPCODE1_TAILBRANCH(OP,DESC,FLAGS) OPCODE1_BRANCH(OP,DESC,FLAGS) +#define OPCODE2_TAILBRANCH(OP,DESC,FLAGS) OPCODE2_BRANCH(OP,DESC,FLAGS) + +#include "interpret_protos.h" + +#undef OPCODE0 +#undef OPCODE1 +#undef OPCODE2 +#undef OPCODE0_TAIL +#undef OPCODE1_TAIL +#undef OPCODE2_TAIL + +#undef OPCODE0_JUMP +#undef OPCODE1_JUMP +#undef OPCODE2_JUMP +#undef OPCODE0_TAILJUMP +#undef OPCODE1_TAILJUMP +#undef OPCODE2_TAILJUMP + +#undef OPCODE0_PTRJUMP +#undef OPCODE1_PTRJUMP +#undef OPCODE2_PTRJUMP +#undef OPCODE0_TAILPTRJUMP +#undef OPCODE1_TAILPTRJUMP +#undef OPCODE2_TAILPTRJUMP + +#undef OPCODE0_RETURN +#undef OPCODE1_RETURN +#undef OPCODE2_RETURN +#undef OPCODE0_TAILRETURN +#undef OPCODE1_TAILRETURN +#undef OPCODE2_TAILRETURN + +#undef OPCODE0_ALIAS +#undef OPCODE1_ALIAS +#undef OPCODE2_ALIAS + +#undef OPCODE0_BRANCH +#undef OPCODE1_BRANCH +#undef OPCODE2_BRANCH +#undef OPCODE0_TAILBRANCH +#undef OPCODE1_TAILBRANCH +#undef OPCODE2_TAILBRANCH + +#else +#define ADDR(X) +#define BRANCHADDR(X) +#define JUMPADDR(X) +#define NULLADDR +#define ALIASADDR(X) +#endif + +#define OPCODE0(OP,DESC,FLAGS) { DESC, OP, FLAGS ADDR(OP) }, +#define OPCODE1(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_HASARG ADDR(OP) }, +#define OPCODE2(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_TWO_ARGS ADDR(OP) }, +#define OPCODE0_TAIL(OP,DESC,FLAGS) OPCODE0(OP,DESC,FLAGS) +#define OPCODE1_TAIL(OP,DESC,FLAGS) OPCODE1(OP,DESC,FLAGS) +#define OPCODE2_TAIL(OP,DESC,FLAGS) OPCODE2(OP,DESC,FLAGS) + +#define OPCODE0_PTRJUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISPTRJUMP JUMPADDR(OP) }, +#define OPCODE1_PTRJUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISPTRJUMPARG JUMPADDR(OP) }, +#define OPCODE2_PTRJUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISPTRJUMPARGS JUMPADDR(OP) }, +#define OPCODE0_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE0_PTRJUMP(OP,DESC,FLAGS) +#define OPCODE1_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE1_PTRJUMP(OP,DESC,FLAGS) +#define OPCODE2_TAILPTRJUMP(OP,DESC,FLAGS) OPCODE2_PTRJUMP(OP,DESC,FLAGS) + +#define OPCODE0_JUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISJUMP JUMPADDR(OP) }, +#define OPCODE1_JUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISJUMPARG JUMPADDR(OP) }, +#define OPCODE2_JUMP(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISJUMPARGS JUMPADDR(OP) }, +#define OPCODE0_TAILJUMP(OP, DESC, FLAGS) OPCODE0_JUMP(OP,DESC,FLAGS) +#define OPCODE1_TAILJUMP(OP, DESC, FLAGS) OPCODE1_JUMP(OP,DESC,FLAGS) +#define OPCODE2_TAILJUMP(OP, DESC, FLAGS) OPCODE2_JUMP(OP,DESC,FLAGS) + +#define OPCODE0_RETURN(OP, DESC, FLAGS) OPCODE0_JUMP(OP,DESC,FLAGS) +#define OPCODE1_RETURN(OP, DESC, FLAGS) OPCODE1_JUMP(OP,DESC,FLAGS) +#define OPCODE2_RETURN(OP, DESC, FLAGS) OPCODE2_JUMP(OP,DESC,FLAGS) +#define OPCODE0_TAILRETURN(OP, DESC, FLAGS) OPCODE0_RETURN(OP,DESC,FLAGS) +#define OPCODE1_TAILRETURN(OP, DESC, FLAGS) OPCODE1_RETURN(OP,DESC,FLAGS) +#define OPCODE2_TAILRETURN(OP, DESC, FLAGS) OPCODE2_RETURN(OP,DESC,FLAGS) + +#define OPCODE0_ALIAS(OP, DESC, FLAGS, A) { DESC, OP, FLAGS ALIASADDR(A) }, +#define OPCODE1_ALIAS(OP, DESC, FLAGS, A) { DESC, OP, FLAGS | I_HASARG ALIASADDR(A) }, +#define OPCODE2_ALIAS(OP, DESC, FLAGS, A) { DESC, OP, FLAGS | I_TWO_ARGS ALIASADDR(A) }, + +#define OPCODE0_BRANCH(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISBRANCH BRANCHADDR(OP) }, +#define OPCODE1_BRANCH(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISBRANCHARG BRANCHADDR(OP) }, +#define OPCODE2_BRANCH(OP,DESC,FLAGS) { DESC, OP, FLAGS | I_ISBRANCHARGS BRANCHADDR(OP) }, +#define OPCODE0_TAILBRANCH(OP,DESC,FLAGS) OPCODE0_BRANCH(OP,DESC,FLAGS) +#define OPCODE1_TAILBRANCH(OP,DESC,FLAGS) OPCODE1_BRANCH(OP,DESC,FLAGS) +#define OPCODE2_TAILBRANCH(OP,DESC,FLAGS) OPCODE2_BRANCH(OP,DESC,FLAGS) + +#define LEXER + +struct keyword instr_names[]= +{ +#ifndef PIKE_PRECOMPILER +#include "interpret_protos.h" +#endif /* !PIKE_PRECOMPILER */ +{ "%=", F_MOD_EQ,0 NULLADDR }, +{ "&=", F_AND_EQ,0 NULLADDR }, +{ "|=", F_OR_EQ,0 NULLADDR }, +{ "*=", F_MULT_EQ,0 NULLADDR }, +{ "+=", F_ADD_EQ,0 NULLADDR }, +{ "-=", F_SUB_EQ,0 NULLADDR }, +{ "/=", F_DIV_EQ,0 NULLADDR }, +{ "<<=", F_LSH_EQ,0 NULLADDR }, +{ ">>=", F_RSH_EQ,0 NULLADDR }, +{ "^=", F_XOR_EQ,0 NULLADDR }, +{ "arg+=1024", F_PREFIX_1024,0 NULLADDR }, +{ "arg+=256", F_PREFIX_256,0 NULLADDR }, +{ "arg+=256*X", F_PREFIX_CHARX256,0 NULLADDR }, +{ "arg+=256*XX", F_PREFIX_WORDX256,0 NULLADDR }, +{ "arg+=256*XXX", F_PREFIX_24BITX256,0 NULLADDR }, +{ "arg+=512", F_PREFIX_512,0 NULLADDR }, +{ "arg+=768", F_PREFIX_768,0 NULLADDR }, + +{ "arg+=1024", F_PREFIX2_1024,0 NULLADDR }, +{ "arg+=256", F_PREFIX2_256,0 NULLADDR }, +{ "arg+=256*X", F_PREFIX2_CHARX256,0 NULLADDR }, +{ "arg+=256*XX", F_PREFIX2_WORDX256,0 NULLADDR }, +{ "arg+=256*XXX", F_PREFIX2_24BITX256,0 NULLADDR }, +{ "arg+=512", F_PREFIX2_512,0 NULLADDR }, +{ "arg+=768", F_PREFIX2_768,0 NULLADDR }, + +{ "break", F_BREAK,0 NULLADDR }, +{ "case", F_CASE,0 NULLADDR }, +{ "continue", F_CONTINUE,0 NULLADDR }, +{ "default", F_DEFAULT,0 NULLADDR }, +{ "do-while", F_DO,0 NULLADDR }, +{ "for", F_FOR,0 NULLADDR }, + +{ "pointer", F_POINTER, I_ISPOINTER NULLADDR }, +{ "data", F_DATA, I_DATA NULLADDR }, +{ "byte", F_BYTE, I_DATA NULLADDR }, +{ "lvalue_list", F_LVALUE_LIST,0 NULLADDR }, +{ "label", F_LABEL,I_HASARG NULLADDR }, +{ "align", F_ALIGN, I_HASARG NULLADDR }, +{ "nop", F_NOP,0 NULLADDR }, +{ "entry", F_ENTRY,0 NULLADDR }, +{ "function start", F_START_FUNCTION,0 NULLADDR }, +{ "notreached!", F_NOTREACHED, 0 NULLADDR }, +}; + +struct instr instrs[F_MAX_INSTR - F_OFFSET]; + +char *low_get_f_name(int n,struct program *p) +{ + static char buf[30]; + + if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name) + { + return instrs[n-F_OFFSET].name; + }else if(n >= F_MAX_OPCODE) { + if(p && + (int)p->num_constants > (int)(n-F_MAX_OPCODE) && + p->constants[n-F_MAX_OPCODE].sval.type==T_FUNCTION && + (p->constants[n-F_MAX_OPCODE].sval.subtype == FUNCTION_BUILTIN) && + p->constants[n-F_MAX_OPCODE].sval.u.efun) + { + return p->constants[n-F_MAX_OPCODE].sval.u.efun->name->str; + }else{ + sprintf(buf, "Call efun %d", n - F_MAX_OPCODE); + return buf; + } + }else{ + sprintf(buf, "<OTHER %d>", n); + return buf; + } +} + +char *get_f_name(int n) +{ + static char buf[30]; + if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name) + { + return instrs[n-F_OFFSET].name; + }else if(n >= F_MAX_OPCODE) { + if(Pike_fp && Pike_fp->context.prog && + (int)Pike_fp->context.prog->num_constants > (int)(n-F_MAX_OPCODE) && + Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.type==T_FUNCTION && + Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.subtype == FUNCTION_BUILTIN && + Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.u.efun) + { + return Pike_fp-> + context.prog-> + constants[n-F_MAX_OPCODE] + .sval + .u + .efun-> + name-> + str; + }else{ + sprintf(buf, "Call efun %d", n - F_MAX_OPCODE); + return buf; + } + }else{ + sprintf(buf, "<OTHER %d>", n); + return buf; + } +} + +#ifdef HAVE_COMPUTED_GOTO +char *get_opcode_name(PIKE_INSTR_T n) +{ + int fcode; + int low = 0; + int high = F_MAX_OPCODE - F_OFFSET; + static char buf[64]; + + if (!n) { + return "<NULL opcode!>"; + } + + while (low < high) { + int mid = (low+high)/2; + if (opcode_to_fcode[mid].opcode < n) { + low = mid + 1; + } else if (opcode_to_fcode[mid].opcode > n) { + high = mid; + } else { + return get_f_name(opcode_to_fcode[mid].fcode); + } + } + + sprintf(buf, "<Unknown opcode 0x%p>", n); + return buf; +} +#endif /* HAVE_COMPUTED_GOTO */ + +char *get_token_name(int n) +{ + static char buf[30]; + if (n<F_MAX_INSTR && instrs[n-F_OFFSET].name) + { + return instrs[n-F_OFFSET].name; + }else{ + sprintf(buf, "<OTHER %d>", n); + return buf; + } +} + +void init_opcodes(void) +{ + unsigned int i; +#ifdef PIKE_DEBUG + int fatal_later=0; +#ifdef INSTR_PROFILING + instr_counter_storage=init_instr_storage_pointers(p_flag); +#endif +#endif + + for(i=0; i<NELEM(instr_names);i++) + { +#ifdef PIKE_DEBUG + if(instr_names[i].token >= F_MAX_INSTR) + { + fprintf(stderr,"Error in instr_names[%u]\n\n",i); + fatal_later++; + } + + if(instrs[instr_names[i].token - F_OFFSET].name) + { + fprintf(stderr,"Duplicate name for %s\n",instr_names[i].word); + fatal_later++; + } +#endif + + instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word; + instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags; +#ifdef PIKE_USE_MACHINE_CODE + instrs[instr_names[i].token - F_OFFSET].address=instr_names[i].address; +#endif + } + +#ifdef PIKE_DEBUG + for(i=1; i<F_MAX_OPCODE-F_OFFSET;i++) + { + if(!instrs[i].name) + { + fprintf(stderr,"Opcode %d does not have a name.\n",i); + fatal_later++; + } + } + if(fatal_later) + Pike_fatal("Found %d errors in instrs.\n",fatal_later); + +#endif + +} + +void exit_opcodes(void) +{ +#ifdef PIKE_DEBUG + if(p_flag) + { + extern void present_constant_profiling(void); + int e; + present_constant_profiling(); + + fprintf(stderr,"Opcode compiles: (opcode, compiled)\n"); + for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) + { + fprintf(stderr,"%08ld;;%-30s\n", + (long)instrs[e].compiles, + low_get_f_name(e+F_OFFSET,0)); + } + +#ifdef INSTR_PROFILING + for(e=0;e<=p_flag;e++) + { + fprintf(stderr,"Opcode x %d usage:\n",e); + present_runned(instr_counter_storage, 0, e); + } + } +#endif +#endif +} diff --git a/src/opcodes.h b/src/opcodes.h index 4d3a2d8487ca8c554750bfaa1b8c44bce6ac2677..e5bea8a2d0fb84227d7adcc7367bf12e51ce56ae 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -2,17 +2,130 @@ || 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: opcodes.h,v 1.35 2003/11/14 09:27:29 mast Exp $ +|| $Id: opcodes.h,v 1.36 2003/11/14 10:12:29 mast Exp $ */ #ifndef OPCODES_H #define OPCODES_H +#include "pikecode.h" + /* To provide the cast and sscanf declarations for compatibility. */ #include "operators.h" #include "sscanf.h" -/* Opcodes */ +struct keyword +{ + char *word; + int token; + int flags; +#ifdef PIKE_USE_MACHINE_CODE + void *address; +#endif +}; + +/* + * Instruction flags + * + * Flags used to classify the instructions. + * + * Note that branches that take arguments use an immediately + * following F_POINTER instruction to hold the destination + * address. + */ +#define I_HASARG 1 /* Instruction has a parameter. */ +#define I_POINTER 2 /* arg is a label number. */ +#define I_JUMP 4 /* Instruction performs a jump. */ +#define I__DATA 8 /* Instruction is raw data (data, byte)*/ +#define I_HASARG2 16 /* Instruction has a second parameter. */ +#define I_HASPOINTER 32 /* Instruction is followed by a F_POINTER. */ +#define I_PC_AT_NEXT 64 /* Opcode has updated Pike_fp->pc. */ +#define I_BRANCH 128 /* Opcode either jumps to the address + * given by I_POINTER/I_HASPOINTER or + * continues. */ +/* The following are useful for the code generator. + * Note that they apply to the change of state as seen + * by the immediately following instruction. + */ +#define I_UPDATE_SP 256 /* Opcode modifies Pike_sp */ +#define I_UPDATE_FP 512 /* Opcode modifies Pike_fp */ +#define I_UPDATE_M_SP 1024 /* Opcode modifies Pike_mark_sp */ + +/* Convenience variants */ +#define I_TWO_ARGS (I_HASARG | I_HASARG2) +#define I_DATA (I_HASARG | I__DATA) +#define I_ISPOINTER (I_HASARG | I_POINTER) /* Only F_POINTER */ +#define I_ISJUMP (I_JUMP) +#define I_ISJUMPARG (I_HASARG | I_JUMP) +#define I_ISJUMPARGS (I_TWO_ARGS | I_JUMP) +#define I_ISPTRJUMP (I_HASARG | I_POINTER | I_JUMP) +#define I_ISPTRJUMPARG (I_HASARG | I_HASPOINTER | I_JUMP) +#define I_ISPTRJUMPARGS (I_TWO_ARGS | I_HASPOINTER | I_JUMP) +#define I_ISBRANCH (I_HASARG | I_POINTER | I_JUMP | I_BRANCH) +#define I_ISBRANCHARG (I_HASARG | I_HASPOINTER | I_JUMP | I_BRANCH) +#define I_ISBRANCHARGS (I_TWO_ARGS | I_HASPOINTER | I_JUMP | I_BRANCH) +#define I_IS_MASK (I_TWO_ARGS | I_POINTER | I_HASPOINTER | I_JUMP) + +#define I_UPDATE_ALL (I_UPDATE_SP | I_UPDATE_FP | I_UPDATE_M_SP) + +/* Valid masked flags: + * + * 0 Generic instruction without immediate arguments. + * I_HAS_ARG Generic instruction with one argument. + * I_TWO_ARGS Generic instruction with two arguments. + * I_DATA Raw data (F_BYTE or F_DATA). + * I_ISPOINTER Raw jump address (F_POINTER). + * I_ISJUMP Jump instruction without immediate arguments. + * I_ISJUMPARG Jump instruction with one argument. + * I_ISJUMPARGS Jump instruction with two arguments. + * I_ISPTRJUMP Jump instruction with pointer. + * I_ISPTRJUMPARG Jump instruction with pointer and one argument. + * I_ISPTRJUMPARGS Jump instruction with pointer and two arguments. + */ + +#ifdef PIKE_DEBUG +#define INSTR_PROFILING +#endif + + +struct instr +{ +#ifdef PIKE_DEBUG + long compiles; +#endif + int flags; + char *name; +#ifdef PIKE_USE_MACHINE_CODE + void *address; +#endif +}; + +#ifdef PIKE_DEBUG +#define ADD_COMPILED(X) instrs[(X)-F_OFFSET].compiles++ +#ifdef INSTR_PROFILING +extern void add_runned(PIKE_INSTR_T); +#define ADD_RUNNED(X) add_runned(X) +#else +#define ADD_RUNNED(X) +#endif +#else +#define ADD_COMPILED(X) +#define ADD_RUNNED(X) +#endif + +#ifndef STRUCT_HASH_ENTRY_DECLARED +#define STRUCT_HASH_ENTRY_DECLARED +struct hash_entry; +#endif + +#ifndef STRUCT_HASH_TABLE_DECLARED +#define STRUCT_HASH_TABLE_DECLARED +struct hash_table; +#endif + +extern struct instr instrs[]; + +/* Opcode enum */ #define OPCODE0(X,Y,F) X, #define OPCODE1(X,Y,F) X, @@ -162,4 +275,15 @@ enum Pike_opcodes #undef OPCODE1_ALIAS #undef OPCODE2_ALIAS -#endif +char *low_get_f_name(int n,struct program *p); +char *get_f_name(int n); +#ifdef HAVE_COMPUTED_GOTO +char *get_opcode_name(PIKE_INSTR_T n); +#else /* !HAVE_COMPUTED_GOTO */ +#define get_opcode_name(n) get_f_name(n + F_OFFSET) +#endif /* HAVE_COMPUTED_GOTO */ +char *get_token_name(int n); +void init_opcodes(void); +void exit_opcodes(void); + +#endif /* !OPCODES_H */