diff options
| author | Lua Team <team@lua.org> | 1998-07-11 12:00:00 +0000 |
|---|---|---|
| committer | repogen <> | 1998-07-11 12:00:00 +0000 |
| commit | 377347776f1f3d820f92151f70bec667f96d5e6b (patch) | |
| tree | cdb3ba26158df33547dfe765547177afcee119d1 /src/luac | |
| parent | 4f8c5d0f284e1f4da717aea5008915f185cd2e05 (diff) | |
| download | lua-github-3.1.tar.gz | |
Lua 3.13.1
Diffstat (limited to 'src/luac')
| -rw-r--r-- | src/luac/Makefile | 16 | ||||
| -rw-r--r-- | src/luac/README | 25 | ||||
| -rw-r--r-- | src/luac/dump.c | 302 | ||||
| -rw-r--r-- | src/luac/luac.c | 176 | ||||
| -rw-r--r-- | src/luac/luac.h | 46 | ||||
| -rw-r--r-- | src/luac/opcode.c | 87 | ||||
| -rw-r--r-- | src/luac/opcode.h | 134 | ||||
| -rw-r--r-- | src/luac/opt.c | 228 | ||||
| -rw-r--r-- | src/luac/print.c | 492 | ||||
| -rw-r--r-- | src/luac/print.h | 79 | ||||
| -rw-r--r-- | src/luac/stubs.c | 68 |
11 files changed, 945 insertions, 708 deletions
diff --git a/src/luac/Makefile b/src/luac/Makefile index 813393e4..195b5cc4 100644 --- a/src/luac/Makefile +++ b/src/luac/Makefile @@ -1,24 +1,28 @@ -# makefile for lua distribution (compiler) +# makefile for lua compiler LUA= ../.. include $(LUA)/config INCS= -I$(INC) $(EXTRA_INCS) -I.. -OBJS= dump.o luac.o print.o -SRCS= dump.c luac.c print.c luac.h print.h -T=$(BIN)/luac +OBJS= dump.o luac.o opcode.o opt.o print.o stubs.o +SRCS= dump.c luac.c opcode.c opt.c print.c stubs.c luac.h opcode.h + +T= $(BIN)/luac all: $T -$T: $(OBJS) +$T: $(OBJS) $(LIB)/liblua.a $(CC) -o $@ $(OBJS) -L$(LIB) -llua +$(LIB)/liblua.a: + cd ..; make + clean: rm -f $(OBJS) $T co: - co -f -M $(SRCS) + co -q -f -M $(SRCS) klean: clean rm -f $(SRCS) diff --git a/src/luac/README b/src/luac/README new file mode 100644 index 00000000..1fd49cc2 --- /dev/null +++ b/src/luac/README @@ -0,0 +1,25 @@ +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. + +luac can also be used to learn about the Lua virtual machine. + +Here are the options it understands: + + -c compile (default) + -u undump + -d generate debugging information + -D predefine symbol for conditional compilation + -l list (default for -u) + -o output file for -c (default is "luac.out") + -O optimize + -p parse only + -q quiet (default for -c) + -v show version information + -V verbose + - compile "stdin" + +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 +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 73839f38..ce9551e6 100644 --- a/src/luac/dump.c +++ b/src/luac/dump.c @@ -1,240 +1,158 @@ /* -** dump.c -** thread and save bytecodes to file +** $Id: dump.c,v 1.11 1998/07/12 00:17:37 lhf Exp $ +** save bytecodes to file +** See Copyright Notice in lua.h */ -char* rcs_dump="$Id: dump.c,v 1.20 1997/06/19 14:56:04 lhf Exp $"; - #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "luac.h" -static int SawVar(int i, int at) +#define NotWord(x) ((unsigned short)x!=x) +#define DumpBlock(b,size,D) fwrite(b,size,1,D) +#define DumpNative(t,D) DumpBlock(&t,sizeof(t),D) + +static void DumpWord(int i, FILE* D) +{ + int hi= 0x0000FF & (i>>8); + int lo= 0x0000FF & i; + fputc(hi,D); + fputc(lo,D); +} + +static void DumpLong(long i, FILE* D) { - int old=VarLoc(i); - VarLoc(i)=at; - return old; + int hi= 0x00FFFF & (i>>16); + int lo= 0x00FFFF & i; + DumpWord(hi,D); + DumpWord(lo,D); } -static int SawStr(int i, int at) +#if ID_NUMBER==ID_REAL4 +/* LUA_NUMBER */ +/* assumes sizeof(long)==4 and sizeof(float)==4 (IEEE) */ +static void DumpFloat(float f, FILE* D) { - int old=StrLoc(i); - StrLoc(i)=at; - return old; + long l=*(long*)&f; + DumpLong(l,D); } +#endif -static void ThreadCode(Byte* code, Byte* end) +#if ID_NUMBER==ID_REAL8 +/* LUA_NUMBER */ +/* assumes sizeof(long)==4 and sizeof(double)==8 (IEEE) */ +static void DumpDouble(double f, FILE* D) { - Byte* p; - int i; - for (i=0; i<lua_ntable; i++) VarLoc(i)=0; - for (i=0; i<lua_nconstant; i++) StrLoc(i)=0; - for (p=code; p!=end;) + long* l=(long*)&f; + int x=1; + if (*(char*)&x==1) /* little-endian */ { - int op=*p; - int at=p-code+1; - switch (op) - { - case PUSHNIL: - case PUSH0: - case PUSH1: - case PUSH2: - case PUSHLOCAL0: - case PUSHLOCAL1: - case PUSHLOCAL2: - case PUSHLOCAL3: - case PUSHLOCAL4: - case PUSHLOCAL5: - case PUSHLOCAL6: - case PUSHLOCAL7: - case PUSHLOCAL8: - case PUSHLOCAL9: - case PUSHINDEXED: - case STORELOCAL0: - case STORELOCAL1: - case STORELOCAL2: - case STORELOCAL3: - case STORELOCAL4: - case STORELOCAL5: - case STORELOCAL6: - case STORELOCAL7: - case STORELOCAL8: - case STORELOCAL9: - case STOREINDEXED0: - case ADJUST0: - case EQOP: - case LTOP: - case LEOP: - case GTOP: - case GEOP: - case ADDOP: - case SUBOP: - case MULTOP: - case DIVOP: - case POWOP: - case CONCOP: - case MINUSOP: - case NOTOP: - case POP: - case RETCODE0: - p++; - break; - case PUSHBYTE: - case PUSHLOCAL: - case STORELOCAL: - case STOREINDEXED: - case STORELIST0: - case ADJUST: - case RETCODE: - case VARARGS: - case STOREMAP: - p+=2; - break; - case PUSHWORD: - case CREATEARRAY: - case ONTJMP: - case ONFJMP: - case JMP: - case UPJMP: - case IFFJMP: - case IFFUPJMP: - case SETLINE: - case STORELIST: - case CALLFUNC: - p+=3; - break; - case PUSHFLOAT: - p+=5; /* assumes sizeof(float)==4 */ - break; - case PUSHFUNCTION: - p+=sizeof(TFunc*)+1; - break; - case PUSHSTRING: - case PUSHSELF: - { - Word w; - p++; - get_word(w,p); - w=SawStr(w,at); - memcpy(p-2,&w,sizeof(w)); - break; - } - case PUSHGLOBAL: - case STOREGLOBAL: - { - Word w; - p++; - get_word(w,p); - w=SawVar(w,at); - memcpy(p-2,&w,sizeof(w)); - break; - } - case STORERECORD: - { - int n=*++p; - p++; - while (n--) - { - Word w; - at=p-code; - get_word(w,p); - w=SawStr(w,at); - memcpy(p-2,&w,sizeof(w)); - } - break; - } - default: /* cannot happen */ - fprintf(stderr,"luac: bad opcode %d at %d\n",*p,(int)(p-code)); - exit(1); - break; - } + DumpLong(l[1],D); + DumpLong(l[0],D); + } + else /* big-endian */ + { + DumpLong(l[0],D); + DumpLong(l[1],D); } } +#endif -static void DumpWord(int i, FILE* D) +static void DumpCode(TProtoFunc* tf, FILE* D) { - Word w=i; - fwrite(&w,sizeof(w),1,D); + int size=CodeSize(tf); + if (NotWord(size)) + fprintf(stderr,"luac: warning: " + "\"%s\":%d code too long for 16-bit machines (%d bytes)\n", + fileName(tf),tf->lineDefined,size); + DumpLong(size,D); + DumpBlock(tf->code,size,D); } -static void DumpBlock(void* b, int size, FILE* D) +static void DumpString(char* s, int size, FILE* D) { - fwrite(b,size,1,D); + if (s==NULL) + DumpWord(0,D); + else + { + if (NotWord(size)) + luaL_verror("string too long (%d bytes): \"%.32s...\"",size,s); + DumpWord(size,D); + DumpBlock(s,size,D); + } } -static void DumpSize(int i, FILE* D) +static void DumpTString(TaggedString* s, FILE* D) { - Word lo=i&0x0FFFF; - Word hi=(i>>16)&0x0FFFF; - fwrite(&hi,sizeof(hi),1,D); - fwrite(&lo,sizeof(lo),1,D); - if (hi!=0) - fprintf(stderr, - "luac: warning: code too long for 16-bit machines (%d bytes)\n",i); + if (s==NULL) DumpString(NULL,0,D); else DumpString(s->str,s->u.s.len+1,D); } -static void DumpString(char* s, FILE* D) +static void DumpLocals(TProtoFunc* tf, FILE* D) { - int n=strlen(s)+1; - if ((Word)n != n) + int n; + LocVar* lv; + for (n=0,lv=tf->locvars; lv && lv->line>=0; lv++) ++n; + DumpWord(n,D); + for (lv=tf->locvars; lv && lv->line>=0; lv++) { - fprintf(stderr,"luac: string too long (%d bytes): \"%.32s...\"\n",n,s); - exit(1); + DumpWord(lv->line,D); + DumpTString(lv->varname,D); } - DumpWord(n,D); - DumpBlock(s,n,D); } -static void DumpStrings(FILE* D) +static void DumpFunction(TProtoFunc* tf, FILE* D); + +static void DumpConstants(TProtoFunc* tf, FILE* D) { - int i; - for (i=0; i<lua_ntable; i++) - { - if (VarLoc(i)!=0) - { - fputc(ID_VAR,D); - DumpWord(VarLoc(i),D); - DumpString(VarStr(i),D); - } - VarLoc(i)=i; - } - for (i=0; i<lua_nconstant; i++) + int i,n=tf->nconsts; + DumpWord(n,D); + for (i=0; i<n; i++) { - if (StrLoc(i)!=0) + TObject* o=tf->consts+i; + fputc(-ttype(o),D); + switch (ttype(o)) { - fputc(ID_STR,D); - DumpWord(StrLoc(i),D); - DumpString(StrStr(i),D); + case LUA_T_NUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_T_STRING: + DumpTString(tsvalue(o),D); + break; + case LUA_T_PROTO: + DumpFunction(tfvalue(o),D); + break; + case LUA_T_NIL: + break; + default: /* cannot happen */ + luaL_verror("cannot dump constant #%d: type=%d [%s]", + i,ttype(o),luaO_typename(o)); + break; } - StrLoc(i)=i; } } -void DumpFunction(TFunc* tf, FILE* D) +static void DumpFunction(TProtoFunc* tf, FILE* D) { - ThreadCode(tf->code,tf->code+tf->size); - fputc(ID_FUN,D); - DumpSize(tf->size,D); DumpWord(tf->lineDefined,D); - if (IsMain(tf)) - DumpString(tf->fileName,D); - else - DumpWord(tf->marked,D); - DumpBlock(tf->code,tf->size,D); - DumpStrings(D); + DumpTString(tf->fileName,D); + DumpCode(tf,D); + DumpLocals(tf,D); + DumpConstants(tf,D); } -void DumpHeader(FILE* D) +static void DumpHeader(TProtoFunc* Main, FILE* D) { - Word w=TEST_WORD; - float f=TEST_FLOAT; + real t=TEST_NUMBER; fputc(ID_CHUNK,D); fputs(SIGNATURE,D); fputc(VERSION,D); - fputc(sizeof(Word),D); - fputc(sizeof(float),D); - fputc(sizeof(TFunc*),D); - fwrite(&w,sizeof(w),1,D); - fwrite(&f,sizeof(f),1,D); + fputc(ID_NUMBER,D); + fputc(sizeof(t),D); + DumpNumber(t,D); +} + +void DumpChunk(TProtoFunc* Main, FILE* D) +{ + DumpHeader(Main,D); + DumpFunction(Main,D); } diff --git a/src/luac/luac.c b/src/luac/luac.c index 713da1fb..c4619153 100644 --- a/src/luac/luac.c +++ b/src/luac/luac.c @@ -1,37 +1,51 @@ /* -** luac.c +** $Id: luac.c,v 1.10 1998/07/12 00:38:30 lhf Exp $ ** lua compiler (saves bytecodes to files; also list binary files) +** See Copyright Notice in lua.h */ -char* rcs_luac="$Id: luac.c,v 1.23 1997/06/20 20:34:04 lhf Exp $"; - #include <stdio.h> #include <stdlib.h> #include <string.h> #include "luac.h" -#include "lex.h" -#include "zio.h" +#include "lparser.h" +#include "lzio.h" +#include "luadebug.h" + +#define OUTPUT "luac.out" /* default output file */ -static void compile(char* filename); -static void undump(char* filename); +extern void DumpChunk(TProtoFunc* Main, FILE* D); +extern void PrintChunk(TProtoFunc* Main); +extern void OptChunk(TProtoFunc* Main); + +static FILE* efopen(char* name, char* mode); +static void doit(int undump, char* filename); static int listing=0; /* list bytecodes? */ +static int debugging=0; /* debug? */ 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 verbose=0; /* tell user what is done */ static FILE* D; /* output file */ static void usage(void) { - fprintf(stderr, - "usage: luac [-c | -u] [-d] [-l] [-p] [-q] [-v] [-o output] file ...\n" + fprintf(stderr,"usage: " + "luac [-c | -u] [-D name] [-d] [-l] [-o output] [-O] [-p] [-q] [-v] [-V] [files]\n" " -c\tcompile (default)\n" " -u\tundump\n" " -d\tgenerate debugging information\n" + " -D\tpredefine symbol for conditional compilation\n" " -l\tlist (default for -u)\n" - " -o\toutput file for -c (default \"luac.out\")\n" + " -o\toutput file for -c (default is \"" OUTPUT "\")\n" + " -O\toptimize\n" " -p\tparse only\n" " -q\tquiet (default for -c)\n" " -v\tshow version information\n" + " -V\tverbose\n" + " -\tcompile \"stdin\"\n" ); exit(1); } @@ -40,8 +54,9 @@ static void usage(void) int main(int argc, char* argv[]) { - char* d="luac.out"; /* default output file */ + char* d=OUTPUT; /* output file name */ int i; + lua_open(); for (i=1; i<argc; i++) { if (argv[i][0]!='-') /* end of options */ @@ -53,14 +68,25 @@ int main(int argc, char* argv[]) 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 */ - lua_debug=1; + debugging=1; else if (IS("-l")) /* list */ listing=1; else if (IS("-o")) /* output file */ d=argv[++i]; - else if (IS("-p")) /* parse only (for timing purposes) */ + else if (IS("-O")) /* optimize */ + optimizing=1; + else if (IS("-p")) /* parse only */ + { dumping=0; + parsing=1; + } else if (IS("-q")) /* quiet */ listing=0; else if (IS("-u")) /* undump */ @@ -71,120 +97,88 @@ int main(int argc, char* argv[]) } 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(); } --i; /* fake new argv[0] */ argc-=i; argv+=i; - if (dumping) + if (dumping || parsing) { if (argc<2) usage(); - for (i=1; i<argc; i++) /* play safe with output file */ - if (IS(d)) - { - fprintf(stderr,"luac: will not overwrite input file \"%s\"\n",d); - exit(1); - } - D=fopen(d,"wb"); /* must open in binary mode */ - if (D==NULL) + if (dumping) { - fprintf(stderr,"luac: cannot open "); - perror(d); - exit(1); + 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 */ +#if ID_NUMBER==ID_NATIVE + if (verbose) fprintf(stderr,"luac: warning: " + "saving numbers in native format. file may not be portable.\n"); +#endif } - for (i=1; i<argc; i++) compile(IS("-")? NULL : argv[i]); - fclose(D); + for (i=1; i<argc; i++) doit(0,IS("-")? NULL : argv[i]); + if (dumping) fclose(D); } if (undumping) { if (argc<2) - undump("luac.out"); + doit(1,OUTPUT); else - for (i=1; i<argc; i++) undump(IS("-")? NULL : argv[i]); + for (i=1; i<argc; i++) doit(1,IS("-")? NULL : argv[i]); } return 0; } -static void do_dump(TFunc* Main) -{ - TFunc* tf; - LinkFunctions(Main); - if (listing) - { - for (tf=Main; tf!=NULL; tf=tf->next) PrintFunction(tf,Main); - } - if (dumping) - { - DumpHeader(D); - for (tf=Main; tf!=NULL; tf=tf->next) DumpFunction(tf,D); - } - for (tf=Main; tf!=NULL; ) - { - TFunc* nf=tf->next; - luaI_freefunc(tf); - tf=nf; - } -} - static void do_compile(ZIO* z) { - TFunc* tf=new(TFunc); - lua_setinput(z); - luaI_initTFunc(tf); - tf->fileName=lua_parsedfile; - lua_parse(tf); - do_dump(tf); + TProtoFunc* Main; + if (optimizing) lua_debug=0; /* set debugging before parsing */ + if (debugging) lua_debug=1; + Main=luaY_parser(z); + if (optimizing) OptChunk(Main); + if (listing) PrintChunk(Main); + if (dumping) DumpChunk(Main,D); } -static void compile(char* filename) +static void do_undump(ZIO* z) { - FILE* f= (filename==NULL) ? stdin : fopen(filename, "r"); - if (f==NULL) - { - fprintf(stderr,"luac: cannot open "); - perror(filename); - exit(1); - } - else + while (1) { - ZIO z; - zFopen(&z,f); - luaI_setparsedfile(filename?filename:"(stdin)"); - do_compile(&z); - fclose(f); + TProtoFunc* Main=luaU_undump1(z); + if (Main==NULL) break; + if (optimizing) OptChunk(Main); + if (listing) PrintChunk(Main); } } -static void do_undump(ZIO* z) +static void doit(int undump, char* filename) { - TFunc* Main; - while ((Main=luaI_undump1(z))) + FILE* f; + ZIO z; + if (filename==NULL) { - if (listing) - { - TFunc* tf; - for (tf=Main; tf!=NULL; tf=tf->next) - PrintFunction(tf,Main); - } - luaI_freefunc(Main); /* TODO: free others */ + f=stdin; filename="(stdin)"; + } + else + { + f=efopen(filename, undump ? "rb" : "r"); } + zFopen(&z,f,filename); + if (verbose) fprintf(stderr,"%s\n",filename); + if (undump) do_undump(&z); else do_compile(&z); + if (f!=stdin) fclose(f); } -static void undump(char* filename) +static FILE* efopen(char* name, char* mode) { - FILE* f= (filename==NULL) ? stdin : fopen(filename, "rb"); + FILE* f=fopen(name,mode); if (f==NULL) { - fprintf(stderr,"luac: cannot open "); - perror(filename); + fprintf(stderr,"luac: cannot open %sput file ",mode[0]=='r' ? "in" : "out"); + perror(name); exit(1); } - else - { - ZIO z; - zFopen(&z,f); - do_undump(&z); - fclose(f); - } + return f; } diff --git a/src/luac/luac.h b/src/luac/luac.h index 815824ca..c3d8d73a 100644 --- a/src/luac/luac.h +++ b/src/luac/luac.h @@ -1,25 +1,33 @@ /* -** luac.h -** definitions for luac compiler -** $Id: luac.h,v 1.8 1997/06/19 17:32:08 lhf Exp $ +** $Id: luac.h,v 1.6 1998/07/12 00:17:37 lhf Exp $ +** definitions for luac +** See Copyright Notice in lua.h */ -#include "inout.h" -#include "luamem.h" -#include "opcode.h" -#include "table.h" -#include "undump.h" +#include "lauxlib.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" -#define VarStr(i) (lua_table[i].varname->str) -#define VarLoc(i) (lua_table[i].varname->u.s.varindex) -#define StrStr(i) (lua_constant[i]->str) -#define StrLoc(i) (lua_constant[i]->u.s.constindex) +typedef struct +{ + char* name; + int size; + int op; + int class; + int arg; + int arg2; +} Opcode; -extern Word lua_ntable; -extern Word lua_nconstant; -extern int lua_debug; +int OpcodeInfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE); +int CodeSize(TProtoFunc* tf); -void LinkFunctions(TFunc* tf); -void PrintFunction(TFunc* tf, TFunc* Main); -void DumpHeader(FILE* D); -void DumpFunction(TFunc* tf, FILE* D); +#define INFO(tf,p,I) OpcodeInfo(tf,p,I,__FILE__,__LINE__) +#define fileName(tf) ( (tf->fileName)==NULL ? NULL : tf->fileName->str ) + +#define NOP 255 +#define STACK -1 +#define ARGS -2 +#define VARARGS -3 diff --git a/src/luac/opcode.c b/src/luac/opcode.c new file mode 100644 index 00000000..c97e46a5 --- /dev/null +++ b/src/luac/opcode.c @@ -0,0 +1,87 @@ +/* +** $Id: opcode.c,v 1.4 1998/07/12 00:17:37 lhf Exp $ +** opcode information +** See Copyright Notice in lua.h +*/ + +#include "luac.h" + +static Opcode Info[]= /* ORDER lopcodes.h */ +{ +#include "opcode.h" +}; + +#define NOPCODES (sizeof(Info)/sizeof(Info[0])) + +int OpcodeInfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE) +{ + Opcode OP; + Byte* code=tf->code; + int op=*p; + if (p==code) + { + OP.name="STACK"; + OP.size=1; + OP.op=STACK; + OP.class=STACK; + OP.arg=op; + } + else if (p==code+1) + { + OP.size=1; + if (op>=ZEROVARARG) + { + OP.name="VARARGS"; + OP.op=VARARGS; + OP.class=VARARGS; + OP.arg=op-ZEROVARARG; + } + else + { + OP.name="ARGS"; + OP.op=ARGS; + OP.class=ARGS; + OP.arg=op; + } + } + else if (op==NOP) + { + OP.name="NOP"; + OP.size=1; + OP.op=NOP; + OP.class=NOP; + } + else if (op>=NOPCODES) /* cannot happen */ + { + luaL_verror("internal error at %s:%d: bad opcode %d at %d in tf=%p", + xFILE, xLINE,op,(int)(p-code),tf); + return 0; + } + else + { + OP=Info[op]; + if (op==SETLIST || op==CLOSURE || op==CALLFUNC) + { + OP.arg=p[1]; + OP.arg2=p[2]; + } + else if (OP.size==2) OP.arg=p[1]; + else if (OP.size>=3) OP.arg=(p[1]<<8)+p[2]; + if (op==SETLISTW || op==CLOSUREW) OP.arg2=p[3]; + } + *I=OP; + return OP.size; +} + +int CodeSize(TProtoFunc* tf) +{ + Byte* code=tf->code; + Byte* p=code; + while (1) + { + 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 new file mode 100644 index 00000000..805933c7 --- /dev/null +++ b/src/luac/opcode.h @@ -0,0 +1,134 @@ +/* +** $Id: opcode.h,v 1.3 1998/06/25 15:50:09 lhf Exp $ +** opcode info to be #included into opcode.c +** extracted automatically from lopcodes.h by mkopcodeh +** See Copyright Notice in lua.h +*/ +{ "ENDCODE", 1, ENDCODE, ENDCODE, ENDCODE-ENDCODE-1, 0 }, +{ "PUSHNIL", 2, PUSHNIL, PUSHNIL, PUSHNIL-PUSHNIL-1, 0 }, +{ "PUSHNIL0", 1, PUSHNIL0, PUSHNIL, PUSHNIL0-PUSHNIL-1, 0 }, +{ "PUSHNUMBER", 2, PUSHNUMBER, PUSHNUMBER, PUSHNUMBER-PUSHNUMBER-1, 0 }, +{ "PUSHNUMBER0", 1, PUSHNUMBER0, PUSHNUMBER, PUSHNUMBER0-PUSHNUMBER-1, 0 }, +{ "PUSHNUMBER1", 1, PUSHNUMBER1, PUSHNUMBER, PUSHNUMBER1-PUSHNUMBER-1, 0 }, +{ "PUSHNUMBER2", 1, PUSHNUMBER2, PUSHNUMBER, PUSHNUMBER2-PUSHNUMBER-1, 0 }, +{ "PUSHNUMBERW", 3, PUSHNUMBERW, PUSHNUMBER, PUSHNUMBERW-PUSHNUMBER-1, 0 }, +{ "PUSHCONSTANT", 2, PUSHCONSTANT, PUSHCONSTANT, PUSHCONSTANT-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT0", 1, PUSHCONSTANT0, PUSHCONSTANT, PUSHCONSTANT0-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT1", 1, PUSHCONSTANT1, PUSHCONSTANT, PUSHCONSTANT1-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT2", 1, PUSHCONSTANT2, PUSHCONSTANT, PUSHCONSTANT2-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT3", 1, PUSHCONSTANT3, PUSHCONSTANT, PUSHCONSTANT3-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT4", 1, PUSHCONSTANT4, PUSHCONSTANT, PUSHCONSTANT4-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT5", 1, PUSHCONSTANT5, PUSHCONSTANT, PUSHCONSTANT5-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT6", 1, PUSHCONSTANT6, PUSHCONSTANT, PUSHCONSTANT6-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANT7", 1, PUSHCONSTANT7, PUSHCONSTANT, PUSHCONSTANT7-PUSHCONSTANT-1, 0 }, +{ "PUSHCONSTANTW", 3, PUSHCONSTANTW, PUSHCONSTANT, PUSHCONSTANTW-PUSHCONSTANT-1, 0 }, +{ "PUSHUPVALUE", 2, PUSHUPVALUE, PUSHUPVALUE, PUSHUPVALUE-PUSHUPVALUE-1, 0 }, +{ "PUSHUPVALUE0", 1, PUSHUPVALUE0, PUSHUPVALUE, PUSHUPVALUE0-PUSHUPVALUE-1, 0 }, +{ "PUSHUPVALUE1", 1, PUSHUPVALUE1, PUSHUPVALUE, PUSHUPVALUE1-PUSHUPVALUE-1, 0 }, +{ "PUSHLOCAL", 2, PUSHLOCAL, PUSHLOCAL, PUSHLOCAL-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL0", 1, PUSHLOCAL0, PUSHLOCAL, PUSHLOCAL0-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL1", 1, PUSHLOCAL1, PUSHLOCAL, PUSHLOCAL1-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL2", 1, PUSHLOCAL2, PUSHLOCAL, PUSHLOCAL2-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL3", 1, PUSHLOCAL3, PUSHLOCAL, PUSHLOCAL3-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL4", 1, PUSHLOCAL4, PUSHLOCAL, PUSHLOCAL4-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL5", 1, PUSHLOCAL5, PUSHLOCAL, PUSHLOCAL5-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL6", 1, PUSHLOCAL6, PUSHLOCAL, PUSHLOCAL6-PUSHLOCAL-1, 0 }, +{ "PUSHLOCAL7", 1, PUSHLOCAL7, PUSHLOCAL, PUSHLOCAL7-PUSHLOCAL-1, 0 }, +{ "GETGLOBAL", 2, GETGLOBAL, GETGLOBAL, GETGLOBAL-GETGLOBAL-1, 0 }, +{ "GETGLOBAL0", 1, GETGLOBAL0, GETGLOBAL, GETGLOBAL0-GETGLOBAL-1, 0 }, +{ "GETGLOBAL1", 1, GETGLOBAL1, GETGLOBAL, GETGLOBAL1-GETGLOBAL-1, 0 }, +{ "GETGLOBAL2", 1, GETGLOBAL2, GETGLOBAL, GETGLOBAL2-GETGLOBAL-1, 0 }, +{ "GETGLOBAL3", 1, GETGLOBAL3, GETGLOBAL, GETGLOBAL3-GETGLOBAL-1, 0 }, +{ "GETGLOBAL4", 1, GETGLOBAL4, GETGLOBAL, GETGLOBAL4-GETGLOBAL-1, 0 }, +{ "GETGLOBAL5", 1, GETGLOBAL5, GETGLOBAL, GETGLOBAL5-GETGLOBAL-1, 0 }, +{ "GETGLOBAL6", 1, GETGLOBAL6, GETGLOBAL, GETGLOBAL6-GETGLOBAL-1, 0 }, +{ "GETGLOBAL7", 1, GETGLOBAL7, GETGLOBAL, GETGLOBAL7-GETGLOBAL-1, 0 }, +{ "GETGLOBALW", 3, GETGLOBALW, GETGLOBAL, GETGLOBALW-GETGLOBAL-1, 0 }, +{ "GETTABLE", 1, GETTABLE, GETTABLE, GETTABLE-GETTABLE-1, 0 }, +{ "GETDOTTED", 2, GETDOTTED, GETDOTTED, GETDOTTED-GETDOTTED-1, 0 }, +{ "GETDOTTED0", 1, GETDOTTED0, GETDOTTED, GETDOTTED0-GETDOTTED-1, 0 }, +{ "GETDOTTED1", 1, GETDOTTED1, GETDOTTED, GETDOTTED1-GETDOTTED-1, 0 }, +{ "GETDOTTED2", 1, GETDOTTED2, GETDOTTED, GETDOTTED2-GETDOTTED-1, 0 }, +{ "GETDOTTED3", 1, GETDOTTED3, GETDOTTED, GETDOTTED3-GETDOTTED-1, 0 }, +{ "GETDOTTED4", 1, GETDOTTED4, GETDOTTED, GETDOTTED4-GETDOTTED-1, 0 }, +{ "GETDOTTED5", 1, GETDOTTED5, GETDOTTED, GETDOTTED5-GETDOTTED-1, 0 }, +{ "GETDOTTED6", 1, GETDOTTED6, GETDOTTED, GETDOTTED6-GETDOTTED-1, 0 }, +{ "GETDOTTED7", 1, GETDOTTED7, GETDOTTED, GETDOTTED7-GETDOTTED-1, 0 }, +{ "GETDOTTEDW", 3, GETDOTTEDW, GETDOTTED, GETDOTTEDW-GETDOTTED-1, 0 }, +{ "PUSHSELF", 2, PUSHSELF, PUSHSELF, PUSHSELF-PUSHSELF-1, 0 }, +{ "PUSHSELF0", 1, PUSHSELF0, PUSHSELF, PUSHSELF0-PUSHSELF-1, 0 }, +{ "PUSHSELF1", 1, PUSHSELF1, PUSHSELF, PUSHSELF1-PUSHSELF-1, 0 }, +{ "PUSHSELF2", 1, PUSHSELF2, PUSHSELF, PUSHSELF2-PUSHSELF-1, 0 }, +{ "PUSHSELF3", 1, PUSHSELF3, PUSHSELF, PUSHSELF3-PUSHSELF-1, 0 }, +{ "PUSHSELF4", 1, PUSHSELF4, PUSHSELF, PUSHSELF4-PUSHSELF-1, 0 }, +{ "PUSHSELF5", 1, PUSHSELF5, PUSHSELF, PUSHSELF5-PUSHSELF-1, 0 }, +{ "PUSHSELF6", 1, PUSHSELF6, PUSHSELF, PUSHSELF6-PUSHSELF-1, 0 }, +{ "PUSHSELF7", 1, PUSHSELF7, PUSHSELF, PUSHSELF7-PUSHSELF-1, 0 }, +{ "PUSHSELFW", 3, PUSHSELFW, PUSHSELF, PUSHSELFW-PUSHSELF-1, 0 }, +{ "CREATEARRAY", 2, CREATEARRAY, CREATEARRAY, CREATEARRAY-CREATEARRAY-1, 0 }, +{ "CREATEARRAY0", 1, CREATEARRAY0, CREATEARRAY, CREATEARRAY0-CREATEARRAY-1, 0 }, +{ "CREATEARRAY1", 1, CREATEARRAY1, CREATEARRAY, CREATEARRAY1-CREATEARRAY-1, 0 }, +{ "CREATEARRAYW", 3, CREATEARRAYW, CREATEARRAY, CREATEARRAYW-CREATEARRAY-1, 0 }, +{ "SETLOCAL", 2, SETLOCAL, SETLOCAL, SETLOCAL-SETLOCAL-1, 0 }, +{ "SETLOCAL0", 1, SETLOCAL0, SETLOCAL, SETLOCAL0-SETLOCAL-1, 0 }, +{ "SETLOCAL1", 1, SETLOCAL1, SETLOCAL, SETLOCAL1-SETLOCAL-1, 0 }, +{ "SETLOCAL2", 1, SETLOCAL2, SETLOCAL, SETLOCAL2-SETLOCAL-1, 0 }, +{ "SETLOCAL3", 1, SETLOCAL3, SETLOCAL, SETLOCAL3-SETLOCAL-1, 0 }, +{ "SETLOCAL4", 1, SETLOCAL4, SETLOCAL, SETLOCAL4-SETLOCAL-1, 0 }, +{ "SETLOCAL5", 1, SETLOCAL5, SETLOCAL, SETLOCAL5-SETLOCAL-1, 0 }, +{ "SETLOCAL6", 1, SETLOCAL6, SETLOCAL, SETLOCAL6-SETLOCAL-1, 0 }, +{ "SETLOCAL7", 1, SETLOCAL7, SETLOCAL, SETLOCAL7-SETLOCAL-1, 0 }, +{ "SETGLOBAL", 2, SETGLOBAL, SETGLOBAL, SETGLOBAL-SETGLOBAL-1, 0 }, +{ "SETGLOBAL0", 1, SETGLOBAL0, SETGLOBAL, SETGLOBAL0-SETGLOBAL-1, 0 }, +{ "SETGLOBAL1", 1, SETGLOBAL1, SETGLOBAL, SETGLOBAL1-SETGLOBAL-1, 0 }, +{ "SETGLOBAL2", 1, SETGLOBAL2, SETGLOBAL, SETGLOBAL2-SETGLOBAL-1, 0 }, +{ "SETGLOBAL3", 1, SETGLOBAL3, SETGLOBAL, SETGLOBAL3-SETGLOBAL-1, 0 }, +{ "SETGLOBAL4", 1, SETGLOBAL4, SETGLOBAL, SETGLOBAL4-SETGLOBAL-1, 0 }, +{ "SETGLOBAL5", 1, SETGLOBAL5, SETGLOBAL, SETGLOBAL5-SETGLOBAL-1, 0 }, +{ "SETGLOBAL6", 1, SETGLOBAL6, SETGLOBAL, SETGLOBAL6-SETGLOBAL-1, 0 }, +{ "SETGLOBAL7", 1, SETGLOBAL7, SETGLOBAL, SETGLOBAL7-SETGLOBAL-1, 0 }, +{ "SETGLOBALW", 3, SETGLOBALW, SETGLOBAL, SETGLOBALW-SETGLOBAL-1, 0 }, +{ "SETTABLE0", 1, SETTABLE0, SETTABLE0, SETTABLE0-SETTABLE0-1, 0 }, +{ "SETTABLE", 2, SETTABLE, SETTABLE, SETTABLE-SETTABLE-1, 0 }, +{ "SETLIST", 3, SETLIST, SETLIST, SETLIST-SETLIST-1, 0 }, +{ "SETLIST0", 2, SETLIST0, SETLIST, SETLIST0-SETLIST-1, 0 }, +{ "SETLISTW", 4, SETLISTW, SETLIST, SETLISTW-SETLIST-1, 0 }, +{ "SETMAP", 2, SETMAP, SETMAP, SETMAP-SETMAP-1, 0 }, +{ "SETMAP0", 1, SETMAP0, SETMAP, SETMAP0-SETMAP-1, 0 }, +{ "EQOP", 1, EQOP, EQOP, EQOP-EQOP-1, 0 }, +{ "NEQOP", 1, NEQOP, NEQOP, NEQOP-NEQOP-1, 0 }, +{ "LTOP", 1, LTOP, LTOP, LTOP-LTOP-1, 0 }, +{ "LEOP", 1, LEOP, LEOP, LEOP-LEOP-1, 0 }, +{ "GTOP", 1, GTOP, GTOP, GTOP-GTOP-1, 0 }, +{ "GEOP", 1, GEOP, GEOP, GEOP-GEOP-1, 0 }, +{ "ADDOP", 1, ADDOP, ADDOP, ADDOP-ADDOP-1, 0 }, +{ "SUBOP", 1, SUBOP, SUBOP, SUBOP-SUBOP-1, 0 }, +{ "MULTOP", 1, MULTOP, MULTOP, MULTOP-MULTOP-1, 0 }, +{ "DIVOP", 1, DIVOP, DIVOP, DIVOP-DIVOP-1, 0 }, +{ "POWOP", 1, POWOP, POWOP, POWOP-POWOP-1, 0 }, +{ "CONCOP", 1, CONCOP, CONCOP, CONCOP-CONCOP-1, 0 }, +{ "MINUSOP", 1, MINUSOP, MINUSOP, MINUSOP-MINUSOP-1, 0 }, +{ "NOTOP", 1, NOTOP, NOTOP, NOTOP-NOTOP-1, 0 }, +{ "ONTJMP", 2, ONTJMP, ONTJMP, ONTJMP-ONTJMP-1, 0 }, +{ "ONTJMPW", 3, ONTJMPW, ONTJMP, ONTJMPW-ONTJMP-1, 0 }, +{ "ONFJMP", 2, ONFJMP, ONFJMP, ONFJMP-ONFJMP-1, 0 }, +{ "ONFJMPW", 3, ONFJMPW, ONFJMP, ONFJMPW-ONFJMP-1, 0 }, +{ "JMP", 2, JMP, JMP, JMP-JMP-1, 0 }, +{ "JMPW", 3, JMPW, JMP, JMPW-JMP-1, 0 }, +{ "IFFJMP", 2, IFFJMP, IFFJMP, IFFJMP-IFFJMP-1, 0 }, +{ "IFFJMPW", 3, IFFJMPW, IFFJMP, IFFJMPW-IFFJMP-1, 0 }, +{ "IFTUPJMP", 2, IFTUPJMP, IFTUPJMP, IFTUPJMP-IFTUPJMP-1, 0 }, +{ "IFTUPJMPW", 3, IFTUPJMPW, IFTUPJMP, IFTUPJMPW-IFTUPJMP-1, 0 }, +{ "IFFUPJMP", 2, IFFUPJMP, IFFUPJMP, IFFUPJMP-IFFUPJMP-1, 0 }, +{ "IFFUPJMPW", 3, IFFUPJMPW, IFFUPJMP, IFFUPJMPW-IFFUPJMP-1, 0 }, +{ "CLOSURE", 3, CLOSURE, CLOSURE, CLOSURE-CLOSURE-1, 0 }, +{ "CLOSUREW", 4, CLOSUREW, CLOSURE, CLOSUREW-CLOSURE-1, 0 }, +{ "CALLFUNC", 3, CALLFUNC, CALLFUNC, CALLFUNC-CALLFUNC-1, 0 }, +{ "CALLFUNC0", 2, CALLFUNC0, CALLFUNC, CALLFUNC0-CALLFUNC-1, 0 }, +{ "CALLFUNC1", 2, CALLFUNC1, CALLFUNC, CALLFUNC1-CALLFUNC-1, 0 }, +{ "RETCODE", 2, RETCODE, RETCODE, RETCODE-RETCODE-1, 0 }, +{ "SETLINE", 2, SETLINE, SETLINE, SETLINE-SETLINE-1, 0 }, +{ "SETLINEW", 3, SETLINEW, SETLINE, SETLINEW-SETLINE-1, 0 }, +{ "POP", 2, POP, POP, POP-POP-1, 0 }, +{ "POP0", 1, POP0, POP, POP0-POP-1, 0 }, +{ "POP1", 1, POP1, POP, POP1-POP-1, 0 }, diff --git a/src/luac/opt.c b/src/luac/opt.c new file mode 100644 index 00000000..5084ddee --- /dev/null +++ b/src/luac/opt.c @@ -0,0 +1,228 @@ +/* +** $Id: opt.c,v 1.4 1998/04/02 20:44:08 lhf Exp $ +** optimize bytecodes +** See Copyright Notice in lua.h +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "luac.h" +#include "lmem.h" + +static void FixConstants(TProtoFunc* tf, int* C) +{ + Byte* code=tf->code; + Byte* p=code; + while (1) + { + Opcode OP; + int n=INFO(tf,p,&OP); + int op=OP.class; + int i=OP.arg; + if (op==ENDCODE) break; + if ( op==PUSHCONSTANT || op==GETDOTTED || op==PUSHSELF || + op==GETGLOBAL || op==SETGLOBAL) + { + int j=C[i]; + if (j==i) + ; + else if (n==1) + { + p[0]=op+j+1; + } + else if (n==2) + { + if (j<8) { p[0]=op+j+1; p[1]=NOP; } else p[1]=j; + } + else + { + if (j<=255) + { + p[0]=op; + p[1]=j; + p[2]=NOP; + } + else + { + p[1]= 0x0000FF & (j>>8); + p[2]= 0x0000FF & j; + } + } + } + p+=n; + } +} + +static TProtoFunc* TF; + +static int compare(const void* a, const void *b) +{ + int ia=*(int*)a; + int ib=*(int*)b; + int t; + TObject* oa=TF->consts+ia; + TObject* ob=TF->consts+ib; + t=ttype(oa)-ttype(ob); if (t) return t; + t=oa->value.i-ob->value.i; if (t) return t; + return ia-ib; +} + +static void OptConstants(TProtoFunc* tf) +{ + static int* C=NULL; + static int* D=NULL; + int i,k; + int n=tf->nconsts; + if (n==0) return; + C=luaM_reallocvector(C,n,int); + D=luaM_reallocvector(D,n,int); + for (i=0; i<n; i++) C[i]=D[i]=i; /* group duplicates */ + TF=tf; qsort(C,n,sizeof(C[0]),compare); + k=C[0]; /* build duplicate table */ + for (i=1; i<n; i++) + { + int j=C[i]; + TObject* oa=tf->consts+k; + TObject* ob=tf->consts+j; + if (ttype(oa)==ttype(ob) && oa->value.i==ob->value.i) D[j]=k; else k=j; + } + k=0; /* build rename map & pack constants */ + for (i=0; i<n; i++) + { + if (D[i]==i) { tf->consts[k]=tf->consts[i]; C[i]=k++; } else C[i]=C[D[i]]; + } + if (k>=n) return; +printf("\t\"%s\":%d reduced constants from %d to %d\n", + tf->fileName->str,tf->lineDefined,n,k); + tf->nconsts=k; + FixConstants(tf,C); +} + +static int NoDebug(TProtoFunc* tf) +{ + Byte* code=tf->code; + Byte* p=code; + int nop=0; + while (1) /* change SETLINE to NOP */ + { + Opcode OP; + int n=INFO(tf,p,&OP); + int op=OP.class; + if (op==ENDCODE) break; + if (op==NOP) ++nop; + if (op==SETLINE) { nop+=n; memset(p,NOP,n); } + 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==ENDCODE) break; + if (op==NOP) ++nop; + p+=n; + } + return nop; +} + +static void FixJumps(TProtoFunc* tf) +{ + Byte* code=tf->code; + Byte* p=code; + while (1) + { + Opcode OP; + int n=INFO(tf,p,&OP); + int op=OP.class; + int i=OP.arg; + int nop; + if (op==ENDCODE) break; + nop=0; + 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); + if (nop>0) + { + int j=i-nop; + if (n==2) + p[1]=j; + else +#if 0 + { + if (j<=255) /* does NOT work for nested loops */ + { + if (op==IFTUPJMP || op==IFFUPJMP) --j; + p[0]=OP.op-1; /* *JMP and *JMPW are consecutive */ + p[1]=j; + p[2]=NOP; + } + else +#endif + { + p[1]= 0x0000FF & (j>>8); + p[2]= 0x0000FF & j; + } +#if 0 + } +#endif + } + p+=n; + } +} + +static void PackCode(TProtoFunc* tf) +{ + Byte* code=tf->code; + Byte* p=code; + Byte* q=code; + while (1) + { + 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\"%s\":%d reduced code from %d to %d\n", + tf->fileName->str,tf->lineDefined,(int)(p-code),(int)(q-code)); +} + +static void OptCode(TProtoFunc* tf) +{ + int nop=NoDebug(tf); + if (nop==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) +{ + tf->locvars=NULL; /* remove local variables table */ + OptConstants(tf); + OptCode(tf); + OptFunctions(tf); +} + +void OptChunk(TProtoFunc* Main) +{ + OptFunction(Main); +} diff --git a/src/luac/print.c b/src/luac/print.c index fb7bf8a7..ce985390 100644 --- a/src/luac/print.c +++ b/src/luac/print.c @@ -1,383 +1,233 @@ /* -** print.c +** $Id: print.c,v 1.13 1998/07/12 00:17:37 lhf Exp $ ** print bytecodes +** See Copyright Notice in lua.h */ -char* rcs_print="$Id: print.c,v 1.17 1997/06/25 17:07:28 lhf Exp $"; - #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "luac.h" -#include "print.h" -void LinkFunctions(TFunc* m) +#ifdef DEBUG +void PrintConstant1(TProtoFunc* tf, int i) +{ + TObject* o=tf->consts+i; + printf("%6d ",i); + if (i<0 || i>=tf->nconsts) + printf("(bad constant #%d: max=%d)",i,tf->nconsts); + else + switch (ttype(o)) + { + case LUA_T_NUMBER: + printf("N " NUMBER_FMT "\n",nvalue(o)); /* LUA_NUMBER */ + break; + case LUA_T_STRING: + printf("S %p\t\"%s\"\n",(void*)tsvalue(o),svalue(o)); + break; + case LUA_T_PROTO: + printf("F %p\n",(void*)tfvalue(o)); + break; + default: /* cannot happen */ + printf("? %d\n",ttype(o)); + break; + } +} + +static void PrintConstants(TProtoFunc* tf) { - static TFunc* lastF; /* list of functions seen in code */ - Byte* code=m->code; - Byte* end=code+m->size; - Byte* p; - if (IsMain(m)) lastF=m; - for (p=code; p!=end;) + int i,n=tf->nconsts; + printf("constants (%d):\n",n); + for (i=0; i<n; i++) PrintConstant1(tf,i); +} +#endif + +static void PrintConstant(TProtoFunc* tf, int i) +{ + if (i<0 || i>=tf->nconsts) + printf("(bad constant #%d: max=%d)",i,tf->nconsts); + else { - int op=*p; - int at=p-code+1; - switch (op) - { - case PUSHNIL: - case PUSH0: - case PUSH1: - case PUSH2: - case PUSHLOCAL0: - case PUSHLOCAL1: - case PUSHLOCAL2: - case PUSHLOCAL3: - case PUSHLOCAL4: - case PUSHLOCAL5: - case PUSHLOCAL6: - case PUSHLOCAL7: - case PUSHLOCAL8: - case PUSHLOCAL9: - case PUSHINDEXED: - case STORELOCAL0: - case STORELOCAL1: - case STORELOCAL2: - case STORELOCAL3: - case STORELOCAL4: - case STORELOCAL5: - case STORELOCAL6: - case STORELOCAL7: - case STORELOCAL8: - case STORELOCAL9: - case STOREINDEXED0: - case ADJUST0: - case EQOP: - case LTOP: - case LEOP: - case GTOP: - case GEOP: - case ADDOP: - case SUBOP: - case MULTOP: - case DIVOP: - case POWOP: - case CONCOP: - case MINUSOP: - case NOTOP: - case POP: - case RETCODE0: - p++; - break; - case PUSHBYTE: - case PUSHLOCAL: - case STORELOCAL: - case STOREINDEXED: - case STORELIST0: - case ADJUST: - case RETCODE: - case VARARGS: - case STOREMAP: - p+=2; - break; - case PUSHWORD: - case PUSHSTRING: - case PUSHGLOBAL: - case PUSHSELF: - case STOREGLOBAL: - case CREATEARRAY: - case ONTJMP: - case ONFJMP: - case JMP: - case UPJMP: - case IFFJMP: - case IFFUPJMP: - case CALLFUNC: - case SETLINE: - case STORELIST: - p+=3; - break; - case PUSHFLOAT: - p+=5; /* assumes sizeof(float)==4 */ - break; - case PUSHFUNCTION: - { - TFunc* tf; - p++; - get_code(tf,p); - tf->marked=at; - tf->next=NULL; /* TODO: remove? */ - lastF=lastF->next=tf; - break; - } - case STORERECORD: - { - int n=*++p; - p+=2*n+1; - break; - } - default: /* cannot happen */ - fprintf(stderr,"luac: bad opcode %d at %d\n",*p,(int)(p-code)); - exit(1); - break; - } + TObject* o=tf->consts+i; + switch (ttype(o)) + { + case LUA_T_NUMBER: + printf(NUMBER_FMT,nvalue(o)); /* LUA_NUMBER */ + 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 */ + printf("(bad constant #%d: type=%d [%s])\n",i,ttype(o),luaO_typename(o)); + break; + } } } -#define LocStr(i) luaI_getlocalname(tf,i+1,line) +#define VarStr(i) svalue(tf->consts+i) -static void PrintCode(TFunc* tf) +static void PrintCode(TProtoFunc* tf) { Byte* code=tf->code; - Byte* end=code+tf->size; - Byte* p; + Byte* p=code; int line=0; - for (p=code; p!=end;) + while (1) { - int op=*p; - if (op>=NOPCODES) - { - fprintf(stderr,"luac: bad opcode %d at %d\n",op,(int)(p-code)); - exit(1); - } - printf("%6d\t%s",(int)(p-code),OpCodeName[op]); - switch (op) - { - case PUSHNIL: - case PUSH0: - case PUSH1: - case PUSH2: - case PUSHINDEXED: - case STOREINDEXED0: - case ADJUST0: - case EQOP: - case LTOP: - case LEOP: - case GTOP: - case GEOP: - case ADDOP: - case SUBOP: - case MULTOP: - case DIVOP: - case POWOP: - case CONCOP: - case MINUSOP: - case NOTOP: - case POP: - case RETCODE0: - p++; - break; - case PUSHLOCAL0: - case PUSHLOCAL1: - case PUSHLOCAL2: - case PUSHLOCAL3: - case PUSHLOCAL4: - case PUSHLOCAL5: - case PUSHLOCAL6: - case PUSHLOCAL7: - case PUSHLOCAL8: - case PUSHLOCAL9: + Opcode OP; + int n=INFO(tf,p,&OP); + int op=OP.op; + int i=OP.arg; + printf("%6d ",(int)(p-code)); { - int i=op-PUSHLOCAL0; - if (tf->locvars) printf("\t\t; %s",LocStr(i)); - p++; - break; + Byte* q=p; + int j=n; + while (j--) printf("%02X",*q++); } - case STORELOCAL0: - case STORELOCAL1: - case STORELOCAL2: - case STORELOCAL3: - case STORELOCAL4: - case STORELOCAL5: - case STORELOCAL6: - case STORELOCAL7: - case STORELOCAL8: - case STORELOCAL9: + printf("%*s%-13s",2*(5-n),"",OP.name); + + if (n!=1 || op<0) printf("\t%d",i); else if (i>=0) printf("\t"); + + switch (OP.class) { - int i=op-STORELOCAL0; - if (tf->locvars) printf("\t\t; %s",LocStr(i)); - p++; + + case ENDCODE: + printf("\n"); + return; + + case CLOSURE: + printf(" %d",OP.arg2); + case PUSHCONSTANT: + case GETDOTTED: + case PUSHSELF: + printf("\t; "); + PrintConstant(tf,i); break; - } + case PUSHLOCAL: - case STORELOCAL: + case SETLOCAL: { - int i=*(p+1); - if (tf->locvars) printf("\t%d\t; %s",i,LocStr(i)); - p+=2; + char* s=luaF_getlocalname(tf,i+1,line); + if (s) printf("\t; %s",s); break; } - case PUSHBYTE: - case STOREINDEXED: - case STORELIST0: - case ADJUST: - case RETCODE: - case VARARGS: - case STOREMAP: - printf("\t%d",*(p+1)); - p+=2; + + case GETGLOBAL: + case SETGLOBAL: + printf("\t; %s",VarStr(i)); + break; + + case SETLIST: + case CALLFUNC: + if (n>=3) printf(" %d",OP.arg2); break; - case PUSHWORD: - case CREATEARRAY: + case SETLINE: - { - Word w; - p++; - get_word(w,p); - printf("\t%d",w); - if (op==SETLINE) line=w; + printf("\t; \"%s\":%d",fileName(tf),line=i); break; - } + +/* suggested by Norman Ramsey <nr@cs.virginia.edu> */ + case IFTUPJMP: + case IFFUPJMP: + i=-i; case ONTJMP: case ONFJMP: case JMP: case IFFJMP: - { /* suggested by Norman Ramsey <nr@cs.virginia.edu> */ - Word w; - p++; - get_word(w,p); - printf("\t%d\t\t; to %d",w,(int)(p-code)+w); - break; - } - case UPJMP: - case IFFUPJMP: - { /* suggested by Norman Ramsey <nr@cs.virginia.edu> */ - Word w; - p++; - get_word(w,p); - printf("\t%d\t\t; to %d",w,(int)(p-code)-w); - break; - } - case PUSHFLOAT: - { - float f; - p++; - get_float(f,p); - printf("\t%g",f); - break; - } - case PUSHSELF: - case PUSHSTRING: - { - Word w; - p++; - get_word(w,p); - printf("\t%d\t; \"%s\"",w,StrStr(w)); - break; - } - case PUSHFUNCTION: - { - TFunc* tf; - p++; - get_code(tf,p); - printf("\t%p\t; \"%s\":%d",tf,tf->fileName,tf->lineDefined); - break; - } - case PUSHGLOBAL: - case STOREGLOBAL: - { - Word w; - p++; - get_word(w,p); - printf("\t%d\t; %s",w,VarStr(w)); - break; - } - case STORELIST: - case CALLFUNC: - printf("\t%d %d",*(p+1),*(p+2)); - p+=3; - break; - case STORERECORD: - { - int n=*++p; - printf("\t%d",n); - p++; - while (n--) - { - Word w; - printf("\n%6d\t FIELD",(int)(p-code)); - get_word(w,p); - printf("\t%d\t; \"%s\"",w,StrStr(w)); - } - break; - } - default: - printf("\tcannot happen: opcode=%d\n",*p); - fprintf(stderr,"luac: bad opcode %d at %d\n",op,(int)(p-code)); - exit(1); + printf("\t; to %d",(int)(p-code)+i+n); break; + } printf("\n"); + p+=n; } } -#undef LocStr - -static void PrintLocals(LocVar* v, int n) +static void PrintLocals(TProtoFunc* tf) { - int i=0; + LocVar* v=tf->locvars; + int n,i=0; if (v==NULL || v->varname==NULL) return; + n=tf->code[1]; if (n>=ZEROVARARG) n-=ZEROVARARG; + + printf("locals:"); if (n>0) { - printf("parameters:"); - for (i=0; i<n; v++,i++) printf(" %s[%d@%d]",v->varname->str,i,v->line); - printf("\n"); + for (i=0; i<n; v++,i++) printf(" %s",v->varname->str); } if (v->varname!=NULL) { - printf("locals:"); for (; v->line>=0; v++) { if (v->varname==NULL) -#if 0 - printf(" %s[%d@%d]","*",--i,v->line); -#else - --i; -#endif + { + printf(")"); --i; + } else - printf(" %s[%d@%d]",v->varname->str,i++,v->line); + { + printf(" (%s",v->varname->str); i++; + } } - printf("\n"); + i-=n; + while (i--) printf(")"); } + printf("\n"); } -void PrintFunction(TFunc* tf, TFunc* Main) +static void PrintHeader(TProtoFunc* tf, TProtoFunc* Main, int at) { - int n=0; + int size=CodeSize(tf); if (IsMain(tf)) - printf("\nmain of \"%s\" (%d bytes at %p)\n",tf->fileName,tf->size,tf); - else + printf("\nmain of \"%s\" (%d bytes at %p)\n",fileName(tf),size,(void*)tf); + else if (Main) + { + printf("\nfunction defined at \"%s\":%d (%d bytes at %p); used at ", + fileName(tf),tf->lineDefined,size,(void*)tf); + if (IsMain(Main)) + printf("main"); + else + printf("%p",(void*)Main); + printf("+%d\n",at); + } +} + +static void PrintFunction(TProtoFunc* tf, TProtoFunc* Main, int at); + +static void PrintFunctions(TProtoFunc* Main) +{ + Byte* code=Main->code; + Byte* p=code; + while (1) { - Byte* p; - p=tf->code; /* get number of parameters */ - while (*p==SETLINE) p+=3; - if (*p==ADJUST) n=p[1]; - p=Main->code+tf->marked+sizeof(TFunc*); - printf("\nfunction "); - switch (*p) /* try to get name */ + Opcode OP; + int n=INFO(Main,p,&OP); + if (OP.class==ENDCODE) break; + if (OP.class==PUSHCONSTANT || OP.class==CLOSURE) { - case STOREGLOBAL: - { - Word w; - p++; get_word(w,p); printf("%s defined at ",VarStr(w)); - break; - } - case STOREINDEXED0: /* try method definition */ - { - if (p[-11]==PUSHGLOBAL && p[-8]==PUSHSTRING) - { - Word w; - Byte* op=p; - int c=(tf->locvars && n>0 && strcmp(tf->locvars->varname->str,"self")==0) - ? ':' : '.'; - p=op-11; p++; get_word(w,p); printf("%s%c",VarStr(w),c); - p=op-8; p++; get_word(w,p); printf("%s defined at ",StrStr(w)); - } - break; - } + int i=OP.arg; + TObject* o=Main->consts+i; + if (ttype(o)==LUA_T_PROTO) PrintFunction(tfvalue(o),Main,(int)(p-code)); } - printf("\"%s\":%d (%d bytes at %p); used at main+%d\n", - tf->fileName,tf->lineDefined,tf->size,tf,tf->marked); + p+=n; } - PrintLocals(tf->locvars,n); +} + +static void PrintFunction(TProtoFunc* tf, TProtoFunc* Main, int at) +{ + PrintHeader(tf,Main,at); + PrintLocals(tf); PrintCode(tf); +#ifdef DEBUG + PrintConstants(tf); +#endif + PrintFunctions(tf); +} + +void PrintChunk(TProtoFunc* Main) +{ + PrintFunction(Main,0,0); } diff --git a/src/luac/print.h b/src/luac/print.h deleted file mode 100644 index 00e344ca..00000000 --- a/src/luac/print.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -** print.h -** opcode names -** $Id: print.h,v 1.3 1997/04/14 14:42:50 lhf Exp $ -*/ - -static char* OpCodeName[]={ /* ATTENTION: same order as enum in opcode.h */ - "PUSHNIL", - "PUSH0", - "PUSH1", - "PUSH2", - "PUSHBYTE", - "PUSHWORD", - "PUSHFLOAT", - "PUSHSTRING", - "PUSHFUNCTION", - "PUSHLOCAL0", - "PUSHLOCAL1", - "PUSHLOCAL2", - "PUSHLOCAL3", - "PUSHLOCAL4", - "PUSHLOCAL5", - "PUSHLOCAL6", - "PUSHLOCAL7", - "PUSHLOCAL8", - "PUSHLOCAL9", - "PUSHLOCAL", - "PUSHGLOBAL", - "PUSHINDEXED", - "PUSHSELF", - "STORELOCAL0", - "STORELOCAL1", - "STORELOCAL2", - "STORELOCAL3", - "STORELOCAL4", - "STORELOCAL5", - "STORELOCAL6", - "STORELOCAL7", - "STORELOCAL8", - "STORELOCAL9", - "STORELOCAL", - "STOREGLOBAL", - "STOREINDEXED0", - "STOREINDEXED", - "STORELIST0", - "STORELIST", - "STORERECORD", - "ADJUST0", - "ADJUST", - "CREATEARRAY", - "EQOP", - "LTOP", - "LEOP", - "GTOP", - "GEOP", - "ADDOP", - "SUBOP", - "MULTOP", - "DIVOP", - "POWOP", - "CONCOP", - "MINUSOP", - "NOTOP", - "ONTJMP", - "ONFJMP", - "JMP", - "UPJMP", - "IFFJMP", - "IFFUPJMP", - "POP", - "CALLFUNC", - "RETCODE0", - "RETCODE", - "SETLINE", - "VARARGS", - "STOREMAP" -}; - -#define NOPCODES (sizeof(OpCodeName)/sizeof(OpCodeName[0])) diff --git a/src/luac/stubs.c b/src/luac/stubs.c new file mode 100644 index 00000000..d42bec25 --- /dev/null +++ b/src/luac/stubs.c @@ -0,0 +1,68 @@ +/* +** $Id: stubs.c,v 1.8 1998/07/12 00:17:37 lhf Exp $ +** avoid runtime modules in luac +** See Copyright Notice in lua.h +*/ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include "luac.h" + +/* +* avoid lapi lauxlib lbuiltin ldo lgc ltable ltm lvm +* use only lbuffer lfunc llex lmem lobject lparser lstate lstring lzio +*/ + +/* simplified from ldo.c */ +void lua_error(char* s) +{ + 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); +} + +/* 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; +} + +/* avoid runtime modules in lstate.c */ +void luaB_predefine(void){} +void luaC_hashcallIM(Hash *l){} +void luaC_strcallIM(TaggedString *l){} +void luaD_gcIM(TObject *o){} +void luaD_init(void){} +void luaH_free(Hash *frees){} +void luaT_init(void){} + +/* +* the code below avoids the lexer and the parser (llex lparser). +* it is useful if you only want to load binary files. +* this works for interpreters like lua.c too. +*/ + +#ifdef NOPARSER + +int lua_debug=0; + +void luaX_init(void){} +void luaY_init(void){} +void luaY_parser(void) { lua_error("parser not loaded"); } + +#endif |
