Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions src/lib_ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,45 +720,57 @@ LJLIB_CF(ffi_fill) LJLIB_REC(.)
return 0;
}

#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
#define HASH_(l, c1, c2) (((int)(l)) << 16 | ((size_t)(c1)) << 8 | (c2))
#define H_(s, c1, c2) HASH_(sizeof((s)) - 1, c1, c2)

/* Test ABI string. */
LJLIB_CF(ffi_abi) LJLIB_REC(.)
{
GCstr *s = lj_lib_checkstr(L, 1);
int b = 0;
switch (s->hash) {
int hash = s->len >= 2 ? HASH_(s->len, strdata(s)[0], strdata(s)[1]): 0;
switch (hash) {
#define STR_CASE_(str, c1, c2) case H_(str, c1, c2): if (lj_str_equ(s, str, sizeof(s) - 1)) { break; }
#if LJ_64
case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */
STR_CASE_("64bit", '6', '4'); b = 1; break; /* 64bit */
#else
case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */
STR_CASE_("32bit", '3', '2'); b = 1; break; /* 32bit */
#endif
#if LJ_ARCH_HASFPU
case H_(e33ee463,e33ee463): b = 1; break; /* fpu */
STR_CASE_("fpu", 'f', 'p'); b = 1; break; /* fpu */
#endif
#if LJ_ABI_SOFTFP
case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */
STR_CASE_("softfp", 's', 'o'); b = 1; break; /* softfp */
#else
case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */
STR_CASE_("hardfp", 'h', 'a'); b = 1; break; /* hardfp */
#endif
#if LJ_ABI_EABI
case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */
STR_CASE_("eabi", 'e', 'a'); b = 1; break; /* eabi */
#endif
#if LJ_ABI_WIN
case H_(4ab624a8,4ab624a8): b = 1; break; /* win */
STR_CASE_("win", 'w', 'i'); b = 1; break; /* win */
#endif
case H_(3af93066,1f001464): b = 1; break; /* le/be */

#if LJ_ARCH_ENDIAN == LUAJIT_BE
STR_CASE_("'be", 'b', 'e'); b = 1; break; /* be */
#else
STR_CASE_("le", 'l', 'e'); b = 1; break; /* le */
#endif

#if LJ_GC64
case H_(9e89d2c9,13c83c92): b = 1; break; /* gc64 */
STR_CASE_("gc64", 'g', 'c'); b = 1; break; /* gc64 */
#endif
default:
break;
#undef STR_CASE_
}
setboolV(L->top-1, b);
setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */
return 1;
}

#undef HASH_
#undef E_
#undef H_

LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
Expand Down
63 changes: 32 additions & 31 deletions src/lj_cparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,8 @@ static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)

/* -- C declaration parser ------------------------------------------------ */

#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
#define HASH_(l, c1, c2) (((int)(l)) << 16 | ((size_t)(c1)) << 8 | (c2))
#define H_(s, c1, c2) HASH_((sizeof(s) - 1), c1, c2)

