Cross compiling Lua byte code

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Cross compiling Lua byte code

Ivaylo Beltchev
Hi

I was wondering if it is possible to compile a chunk using a x86 Lua using doubles, and run it on a PowerPC Lua using floats. Both are version 5.1.
There are 2 problems here - byte order and double vs. float. Is it possible (and easy) to post-process the binary output to convert from one format to the other? Can there be any other incompatibilities between the architectures?

Is it even worth it? If anyone is using pre-compiled chunks, can you comment on the performance improvements you get vs. using text files?

Thanks
Ivo

Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Kein-Hong Man
Ivaylo Beltchev wrote:
> I was wondering if it is possible to compile a chunk using a x86 Lua using doubles, and run it on a PowerPC Lua using floats. Both are version 5.1.
> There are 2 problems here - byte order and double vs. float. Is it possible (and easy) to post-process the binary output to convert from one format to the other? Can there be any other incompatibilities between the architectures?

Hacking undump to do this should be pretty easy. This:
http://luaforge.net/projects/chunkspy/ can also do the job for you.

> Is it even worth it?

It is like driving on the autobahn with blindfolds. On one hand,
you might survive with nary a scratch, but on the other hand... I
see shades of Ariane 501.

> If anyone is using pre-compiled chunks, can you comment on the performance improvements you get vs. using text files?

Loading a binary chunk bypasses lexing and parsing, that's about
all. With fast processors, there isn't much difference. Has anyone
measured the difference?

--
Cheers,
Kein-Hong Man (esq.)
Kuala Lumpur, Malaysia

Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Mike Pall-5-2
In reply to this post by Ivaylo Beltchev
Hi,

Ivaylo Beltchev wrote:
> I was wondering if it is possible to compile a chunk using a
> x86 Lua using doubles, and run it on a PowerPC Lua using
> floats. Both are version 5.1. There are 2 problems here - byte
> order and double vs. float. Is it possible (and easy) to
> post-process the binary output to convert from one format to
> the other? Can there be any other incompatibilities between the
> architectures?

ChunkSpy is able to convert between the different machine
specific bytecode formats. See:
  http://luaforge.net/projects/chunkspy/

> Is it even worth it? If anyone is using pre-compiled chunks,
> can you comment on the performance improvements you get vs.
> using text files?

Loading a stripped, precompiled chunk (luac -s) is 6x - 8x faster
than loading the equivalent Lua source code (100 - 1000 lines,
including comments).

Bye,
     Mike
Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Luiz Henrique de Figueiredo
In reply to this post by Kein-Hong Man
> Hacking undump to do this should be pretty easy.

Here it is... (partially untested.)
Just be careful to build your PPC Lua with this module but your x86 Lua with
the original lundump.c.
--lhf

