diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 136e98e89..fa1f89d66 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -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. */ diff --git a/src/lj_cparse.c b/src/lj_cparse.c index 83cfd1128..cf034d457 100644 --- a/src/lj_cparse.c +++ b/src/lj_cparse.c @@ -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) @@ -1052,6 +1053,7 @@ 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, '('); @@ -1059,50 +1061,49 @@ static void cp_decl_gccattribute(CPState *cp, CPDecl *decl) 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); @@ -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, ')'); @@ -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); @@ -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 { @@ -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_ /* ------------------------------------------------------------------------ */ diff --git a/src/lj_str.c b/src/lj_str.c index dc965bf7d..69cc5f3ae 100644 --- a/src/lj_str.c +++ b/src/lj_str.c @@ -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) { diff --git a/src/lj_str.h b/src/lj_str.h index 85c1e405b..9a4ea251d 100644 --- a/src/lj_str.h +++ b/src/lj_str.h @@ -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); diff --git a/src/x64/test/Makefile b/src/x64/test/Makefile index 4326ab3db..3ec44eae8 100644 --- a/src/x64/test/Makefile +++ b/src/x64/test/Makefile @@ -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 diff --git a/src/x64/test/unit/ffi/test_abi.lua b/src/x64/test/unit/ffi/test_abi.lua new file mode 100644 index 000000000..9fafcf55d --- /dev/null +++ b/src/x64/test/unit/ffi/test_abi.lua @@ -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")) diff --git a/src/x64/test/unit/ffi/test_line_directive.lua b/src/x64/test/unit/ffi/test_line_directive.lua new file mode 100644 index 000000000..a8b0403cb --- /dev/null +++ b/src/x64/test/unit/ffi/test_line_directive.lua @@ -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) diff --git a/src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua b/src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua new file mode 100644 index 000000000..5f1bdd30b --- /dev/null +++ b/src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua @@ -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) diff --git a/src/x64/test/unit/ffi/test_var_attribute.lua b/src/x64/test/unit/ffi/test_var_attribute.lua new file mode 100644 index 000000000..0b4d437a0 --- /dev/null +++ b/src/x64/test/unit/ffi/test_var_attribute.lua @@ -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) diff --git a/src/x64/test/unit_test.sh b/src/x64/test/unit_test.sh new file mode 100755 index 000000000..c6633ca2e --- /dev/null +++ b/src/x64/test/unit_test.sh @@ -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