/* Reset declaration state to declaration specifier. */
static void cp_decl_reset(CPDecl *decl)
Expand Down Expand Up @@ -1052,57 +1053,57 @@ static void cp_decl_mode(CPState *cp, CPDecl *decl)
/* Parse GCC __attribute__((...)). */
static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
{
MSize hash = 0;
cp_next(cp);
cp_check(cp, '(');
cp_check(cp, '(');
while (cp->tok != ')') {
if (cp->tok == CTOK_IDENT) {
GCstr *attrstr = cp->str;
cp_next(cp);
switch (attrstr->hash) {
case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */
cp_decl_align(cp, decl);
break;
case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */
decl->attr |= CTFP_PACKED;
break;
case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */
cp_decl_mode(cp, decl);
break;
case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */
{
CTSize vsize = cp_decl_sizeattr(cp);
if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
}
hash = attrstr->len >= 2 ?
HASH_(attrstr->len, strdata(attrstr)[0], strdata(attrstr)[1]) : 0;
switch (hash) {
#define STR_CASE_(s, c1, c2) case H_(s, c1, c2): if (lj_str_equ(attrstr, s, sizeof(s) - 1)) { break; }
STR_CASE_("aligned", 'a', 'l') /* aligned */
cp_decl_align(cp, decl); break;
STR_CASE_("packed", 'p', 'a') /* packed */
decl->attr |= CTFP_PACKED; break;
STR_CASE_("mode", 'm', 'o') /* mode */
cp_decl_mode(cp, decl); break;
STR_CASE_("vector_size", 'v', 'e') /* vector_size */
CTSize vsize = cp_decl_sizeattr(cp);
if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
break;
#if LJ_TARGET_X86
case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */
STR_CASE_("regparm", 'r', 'e') /* regparm */
CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
decl->fattr |= CTFP_CCONV;
break;
case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */
STR_CASE_("cdecl", 'c', 'd') /* cdecl */
CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
decl->fattr |= CTFP_CCONV;
break;
case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */
STR_CASE_("thiscall", 't', 'h') /* thiscall */
CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
decl->fattr |= CTFP_CCONV;
break;
case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */
STR_CASE_("fastcall", 'f', 'a') /* fastcall */
CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
decl->fattr |= CTFP_CCONV;
break;
case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */
STR_CASE_("stdcall", 's', 't') /* stdcall */
CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
decl->fattr |= CTFP_CCONV;
break;
case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */
STR_CASE_("sseregparm", 's', 's') /* sseregparm */
decl->fattr |= CTF_SSEREGPARM;
decl->fattr |= CTFP_CCONV;
break;
#endif
default: /* Skip all other attributes. */
goto skip_attr;
#undef STR_CASE_
}
} else if (cp->tok >= CTOK_FIRSTDECL) { /* For __attribute((const)) etc. */
cp_next(cp);
Expand All @@ -1128,11 +1129,10 @@ static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
while (cp->tok == CTOK_IDENT) {
GCstr *attrstr = cp->str;
cp_next(cp);
switch (attrstr->hash) {
case H_(bc2395fa,98f267f8): /* align */
if (!lj_str_equ(attrstr, "align", 5)) {
cp_decl_align(cp, decl);
break;
default: /* Ignore all other attributes. */
} else {
/* Ignore all other attributes. */
if (cp_opt(cp, '(')) {
while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
cp_check(cp, ')');
Expand Down Expand Up @@ -1718,16 +1718,16 @@ static void cp_pragma(CPState *cp, BCLine pragmaline)
{
cp_next(cp);
if (cp->tok == CTOK_IDENT &&
cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */
!lj_str_equ(cp->str, "pack", 4)) { /* pack */
cp_next(cp);
cp_check(cp, '(');
if (cp->tok == CTOK_IDENT) {
if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */
if (!lj_str_equ(cp->str, "push", 4)) { /* push */
if (cp->curpack < CPARSE_MAX_PACKSTACK) {
cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
cp->curpack++;
}
} else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */
} else if (!lj_str_equ(cp->str, "pop", 3)) { /* pop */
if (cp->curpack > 0) cp->curpack--;
} else {
cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
Expand Down Expand Up @@ -1777,12 +1777,12 @@ static void cp_decl_multi(CPState *cp)
cp_line(cp, hashline);
continue;
} else if (tok == CTOK_IDENT &&
cp->str->hash == H_(187aab88,fcb60b42)) { /* line */
lj_str_equ(cp->str, "line", 4) == 0) { /* line */
if (cp_next(cp) != CTOK_INTEGER) cp_err_token(cp, tok);
cp_line(cp, hashline);
continue;
} else if (tok == CTOK_IDENT &&
cp->str->hash == H_(f5e6b4f8,1d509107)) { /* pragma */
lj_str_equ(cp->str, "pragma", 6) == 0) { /* pragma */
cp_pragma(cp, hashline);
continue;
} else {
Expand Down Expand Up @@ -1853,6 +1853,7 @@ static void cp_decl_single(CPState *cp)
if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
}

#undef HASH_
#undef H_

/* ------------------------------------------------------------------------ */
Expand Down
12 changes: 12 additions & 0 deletions src/lj_str.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
return 0;
}

int32_t LJ_FASTCALL lj_str_equ(GCstr *a, const char *b, MSize b_len)
{
if (a->len != b_len) {
return 1;
}

/* Do *NOT* transpose the 1st and 2nd argument, as the 2nd argument must be
* aligned at least at 4-byte boundary.
*/
return str_fastcmp(b, strdata(a), b_len);
}

/* Find fixed string p inside string s. */
const char *lj_str_find(const char *s, const char *p, MSize slen, MSize plen)
{
Expand Down
2 changes: 2 additions & 0 deletions src/lj_str.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

/* String helpers. */
LJ_FUNC int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b);
LJ_FUNC int32_t LJ_FASTCALL lj_str_equ(GCstr *a, const char *b, MSize b_len);

LJ_FUNC const char *lj_str_find(const char *s, const char *f,
MSize slen, MSize flen);
LJ_FUNC int lj_str_haspattern(GCstr *s);
Expand Down
1 change: 1 addition & 0 deletions src/x64/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ CXXFLAGS := -O3 -MD -g -msse4.2 -Wall -I../src -I../../../src
test: $(TEST_PROGRAM)
@echo "some unit test"
$(VALGRIND) ./$(TEST_PROGRAM)
./unit_test.sh

@echo "smoke test"
../../luajit test_str_comp.lua
Expand Down
10 changes: 10 additions & 0 deletions src/x64/test/unit/ffi/test_abi.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
local ffi = require "ffi"

-- TODO: test "gc64" and "win" parameters
assert((ffi.abi("32bit") or ffi.abi("64bit"))
and ffi.abi("le")
and not ffi.abi("be")
and ffi.abi("fpu")
and not ffi.abi("softfp")
and ffi.abi("hardfp")
and not ffi.abi("eabi"))
15 changes: 15 additions & 0 deletions src/x64/test/unit/ffi/test_line_directive.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local x = [=[
local ffi = require "ffi"

ffi.cdef [[
#line 100
typedef Int xxx
]]
]=]

local function foo()
loadstring(x)()
end

local r, e = pcall(foo)
assert(string.find(e, "declaration specifier expected near 'Int' at line 100") ~= nil)
12 changes: 12 additions & 0 deletions src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
local ffi = require "ffi"

ffi.cdef[[
#pragma pack(push, 1)
typedef struct {
char x;
double y;
} foo;
#pragma pack(pop)
]]

assert(ffi.sizeof("foo") == 9)
13 changes: 13 additions & 0 deletions src/x64/test/unit/ffi/test_var_attribute.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local ffi = require "ffi"

ffi.cdef[[
typedef struct { int a; char b; } __attribute__((packed)) myty1;
typedef struct { int a; char b; } __attribute__((aligned(16))) myty2;
typedef int __attribute__ ((vector_size (32))) myty3;
typedef int __attribute__ ((mode(DI))) myty4;
]]

assert(ffi.sizeof("myty1") == 5 and
ffi.alignof("myty2") == 16 and
ffi.sizeof("myty3") == 32 and
ffi.sizeof("myty4") == 8)
22 changes: 22 additions & 0 deletions src/x64/test/unit_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
DIR=$(cd $(dirname $0); pwd)
cd $DIR

LUAJIT=$DIR/../../luajit
HASERR=0

find $DIR/unit -name "*.lua" -print | while read x; do
$LUAJIT $x >/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
echo "$x ok"
else
HASERR=1
echo "$x failed"
fi
done

if [ $HASERR -eq 0 ]; then
exit 0
fi

exit 1