/*
** $Id: lundump.c,v 1.60 2006/02/16 15:53:49 lhf Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/

#include <string.h>

#define lundump_c
#define LUA_CORE

#include "lua.h"

#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstring.h"
#include "lundump.h"
#include "lzio.h"

typedef struct {
 lua_State* L;
 ZIO* Z;
 Mbuffer* b;
 const char* name;
 int swap;
} LoadState;

#ifdef LUAC_TRUST_BINARIES
#define IF(c,s)
#else
#define IF(c,s) if (c) error(S,s)

static void error(LoadState* S, const char* why)
{
 luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
 luaD_throw(S->L,LUA_ERRSYNTAX);
}
#endif

#define LoadByte(S) (lu_byte)LoadChar(S)
#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)

static void LoadBlock(LoadState* S, void* b, size_t size)
{
 size_t r=luaZ_read(S->Z,b,size);
 IF (r!=0, "unexpected end");
}

static void LoadMem (LoadState* S, void* b, int n, size_t size)
{
 LoadBlock(S,b,n*size);
 if (S->swap)
 {
  char* p=(char*) b;
  char c;
  switch (size)
  {
   case 1:
  break;
   case 2:
        while (n--)
        {
         c=p[0]; p[0]=p[1]; p[1]=c;
         p+=2;
        }
  break;
   case 4:
        while (n--)
        {
         c=p[0]; p[0]=p[3]; p[3]=c;
         c=p[1]; p[1]=p[2]; p[2]=c;
         p+=4;
        }
  break;
   case 8:
        while (n--)
        {
         c=p[0]; p[0]=p[7]; p[7]=c;
         c=p[1]; p[1]=p[6]; p[6]=c;
         c=p[2]; p[2]=p[5]; p[5]=c;
         c=p[3]; p[3]=p[4]; p[4]=c;
         p+=8;
        }
  break;
   default:
    IF(1, "bad size");
  break;
  }
 }
}

static int LoadChar(LoadState* S)
{
 char x;
 LoadVar(S,x);
 return x;
}

static int LoadInt(LoadState* S)
{
 int x;
 LoadVar(S,x);
 IF (x<0, "bad integer");
 return x;
}

static lua_Number LoadNumber(LoadState* S)
{
 double x;
 LoadVar(S,x);
 return (lua_Number) x;
}

static TString* LoadString(LoadState* S)
{
 size_t size;
 LoadVar(S,size);
 if (size==0)
  return NULL;
 else
 {
  char* s=luaZ_openspace(S->L,S->b,size);
  LoadBlock(S,s,size);
  return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
 }
}

static void LoadCode(LoadState* S, Proto* f)
{
 int n=LoadInt(S);
 f->code=luaM_newvector(S->L,n,Instruction);
 f->sizecode=n;
 LoadVector(S,f->code,n,sizeof(Instruction));
}

static Proto* LoadFunction(LoadState* S, TString* p);

static void LoadConstants(LoadState* S, Proto* f)
{
 int i,n;
 n=LoadInt(S);
 f->k=luaM_newvector(S->L,n,TValue);
 f->sizek=n;
 for (i=0; i<n; i++) setnilvalue(&f->k[i]);
 for (i=0; i<n; i++)
 {
  TValue* o=&f->k[i];
  int t=LoadChar(S);
  switch (t)
  {
   case LUA_TNIL:
    setnilvalue(o);
        break;
   case LUA_TBOOLEAN:
    setbvalue(o,LoadChar(S));
        break;
   case LUA_TNUMBER:
        setnvalue(o,LoadNumber(S));
        break;
   case LUA_TSTRING:
        setsvalue2n(S->L,o,LoadString(S));
        break;
   default:
        IF (1, "bad constant");
        break;
  }
 }
 n=LoadInt(S);
 f->p=luaM_newvector(S->L,n,Proto*);
 f->sizep=n;
 for (i=0; i<n; i++) f->p[i]=NULL;
 for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
}

static void LoadDebug(LoadState* S, Proto* f)
{
 int i,n;
 n=LoadInt(S);
 f->lineinfo=luaM_newvector(S->L,n,int);
 f->sizelineinfo=n;
 LoadVector(S,f->lineinfo,n,sizeof(int));
 n=LoadInt(S);
 f->locvars=luaM_newvector(S->L,n,LocVar);
 f->sizelocvars=n;
 for (i=0; i<n; i++) f->locvars[i].varname=NULL;
 for (i=0; i<n; i++)
 {
  f->locvars[i].varname=LoadString(S);
  f->locvars[i].startpc=LoadInt(S);
  f->locvars[i].endpc=LoadInt(S);
 }
 n=LoadInt(S);
 f->upvalues=luaM_newvector(S->L,n,TString*);
 f->sizeupvalues=n;
 for (i=0; i<n; i++) f->upvalues[i]=NULL;
 for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
}

static Proto* LoadFunction(LoadState* S, TString* p)
{
 Proto* f=luaF_newproto(S->L);
 setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
 f->source=LoadString(S); if (f->source==NULL) f->source=p;
 f->linedefined=LoadInt(S);
 f->lastlinedefined=LoadInt(S);
 f->nups=LoadByte(S);
 f->numparams=LoadByte(S);
 f->is_vararg=LoadByte(S);
 f->maxstacksize=LoadByte(S);
 LoadCode(S,f);
 LoadConstants(S,f);
 LoadDebug(S,f);
 IF (!luaG_checkcode(f), "bad code");
 S->L->top--;
 return f;
}

static void LoadHeader(LoadState* S)
{
 char h[LUAC_HEADERSIZE];
 char s[LUAC_HEADERSIZE];
 luaU_header(h);
 LoadBlock(S,s,LUAC_HEADERSIZE);
 S->swap=(s[6]!=h[6]); s[6]=h[6];
 s[10]=h[10];
 IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
}

/*
** load precompiled chunk
*/
Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
{
 LoadState S;
 if (*name=='@' || *name=='=')
  S.name=name+1;
 else if (*name==LUA_SIGNATURE[0])
  S.name="binary string";
 else
  S.name=name;
 S.L=L;
 S.Z=Z;
 S.b=buff;
 LoadHeader(&S);
 return LoadFunction(&S,luaS_newliteral(L,"=?"));
}

