diff options
| author | Lua Team <team@lua.org> | 2000-11-06 12:00:00 +0000 |
|---|---|---|
| committer | repogen <> | 2000-11-06 12:00:00 +0000 |
| commit | 8cb71cb5548e3138e5d4e4744f52c79d9fafb116 (patch) | |
| tree | 25859eb162c67eafc46866e0ec3a9a7ebf93157a /src/luac | |
| parent | b7610da5fed99f59ac73ae452da8839a0f2c1bda (diff) | |
| download | lua-github-4.0.tar.gz | |
Lua 4.04.0
Diffstat (limited to 'src/luac')
| -rw-r--r-- | src/luac/Makefile | 6 | ||||
| -rw-r--r-- | src/luac/README | 34 | ||||
| -rw-r--r-- | src/luac/dump.c | 173 | ||||
| -rw-r--r-- | src/luac/luac.c | 252 | ||||
| -rw-r--r-- | src/luac/luac.h | 37 | ||||
| -rw-r--r-- | src/luac/opcode.c | 102 | ||||
| -rw-r--r-- | src/luac/opcode.h | 70 | ||||
| -rw-r--r-- | src/luac/opt.c | 326 | ||||
| -rw-r--r-- | src/luac/print.c | 252 | ||||
| -rw-r--r-- | src/luac/print.h | 55 | ||||
| -rw-r--r-- | src/luac/stubs.c | 176 | ||||
| -rw-r--r-- | src/luac/test.c | 253 |
12 files changed, 527 insertions, 1209 deletions
diff --git a/src/luac/Makefile b/src/luac/Makefile index e2950e60..4517d82b 100644 --- a/src/luac/Makefile +++ b/src/luac/Makefile @@ -1,12 +1,12 @@ -# makefile for lua compiler +# makefile for Lua compiler LUA= ../.. include $(LUA)/config INCS= -I$(INC) $(EXTRA_INCS) -I.. -OBJS= dump.o luac.o opcode.o opt.o print.o stubs.o test.o -SRCS= dump.c luac.c opcode.c opt.c print.c stubs.c test.c luac.h opcode.h +OBJS= dump.o luac.o opt.o print.o stubs.o +SRCS= dump.c luac.c opt.c print.c stubs.c luac.h print.h T= $(BIN)/luac diff --git a/src/luac/README b/src/luac/README index 9fba74bb..8d8bb491 100644 --- a/src/luac/README +++ b/src/luac/README @@ -1,28 +1,22 @@ +This is luac, the Lua compiler. +There are man pages for it in both nroff and html in ../../doc. + luac translates Lua programs into binary files that can be loaded and executed with lua_dofile in C or with dofile in Lua. -The main advantages of pre-compiling chunks are: faster loading, -protecting source code from user changes, off-line syntax error detection. +The main advantages of pre-compiling chunks are: faster loading, protecting +source code from user changes, and off-line syntax error detection. luac can also be used to learn about the Lua virtual machine. Here are the options that luac understands: - -c compile (default) - -d generate debugging information - -D name predefine 'name' for conditional compilation - -l list (default for -u) - -n save numbers in native format (file may not be portable) - -o file output file for -c (default is "luac.out") - -O optimize - -p parse only - -q quiet (default for -c) - -t test code integrity - -u undump - -U name undefine 'name' for conditional compilation - -v show version information - -V verbose - - compile "stdin" + - process stdin + -l list + -o file output file (default is "luac.out") + -p parse only + -s strip debug information + -t test code integrity + -v show version information -Finally, luac is an example of how to use the internals of Lua (politely). -Also, luac does not need the runtime code and stubs.c makes sure it is not +luac is also an example of how to use the internals of Lua (politely). +Finally, luac does not need the runtime code, and stubs.c makes sure it is not linked into luac. This file also shows how to avoid linking the parser. - diff --git a/src/luac/dump.c b/src/luac/dump.c index 479ce5d4..149469ba 100644 --- a/src/luac/dump.c +++ b/src/luac/dump.c @@ -1,154 +1,121 @@ /* -** $Id: dump.c,v 1.20 1999/07/02 19:34:26 lhf Exp $ +** $Id: dump.c,v 1.30 2000/10/31 16:57:23 lhf Exp $ ** save bytecodes to file ** See Copyright Notice in lua.h */ -#include <errno.h> #include <stdio.h> #include <stdlib.h> -#include "luac.h" +#include <string.h> -#ifdef OLD_ANSI -#define strerror(e) "(no error message provided by operating system)" -#endif +#include "luac.h" +#define DumpVector(b,n,size,D) fwrite(b,size,n,D) #define DumpBlock(b,size,D) fwrite(b,size,1,D) -#define DumpInt DumpLong +#define DumpByte fputc -static void DumpWord(int i, FILE* D) +static void DumpInt(int x, FILE* D) { - int hi= 0x0000FF & (i>>8); - int lo= 0x0000FF & i; - fputc(hi,D); - fputc(lo,D); + DumpBlock(&x,sizeof(x),D); } -static void DumpLong(long i, FILE* D) +static void DumpSize(size_t x, FILE* D) { - int hi= 0x00FFFF & (i>>16); - int lo= 0x00FFFF & i; - DumpWord(hi,D); - DumpWord(lo,D); + DumpBlock(&x,sizeof(x),D); } -static void DumpNumber(real x, FILE* D, int native, TProtoFunc* tf) +static void DumpNumber(Number x, FILE* D) { - if (native) - DumpBlock(&x,sizeof(x),D); - else - { - char b[256]; - int n; - sprintf(b,NUMBER_FMT"%n",x,&n); - luaU_str2d(b,tf->source->str); /* help lundump not to fail */ - fputc(n,D); - DumpBlock(b,n,D); - } + DumpBlock(&x,sizeof(x),D); } -static void DumpCode(TProtoFunc* tf, FILE* D) +static void DumpString(const TString* s, FILE* D) { - int size=luaU_codesize(tf); - DumpLong(size,D); - DumpBlock(tf->code,size,D); -} - -static void DumpString(char* s, int size, FILE* D) -{ - if (s==NULL) - DumpLong(0,D); + if (s==NULL || s->str==NULL) + DumpSize(0,D); else { - DumpLong(size,D); - DumpBlock(s,size,D); + size_t size=s->len+1; /* include trailing '\0' */ + DumpSize(size,D); + DumpBlock(s->str,size,D); } } -static void DumpTString(TaggedString* s, FILE* D) +static void DumpCode(const Proto* tf, FILE* D) { - if (s==NULL) - DumpString(NULL,0,D); - else - DumpString(s->str,s->u.s.len+1,D); + DumpInt(tf->ncode,D); + DumpVector(tf->code,tf->ncode,sizeof(*tf->code),D); } -static void DumpLocals(TProtoFunc* tf, FILE* D) +static void DumpLocals(const Proto* tf, FILE* D) { - if (tf->locvars==NULL) - DumpInt(0,D); - else + int i,n=tf->nlocvars; + DumpInt(n,D); + for (i=0; i<n; i++) { - LocVar* v; - int n=0; - for (v=tf->locvars; v->line>=0; v++) - ++n; - DumpInt(n,D); - for (v=tf->locvars; v->line>=0; v++) - { - DumpInt(v->line,D); - DumpTString(v->varname,D); - } + DumpString(tf->locvars[i].varname,D); + DumpInt(tf->locvars[i].startpc,D); + DumpInt(tf->locvars[i].endpc,D); } } -static void DumpFunction(TProtoFunc* tf, FILE* D, int native); +static void DumpLines(const Proto* tf, FILE* D) +{ + DumpInt(tf->nlineinfo,D); + DumpVector(tf->lineinfo,tf->nlineinfo,sizeof(*tf->lineinfo),D); +} + +static void DumpFunction(const Proto* tf, FILE* D); -static void DumpConstants(TProtoFunc* tf, FILE* D, int native) +static void DumpConstants(const Proto* tf, FILE* D) { - int i,n=tf->nconsts; - DumpInt(n,D); + int i,n; + DumpInt(n=tf->nkstr,D); for (i=0; i<n; i++) - { - TObject* o=tf->consts+i; - fputc(-ttype(o),D); /* ttype(o) is negative - ORDER LUA_T */ - switch (ttype(o)) - { - case LUA_T_NUMBER: - DumpNumber(nvalue(o),D,native,tf); - break; - case LUA_T_STRING: - DumpTString(tsvalue(o),D); - break; - case LUA_T_PROTO: - DumpFunction(tfvalue(o),D,native); - break; - case LUA_T_NIL: - break; - default: /* cannot happen */ - luaU_badconstant("dump",i,o,tf); - break; - } - } + DumpString(tf->kstr[i],D); + DumpInt(tf->nknum,D); + DumpVector(tf->knum,tf->nknum,sizeof(*tf->knum),D); + DumpInt(n=tf->nkproto,D); + for (i=0; i<n; i++) + DumpFunction(tf->kproto[i],D); } -static void DumpFunction(TProtoFunc* tf, FILE* D, int native) +static void DumpFunction(const Proto* tf, FILE* D) { + DumpString(tf->source,D); DumpInt(tf->lineDefined,D); - DumpTString(tf->source,D); - DumpCode(tf,D); + DumpInt(tf->numparams,D); + DumpByte(tf->is_vararg,D); + DumpInt(tf->maxstacksize,D); DumpLocals(tf,D); - DumpConstants(tf,D,native); + DumpLines(tf,D); + DumpConstants(tf,D); + DumpCode(tf,D); if (ferror(D)) - luaL_verror("write error" IN ": %s (errno=%d)",INLOC,strerror(errno),errno); + { + perror("luac: write error"); + exit(1); + } } -static void DumpHeader(TProtoFunc* Main, FILE* D, int native) +static void DumpHeader(FILE* D) { - fputc(ID_CHUNK,D); + DumpByte(ID_CHUNK,D); fputs(SIGNATURE,D); - fputc(VERSION,D); - if (native) - { - fputc(sizeof(real),D); - DumpNumber(TEST_NUMBER,D,native,Main); - } - else - fputc(0,D); + DumpByte(VERSION,D); + DumpByte(luaU_endianess(),D); + DumpByte(sizeof(int),D); + DumpByte(sizeof(size_t),D); + DumpByte(sizeof(Instruction),D); + DumpByte(SIZE_INSTRUCTION,D); + DumpByte(SIZE_OP,D); + DumpByte(SIZE_B,D); + DumpByte(sizeof(Number),D); + DumpNumber(TEST_NUMBER,D); } -void luaU_dumpchunk(TProtoFunc* Main, FILE* D, int native) +void luaU_dumpchunk(const Proto* Main, FILE* D) { - DumpHeader(Main,D,native); - DumpFunction(Main,D,native); + DumpHeader(D); + DumpFunction(Main,D); } diff --git a/src/luac/luac.c b/src/luac/luac.c index 68af1c76..8832de62 100644 --- a/src/luac/luac.c +++ b/src/luac/luac.c @@ -1,5 +1,5 @@ /* -** $Id: luac.c,v 1.17 1999/07/02 19:34:26 lhf Exp $ +** $Id: luac.c,v 1.28 2000/11/06 20:06:27 lhf Exp $ ** lua compiler (saves bytecodes to files; also list binary files) ** See Copyright Notice in lua.h */ @@ -7,181 +7,197 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "luac.h" + #include "lparser.h" #include "lstate.h" #include "lzio.h" +#include "luac.h" #define OUTPUT "luac.out" /* default output file */ -static FILE* efopen(char* name, char* mode); -static void doit(int undump, char* filename); +static void usage(const char* message, const char* arg); +static int doargs(int argc, const char* argv[]); +static Proto* load(const char* filename); +static FILE* efopen(const char* name, const char* mode); +static void strip(Proto* tf); +static Proto* combine(Proto** P, int n); + +lua_State* lua_state=NULL; /* lazy! */ static int listing=0; /* list bytecodes? */ -static int debugging=0; /* emit debug information? */ static int dumping=1; /* dump bytecodes? */ -static int undumping=0; /* undump bytecodes? */ -static int optimizing=0; /* optimize? */ -static int parsing=0; /* parse only? */ +static int stripping=0; /* strip debug information? */ static int testing=0; /* test integrity? */ -static int verbose=0; /* tell user what is done */ -static int native=0; /* save numbers in native format? */ -static FILE* D; /* output file */ +static const char* output=OUTPUT; /* output file name */ -static void usage(char* op) +#define IS(s) (strcmp(argv[i],s)==0) + +int main(int argc, const char* argv[]) { - if (op) fprintf(stderr,"luac: unrecognized option '%s'\n",op); + Proto** P,*tf; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given",NULL); + L=lua_open(0); + P=luaM_newvector(L,argc,Proto*); + for (i=0; i<argc; i++) + P[i]=load(IS("-")? NULL : argv[i]); + tf=combine(P,argc); + if (dumping) luaU_optchunk(tf); + if (listing) luaU_printchunk(tf); + if (testing) luaU_testchunk(tf); + if (dumping) + { + if (stripping) strip(tf); + luaU_dumpchunk(tf,efopen(output,"wb")); + } + return 0; +} + +static void usage(const char* message, const char* arg) +{ + if (message!=NULL) + { + fprintf(stderr,"luac: "); fprintf(stderr,message,arg); fprintf(stderr,"\n"); + } fprintf(stderr, "usage: luac [options] [filenames]. Available options are:\n" - " -c\t\tcompile (default)\n" - " -d\t\tgenerate debugging information\n" - " -D name\tpredefine 'name' for conditional compilation\n" - " -l\t\tlist (default for -u)\n" - " -n\t\tsave numbers in native format (file may not be portable)\n" - " -o file\toutput file for -c (default is \"" OUTPUT "\")\n" - " -O\t\toptimize\n" - " -p\t\tparse only\n" - " -q\t\tquiet (default for -c)\n" - " -t\t\ttest code integrity\n" - " -u\t\tundump\n" - " -U name\tundefine 'name' for conditional compilation\n" - " -v\t\tshow version information\n" - " -V\t\tverbose\n" - " -\t\tcompile \"stdin\"\n" + " - process stdin\n" + " -l list\n" + " -o file output file (default is \"" OUTPUT "\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -t test code integrity\n" + " -v show version information\n" ); exit(1); } -#define IS(s) (strcmp(argv[i],s)==0) - -int main(int argc, char* argv[]) +static int doargs(int argc, const char* argv[]) { - char* d=OUTPUT; /* output file name */ int i; - lua_open(); for (i=1; i<argc; i++) { - if (argv[i][0]!='-') /* end of options */ + if (*argv[i]!='-') /* end of options */ break; else if (IS("-")) /* end of options; use stdin */ - break; - else if (IS("-c")) /* compile (and dump) */ - { - dumping=1; - undumping=0; - } - else if (IS("-D")) /* $define */ - { - TaggedString* s=luaS_new(argv[++i]); - s->u.s.globalval.ttype=LUA_T_NUMBER; - s->u.s.globalval.value.n=1; - } - else if (IS("-d")) /* debug */ - debugging=1; + return i; else if (IS("-l")) /* list */ listing=1; - else if (IS("-n")) /* native */ - native=1; else if (IS("-o")) /* output file */ - d=argv[++i]; - else if (IS("-O")) /* optimize */ - optimizing=1; - else if (IS("-p")) /* parse only */ { - dumping=0; - parsing=1; + output=argv[++i]; + if (output==NULL) usage(NULL,NULL); } - else if (IS("-q")) /* quiet */ - listing=0; + else if (IS("-p")) /* parse only */ + dumping=0; + else if (IS("-s")) /* strip debug information */ + stripping=1; else if (IS("-t")) /* test */ - testing=1; - else if (IS("-u")) /* undump */ { + testing=1; dumping=0; - undumping=1; - listing=1; - } - else if (IS("-U")) /* undefine */ - { - TaggedString* s=luaS_new(argv[++i]); - s->u.s.globalval.ttype=LUA_T_NIL; } else if (IS("-v")) /* show version */ - printf("%s %s\n(written by %s)\n\n",LUA_VERSION,LUA_COPYRIGHT,LUA_AUTHORS); - else if (IS("-V")) /* verbose */ - verbose=1; - else /* unknown option */ - usage(argv[i]); - } - --i; /* fake new argv[0] */ - argc-=i; - argv+=i; - if (dumping || parsing) - { - if (argc<2) usage(NULL); - if (dumping) { - for (i=1; i<argc; i++) /* play safe with output file */ - if (IS(d)) luaL_verror("will not overwrite input file \"%s\"",d); - D=efopen(d,"wb"); /* must open in binary mode */ + printf("%s %s\n",LUA_VERSION,LUA_COPYRIGHT); + if (argc==2) exit(0); } - for (i=1; i<argc; i++) doit(0,IS("-")? NULL : argv[i]); - if (dumping) fclose(D); + else /* unknown option */ + usage("unrecognized option `%s'",argv[i]); } - if (undumping) + if (i==argc && (listing || testing)) { - if (argc<2) - doit(1,OUTPUT); - else - for (i=1; i<argc; i++) doit(1,IS("-")? NULL : argv[i]); + dumping=0; + argv[--i]=OUTPUT; } - return 0; + return i; } -static void do_compile(ZIO* z) +static Proto* load(const char* filename) { - TProtoFunc* Main; - if (optimizing) L->debug=0; - if (debugging) L->debug=1; - Main=luaY_parser(z); - if (optimizing) luaU_optchunk(Main); - if (listing) luaU_printchunk(Main); - if (testing) luaU_testchunk(Main); - if (dumping) luaU_dumpchunk(Main,D,native); + Proto* tf; + ZIO z; + char source[512]; + FILE* f; + int c,undump; + if (filename==NULL) + { + f=stdin; + filename="(stdin)"; + } + else + f=efopen(filename,"r"); + c=ungetc(fgetc(f),f); + if (ferror(f)) + { + fprintf(stderr,"luac: cannot read from "); + perror(filename); + exit(1); + } + undump=(c==ID_CHUNK); + if (undump && f!=stdin) + { + fclose(f); + f=efopen(filename,"rb"); + } + sprintf(source,"@%.*s",Sizeof(source)-2,filename); + luaZ_Fopen(&z,f,source); + tf = undump ? luaU_undump(L,&z) : luaY_parser(L,&z); + if (f!=stdin) fclose(f); + return tf; } -static void do_undump(ZIO* z) +static Proto* combine(Proto** P, int n) { - for (;;) + if (n==1) + return P[0]; + else { - TProtoFunc* Main=luaU_undump1(z); - if (Main==NULL) break; - if (optimizing) luaU_optchunk(Main); - if (listing) luaU_printchunk(Main); - if (testing) luaU_testchunk(Main); + int i,pc=0; + Proto* tf=luaF_newproto(L); + tf->source=luaS_new(L,"=(luac)"); + tf->maxstacksize=1; + tf->kproto=P; + tf->nkproto=n; + tf->ncode=2*n+1; + tf->code=luaM_newvector(L,tf->ncode,Instruction); + for (i=0; i<n; i++) + { + tf->code[pc++]=CREATE_AB(OP_CLOSURE,i,0); + tf->code[pc++]=CREATE_AB(OP_CALL,0,0); + } + tf->code[pc++]=OP_END; + return tf; } } -static void doit(int undump, char* filename) +static void strip(Proto* tf) { - FILE* f= (filename==NULL) ? stdin : efopen(filename, undump ? "rb" : "r"); - ZIO z; - char source[255+2]; /* +2 for '@' and '\0' */ - luaL_filesource(source,filename,sizeof(source)); - zFopen(&z,f,source); - if (verbose) fprintf(stderr,"%s\n",source+1); - if (undump) do_undump(&z); else do_compile(&z); - if (f!=stdin) fclose(f); + int i,n=tf->nkproto; + tf->lineinfo=NULL; + tf->nlineinfo=0; + tf->source=luaS_new(L,"=(none)"); + tf->locvars=NULL; + tf->nlocvars=0; + for (i=0; i<n; i++) strip(tf->kproto[i]); } -static FILE* efopen(char* name, char* mode) +static FILE* efopen(const char* name, const char* mode) { FILE* f=fopen(name,mode); if (f==NULL) { - fprintf(stderr,"luac: cannot open %sput file ",mode[0]=='r' ? "in" : "out"); + fprintf(stderr,"luac: cannot open %sput file ",*mode=='r' ? "in" : "out"); perror(name); exit(1); } return f; } + +void luaU_testchunk(const Proto* Main) +{ + UNUSED(Main); + fprintf(stderr,"luac: -t not operational in this version\n"); + exit(1); +} diff --git a/src/luac/luac.h b/src/luac/luac.h index 1ae5267b..f8987cf2 100644 --- a/src/luac/luac.h +++ b/src/luac/luac.h @@ -1,48 +1,31 @@ /* -** $Id: luac.h,v 1.11 1999/07/02 19:34:26 lhf Exp $ +** $Id: luac.h,v 1.18 2000/10/31 16:57:23 lhf Exp $ ** definitions for luac ** See Copyright Notice in lua.h */ -#include "lauxlib.h" +#include "ldebug.h" #include "lfunc.h" #include "lmem.h" #include "lobject.h" #include "lopcodes.h" #include "lstring.h" +#include "ltable.h" #include "lundump.h" -typedef struct -{ - char* name; /* name of opcode */ - int op; /* value of opcode */ - int class; /* class of opcode (byte variant) */ - int args; /* types of arguments (operands) */ - int arg; /* arg #1 */ - int arg2; /* arg #2 */ -} Opcode; +extern lua_State *lua_state; +#define L lua_state /* lazy! */ /* from dump.c */ -void luaU_dumpchunk(TProtoFunc* Main, FILE* D, int native); - -/* from opcode.c */ -int luaU_opcodeinfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE); -int luaU_codesize(TProtoFunc* tf); +void luaU_dumpchunk(const Proto* Main, FILE* D); /* from opt.c */ -void luaU_optchunk(TProtoFunc* Main); +void luaU_optchunk(Proto* Main); /* from print.c */ -void luaU_printchunk(TProtoFunc* Main); +void luaU_printchunk(const Proto* Main); /* from test.c */ -void luaU_testchunk(TProtoFunc* Main); -TObject* luaU_getconstant(TProtoFunc* tf, int i, int at); - -#define INFO(tf,p,I) luaU_opcodeinfo(tf,p,I,__FILE__,__LINE__) +void luaU_testchunk(const Proto* Main); -/* fake (but convenient) opcodes */ -#define NOP 255 -#define STACK (-1) -#define ARGS (-2) -#define VARARGS (-3) +#define Sizeof(x) ((int)sizeof(x)) diff --git a/src/luac/opcode.c b/src/luac/opcode.c deleted file mode 100644 index c2d4ae7d..00000000 --- a/src/luac/opcode.c +++ /dev/null @@ -1,102 +0,0 @@ -/* -** $Id: opcode.c,v 1.9 1999/05/25 19:58:55 lhf Exp $ -** opcode information -** See Copyright Notice in lua.h -*/ - -#include "luac.h" - -enum { /* for Opcode.args */ - ARGS_NONE, - ARGS_B, - ARGS_W, - ARGS_BB, - ARGS_WB -}; - -static Opcode Info[]= /* ORDER lopcodes.h */ -{ -#include "opcode.h" -}; - -static Opcode Fake[]= /* ORDER luac.h */ -{ -{ "NOP", NOP, NOP, ARGS_NONE, -1, -1 }, -{ "STACK", STACK, STACK, ARGS_B, -1, -1 }, -{ "ARGS", ARGS, ARGS, ARGS_B, -1, -1 }, -{ "VARARGS", VARARGS, VARARGS, ARGS_B, -1, -1 }, -}; - -#define NOPCODES (sizeof(Info)/sizeof(Info[0])) - -int luaU_opcodeinfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE) -{ - Opcode OP; - Byte* code=tf->code; - int op=*p; - int size=1; - if (p==code) /* first byte is STACK */ - { - OP=Fake[-STACK]; - OP.arg=op; - } - else if (p==code+1) /* second byte is ARGS or VARARGS */ - { - if (op<ZEROVARARG) - { - OP=Fake[-ARGS]; - OP.arg=op; - } - else - { - OP=Fake[-VARARGS]; - OP.arg=op-ZEROVARARG; - } - } - else if (op==NOP) /* NOP is fake */ - { - OP=Fake[0]; - } - else if (op>=NOPCODES) /* cannot happen */ - { - luaL_verror("[%s:%d] bad opcode %d at pc=%d" IN, - xFILE,xLINE,op,(int)(p-code),INLOC); - return 0; - } - else /* ordinary opcode */ - { - OP=Info[op]; - switch (OP.args) - { - case ARGS_NONE: size=1; - break; - case ARGS_B: size=2; OP.arg=p[1]; - break; - case ARGS_W: size=3; OP.arg=(p[1]<<8)+p[2]; - break; - case ARGS_BB: size=3; OP.arg=p[1]; OP.arg2=p[2]; - break; - case ARGS_WB: size=4; OP.arg=(p[1]<<8)+p[2]; OP.arg2=p[3]; - break; - default: /* cannot happen */ - luaL_verror("[%s:%d] bad args %d for %s at pc=%d" IN, - __FILE__,__LINE__,OP.args,OP.name,(int)(p-code),INLOC); - break; - } - } - *I=OP; - return size; -} - -int luaU_codesize(TProtoFunc* tf) -{ - Byte* code=tf->code; - Byte* p=code; - for (;;) - { - Opcode OP; - p+=INFO(tf,p,&OP); - if (OP.op==ENDCODE) break; - } - return p-code; -} diff --git a/src/luac/opcode.h b/src/luac/opcode.h deleted file mode 100644 index 4ae910f5..00000000 --- a/src/luac/opcode.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -** $Id: opcode.h,v 1.1 1999/03/25 13:43:05 lhf Exp $ -** opcode info to be #included into opcode.c -** extracted automatically from lopcodes.h by mkopcodeh -- DO NOT EDIT -** See Copyright Notice in lua.h -*/ -{ "ENDCODE", ENDCODE, ENDCODE, ARGS_NONE, -1, -1 }, -{ "RETCODE", RETCODE, RETCODE, ARGS_B, -1, -1 }, -{ "CALL", CALL, CALL, ARGS_BB, -1, -1 }, -{ "TAILCALL", TAILCALL, TAILCALL, ARGS_BB, -1, -1 }, -{ "PUSHNIL", PUSHNIL, PUSHNIL, ARGS_B, -1, -1 }, -{ "POP", POP, POP, ARGS_B, -1, -1 }, -{ "PUSHNUMBERW", PUSHNUMBERW, PUSHNUMBER, ARGS_W, -1, -1 }, -{ "PUSHNUMBER", PUSHNUMBER, PUSHNUMBER, ARGS_B, -1, -1 }, -{ "PUSHNUMBERNEGW", PUSHNUMBERNEGW, PUSHNUMBERNEG, ARGS_W, -1, -1 }, -{ "PUSHNUMBERNEG", PUSHNUMBERNEG, PUSHNUMBERNEG, ARGS_B, -1, -1 }, -{ "PUSHCONSTANTW", PUSHCONSTANTW, PUSHCONSTANT, ARGS_W, -1, -1 }, -{ "PUSHCONSTANT", PUSHCONSTANT, PUSHCONSTANT, ARGS_B, -1, -1 }, -{ "PUSHUPVALUE", PUSHUPVALUE, PUSHUPVALUE, ARGS_B, -1, -1 }, -{ "PUSHLOCAL", PUSHLOCAL, PUSHLOCAL, ARGS_B, -1, -1 }, -{ "GETGLOBALW", GETGLOBALW, GETGLOBAL, ARGS_W, -1, -1 }, -{ "GETGLOBAL", GETGLOBAL, GETGLOBAL, ARGS_B, -1, -1 }, -{ "GETTABLE", GETTABLE, GETTABLE, ARGS_NONE, -1, -1 }, -{ "GETDOTTEDW", GETDOTTEDW, GETDOTTED, ARGS_W, -1, -1 }, -{ "GETDOTTED", GETDOTTED, GETDOTTED, ARGS_B, -1, -1 }, -{ "PUSHSELFW", PUSHSELFW, PUSHSELF, ARGS_W, -1, -1 }, -{ "PUSHSELF", PUSHSELF, PUSHSELF, ARGS_B, -1, -1 }, -{ "CREATEARRAYW", CREATEARRAYW, CREATEARRAY, ARGS_W, -1, -1 }, -{ "CREATEARRAY", CREATEARRAY, CREATEARRAY, ARGS_B, -1, -1 }, -{ "SETLOCAL", SETLOCAL, SETLOCAL, ARGS_B, -1, -1 }, -{ "SETGLOBALW", SETGLOBALW, SETGLOBAL, ARGS_W, -1, -1 }, -{ "SETGLOBAL", SETGLOBAL, SETGLOBAL, ARGS_B, -1, -1 }, -{ "SETTABLEPOP", SETTABLEPOP, SETTABLEPOP, ARGS_NONE, -1, -1 }, -{ "SETTABLE", SETTABLE, SETTABLE, ARGS_B, -1, -1 }, -{ "SETLISTW", SETLISTW, SETLIST, ARGS_WB, -1, -1 }, -{ "SETLIST", SETLIST, SETLIST, ARGS_BB, -1, -1 }, -{ "SETMAP", SETMAP, SETMAP, ARGS_B, -1, -1 }, -{ "NEQOP", NEQOP, NEQOP, ARGS_NONE, -1, -1 }, -{ "EQOP", EQOP, EQOP, ARGS_NONE, -1, -1 }, -{ "LTOP", LTOP, LTOP, ARGS_NONE, -1, -1 }, -{ "LEOP", LEOP, LEOP, ARGS_NONE, -1, -1 }, -{ "GTOP", GTOP, GTOP, ARGS_NONE, -1, -1 }, -{ "GEOP", GEOP, GEOP, ARGS_NONE, -1, -1 }, -{ "ADDOP", ADDOP, ADDOP, ARGS_NONE, -1, -1 }, -{ "SUBOP", SUBOP, SUBOP, ARGS_NONE, -1, -1 }, -{ "MULTOP", MULTOP, MULTOP, ARGS_NONE, -1, -1 }, -{ "DIVOP", DIVOP, DIVOP, ARGS_NONE, -1, -1 }, -{ "POWOP", POWOP, POWOP, ARGS_NONE, -1, -1 }, -{ "CONCOP", CONCOP, CONCOP, ARGS_NONE, -1, -1 }, -{ "MINUSOP", MINUSOP, MINUSOP, ARGS_NONE, -1, -1 }, -{ "NOTOP", NOTOP, NOTOP, ARGS_NONE, -1, -1 }, -{ "ONTJMPW", ONTJMPW, ONTJMP, ARGS_W, -1, -1 }, -{ "ONTJMP", ONTJMP, ONTJMP, ARGS_B, -1, -1 }, -{ "ONFJMPW", ONFJMPW, ONFJMP, ARGS_W, -1, -1 }, -{ "ONFJMP", ONFJMP, ONFJMP, ARGS_B, -1, -1 }, -{ "JMPW", JMPW, JMP, ARGS_W, -1, -1 }, -{ "JMP", JMP, JMP, ARGS_B, -1, -1 }, -{ "IFFJMPW", IFFJMPW, IFFJMP, ARGS_W, -1, -1 }, -{ "IFFJMP", IFFJMP, IFFJMP, ARGS_B, -1, -1 }, -{ "IFTUPJMPW", IFTUPJMPW, IFTUPJMP, ARGS_W, -1, -1 }, -{ "IFTUPJMP", IFTUPJMP, IFTUPJMP, ARGS_B, -1, -1 }, -{ "IFFUPJMPW", IFFUPJMPW, IFFUPJMP, ARGS_W, -1, -1 }, -{ "IFFUPJMP", IFFUPJMP, IFFUPJMP, ARGS_B, -1, -1 }, -{ "CLOSUREW", CLOSUREW, CLOSURE, ARGS_WB, -1, -1 }, -{ "CLOSURE", CLOSURE, CLOSURE, ARGS_BB, -1, -1 }, -{ "SETLINEW", SETLINEW, SETLINE, ARGS_W, -1, -1 }, -{ "SETLINE", SETLINE, SETLINE, ARGS_B, -1, -1 }, -{ "LONGARGW", LONGARGW, LONGARG, ARGS_W, -1, -1 }, -{ "LONGARG", LONGARG, LONGARG, ARGS_B, -1, -1 }, -{ "CHECKSTACK", CHECKSTACK, CHECKSTACK, ARGS_B, -1, -1 }, diff --git a/src/luac/opt.c b/src/luac/opt.c index e2becc2a..e51a0868 100644 --- a/src/luac/opt.c +++ b/src/luac/opt.c @@ -1,5 +1,5 @@ /* -** $Id: opt.c,v 1.12 1999/07/02 19:34:26 lhf Exp $ +** $Id: opt.c,v 1.22 2000/10/31 16:57:23 lhf Exp $ ** optimize bytecodes ** See Copyright Notice in lua.h */ @@ -7,275 +7,121 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "luac.h" -static void FixArg(Byte* p, int i, int j, int isconst) -{ - if (j==i) - ; - else if (i<=MAX_BYTE) /* j<i, so j fits where i did */ - p[1]=j; - else if (i<=MAX_WORD) - { - if (isconst && j<=MAX_BYTE) /* may use byte variant instead */ - { - p[0]++; /* byte variant follows word variant */ - p[1]=j; - p[2]=NOP; - } - else /* stuck with word variant */ - { - p[1]=j>>8; - p[2]=j; - } - } - else /* previous instruction must've been LONGARG */ - { - if (isconst && j<=MAX_WORD) p[-2]=p[-1]=NOP; else p[-1]=j>>16; - p[1]=j>>8; - p[2]=j; - } -} +#include "luac.h" -static void FixConstants(TProtoFunc* tf, int* C) +static int MapConstant(Hash* t, int j, const TObject* key) { - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - for (;;) + const TObject* o=luaH_get(L,t,key); + if (ttype(o)==LUA_TNUMBER) + return (int) nvalue(o); + else { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - longarg=0; - if (op==PUSHCONSTANT || op==GETGLOBAL || op==GETDOTTED || - op==PUSHSELF || op==SETGLOBAL || op==CLOSURE) - FixArg(p,i,C[i],1); - else if (op==LONGARG) longarg=i<<16; - else if (op==ENDCODE) break; - p+=n; + TObject val; + ttype(&val)=LUA_TNUMBER; + nvalue(&val)=j; + *luaH_set(L,t,key)=val; + LUA_ASSERT(j>=0,"MapConstant returns negative!"); + return j; } } -#define UNREF 1 /* "type" of unused constants */ -#define BIAS 128 /* mark for used constants */ - -static void NoUnrefs(TProtoFunc* tf) +static int MapConstants(Proto* tf, Hash* map) { - int i,n=tf->nconsts; - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - for (;;) /* mark all used constants */ - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - longarg=0; - if (op==PUSHCONSTANT || op==GETGLOBAL || op==GETDOTTED || - op==PUSHSELF || op==SETGLOBAL || op==CLOSURE) - { - TObject* o=tf->consts+i; - if (ttype(o)<=0) ttype(o)+=BIAS; /* mark as used */ - } - else if (op==LONGARG) longarg=i<<16; - else if (op==ENDCODE) break; - p+=n; - } - for (i=0; i<n; i++) /* mark all unused constants */ + int i,j,k,n,m=0; + TObject o; + j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER; + for (i=0; i<n; i++) { - TObject* o=tf->consts+i; - if (ttype(o)<=0) - ttype(o)=UNREF; /* mark as unused */ - else - ttype(o)-=BIAS; /* unmark used constant */ + nvalue(&o)=tf->knum[i]; + k=MapConstant(map,j,&o); + if (k==j) j++; } -} - -#define CMP(oa,ob,f) memcmp(&f(oa),&f(ob),sizeof(f(oa))) - -static int compare(TProtoFunc* tf, int ia, int ib) -{ - TObject* oa=tf->consts+ia; - TObject* ob=tf->consts+ib; - int t=ttype(oa)-ttype(ob); - if (t) return t; - switch (ttype(oa)) + m=j; + j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING; + for (i=0; i<n; i++) { - case LUA_T_NUMBER: return CMP(oa,ob,nvalue); - case LUA_T_STRING: return CMP(oa,ob,tsvalue); - case LUA_T_PROTO: return CMP(oa,ob,tfvalue); - case LUA_T_NIL: return 0; - case UNREF: return 0; - default: return ia-ib; /* cannot happen */ + tsvalue(&o)=tf->kstr[i]; + k=MapConstant(map,j,&o); + if (k==j) j++; } + return m+j; } -static TProtoFunc* TF; /* for sort */ - -static int compare1(const void* a, const void* b) -{ - int ia=*(int*)a; - int ib=*(int*)b; - int t=compare(TF,ia,ib); - return (t) ? t : ia-ib; -} - -static void OptConstants(TProtoFunc* tf) +static void PackConstants(Proto* tf, Hash* map) { - static int* C=NULL; - static int* D=NULL; - int i,k; - int n=tf->nconsts; - if (n==0) return; - luaM_reallocvector(C,n,int); - luaM_reallocvector(D,n,int); - NoUnrefs(tf); - for (i=0; i<n; i++) C[i]=D[i]=i; /* group duplicates */ - TF=tf; qsort(C,n,sizeof(C[0]),compare1); - k=C[0]; /* build duplicate table */ - for (i=1; i<n; i++) - { - int j=C[i]; - if (compare(tf,k,j)==0) D[j]=k; else k=j; - } - k=0; /* build rename map & pack constants */ + int i,j,k,n; + TObject o; +#ifdef DEBUG + printf("%p before pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr); +#endif + j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER; for (i=0; i<n; i++) { - if (D[i]==i) /* new value */ - { - TObject* o=tf->consts+i; - if (ttype(o)!=UNREF) - { - tf->consts[k]=tf->consts[i]; - C[i]=k++; - } - } - else C[i]=C[D[i]]; + nvalue(&o)=tf->knum[i]; + k=MapConstant(map,-1,&o); + if (k==j) tf->knum[j++]=tf->knum[i]; } - if (k<n) + tf->nknum=j; + j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING; + for (i=0; i<n; i++) { -printf("\t" SOURCE " reduced constants from %d to %d\n", - tf->source->str,tf->lineDefined,n,k); - FixConstants(tf,C); - tf->nconsts=k; + tsvalue(&o)=tf->kstr[i]; + k=MapConstant(map,-1,&o); + if (k==j) tf->kstr[j++]=tf->kstr[i]; } + tf->nkstr=j; +#ifdef DEBUG + printf("%p after pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr); +#endif } -static int NoDebug(TProtoFunc* tf) +static void OptConstants(Proto* tf) { - Byte* code=tf->code; - Byte* p=code; - int lop=NOP; /* last opcode */ - int nop=0; - for (;;) /* change SETLINE to NOP */ + Instruction* p; + int n=tf->nknum+tf->nkstr; + Hash* map=luaH_new(L,n); + int m=MapConstants(tf,map); +#ifdef DEBUG + printf("%p n=%d m=%d %s\n",tf,n,m,(m==n)?"nothing to optimize":"yes!"); +#endif + if (m==n) return; + for (p=tf->code;; p++) { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - if (op==NOP) ++nop; - else if (op==SETLINE) + Instruction i=*p; + int op=GET_OPCODE(i); + switch (op) { - int m; - if (lop==LONGARG) m=2; else if (lop==LONGARGW) m=3; else m=0; - nop+=n+m; memset(p-m,NOP,n+m); + TObject o; + int j,k; + case OP_PUSHNUM: case OP_PUSHNEGNUM: + j=GETARG_U(i); + ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j]; + k=MapConstant(map,-1,&o); + if (k!=j) *p=CREATE_U(op,k); + break; + case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED: + case OP_PUSHSELF: case OP_SETGLOBAL: + j=GETARG_U(i); + ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j]; + k=MapConstant(map,-1,&o); + if (k!=j) *p=CREATE_U(op,k); + break; + case OP_END: + PackConstants(tf,map); + luaH_free(L,map); + return; + default: + break; } - else if (op==ENDCODE) break; - lop=OP.op; - p+=n; } - return nop; } -static int FixJump(TProtoFunc* tf, Byte* a, Byte* b) -{ - Byte* p; - int nop=0; - for (p=a; p<b; ) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - if (op==NOP) ++nop; - else if (op==ENDCODE) break; - p+=n; - } - return nop; -} +#define OptFunction luaU_optchunk -static void FixJumps(TProtoFunc* tf) -{ - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - for (;;) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - int nop=0; - longarg=0; - if (op==ENDCODE) break; - else if (op==IFTUPJMP || op==IFFUPJMP) - nop=FixJump(tf,p-i+n,p); - else if (op==ONTJMP || op==ONFJMP || op==JMP || op==IFFJMP) - nop=FixJump(tf,p,p+i+n); - else if (op==LONGARG) longarg=i<<16; - if (nop>0) FixArg(p,i,i-nop,0); - p+=n; - } -} - -static void PackCode(TProtoFunc* tf) -{ - Byte* code=tf->code; - Byte* p=code; - Byte* q=code; - for (;;) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - if (op!=NOP) { memcpy(q,p,n); q+=n; } - p+=n; - if (op==ENDCODE) break; - } -printf("\t" SOURCE " reduced code from %d to %d\n", - tf->source->str,tf->lineDefined,(int)(p-code),(int)(q-code)); -} - -static void OptCode(TProtoFunc* tf) -{ - if (NoDebug(tf)==0) return; /* cannot improve code */ - FixJumps(tf); - PackCode(tf); -} - -static void OptFunction(TProtoFunc* tf); - -static void OptFunctions(TProtoFunc* tf) -{ - int i,n=tf->nconsts; - for (i=0; i<n; i++) - { - TObject* o=tf->consts+i; - if (ttype(o)==LUA_T_PROTO) OptFunction(tfvalue(o)); - } -} - -static void OptFunction(TProtoFunc* tf) +void OptFunction(Proto* tf) { + int i,n=tf->nkproto; OptConstants(tf); - OptCode(tf); - OptFunctions(tf); - tf->source=luaS_new(""); - tf->locvars=NULL; -} - -void luaU_optchunk(TProtoFunc* Main) -{ - OptFunction(Main); + for (i=0; i<n; i++) OptFunction(tf->kproto[i]); } diff --git a/src/luac/print.c b/src/luac/print.c index b1ee8934..4ffc8b3d 100644 --- a/src/luac/print.c +++ b/src/luac/print.c @@ -1,223 +1,99 @@ /* -** $Id: print.c,v 1.21 1999/05/25 19:58:55 lhf Exp $ +** $Id: print.c,v 1.32 2000/11/06 20:04:36 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ #include <stdio.h> #include <stdlib.h> + #include "luac.h" -#ifdef DEBUG -static void PrintConstants(TProtoFunc* tf) +/* macros used in print.h, included in PrintCode */ +#define P_OP(x) printf("%-11s\t",x) +#define P_NONE +#define P_AB printf("%d %d",GETARG_A(i),GETARG_B(i)) +#define P_F printf("%d %d\t; %p",GETARG_A(i),GETARG_B(i),tf->kproto[GETARG_A(i)]) +#define P_J printf("%d\t; to %d",GETARG_S(i),GETARG_S(i)+at+1) +#define P_Q PrintString(tf,GETARG_U(i)) +#define P_K printf("%d\t; %s",GETARG_U(i),tf->kstr[GETARG_U(i)]->str) +#define P_L PrintLocal(tf,GETARG_U(i),at-1) +#define P_N printf("%d\t; " NUMBER_FMT,GETARG_U(i),tf->knum[GETARG_U(i)]) +#define P_S printf("%d",GETARG_S(i)) +#define P_U printf("%u",GETARG_U(i)) + +static void PrintString(const Proto* tf, int n) { - int i,n=tf->nconsts; - printf("constants (%d) for %p:\n",n,tf); - for (i=0; i<n; i++) + const char* s=tf->kstr[n]->str; + printf("%d\t; ",n); + putchar('"'); + for (; *s; s++) { - TObject* o=tf->consts+i; - printf("%6d ",i); - switch (ttype(o)) + switch (*s) { - case LUA_T_NUMBER: - printf("N " NUMBER_FMT "\n",(double)nvalue(o)); - break; - case LUA_T_STRING: - printf("S %p\t\"%s\"\n",tsvalue(o),svalue(o)); - break; - case LUA_T_PROTO: - printf("F %p\n",tfvalue(o)); - break; - case LUA_T_NIL: - printf("nil\n"); - break; - default: /* cannot happen */ - printf("? type=%d\n",ttype(o)); - break; + case '"': printf("\\\""); break; + case '\a': printf("\\a"); break; + case '\b': printf("\\b"); break; + case '\f': printf("\\f"); break; + case '\n': printf("\\n"); break; + case '\r': printf("\\r"); break; + case '\t': printf("\\t"); break; + case '\v': printf("\\v"); break; + default: putchar(*s); break; } } + putchar('"'); } -#endif -static void PrintConstant(TProtoFunc* tf, int i, int at) +static void PrintLocal(const Proto* tf, int n, int pc) { - TObject* o=luaU_getconstant(tf,i,at); - switch (ttype(o)) - { - case LUA_T_NUMBER: - printf(NUMBER_FMT,(double)nvalue(o)); - break; - case LUA_T_STRING: - printf("\"%s\"",svalue(o)); - break; - case LUA_T_PROTO: - printf("function at %p",(void*)tfvalue(o)); - break; - case LUA_T_NIL: - printf("(nil)"); - break; - default: /* cannot happen */ - luaU_badconstant("print",i,o,tf); - break; - } + const char* s=luaF_getlocalname(tf,n+1,pc); + printf("%u",n); + if (s!=NULL) printf("\t; %s",s); } -static void PrintCode(TProtoFunc* tf) +static void PrintCode(const Proto* tf) { - Byte* code=tf->code; - Byte* p=code; - int line=0; - int longarg=0; + const Instruction* code=tf->code; + const Instruction* p=code; for (;;) { - Opcode OP; - int n=INFO(tf,p,&OP); - int i=OP.arg+longarg; - int at=p-code; - longarg=0; - printf("%6d ",at); - { - Byte* q=p; - int j=n; - while (j--) printf("%02X",*q++); - } - printf("%*s%-14s ",2*(5-n),"",OP.name); - if (OP.arg >=0) printf("%d",i); - if (OP.arg2>=0) printf(" %d",OP.arg2); - - switch (OP.class) - { - - case ENDCODE: - printf("\n"); - return; - - case PUSHCONSTANT: - case GETGLOBAL: - case SETGLOBAL: - case GETDOTTED: - case PUSHSELF: - case CLOSURE: - printf("\t; "); - PrintConstant(tf,i,at); - break; - - case PUSHLOCAL: - case SETLOCAL: - { - char* s=luaF_getlocalname(tf,i+1,line); - if (s) printf("\t; %s",s); - break; - } - - case SETLINE: - printf("\t; " SOURCE,tf->source->str,line=i); - break; - - case LONGARG: - longarg=i<<16; - break; - -/* suggested by Norman Ramsey <nr@cs.virginia.edu> */ - case ONTJMP: - case ONFJMP: - case JMP: - case IFFJMP: - printf("\t; to %d",at+i+n); - break; - case IFTUPJMP: - case IFFUPJMP: - printf("\t; to %d",at-i+n); - break; - - } - printf("\n"); - p+=n; - } -} - -static void PrintLocals(TProtoFunc* tf) -{ - LocVar* v=tf->locvars; - int n,i; - if (v==NULL || v->line<0) return; - n=tf->code[1]; if (n>=ZEROVARARG) n-=ZEROVARARG; - printf("locals:"); - for (i=0; i<n; v++,i++) /* arguments */ - printf(" %s",v->varname->str); - for (; v->line>=0; v++) - { - if (v->varname==NULL) - { - --i; if (i<0) luaL_verror("bad locvars[%d]",v-tf->locvars); else printf(")"); - } - else - { - ++i; printf(" (%s",v->varname->str); + int at=p-code+1; + Instruction i=*p; + int line=luaG_getline(tf->lineinfo,at-1,1,NULL); + printf("%6d\t",at); + if (line>=0) printf("[%d]\t",line); else printf("[-]\t"); + switch (GET_OPCODE(i)) { +#include "print.h" } + printf("\n"); + if (i==OP_END) break; + p++; } - i-=n; - while (i--) printf(")"); - printf("\n"); } #define IsMain(tf) (tf->lineDefined==0) -static void PrintHeader(TProtoFunc* tf, TProtoFunc* Main, int at) -{ - int size=luaU_codesize(tf); - if (IsMain(tf)) - printf("\nmain " SOURCE " (%d bytes at %p)\n", - tf->source->str,tf->lineDefined,size,tf); - else - { - printf("\nfunction " SOURCE " (%d bytes at %p); used at ", - tf->source->str,tf->lineDefined,size,tf); - if (Main && IsMain(Main)) - printf("main"); - else - printf("%p",Main); - printf("+%d\n",at); - } -} - -static void PrintFunction(TProtoFunc* tf, TProtoFunc* Main, int at); +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) -static void PrintFunctions(TProtoFunc* Main) +static void PrintHeader(const Proto* tf) { - Byte* code=Main->code; - Byte* p=code; - int longarg=0; - for (;;) - { - Opcode OP; - int n=INFO(Main,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - longarg=0; - if (op==PUSHCONSTANT || op==CLOSURE) - { - TObject* o=Main->consts+i; - if (ttype(o)==LUA_T_PROTO) PrintFunction(tfvalue(o),Main,(int)(p-code)); - } - else if (op==LONGARG) longarg=i<<16; - else if (op==ENDCODE) break; - p+=n; - } + printf("\n%s " SOURCE_FMT " (%d instruction%s/%d bytes at %p)\n", + IsMain(tf)?"main":"function",SOURCE, + S(tf->ncode),tf->ncode*Sizeof(Instruction),tf); + printf("%d%s param%s, %d stack%s, ", + tf->numparams,tf->is_vararg?"+":"",SS(tf->numparams),S(tf->maxstacksize)); + printf("%d local%s, %d string%s, %d number%s, %d function%s, %d line%s\n", + S(tf->nlocvars),S(tf->nkstr),S(tf->nknum),S(tf->nkproto),S(tf->nlineinfo)); } -static void PrintFunction(TProtoFunc* tf, TProtoFunc* Main, int at) -{ - PrintHeader(tf,Main,at); - PrintLocals(tf); - PrintCode(tf); -#ifdef DEBUG - PrintConstants(tf); -#endif - PrintFunctions(tf); -} +#define PrintFunction luaU_printchunk -void luaU_printchunk(TProtoFunc* Main) +void PrintFunction(const Proto* tf) { - PrintFunction(Main,0,0); + int i,n=tf->nkproto; + PrintHeader(tf); + PrintCode(tf); + for (i=0; i<n; i++) PrintFunction(tf->kproto[i]); } diff --git a/src/luac/print.h b/src/luac/print.h new file mode 100644 index 00000000..5f74e149 --- /dev/null +++ b/src/luac/print.h @@ -0,0 +1,55 @@ +/* +** $Id: print.h,v 1.1 2000/11/06 20:03:12 lhf Exp $ +** extracted automatically from lopcodes.h by mkprint.lua -- DO NOT EDIT +** See Copyright Notice in lua.h +*/ + + case OP_END: P_OP("END"); P_NONE; break; + case OP_RETURN: P_OP("RETURN"); P_U; break; + case OP_CALL: P_OP("CALL"); P_AB; break; + case OP_TAILCALL: P_OP("TAILCALL"); P_AB; break; + case OP_PUSHNIL: P_OP("PUSHNIL"); P_U; break; + case OP_POP: P_OP("POP"); P_U; break; + case OP_PUSHINT: P_OP("PUSHINT"); P_S; break; + case OP_PUSHSTRING: P_OP("PUSHSTRING"); P_Q; break; + case OP_PUSHNUM: P_OP("PUSHNUM"); P_N; break; + case OP_PUSHNEGNUM: P_OP("PUSHNEGNUM"); P_N; break; + case OP_PUSHUPVALUE: P_OP("PUSHUPVALUE"); P_U; break; + case OP_GETLOCAL: P_OP("GETLOCAL"); P_L; break; + case OP_GETGLOBAL: P_OP("GETGLOBAL"); P_K; break; + case OP_GETTABLE: P_OP("GETTABLE"); P_NONE; break; + case OP_GETDOTTED: P_OP("GETDOTTED"); P_K; break; + case OP_GETINDEXED: P_OP("GETINDEXED"); P_L; break; + case OP_PUSHSELF: P_OP("PUSHSELF"); P_K; break; + case OP_CREATETABLE: P_OP("CREATETABLE"); P_U; break; + case OP_SETLOCAL: P_OP("SETLOCAL"); P_L; break; + case OP_SETGLOBAL: P_OP("SETGLOBAL"); P_K; break; + case OP_SETTABLE: P_OP("SETTABLE"); P_AB; break; + case OP_SETLIST: P_OP("SETLIST"); P_AB; break; + case OP_SETMAP: P_OP("SETMAP"); P_U; break; + case OP_ADD: P_OP("ADD"); P_NONE; break; + case OP_ADDI: P_OP("ADDI"); P_S; break; + case OP_SUB: P_OP("SUB"); P_NONE; break; + case OP_MULT: P_OP("MULT"); P_NONE; break; + case OP_DIV: P_OP("DIV"); P_NONE; break; + case OP_POW: P_OP("POW"); P_NONE; break; + case OP_CONCAT: P_OP("CONCAT"); P_U; break; + case OP_MINUS: P_OP("MINUS"); P_NONE; break; + case OP_NOT: P_OP("NOT"); P_NONE; break; + case OP_JMPNE: P_OP("JMPNE"); P_J; break; + case OP_JMPEQ: P_OP("JMPEQ"); P_J; break; + case OP_JMPLT: P_OP("JMPLT"); P_J; break; + case OP_JMPLE: P_OP("JMPLE"); P_J; break; + case OP_JMPGT: P_OP("JMPGT"); P_J; break; + case OP_JMPGE: P_OP("JMPGE"); P_J; break; + case OP_JMPT: P_OP("JMPT"); P_J; break; + case OP_JMPF: P_OP("JMPF"); P_J; break; + case OP_JMPONT: P_OP("JMPONT"); P_J; break; + case OP_JMPONF: P_OP("JMPONF"); P_J; break; + case OP_JMP: P_OP("JMP"); P_J; break; + case OP_PUSHNILJMP: P_OP("PUSHNILJMP"); P_NONE; break; + case OP_FORPREP: P_OP("FORPREP"); P_J; break; + case OP_FORLOOP: P_OP("FORLOOP"); P_J; break; + case OP_LFORPREP: P_OP("LFORPREP"); P_J; break; + case OP_LFORLOOP: P_OP("LFORLOOP"); P_J; break; + case OP_CLOSURE: P_OP("CLOSURE"); P_F; break; diff --git a/src/luac/stubs.c b/src/luac/stubs.c index 5f38940e..74f509eb 100644 --- a/src/luac/stubs.c +++ b/src/luac/stubs.c @@ -1,68 +1,109 @@ /* -** $Id: stubs.c,v 1.11 1999/03/11 17:09:10 lhf Exp $ +** $Id: stubs.c,v 1.20 2000/10/31 16:57:23 lhf Exp $ ** avoid runtime modules in luac ** See Copyright Notice in lua.h */ -#ifdef NOSTUBS - -/* according to gcc, ANSI C forbids an empty source file */ -void luaU_dummy(void); -void luaU_dummy(void){} - -#else - -#include <stdarg.h> #include <stdio.h> #include <stdlib.h> + +#include "ldo.h" +#include "llex.h" #include "luac.h" +#undef L + +#ifndef NOSTUBS + +const char luac_ident[] = "$luac: " LUA_VERSION " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $"; /* -* avoid lapi lauxlib lbuiltin ldo lgc ltable ltm lvm -* use only lbuffer lfunc llex lmem lobject lparser lstate lstring lzio +* avoid lapi ldebug ldo lgc lstate ltm lvm +* use only lcode lfunc llex lmem lobject lparser lstring ltable lzio */ /* simplified from ldo.c */ -void lua_error(char* s) -{ - if (s) fprintf(stderr,"luac: %s\n",s); - exit(1); +void lua_error (lua_State* L, const char* s) { + UNUSED(L); + if (s) fprintf(stderr,"luac: %s\n",s); + exit(1); } -/* copied from lauxlib.c */ -void luaL_verror (char *fmt, ...) -{ - char buff[500]; - va_list argp; - va_start(argp, fmt); - vsprintf(buff, fmt, argp); - va_end(argp); - lua_error(buff); +/* simplified from ldo.c */ +void luaD_breakrun (lua_State *L, int errcode) { + UNUSED(errcode); + lua_error(L,"memory allocation error"); } -/* copied from lauxlib.c */ -void luaL_filesource (char *out, char *filename, int len) { - if (filename == NULL) filename = "(stdin)"; - sprintf(out, "@%.*s", len-2, filename); /* -2 for '@' and '\0' */ +/* simplified from lstate.c */ +lua_State *lua_open (int stacksize) { + lua_State *L = luaM_new(NULL, lua_State); + if (L == NULL) return NULL; /* memory allocation error */ + L->stack = NULL; + L->strt.size = L->udt.size = 0; + L->strt.nuse = L->udt.nuse = 0; + L->strt.hash = NULL; + L->udt.hash = NULL; + L->Mbuffer = NULL; + L->Mbuffsize = 0; + L->rootproto = NULL; + L->rootcl = NULL; + L->roottable = NULL; + L->TMtable = NULL; + L->last_tag = -1; + L->refArray = NULL; + L->refSize = 0; + L->refFree = NONEXT; + L->nblocks = sizeof(lua_State); + L->GCthreshold = MAX_INT; /* to avoid GC during pre-definitions */ + L->callhook = NULL; + L->linehook = NULL; + L->allowhooks = 1; + L->errorJmp = NULL; + if (stacksize == 0) + stacksize = DEFAULT_STACK_SIZE; + else + stacksize += LUA_MINSTACK; + L->gt = luaH_new(L, 10); /* table of globals */ + luaS_init(L); + luaX_init(L); + L->GCthreshold = 2*L->nblocks; + return L; } -/* avoid runtime modules in lstate.c */ - -#include "lbuiltin.h" -#include "ldo.h" -#include "lgc.h" -#include "ltable.h" -#include "ltm.h" - -void luaB_predefine(void){} -void luaC_hashcallIM(Hash *l){} -void luaC_strcallIM(TaggedString *l){} -void luaD_gcIM(TObject *o){} -void luaH_free(Hash *frees){} -void luaT_init(void){} +/* copied from ldebug.c */ +int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { + int refi; + if (lineinfo == NULL || pc == -1) + return -1; /* no line info or function is not active */ + refi = prefi ? *prefi : 0; + if (lineinfo[refi] < 0) + refline += -lineinfo[refi++]; + LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); + while (lineinfo[refi] > pc) { + refline--; + refi--; + if (lineinfo[refi] < 0) + refline -= -lineinfo[refi--]; + LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); + } + for (;;) { + int nextline = refline + 1; + int nextref = refi + 1; + if (lineinfo[nextref] < 0) + nextline += -lineinfo[nextref++]; + LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info"); + if (lineinfo[nextref] > pc) + break; + refline = nextline; + refi = nextref; + } + if (prefi) *prefi = refi; + return refline; +} /* -* the code below avoids the lexer and the parser (llex lparser). +* the code below avoids the lexer and the parser (llex lparser lcode). * it is useful if you only want to load binary files. * this works for interpreters like lua.c too. */ @@ -72,49 +113,14 @@ void luaT_init(void){} #include "llex.h" #include "lparser.h" -void luaX_init(void){} -void luaD_init(void){} - -TProtoFunc* luaY_parser(ZIO *z) { - lua_error("parser not loaded"); - return NULL; -} - -#else - -/* copied from lauxlib.c */ -int luaL_findstring (char *name, char *list[]) { - int i; - for (i=0; list[i]; i++) - if (strcmp(list[i], name) == 0) - return i; - return -1; /* name not found */ -} - -/* copied from lauxlib.c */ -void luaL_chunkid (char *out, char *source, int len) { - len -= 13; /* 13 = strlen("string ''...\0") */ - if (*source == '@') - sprintf(out, "file `%.*s'", len, source+1); - else if (*source == '(') - strcpy(out, "(C code)"); - else { - char *b = strchr(source , '\n'); /* stop string at first new line */ - int lim = (b && (b-source)<len) ? b-source : len; - sprintf(out, "string `%.*s'", lim, source); - strcpy(out+lim+(13-5), "...'"); /* 5 = strlen("...'\0") */ - } +void luaX_init(lua_State *L) { + UNUSED(L); } -void luaD_checkstack(int n){} - -#define STACK_UNIT 128 - -/* copied from ldo.c */ -void luaD_init (void) { - L->stack.stack = luaM_newvector(STACK_UNIT, TObject); - L->stack.top = L->stack.stack; - L->stack.last = L->stack.stack+(STACK_UNIT-1); +Proto *luaY_parser(lua_State *L, ZIO *z) { + UNUSED(z); + lua_error(L,"parser not loaded"); + return NULL; } #endif diff --git a/src/luac/test.c b/src/luac/test.c deleted file mode 100644 index 78ba4556..00000000 --- a/src/luac/test.c +++ /dev/null @@ -1,253 +0,0 @@ -/* -** $Id: test.c,v 1.10 1999/07/02 19:34:26 lhf Exp $ -** test integrity -** See Copyright Notice in lua.h -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "luac.h" - -#define AT "pc=%d" -#define ATLOC 0) -#define UNSAFE(s) \ - luaL_verror("unsafe code at " AT IN "\n " s,at,INLOC - -TObject* luaU_getconstant(TProtoFunc* tf, int i, int at) -{ - if (i>=tf->nconsts) UNSAFE("bad constant #%d (max=%d)"),i,tf->nconsts-1,ATLOC; - return tf->consts+i; -} - -static int check(int n, TProtoFunc* tf, int at, int sp, int ss) -{ - if (n==0) return sp; - sp+=n; - if (sp<00) UNSAFE("stack underflow (sp=%d)"),sp,ATLOC; - if (sp>ss) UNSAFE("stack overflow (sp=%d ss=%d)"),sp,ss,ATLOC; - return sp; -} - -#define CHECK(before,after) \ - sp=check(-(before),tf,at,sp,ss), sp=check(after,tf,at,sp,ss) - -static int jmpok(TProtoFunc* tf, int size, int at, int d) -{ - int to=at+d; - if (to<2 || to>=size) - UNSAFE("invalid jump to %d (valid range is 2..%d)"),to,size-1,ATLOC; - return to; -} - -static void TestStack(TProtoFunc* tf, int size, int* SP, int* JP) -{ - Byte* code=tf->code; - Byte* p=code; - int longarg=0; - int ss=0; - int sp=0; - for (;;) - { - Opcode OP; - int n=INFO(tf,p,&OP); - int op=OP.class; - int i=OP.arg+longarg; - int at=p-code; - longarg=0; - switch (op) /* test sanity of operands */ - { - case PUSHCONSTANT: - case GETGLOBAL: - case GETDOTTED: - case PUSHSELF: - case SETGLOBAL: - case CLOSURE: - { - TObject* o=luaU_getconstant(tf,i,at); - if ((op==CLOSURE && ttype(o)!=LUA_T_PROTO) - || (op==GETGLOBAL && ttype(o)!=LUA_T_STRING) - || (op==SETGLOBAL && ttype(o)!=LUA_T_STRING)) - UNSAFE("bad operand to %s"),OP.name,ATLOC; - break; - } - case PUSHLOCAL: - if (i>=sp) UNSAFE("bad local #%d (max=%d)"),i,sp-1,ATLOC; - break; - case SETLOCAL: - if (i>=(sp-1)) UNSAFE("bad local #%d (max=%d)"),i,sp-2,ATLOC; - break; - case ONTJMP: - case ONFJMP: /* negate to remember ON?JMP */ - JP[at]=-jmpok(tf,size,at,i+n); - break; - case JMP: /* remember JMP targets */ - case IFFJMP: - JP[at]= jmpok(tf,size,at,i+n); - break; - case IFTUPJMP: - case IFFUPJMP: - JP[at]= jmpok(tf,size,at,-i+n); - break; - } - - SP[at]=sp; /* remember depth before instruction */ - - switch (op) - { - case STACK: ss=i; break; - case ARGS: CHECK(0,i); break; - case VARARGS: break; - case ENDCODE: return; - case RETCODE: CHECK(i,0); sp=i; break; - case CALL: CHECK(OP.arg2+1,i); break; - case TAILCALL: CHECK(OP.arg2,0); sp=i; break; - case PUSHNIL: CHECK(0,i+1); break; - case POP: CHECK(0,-i); break; - case PUSHNUMBER: - case PUSHNUMBERNEG: - case PUSHCONSTANT: - case PUSHUPVALUE: - case PUSHLOCAL: - case GETGLOBAL: CHECK(0,1); break; - case GETTABLE: CHECK(2,1); break; - case GETDOTTED: CHECK(1,1); break; - case PUSHSELF: CHECK(1,2); break; - case CREATEARRAY: CHECK(0,1); break; - case SETLOCAL: CHECK(1,0); break; - case SETGLOBAL: CHECK(1,0); break; - case SETTABLEPOP: CHECK(3,0); break; - case SETTABLE: CHECK(i+3,i+2); break; - case SETLIST: CHECK(OP.arg2+1,1); break; - case SETMAP: CHECK(2*(i+1)+1,1); break; - case NEQOP: - case EQOP: - case LTOP: - case LEOP: - case GTOP: - case GEOP: - case ADDOP: - case SUBOP: - case MULTOP: - case DIVOP: - case POWOP: - case CONCOP: CHECK(2,1); break; - case MINUSOP: - case NOTOP: CHECK(1,1); break; - case ONTJMP: - case ONFJMP: - case IFFJMP: - case IFTUPJMP: - case IFFUPJMP: CHECK(1,0); break; - case JMP: break; - case CLOSURE: CHECK(OP.arg2,1); break; - case SETLINE: break; - case LONGARG: - longarg=i<<16; - if (longarg<0) UNSAFE("longarg overflow"),ATLOC; - break; - case CHECKSTACK: break; - default: /* cannot happen */ - UNSAFE("cannot test opcode %d [%s]"),OP.op,OP.name,ATLOC; - break; - } - p+=n; - } -} - -static void TestJumps(TProtoFunc* tf, int size, int* SP, int* JP) -{ - int i; - for (i=0; i<size; i++) - { - int to=JP[i]; - if (to!=0) - { - int at=i; /* for ATLOC */ - int a,b,j; - int on=(to<0); /* ON?JMP */ - if (on) to=-to; - a=SP[to]; - if (a<0) - UNSAFE("invalid jump to %d (not an instruction)"),to,ATLOC; - for (j=i; SP[++j]<0; ) /* find next instruction */ - ; - b=SP[j]+on; - if (a!=b) - UNSAFE("stack inconsistency in jump to %d (expected %d, found %d)"), - to,a,b,ATLOC; - } - } -} - -static void TestCode(TProtoFunc* tf) -{ - static int* SP=NULL; - static int* JP=NULL; - int size=luaU_codesize(tf); - luaM_reallocvector(SP,size,int); memset(SP,-1,size*sizeof(int)); - luaM_reallocvector(JP,size,int); memset(JP, 0,size*sizeof(int)); - TestStack(tf,size,SP,JP); - TestJumps(tf,size,SP,JP); -} - -#undef AT -#define AT "locvars[%d]" -static void TestLocals(TProtoFunc* tf) -{ - LocVar* v; - int l=1; - int d=0; - if (tf->locvars==NULL) return; - for (v=tf->locvars; v->line>=0; v++) - { - int at=v-tf->locvars; /* for ATLOC */ - if (l>v->line) - UNSAFE("bad line number %d; expected at least %d"),v->line,l,ATLOC; - l=v->line; - if (v->varname==NULL) - { - if (--d<0) UNSAFE("no scope to close"),ATLOC; - } - else - ++d; - } -} - -static void TestFunction(TProtoFunc* tf); - -static void TestConstants(TProtoFunc* tf) -{ - int i,n=tf->nconsts; - for (i=0; i<n; i++) - { - TObject* o=tf->consts+i; - switch (ttype(o)) - { - case LUA_T_NUMBER: - break; - case LUA_T_STRING: - break; - case LUA_T_PROTO: - TestFunction(tfvalue(o)); - break; - case LUA_T_NIL: - break; - default: /* cannot happen */ - luaU_badconstant("print",i,o,tf); - break; - } - } -} - -static void TestFunction(TProtoFunc* tf) -{ - TestCode(tf); - TestLocals(tf); - TestConstants(tf); -} - -void luaU_testchunk(TProtoFunc* Main) -{ - TestFunction(Main); -} |
