1
0
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:
Bogdan Marinescu 2008-09-19 20:13:30 +00:00
parent 4793225724
commit 810b787ec3
5 changed files with 245 additions and 17 deletions

23
cross-lua.py Normal file
View 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 ) ) )

View File

@ -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);
}

View File

@ -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},

View File

@ -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");

View File

@ -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