/*
* make header
*/
void luaU_header (char* h)
{
 int x=1;
 memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
 h+=sizeof(LUA_SIGNATURE)-1;
 *h++=(char)LUAC_VERSION;
 *h++=(char)LUAC_FORMAT;
 *h++=(char)*(char*)&x; /* endianness */
 *h++=(char)sizeof(int);
 *h++=(char)sizeof(size_t);
 *h++=(char)sizeof(Instruction);
 *h++=(char)sizeof(lua_Number);
 *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
}
Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Joshua Jensen
Luiz Henrique de Figueiredo wrote:
> void luaU_header (char* h)
> {
>  int x=1;
>  *h++=(char)*(char*)&x; /* endianness */
> }
>  
A small point of interest.  When working the Xbox 360, the above
endianness didn't work using a local variable.  Instead, I had to create
a static global.  :(  This was under Lua 5.0, but I'm guessing it will
still apply now.

static int x = 1;

int luaU_endianness (void)
{
/* int x=1; */
 return *(char*)&x;
}

Take it for what it's worth.

Josh
Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Luiz Henrique de Figueiredo
> A small point of interest.  When working the Xbox 360, the above
> endianness didn't work using a local variable.

In what sense did it not work?

Anyway, could you please try this?
        volatile int x = 1;

(A *local* volatile var.)
--lhf
Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Joshua Jensen
Luiz Henrique de Figueiredo wrote:
A small point of interest.  When working the Xbox 360, the above 
endianness didn't work using a local variable.
    

In what sense did it not work?

Anyway, could you please try this?
	volatile int x = 1;

(A *local* volatile var.)
  
It simply returned the wrong result.  If I had understood PowerPC assembly better at the time, I might be able to tell you why.  Perhaps it was a compiler bug, although it still continued to return the wrong result 6 months after I made the change in the first place.

In any case, as of a month ago, I don't have access to Xbox 360s anymore.  If there is someone else on this list working with Xbox 360s, perhaps they can give it a try and see if it is an issue anymore.

(The 'volatile' is an interesting trick.  I should have thought about doing that in the first place.)

Josh

Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Ivaylo Beltchev
In reply to this post by Luiz Henrique de Figueiredo
Thanks.

I think that's exactly what I need!

Ivo

----- Original Message -----
From: "Luiz Henrique de Figueiredo" <[hidden email]>
To: "Lua list" <[hidden email]>
Sent: Thursday, May 04, 2006 12:01 PM
Subject: Re: Cross compiling Lua byte code


> > Hacking undump to do this should be pretty easy.
>
> Here it is... (partially untested.)
> Just be careful to build your PPC Lua with this module but your x86 Lua with
> the original lundump.c.
> --lhf
>
> /*
> ** $Id: lundump.c,v 1.60 2006/02/16 15:53:49 lhf Exp $
> ** load precompiled Lua chunks
> ** See Copyright Notice in lua.h
> */
>
> #include <string.h>
>
> #define lundump_c
> #define LUA_CORE
>
> #include "lua.h"
>
> #include "ldebug.h"
> #include "ldo.h"
> #include "lfunc.h"
> #include "lmem.h"
> #include "lobject.h"
> #include "lstring.h"
> #include "lundump.h"
> #include "lzio.h"
>
> typedef struct {
>  lua_State* L;
>  ZIO* Z;
>  Mbuffer* b;
>  const char* name;
>  int swap;
> } LoadState;
>
> #ifdef LUAC_TRUST_BINARIES
> #define IF(c,s)
> #else
> #define IF(c,s) if (c) error(S,s)
>
> static void error(LoadState* S, const char* why)
> {
>  luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
>  luaD_throw(S->L,LUA_ERRSYNTAX);
> }
> #endif
>
> #define LoadByte(S) (lu_byte)LoadChar(S)
> #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
> #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
>
> static void LoadBlock(LoadState* S, void* b, size_t size)
> {
>  size_t r=luaZ_read(S->Z,b,size);
>  IF (r!=0, "unexpected end");
> }
>
> static void LoadMem (LoadState* S, void* b, int n, size_t size)
> {
>  LoadBlock(S,b,n*size);
>  if (S->swap)
>  {
>   char* p=(char*) b;
>   char c;
>   switch (size)
>   {
>    case 1:
>   break;
>    case 2:
> while (n--)
> {
> c=p[0]; p[0]=p[1]; p[1]=c;
> p+=2;
> }
>   break;
>    case 4:
> while (n--)
> {
> c=p[0]; p[0]=p[3]; p[3]=c;
> c=p[1]; p[1]=p[2]; p[2]=c;
> p+=4;
> }
>   break;
>    case 8:
> while (n--)
> {
> c=p[0]; p[0]=p[7]; p[7]=c;
> c=p[1]; p[1]=p[6]; p[6]=c;
> c=p[2]; p[2]=p[5]; p[5]=c;
> c=p[3]; p[3]=p[4]; p[4]=c;
> p+=8;
> }
>   break;
>    default:
>    IF(1, "bad size");
>   break;
>   }
>  }
> }
>
> static int LoadChar(LoadState* S)
> {
>  char x;
>  LoadVar(S,x);
>  return x;
> }
>
> static int LoadInt(LoadState* S)
> {
>  int x;
>  LoadVar(S,x);
>  IF (x<0, "bad integer");
>  return x;
> }
>
> static lua_Number LoadNumber(LoadState* S)
> {
>  double x;
>  LoadVar(S,x);
>  return (lua_Number) x;
> }
>
> static TString* LoadString(LoadState* S)
> {
>  size_t size;
>  LoadVar(S,size);
>  if (size==0)
>   return NULL;
>  else
>  {
>   char* s=luaZ_openspace(S->L,S->b,size);
>   LoadBlock(S,s,size);
>   return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
>  }
> }
>
> static void LoadCode(LoadState* S, Proto* f)
> {
>  int n=LoadInt(S);
>  f->code=luaM_newvector(S->L,n,Instruction);
>  f->sizecode=n;
>  LoadVector(S,f->code,n,sizeof(Instruction));
> }
>
> static Proto* LoadFunction(LoadState* S, TString* p);
>
> static void LoadConstants(LoadState* S, Proto* f)
> {
>  int i,n;
>  n=LoadInt(S);
>  f->k=luaM_newvector(S->L,n,TValue);
>  f->sizek=n;
>  for (i=0; i<n; i++) setnilvalue(&f->k[i]);
>  for (i=0; i<n; i++)
>  {
>   TValue* o=&f->k[i];
>   int t=LoadChar(S);
>   switch (t)
>   {
>    case LUA_TNIL:
>    setnilvalue(o);
> break;
>    case LUA_TBOOLEAN:
>    setbvalue(o,LoadChar(S));
> break;
>    case LUA_TNUMBER:
> setnvalue(o,LoadNumber(S));
> break;
>    case LUA_TSTRING:
> setsvalue2n(S->L,o,LoadString(S));
> break;
>    default:
> IF (1, "bad constant");
> break;
>   }
>  }
>  n=LoadInt(S);
>  f->p=luaM_newvector(S->L,n,Proto*);
>  f->sizep=n;
>  for (i=0; i<n; i++) f->p[i]=NULL;
>  for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
> }
>
> static void LoadDebug(LoadState* S, Proto* f)
> {
>  int i,n;
>  n=LoadInt(S);
>  f->lineinfo=luaM_newvector(S->L,n,int);
>  f->sizelineinfo=n;
>  LoadVector(S,f->lineinfo,n,sizeof(int));
>  n=LoadInt(S);
>  f->locvars=luaM_newvector(S->L,n,LocVar);
>  f->sizelocvars=n;
>  for (i=0; i<n; i++) f->locvars[i].varname=NULL;
>  for (i=0; i<n; i++)
>  {
>   f->locvars[i].varname=LoadString(S);
>   f->locvars[i].startpc=LoadInt(S);
>   f->locvars[i].endpc=LoadInt(S);
>  }
>  n=LoadInt(S);
>  f->upvalues=luaM_newvector(S->L,n,TString*);
>  f->sizeupvalues=n;
>  for (i=0; i<n; i++) f->upvalues[i]=NULL;
>  for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
> }
>
> static Proto* LoadFunction(LoadState* S, TString* p)
> {
>  Proto* f=luaF_newproto(S->L);
>  setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
>  f->source=LoadString(S); if (f->source==NULL) f->source=p;
>  f->linedefined=LoadInt(S);
>  f->lastlinedefined=LoadInt(S);
>  f->nups=LoadByte(S);
>  f->numparams=LoadByte(S);
>  f->is_vararg=LoadByte(S);
>  f->maxstacksize=LoadByte(S);
>  LoadCode(S,f);
>  LoadConstants(S,f);
>  LoadDebug(S,f);
>  IF (!luaG_checkcode(f), "bad code");
>  S->L->top--;
>  return f;
> }
>
> static void LoadHeader(LoadState* S)
> {
>  char h[LUAC_HEADERSIZE];
>  char s[LUAC_HEADERSIZE];
>  luaU_header(h);
>  LoadBlock(S,s,LUAC_HEADERSIZE);
>  S->swap=(s[6]!=h[6]); s[6]=h[6];
>  s[10]=h[10];
>  IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
> }
>
> /*
> ** load precompiled chunk
> */
> Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
> {
>  LoadState S;
>  if (*name=='@' || *name=='=')
>   S.name=name+1;
>  else if (*name==LUA_SIGNATURE[0])
>   S.name="binary string";
>  else
>   S.name=name;
>  S.L=L;
>  S.Z=Z;
>  S.b=buff;
>  LoadHeader(&S);
>  return LoadFunction(&S,luaS_newliteral(L,"=?"));
> }
>
> /*
> * make header
> */
> void luaU_header (char* h)
> {
>  int x=1;
>  memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
>  h+=sizeof(LUA_SIGNATURE)-1;
>  *h++=(char)LUAC_VERSION;
>  *h++=(char)LUAC_FORMAT;
>  *h++=(char)*(char*)&x; /* endianness */
>  *h++=(char)sizeof(int);
>  *h++=(char)sizeof(size_t);
>  *h++=(char)sizeof(Instruction);
>  *h++=(char)sizeof(lua_Number);
>  *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
> }
>
Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

Dakota Knutson
luaforums.co.nr

On 5/4/06, Ivaylo Beltchev <[hidden email]> wrote:
Thanks.

I think that's exactly what I need!

Ivo

----- Original Message -----
From: "Luiz Henrique de Figueiredo" <[hidden email]>
To: "Lua list" <[hidden email]>
Sent: Thursday, May 04, 2006 12:01 PM
Subject: Re: Cross compiling Lua byte code


> > Hacking undump to do this should be pretty easy.
>
> Here it is... (partially untested.)
> Just be careful to build your PPC Lua with this module but your x86 Lua with

> the original lundump.c.
> --lhf
>
> /*
> ** $Id: lundump.c,v 1.60 2006/02/16 15:53:49 lhf Exp $
> ** load precompiled Lua chunks
> ** See Copyright Notice in lua.h
> */
>
> #include <string.h>
>
> #define lundump_c
> #define LUA_CORE
>
> #include "lua.h"
>
> #include " ldebug.h"
> #include "ldo.h"
> #include "lfunc.h"
> #include "lmem.h"
> #include "lobject.h"
> #include "lstring.h"
> #include " lundump.h"
> #include "lzio.h"
>
> typedef struct {
>  lua_State* L;
>  ZIO* Z;
>  Mbuffer* b;
>  const char* name;
>  int swap;
> } LoadState;
>
> #ifdef LUAC_TRUST_BINARIES

> #define IF(c,s)
> #else
> #define IF(c,s) if (c) error(S,s)
>
> static void error(LoadState* S, const char* why)
> {
>  luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
>  luaD_throw(S->L,LUA_ERRSYNTAX);
> }
> #endif
>
> #define LoadByte(S) (lu_byte)LoadChar(S)
> #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
> #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
>
> static void LoadBlock(LoadState* S, void* b, size_t size)
> {
>  size_t r=luaZ_read(S->Z,b,size);
>  IF (r!=0, "unexpected end");
> }
>
> static void LoadMem (LoadState* S, void* b, int n, size_t size)
> {
>  LoadBlock(S,b,n*size);
>  if (S->swap)
>  {
>   char* p=(char*) b;
>   char c;
>   switch (size)
>   {
>    case 1:
>   break;
>    case 2:
> while (n--)
> {
> c=p[0]; p[0]=p[1]; p[1]=c;
> p+=2;
> }
>   break;
>    case 4:
> while (n--)
> {
> c=p[0]; p[0]=p[3]; p[3]=c;
> c=p[1]; p[1]=p[2]; p[2]=c;
> p+=4;
> }

>   break;
>    case 8:
> while (n--)
> {
> c=p[0]; p[0]=p[7]; p[7]=c;
> c=p[1]; p[1]=p[6]; p[6]=c;
> c=p[2]; p[2]=p[5]; p[5]=c;
> c=p[3]; p[3]=p[4]; p[4]=c;
> p+=8;
> }
>   break;
>    default:
>    IF(1, "bad size");
>   break;
>   }
>  }
> }
>
> static int LoadChar(LoadState* S)
> {
>  char x;
>  LoadVar(S,x);
>  return x;
> }
>
> static int LoadInt(LoadState* S)
> {
>  int x;
>  LoadVar(S,x);
>  IF (x<0, "bad integer");
>  return x;
> }
>
> static lua_Number LoadNumber(LoadState* S)
> {
>  double x;
>  LoadVar(S,x);
>  return (lua_Number) x;
> }
>
> static TString* LoadString(LoadState* S)
> {
>  size_t size;
>  LoadVar(S,size);
>  if (size==0)
>   return NULL;
>  else
>  {
>   char* s=luaZ_openspace(S->L,S->b,size);
>   LoadBlock(S,s,size);
>   return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
>  }
> }
>
> static void LoadCode(LoadState* S, Proto* f)
> {
>  int n=LoadInt(S);
>  f->code=luaM_newvector(S->L,n,Instruction);
>  f->sizecode=n;
>  LoadVector(S,f->code,n,sizeof(Instruction));
> }
>
> static Proto* LoadFunction(LoadState* S, TString* p);
>
> static void LoadConstants(LoadState* S, Proto* f)
> {
>  int i,n;
>  n=LoadInt(S);
>  f->k=luaM_newvector(S->L,n,TValue);
>  f->sizek=n;
>  for (i=0; i<n; i++) setnilvalue(&f->k[i]);
>  for (i=0; i<n; i++)
>  {
>   TValue* o=&f->k[i];
>   int t=LoadChar(S);
>   switch (t)
>   {
>    case LUA_TNIL:
>    setnilvalue(o);
> break;
>    case LUA_TBOOLEAN:
>    setbvalue(o,LoadChar(S));
> break;
>    case LUA_TNUMBER:
> setnvalue(o,LoadNumber(S));
> break;
>    case LUA_TSTRING:
> setsvalue2n(S->L,o,LoadString(S));
> break;
>    default:
> IF (1, "bad constant");
> break;
>   }
>  }
>  n=LoadInt(S);
>  f->p=luaM_newvector(S->L,n,Proto*);
>  f->sizep=n;
>  for (i=0; i<n; i++) f->p[i]=NULL;
>  for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
> }
>
> static void LoadDebug(LoadState* S, Proto* f)
> {

>  int i,n;
>  n=LoadInt(S);
>  f->lineinfo=luaM_newvector(S->L,n,int);
>  f->sizelineinfo=n;
>  LoadVector(S,f->lineinfo,n,sizeof(int));
>  n=LoadInt(S);
>  f->locvars=luaM_newvector(S->L,n,LocVar);
>  f->sizelocvars=n;
>  for (i=0; i<n; i++) f->locvars[i].varname=NULL;
>  for (i=0; i<n; i++)
>  {
>   f->locvars[i].varname=LoadString(S);
>   f->locvars[i].startpc=LoadInt(S);
>   f->locvars[i].endpc=LoadInt(S);
>  }
>  n=LoadInt(S);
>  f->upvalues=luaM_newvector(S->L,n,TString*);
>  f->sizeupvalues=n;
>  for (i=0; i<n; i++) f->upvalues[i]=NULL;
>  for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
> }
>
> static Proto* LoadFunction(LoadState* S, TString* p)
> {
>  Proto* f=luaF_newproto(S->L);
>  setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
>  f->source=LoadString(S); if (f->source==NULL) f->source=p;
>  f->linedefined=LoadInt(S);
>  f->lastlinedefined=LoadInt(S);
>  f->nups=LoadByte(S);
>  f->numparams=LoadByte(S);
>  f->is_vararg=LoadByte(S);
>  f->maxstacksize=LoadByte(S);
>  LoadCode(S,f);
>  LoadConstants(S,f);
>  LoadDebug(S,f);
>  IF (!luaG_checkcode(f), "bad code");
>  S->L->top--;
>  return f;
> }
>
> static void LoadHeader(LoadState* S)
> {
>  char h[LUAC_HEADERSIZE];
>  char s[LUAC_HEADERSIZE];
>  luaU_header(h);
>  LoadBlock(S,s,LUAC_HEADERSIZE);
>  S->swap=(s[6]!=h[6]); s[6]=h[6];
>  s[10]=h[10];
>  IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
> }
>
> /*
> ** load precompiled chunk
> */
> Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
> {
>  LoadState S;
>  if (*name=='@' || *name=='=')
>   S.name=name+1;
>  else if (*name==LUA_SIGNATURE[0])
>   S.name="binary string";
>  else
>   S.name=name;
>  S.L=L;

>  S.Z=Z;
>  S.b=buff;
>  LoadHeader(&S);
>  return LoadFunction(&S,luaS_newliteral(L,"=?"));
> }
>
> /*
> * make header
> */
> void luaU_header (char* h)
> {
>  int x=1;
>  memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
>  h+=sizeof(LUA_SIGNATURE)-1;
>  *h++=(char)LUAC_VERSION;
>  *h++=(char)LUAC_FORMAT;
>  *h++=(char)*(char*)&x; /* endianness */
>  *h++=(char)sizeof(int);
>  *h++=(char)sizeof(size_t);
>  *h++=(char)sizeof(Instruction);
>  *h++=(char)sizeof(lua_Number);
>  *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
> }
>

Reply | Threaded
Open this post in threaded view
|

Re: Cross compiling Lua byte code

David Jones-2
In reply to this post by Joshua Jensen

On May 04, 2006, at 21:41, Joshua Jensen wrote:

> Luiz Henrique de Figueiredo wrote:
>> void luaU_header (char* h)
>> {
>>  int x=1;
>>  *h++=(char)*(char*)&x; /* endianness */
>> }
>>
> A small point of interest.  When working the Xbox 360, the above
> endianness didn't work using a local variable.  Instead, I had to
> create a static global.  :(  This was under Lua 5.0, but I'm guessing
> it will still apply now.
>
> static int x = 1;
>
> int luaU_endianness (void)
> {
> /* int x=1; */
> return *(char*)&x;
> }
>
> Take it for what it's worth.

A compiler bug.  Accessing any C type by treating it as an array of
char is completely legal.  Aliasing must be be honoured.  That's how
memcpy works, it copies objects char by char (at least conceptually).

drj