summaryrefslogtreecommitdiff
path: root/src/luac
diff options
context:
space:
mode:
authorLua Team <team@lua.org>1998-07-11 12:00:00 +0000
committerrepogen <>1998-07-11 12:00:00 +0000
commit377347776f1f3d820f92151f70bec667f96d5e6b (patch)
treecdb3ba26158df33547dfe765547177afcee119d1 /src/luac
parent4f8c5d0f284e1f4da717aea5008915f185cd2e05 (diff)
downloadlua-github-3.1.tar.gz
Lua 3.13.1
Diffstat (limited to 'src/luac')
-rw-r--r--src/luac/Makefile16
-rw-r--r--src/luac/README25
-rw-r--r--src/luac/dump.c302
-rw-r--r--src/luac/luac.c176
-rw-r--r--src/luac/luac.h46
-rw-r--r--src/luac/opcode.c87
-rw-r--r--src/luac/opcode.h134
-rw-r--r--src/luac/opt.c228
-rw-r--r--src/luac/print.c492
-rw-r--r--src/luac/print.h79
-rw-r--r--src/luac/stubs.c68
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