mirror of
https://github.com/elua/elua.git
synced 2025-01-25 01:02:54 +08:00
added cross-compile support
This commit is contained in:
parent
4793225724
commit
810b787ec3
23
cross-lua.py
Normal file
23
cross-lua.py
Normal file
@ -0,0 +1,23 @@
|
||||
import os, sys
|
||||
|
||||
output = 'luac'
|
||||
cdefs = '-DLUA_CROSS_COMPILER'
|
||||
|
||||
# Lua source files and include path
|
||||
lua_files = """lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c
|
||||
lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c
|
||||
ldblib.c liolib.c lmathlib.c loslib.c ltablib.c lstrlib.c loadlib.c linit.c luac.c print.c"""
|
||||
lua_full_files = " " + " ".join( [ "src/lua/%s" % name for name in lua_files.split() ] )
|
||||
local_include = "-Isrc/lua"
|
||||
|
||||
# Compiler/linker options
|
||||
cccom = "gcc -O3 %s -Wall %s -c $SOURCE -o $TARGET" % ( local_include, cdefs )
|
||||
linkcom = "gcc -o $TARGET $SOURCES -lm"
|
||||
|
||||
# Env for building the program
|
||||
comp = Environment( CCCOM = cccom,
|
||||
LINKCOM = linkcom,
|
||||
ENV = os.environ )
|
||||
comp.TargetSignatures( 'content' )
|
||||
comp.SourceSignatures( 'MD5' )
|
||||
Default( comp.Program( output, Split( lua_full_files ) ) )
|
172
src/lua/ldump.c
172
src/lua/ldump.c
@ -5,6 +5,8 @@
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldump_c
|
||||
#define LUA_CORE
|
||||
@ -21,6 +23,7 @@ typedef struct {
|
||||
void* data;
|
||||
int strip;
|
||||
int status;
|
||||
DumpTargetInfo target;
|
||||
} DumpState;
|
||||
|
||||
#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
|
||||
@ -42,20 +45,125 @@ static void DumpChar(int y, DumpState* D)
|
||||
DumpVar(x,D);
|
||||
}
|
||||
|
||||
static void MaybeByteSwap(char *number, size_t numbersize, DumpState *D)
|
||||
{
|
||||
int x=1;
|
||||
int platform_little_endian = *(char*)&x;
|
||||
if (platform_little_endian != D->target.little_endian)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<numbersize/2; i++)
|
||||
{
|
||||
char temp = number[i];
|
||||
number[i] = number[numbersize-1-i];
|
||||
number[numbersize-1-i] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpIntWithSize(int x, int sizeof_int, DumpState* D)
|
||||
{
|
||||
/* dump signed integer */
|
||||
switch(sizeof_int) {
|
||||
case 1: {
|
||||
if (x>0x7F || x<(-0x80)) D->status=LUA_ERR_CC_INTOVERFLOW;
|
||||
DumpChar(x,D);
|
||||
} break;
|
||||
case 2: {
|
||||
if (x>0x7FFF || x<(-0x8000)) D->status=LUA_ERR_CC_INTOVERFLOW;
|
||||
int16_t y=x;
|
||||
MaybeByteSwap((char*)&y,2,D);
|
||||
DumpVar(y,D);
|
||||
} break;
|
||||
case 4: {
|
||||
/* Need to reduce bounds by 1 to avoid messing 32-bit compilers up */
|
||||
if (x>0x7FFFFFFE || x<(-0x7FFFFFFF)) D->status=LUA_ERR_CC_INTOVERFLOW;
|
||||
int32_t y=x;
|
||||
MaybeByteSwap((char*)&y,4,D);
|
||||
DumpVar(y,D);
|
||||
} break;
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpInt(int x, DumpState* D)
|
||||
{
|
||||
DumpVar(x,D);
|
||||
DumpIntWithSize(x,D->target.sizeof_int,D);
|
||||
}
|
||||
|
||||
static void DumpSize(size_t x, DumpState* D)
|
||||
{
|
||||
/* dump unsigned integer */
|
||||
switch(D->target.sizeof_size_t) {
|
||||
case 1: {
|
||||
if (x>0xFF) D->status=LUA_ERR_CC_INTOVERFLOW;
|
||||
DumpChar(x,D);
|
||||
} break;
|
||||
case 2: {
|
||||
if (x>0xFFFF) D->status=LUA_ERR_CC_INTOVERFLOW;
|
||||
unsigned short y=x;
|
||||
MaybeByteSwap((char*)&y,2,D);
|
||||
DumpVar(y,D);
|
||||
} break;
|
||||
case 4: {
|
||||
/* Reduce bounds to avoid messing 32-bit compilers up */
|
||||
if (x>0xFFFFFFFE) D->status=LUA_ERR_CC_INTOVERFLOW;
|
||||
unsigned long y=x;
|
||||
MaybeByteSwap((char*)&y,4,D);
|
||||
DumpVar(y,D);
|
||||
} break;
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpNumber(lua_Number x, DumpState* D)
|
||||
{
|
||||
DumpVar(x,D);
|
||||
if (D->target.lua_Number_integral)
|
||||
{
|
||||
if (((float)(int)x)!=x) D->status=LUA_ERR_CC_NOTINTEGER;
|
||||
DumpIntWithSize(x,D->target.sizeof_lua_Number,D);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(D->target.sizeof_lua_Number)
|
||||
{
|
||||
/* do we need bounds checking? */
|
||||
case 4: {
|
||||
float y=x;
|
||||
MaybeByteSwap((char*)&y,4,D);
|
||||
DumpVar(y,D);
|
||||
} break;
|
||||
case 8: {
|
||||
double y=x;
|
||||
// ARM FPA mode: keep endianness, but swap high and low parts of the
|
||||
// memory representation. This is the default compilation mode for ARM
|
||||
// targets (at least with GCC)
|
||||
if(D->target.is_arm_fpa)
|
||||
{
|
||||
char *pnum=(char*)&y, temp[4];
|
||||
memcpy(temp,pnum,4);
|
||||
memcpy(pnum,pnum+4,4);
|
||||
memcpy(pnum+4,temp,4);
|
||||
}
|
||||
MaybeByteSwap((char*)&y,8,D);
|
||||
DumpVar(y,D);
|
||||
} break;
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
|
||||
static void DumpCode(const Proto *f, DumpState* D)
|
||||
{
|
||||
DumpInt(n,D);
|
||||
DumpMem(b,n,size,D);
|
||||
DumpInt(f->sizecode,D);
|
||||
char buf[10];
|
||||
int i;
|
||||
for (i=0; i<f->sizecode; i++)
|
||||
{
|
||||
memcpy(buf,&f->code[i],sizeof(Instruction));
|
||||
MaybeByteSwap(buf,sizeof(Instruction),D);
|
||||
DumpBlock(buf,sizeof(Instruction),D);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpString(const TString* s, DumpState* D)
|
||||
@ -63,18 +171,16 @@ static void DumpString(const TString* s, DumpState* D)
|
||||
if (s==NULL || getstr(s)==NULL)
|
||||
{
|
||||
size_t size=0;
|
||||
DumpVar(size,D);
|
||||
DumpSize(size,D);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t size=s->tsv.len+1; /* include trailing '\0' */
|
||||
DumpVar(size,D);
|
||||
DumpSize(size,D);
|
||||
DumpBlock(getstr(s),size,D);
|
||||
}
|
||||
}
|
||||
|
||||
#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
|
||||
|
||||
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
|
||||
|
||||
static void DumpConstants(const Proto* f, DumpState* D)
|
||||
@ -112,7 +218,12 @@ static void DumpDebug(const Proto* f, DumpState* D)
|
||||
{
|
||||
int i,n;
|
||||
n= (D->strip) ? 0 : f->sizelineinfo;
|
||||
DumpVector(f->lineinfo,n,sizeof(int),D);
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
DumpInt(f->lineinfo[i],D);
|
||||
}
|
||||
|
||||
n= (D->strip) ? 0 : f->sizelocvars;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++)
|
||||
@ -121,6 +232,7 @@ static void DumpDebug(const Proto* f, DumpState* D)
|
||||
DumpInt(f->locvars[i].startpc,D);
|
||||
DumpInt(f->locvars[i].endpc,D);
|
||||
}
|
||||
|
||||
n= (D->strip) ? 0 : f->sizeupvalues;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
|
||||
@ -142,15 +254,28 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
|
||||
|
||||
static void DumpHeader(DumpState* D)
|
||||
{
|
||||
char h[LUAC_HEADERSIZE];
|
||||
luaU_header(h);
|
||||
DumpBlock(h,LUAC_HEADERSIZE,D);
|
||||
char buf[LUAC_HEADERSIZE];
|
||||
char *h=buf;
|
||||
|
||||
/* This code must be kept in sync wiht luaU_header */
|
||||
memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
|
||||
h+=sizeof(LUA_SIGNATURE)-1;
|
||||
*h++=(char)LUAC_VERSION;
|
||||
*h++=(char)LUAC_FORMAT;
|
||||
*h++=(char)D->target.little_endian;
|
||||
*h++=(char)D->target.sizeof_int;
|
||||
*h++=(char)D->target.sizeof_size_t;
|
||||
*h++=(char)sizeof(Instruction);
|
||||
*h++=(char)D->target.sizeof_lua_Number;
|
||||
*h++=(char)D->target.lua_Number_integral;
|
||||
|
||||
DumpBlock(buf,LUAC_HEADERSIZE,D);
|
||||
}
|
||||
|
||||
/*
|
||||
** dump Lua function as precompiled chunk
|
||||
** dump Lua function as precompiled chunk with specified target
|
||||
*/
|
||||
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
|
||||
int luaU_dump_crosscompile (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip, DumpTargetInfo target)
|
||||
{
|
||||
DumpState D;
|
||||
D.L=L;
|
||||
@ -158,7 +283,24 @@ int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip
|
||||
D.data=data;
|
||||
D.strip=strip;
|
||||
D.status=0;
|
||||
D.target=target;
|
||||
DumpHeader(&D);
|
||||
DumpFunction(f,NULL,&D);
|
||||
return D.status;
|
||||
}
|
||||
|
||||
/*
|
||||
** dump Lua function as precompiled chunk with local machine as target
|
||||
*/
|
||||
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
|
||||
{
|
||||
DumpTargetInfo target;
|
||||
int test=1;
|
||||
target.little_endian=*(char*)&test;
|
||||
target.sizeof_int=sizeof(int);
|
||||
target.sizeof_size_t=sizeof(size_t);
|
||||
target.sizeof_lua_Number=sizeof(lua_Number);
|
||||
target.lua_Number_integral=(((lua_Number)0.5)==0);
|
||||
target.is_arm_fpa=0;
|
||||
return luaU_dump_crosscompile(L,f,w,data,strip,target);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
|
||||
@ -13,7 +12,9 @@
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
#include "platform_libs.h"
|
||||
#endif
|
||||
|
||||
static const luaL_Reg lualibs[] = {
|
||||
{"", luaopen_base},
|
||||
|
@ -32,6 +32,7 @@ static int stripping=0; /* strip debug information? */
|
||||
static char Output[]={ OUTPUT }; /* default output file name */
|
||||
static const char* output=Output; /* actual output file name */
|
||||
static const char* progname=PROGNAME; /* actual program name */
|
||||
static DumpTargetInfo target;
|
||||
|
||||
static void fatal(const char* message)
|
||||
{
|
||||
@ -60,6 +61,9 @@ static void usage(const char* message)
|
||||
" -p parse only\n"
|
||||
" -s strip debug information\n"
|
||||
" -v show version information\n"
|
||||
" -cci bits cross-compile with given integer size\n"
|
||||
" -ccn type bits cross-compile with given lua_Number type and size\n"
|
||||
" -cce endian cross-compile with given endianness ('big' or 'little')\n"
|
||||
" -- stop handling options\n",
|
||||
progname,Output);
|
||||
exit(EXIT_FAILURE);
|
||||
@ -98,6 +102,33 @@ static int doargs(int argc, char* argv[])
|
||||
stripping=1;
|
||||
else if (IS("-v")) /* show version */
|
||||
++version;
|
||||
else if (IS("-cci")) /* target integer size */
|
||||
{
|
||||
int s = target.sizeof_int = target.sizeof_size_t = atoi(argv[++i])/8;
|
||||
if (!(s==1 || s==2 || s==4)) fatal(LUA_QL("-cci") " must be 8, 16 or 32");
|
||||
}
|
||||
else if (IS("-ccn")) /* target lua_Number type and size */
|
||||
{
|
||||
const char *type=argv[++i];
|
||||
if (strcmp(type,"int")==0) target.lua_Number_integral=1;
|
||||
else if (strcmp(type,"float")==0) target.lua_Number_integral=0;
|
||||
else if (strcmp(type,"float_arm")==0)
|
||||
{
|
||||
target.lua_Number_integral=0;
|
||||
target.is_arm_fpa=1;
|
||||
}
|
||||
else fatal(LUA_QL("-ccn") " type must be " LUA_QL("int") " or " LUA_QL("float") " or " LUA_QL("float_arm"));
|
||||
int s = target.sizeof_lua_Number = atoi(argv[++i])/8;
|
||||
if (target.lua_Number_integral && !(s==1 || s==2 || s==4)) fatal(LUA_QL("-ccn") " size must be 8, 16, or 32 for int");
|
||||
if (!target.lua_Number_integral && !(s==4 || s==8)) fatal(LUA_QL("-ccn") " size must be 32 or 64 for float");
|
||||
}
|
||||
else if (IS("-cce")) /* target endianness */
|
||||
{
|
||||
const char *val=argv[++i];
|
||||
if (strcmp(val,"big")==0) target.little_endian=0;
|
||||
else if (strcmp(val,"little")==0) target.little_endian=1;
|
||||
else fatal(LUA_QL("-cce") " must be " LUA_QL("big") " or " LUA_QL("little"));
|
||||
}
|
||||
else /* unknown option */
|
||||
usage(argv[i]);
|
||||
}
|
||||
@ -175,8 +206,10 @@ static int pmain(lua_State* L)
|
||||
FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
|
||||
if (D==NULL) cannot("open");
|
||||
lua_lock(L);
|
||||
luaU_dump(L,f,writer,D,stripping);
|
||||
int result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
|
||||
lua_unlock(L);
|
||||
if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type");
|
||||
if (result==LUA_ERR_CC_NOTINTEGER) fatal("target lua_Number is integral but fractional value found");
|
||||
if (ferror(D)) cannot("write");
|
||||
if (fclose(D)) cannot("close");
|
||||
}
|
||||
@ -187,6 +220,15 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
lua_State* L;
|
||||
struct Smain s;
|
||||
|
||||
int test=1;
|
||||
target.little_endian=*(char*)&test;
|
||||
target.sizeof_int=sizeof(int);
|
||||
target.sizeof_size_t=sizeof(size_t);
|
||||
target.sizeof_lua_Number=sizeof(lua_Number);
|
||||
target.lua_Number_integral=(((lua_Number)0.5)==0);
|
||||
target.is_arm_fpa=0;
|
||||
|
||||
int i=doargs(argc,argv);
|
||||
argc-=i; argv+=i;
|
||||
if (argc<=0) usage("no input files given");
|
||||
|
@ -10,12 +10,25 @@
|
||||
#include "lobject.h"
|
||||
#include "lzio.h"
|
||||
|
||||
/* info about target machine for cross-compilation */
|
||||
typedef struct {
|
||||
int little_endian;
|
||||
int sizeof_int;
|
||||
int sizeof_size_t;
|
||||
int sizeof_lua_Number;
|
||||
int lua_Number_integral;
|
||||
int is_arm_fpa;
|
||||
} DumpTargetInfo;
|
||||
|
||||
/* load one chunk; from lundump.c */
|
||||
LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
|
||||
|
||||
/* make header; from lundump.c */
|
||||
LUAI_FUNC void luaU_header (char* h);
|
||||
|
||||
/* dump one chunk to a different target; from ldump.c */
|
||||
int luaU_dump_crosscompile (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip, DumpTargetInfo target);
|
||||
|
||||
/* dump one chunk; from ldump.c */
|
||||
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
|
||||
|
||||
@ -33,4 +46,11 @@ LUAI_FUNC void luaU_print (const Proto* f, int full);
|
||||
/* size of header of binary files */
|
||||
#define LUAC_HEADERSIZE 12
|
||||
|
||||
/* error codes from cross-compiler */
|
||||
/* target integer is too small to hold a value */
|
||||
#define LUA_ERR_CC_INTOVERFLOW 101
|
||||
|
||||
/* target lua_Number is integral but a constant is non-integer */
|
||||
#define LUA_ERR_CC_NOTINTEGER 102
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user