diff options
author | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
---|---|---|
committer | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
commit | c6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch) | |
tree | 1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/texk/web2c/luatexdir/luaffi | |
parent | 07ee7222e389b0777456b427a55c22d0e6ffd267 (diff) |
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luaffi')
36 files changed, 0 insertions, 27132 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luaffi/CONTRIBUTING.md b/Build/source/texk/web2c/luatexdir/luaffi/CONTRIBUTING.md deleted file mode 100644 index 3591e05a0b0..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/CONTRIBUTING.md +++ /dev/null @@ -1,30 +0,0 @@ -# Contributing to luaffifb -We want to make contributing to this project as easy and transparent as -possible. - -## Our Development Process -... (in particular how this is synced with internal changes to the project) - -## Pull Requests -We actively welcome your pull requests. -1. Fork the repo and create your branch from `master`. -2. If you've added code that should be tested, add tests -3. If you haven't already, complete the Contributor License Agreement ("CLA"). - -## Contributor License Agreement ("CLA") -In order to accept your pull request, we need you to submit a CLA. You only need -to do this once to work on any of Facebook's open source projects. - -Complete your CLA here: <https://code.facebook.com/cla> - -## Issues -We use GitHub issues to track public bugs. Please ensure your description is -clear and has sufficient instructions to be able to reproduce the issue. - -## Coding Style -* Use four spaces for indentation rather than tabs -* 80 character line length - -## License -By contributing to luaffifb, you agree that your contributions will be licensed -under its BSD license. diff --git a/Build/source/texk/web2c/luatexdir/luaffi/LICENSE b/Build/source/texk/web2c/luatexdir/luaffi/LICENSE deleted file mode 100644 index d38b1644499..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/LICENSE +++ /dev/null @@ -1,58 +0,0 @@ -BSD License - -For luaffifb software - -Copyright (c) 2015, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------- - -This product contains portions of third party software provided under this license: - -luaffi software - -Copyright (c) 2011 James R. McKaskill - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -Facebook provides this code under the BSD License above. diff --git a/Build/source/texk/web2c/luatexdir/luaffi/Makefile.orig b/Build/source/texk/web2c/luatexdir/luaffi/Makefile.orig deleted file mode 100644 index 79bbd4cedef..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/Makefile.orig +++ /dev/null @@ -1,32 +0,0 @@ -# -# Use luarocks to install LuaFFI: -# > git clone https://github.com/facebook/luaffifb -# > cd luaffifb && luarocks make -# -# To rebuild the call_* headers: -# > rm call_*.h && make headers -# - -.PHONY: build clean headers -LUA=lua - -build: - luarocks make - -clean: - rm -f *.o *.so *.dylib - -headers: - $(MAKE) call_x86.h call_x64.h call_x64win.h call_arm.h - -call_x86.h: call_x86.dasc dynasm/*.lua - $(LUA) dynasm/dynasm.lua -LN -o $@ $< - -call_x64.h: call_x86.dasc dynasm/*.lua - $(LUA) dynasm/dynasm.lua -D X64 -LN -o $@ $< - -call_x64win.h: call_x86.dasc dynasm/*.lua - $(LUA) dynasm/dynasm.lua -D X64 -D X64WIN -LN -o $@ $< - -call_arm.h: call_arm.dasc dynasm/*.lua - $(LUA) dynasm/dynasm.lua -LNE -o $@ $< diff --git a/Build/source/texk/web2c/luatexdir/luaffi/PATENTS b/Build/source/texk/web2c/luatexdir/luaffi/PATENTS deleted file mode 100644 index f6388c50d5b..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/PATENTS +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the luaffifb software distributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook’s rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/Build/source/texk/web2c/luatexdir/luaffi/README b/Build/source/texk/web2c/luatexdir/luaffi/README deleted file mode 100644 index bff350f6f64..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/README +++ /dev/null @@ -1,78 +0,0 @@ -This is luaffifb from https://github.com/facebook/luaffifb -patched to compile for TeXLive.. - -It should compile even where the ffi is not defined, -because there is a ffi stub that does nothing: - -local info = [[ -The ffi module is available for: - - archictures : ARCH_X86 and ARCH_X64, - operating systems : OS_CE, OS_WIN, OS_LINUX, OS_BSD and OS_POSIX - -The ARM processor is currently not supported. There are subtle -differences between this module and the one in luajitTeX -and we hope to be in sync around TeXLive 2018. -Different OS can have different interfaces, -for instance OS_WIN has not 'complex.h'. If you want portable -code, stick to the most common concepts. -]] - -local function stub() - texio.write_nl(info) -end - -ffi = { - fill = stub, - cast = stub, - offsetof = stub, - copy = stub, - string = stub, - abi = stub, - cdef = stub, - typeof = stub, - sizeof = stub, - type = stub, - number = stub, - gc = stub, - metatype = stub, - errno = stub, - debug = stub, - os = '' , - arch = '' , - NULL = nil , - alignof = stub, - new = stub, - u64 = stub, - i64 = stub, - istype = stub, - load = stub, - C = nil , -} - - -So the following chunk of code can be used as an -example of how to check the ffi: - - if ffi then - if (ffi.os=='' and ffi.arch=='') then - -- ffi is the stub - -- or it's not a sane ffi - -- This should print something on terminal - print(ffi.cdef('')) - else - -- ffi looks ok - end - else - -- no ffi at all: perhaps an old luatex ? - end - -The ARCH enabled ARCH_X86 and ARCH_X64, -the OS enabled are OS_CE, OS_WIN, OS_LINUX, OS BD and OS_POSIX. -Currently ARM is not supported. - -The module is not aligned with luajit-2.1.0.beta2 -(the plan is to be in sync for TeXLive 2018) and -test.lua can fail. Be careful that different OS have different -interfaces (i.e. OS_WIN has not complex.h, for example) -so extra care must be take to ensure code portability. diff --git a/Build/source/texk/web2c/luatexdir/luaffi/README.md b/Build/source/texk/web2c/luatexdir/luaffi/README.md deleted file mode 100644 index b9a168c1006..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/README.md +++ /dev/null @@ -1,86 +0,0 @@ -[![Build Status](https://travis-ci.org/facebook/luaffifb.svg?branch=master)](https://travis-ci.org/facebook/luaffifb) - -About ------ -This is a library for calling C function and manipulating C types from lua. It -is designed to be interface compatible with the FFI library in LuaJIT (see -http://luajit.org/ext_ffi.html). It can parse C function declarations and -struct definitions that have been directly copied out of C header files and -into lua source as a string. - -This is a fork of https://github.com/jmckaskill/luaffi - -Source ------- -https://github.com/facebook/luaffifb - -Platforms ---------- -Currently supported: -- Linux x86/x64 -- OS X x86/x64 - -Runs with Lua 5.1, 5.2, and 5.3 - -Build ------ -In a terminal: - -```bash -git clone https://github.com/facebook/luaffifb -cd luaffifb -luarocks make -``` - -Documentation -------------- -This library is designed to be source compatible with LuaJIT's FFI extension. The documentation at http://luajit.org/ext_ffi.html describes the API and semantics. - -Pointer Comparison ------------- -Use `ffi.NULL` instead of `nil` when checking for `NULL` pointers. -```lua - ffi.new('void *', 0) == ffi.NULL -- true -``` - -Known Issues ------------- -- Comparing a ctype pointer to `nil` doesn't work the same as in LuaJIT (see above). - This is unfixable with the current metamethod semantics. -- Constant expressions can't handle non integer intermediate values (eg - offsetof won't work because it manipulates pointers) -- Not all metamethods work with Lua 5.1 (eg char* + number). This is due to - the way metamethods are looked up with mixed types in Lua 5.1. If you need -this upgrade to Lua 5.2 or use boxed numbers (uint64_t and uintptr_t). -- All bitfields are treated as unsigned (does anyone even use signed - bitfields?). Note that "int s:8" is unsigned on unix x86/x64, but signed on -windows. - - -How it works ------------- -Types are represented by a struct ctype structure and an associated user value -table. The table is shared between all related types for structs, unions, and -functions. It's members have the types of struct members, function argument -types, etc. The struct ctype structure then contains the modifications from -the base type (eg number of pointers, array size, etc). - -Types are pushed into lua as a userdata containing the struct ctype with a -user value (or fenv in 5.1) set to the shared type table. - -Boxed cdata types are pushed into lua as a userdata containing the struct -cdata structure (which contains the struct ctype of the data as its header) -followed by the boxed data. - -The functions in `ffi.C` provide the `cdata` and `ctype` metatables and ffi.* -functions which manipulate these two types. - -C functions (and function pointers) are pushed into lua as a lua c function -with the function pointer cdata as the first upvalue. The actual code is JITed -using dynasm (see call_x86.dasc). The JITed code does the following in order: - -1. Calls the needed unpack functions in `ffi.C` placing each argument on the HW stack -2. Updates `errno` -3. Performs the C call -4. Retrieves `errno` -5. Pushes the result back into lua from the HW register or stack diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call.c b/Build/source/texk/web2c/luatexdir/luaffi/call.c deleted file mode 100644 index 71bb3aea884..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call.c +++ /dev/null @@ -1,275 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#include "ffi.h" - -static cfunction compile(Dst_DECL, lua_State* L, cfunction func, int ref); - -static void* reserve_code(struct jit* jit, lua_State* L, size_t sz); -static void commit_code(struct jit* jit, void* p, size_t sz); - -static void push_int(lua_State* L, int val) -{ lua_pushinteger(L, val); } - -static void push_uint(lua_State* L, unsigned int val) -{ lua_pushinteger(L, val); } - -static void push_float(lua_State* L, float val) -{ lua_pushnumber(L, val); } - -#ifndef _WIN32 -static int GetLastError(void) -{ return errno; } -static void SetLastError(int err) -{ errno = err; } -#endif - -#ifdef NDEBUG -#define shred(a,b,c) -#else -#define shred(p,s,e) memset((uint8_t*)(p)+(s),0xCC,(e)-(s)) -#endif - - -#ifdef _WIN64 -#include "dynasm/dasm_x86.h" -#include "call_x64win.h" -#elif defined __amd64__ -#include "dynasm/dasm_x86.h" -#include "call_x64.h" -#elif defined __arm__ || defined __arm || defined __ARM__ || defined __ARM || defined ARM || defined _ARM_ || defined ARMV4I || defined _M_ARM -#include "dynasm/dasm_arm.h" -#include "call_arm.h" -#else -#include "dynasm/dasm_x86.h" -#include "call_x86.h" -#endif - -struct jit_head { - size_t size; - int ref; - uint8_t jump[JUMP_SIZE]; -}; - -#define LINKTABLE_MAX_SIZE (sizeof(extnames) / sizeof(extnames[0]) * (JUMP_SIZE)) - -static cfunction compile(struct jit* jit, lua_State* L, cfunction func, int ref) -{ - struct jit_head* code; - size_t codesz; - int err; - - dasm_checkstep(jit, -1); - if ((err = dasm_link(jit, &codesz)) != 0) { - char buf[32]; - sprintf(buf, "%x", err); - luaL_error(L, "dasm_link error %s", buf); - } - - codesz += sizeof(struct jit_head); - code = (struct jit_head*) reserve_code(jit, L, codesz); - code->ref = ref; - code->size = codesz; - compile_extern_jump(jit, L, func, code->jump); - - if ((err = dasm_encode(jit, code+1)) != 0) { - char buf[32]; - sprintf(buf, "%x", err); - commit_code(jit, code, 0); - luaL_error(L, "dasm_encode error %s", buf); - } - - commit_code(jit, code, codesz); - return (cfunction) (code+1); -} - -typedef uint8_t jump_t[JUMP_SIZE]; - -int get_extern(struct jit* jit, uint8_t* addr, int idx, int type) -{ - struct page* page = jit->pages[jit->pagenum-1]; - jump_t* jumps = (jump_t*) (page+1); - struct jit_head* h = (struct jit_head*) ((uint8_t*) page + page->off); - uint8_t* jmp; - ptrdiff_t off; - - if (idx == jit->function_extern) { - jmp = h->jump; - } else { - jmp = jumps[idx]; - } - - /* compensate for room taken up for the offset so that we can work rip - * relative */ - addr += BRANCH_OFF; - - /* see if we can fit the offset in the branch displacement, if not use the - * jump instruction */ - off = *(uint8_t**) jmp - addr; - - if (MIN_BRANCH <= off && off <= MAX_BRANCH) { - return (int32_t) off; - } else { - return (int32_t)(jmp + sizeof(uint8_t*) - addr); - } -} - -static void* reserve_code(struct jit* jit, lua_State* L, size_t sz) -{ - struct page* page; - size_t off = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->off : 0; - size_t size = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->size : 0; - - if (off + sz >= size) { - int i; - uint8_t* pdata; - cfunction func; - - /* need to create a new page */ - jit->pages = (struct page**) realloc(jit->pages, (++jit->pagenum) * sizeof(jit->pages[0])); - - size = ALIGN_UP(sz + LINKTABLE_MAX_SIZE + sizeof(struct page), jit->align_page_size); - - page = (struct page*) AllocPage(size); - jit->pages[jit->pagenum-1] = page; - pdata = (uint8_t*) page; - page->size = size; - page->off = sizeof(struct page); - - lua_newtable(L); - -#define ADDFUNC(DLL, NAME) \ - lua_pushliteral(L, #NAME); \ - func = DLL ? (cfunction) GetProcAddressA(DLL, #NAME) : NULL; \ - func = func ? func : (cfunction) &NAME; \ - lua_pushcfunction(L, (lua_CFunction) func); \ - lua_rawset(L, -3) - - ADDFUNC(NULL, check_double); - ADDFUNC(NULL, check_float); - ADDFUNC(NULL, check_uint64); - ADDFUNC(NULL, check_int64); - ADDFUNC(NULL, check_int32); - ADDFUNC(NULL, check_uint32); - ADDFUNC(NULL, check_uintptr); - ADDFUNC(NULL, check_enum); - ADDFUNC(NULL, check_typed_pointer); - ADDFUNC(NULL, check_typed_cfunction); - ADDFUNC(NULL, check_complex_double); - ADDFUNC(NULL, check_complex_float); - ADDFUNC(NULL, unpack_varargs_stack); - ADDFUNC(NULL, unpack_varargs_stack_skip); - ADDFUNC(NULL, unpack_varargs_reg); - ADDFUNC(NULL, unpack_varargs_float); - ADDFUNC(NULL, unpack_varargs_int); - ADDFUNC(NULL, push_cdata); - ADDFUNC(NULL, push_int); - ADDFUNC(NULL, push_uint); - ADDFUNC(NULL, lua_pushinteger); - ADDFUNC(NULL, push_float); - ADDFUNC(jit->kernel32_dll, SetLastError); - ADDFUNC(jit->kernel32_dll, GetLastError); - ADDFUNC(jit->lua_dll, luaL_error); - ADDFUNC(jit->lua_dll, lua_pushnumber); - ADDFUNC(jit->lua_dll, lua_pushboolean); - ADDFUNC(jit->lua_dll, lua_gettop); - ADDFUNC(jit->lua_dll, lua_rawgeti); - ADDFUNC(jit->lua_dll, lua_pushnil); - ADDFUNC(jit->lua_dll, lua_callk); - ADDFUNC(jit->lua_dll, lua_settop); - ADDFUNC(jit->lua_dll, lua_remove); -#undef ADDFUNC - - for (i = 0; extnames[i] != NULL; i++) { - - if (strcmp(extnames[i], "FUNCTION") == 0) { - shred(pdata + page->off, 0, JUMP_SIZE); - jit->function_extern = i; - - } else { - lua_getfield(L, -1, extnames[i]); - func = (cfunction) lua_tocfunction(L, -1); - - if (func == NULL) { - luaL_error(L, "internal error: missing link for %s", extnames[i]); - } - - compile_extern_jump(jit, L, func, pdata + page->off); - lua_pop(L, 1); - } - - page->off += JUMP_SIZE; - } - - page->freed = page->off; - lua_pop(L, 1); - - } else { - page = jit->pages[jit->pagenum-1]; - EnableWrite(page, page->size); - } - - return (uint8_t*) page + page->off; -} - -static void commit_code(struct jit* jit, void* code, size_t sz) -{ - struct page* page = jit->pages[jit->pagenum-1]; - page->off += sz; - EnableExecute(page, page->size); - { -#if 0 - FILE* out = fopen("\\Hard Disk\\out.bin", "wb"); - fwrite(page, page->off, 1, out); - fclose(out); -#endif - } -} - -/* push_func_ref pushes a copy of the upval table embedded in the compiled - * function func. - */ -void push_func_ref(lua_State* L, cfunction func) -{ - struct jit_head* h = ((struct jit_head*) func) - 1; - lua_rawgeti(L, LUA_REGISTRYINDEX, h->ref); -} - -void free_code(struct jit* jit, lua_State* L, cfunction func) -{ - size_t i; - struct jit_head* h = ((struct jit_head*) func) - 1; - for (i = 0; i < jit->pagenum; i++) { - struct page* p = jit->pages[i]; - - if ((uint8_t*) h < (uint8_t*) p || (uint8_t*) p + p->size <= (uint8_t*) h) { - continue; - } - - luaL_unref(L, LUA_REGISTRYINDEX, h->ref); - - EnableWrite(p, p->size); - p->freed += h->size; - - shred(h, 0, h->size); - - if (p->freed < p->off) { - EnableExecute(p, p->size); - return; - } - - FreePage(p, p->size); - memmove(&jit->pages[i], &jit->pages[i+1], (jit->pagenum - (i+1)) * sizeof(jit->pages[0])); - jit->pagenum--; - return; - } - - assert(!"couldn't find func in the jit pages"); -} - - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call_arm.dasc b/Build/source/texk/web2c/luatexdir/luaffi/call_arm.dasc deleted file mode 100644 index f85753255fb..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call_arm.dasc +++ /dev/null @@ -1,610 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -|.arch arm -|.actionlist build_actionlist -|.globalnames globnames -|.externnames extnames - -#define JUMP_SIZE 8 -#define MIN_BRANCH ((INT32_MIN) >> 8) -#define MAX_BRANCH ((INT32_MAX) >> 8) -#define BRANCH_OFF 4 - -static void compile_extern_jump(struct jit* jit, lua_State* L, cfunction func, uint8_t* code) -{ - /* The jump code is the function pointer followed by a stub to call the - * function pointer. The stub exists so we can jump to functions with an - * offset greater than 32MB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state. - */ - *(cfunction*) code = func; - /* ldr pc, [pc - 12] */ - *(uint32_t*) &code[4] = 0xE51FF00CU; -} - -|.define TOP, r4 -|.define L_ARG, r5 -|.define DATA, r6 -|.define DATA2, r7 - -|.macro load32, reg, val -| ldr reg, [pc] -| b >5 -|.long val -|5: -|.endmacro - -|.macro lcall, func -| mov r0, L_ARG -| bl func -|.endmacro - -void compile_globals(struct jit* jit, lua_State* L) -{ - (void) jit; -} - -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct) -{ - struct jit* Dst = get_jit(L);; - int i, nargs, num_upvals, ref; - const struct ctype* mt; - - int top = lua_gettop(L); - - ct_usr = lua_absindex(L, ct_usr); - fidx = lua_absindex(L, fidx); - nargs = (int) lua_rawlen(L, ct_usr); - - dasm_setup(Dst, build_actionlist); - - lua_newtable(L); - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - num_upvals = 0; - - if (ct->has_var_arg) { - luaL_error(L, "can't create callbacks with varargs"); - } - - /* prolog and get the upval table */ - | mov r12, sp - | push {r0, r1, r2, r3} // do this first so that r0-r3 is right before stack bound arguments - | push {TOP, L_ARG, DATA, DATA2, r12, lr} - | sub DATA, r12, #16 // points to r0 on stack - | ldr L_ARG, [pc, #8] - | ldr r2, [pc, #8] - | ldr r1, [pc, #8] - | b >1 - |.long L, ref, LUA_REGISTRYINDEX - |1: - | lcall extern lua_rawgeti - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - | mov r2, #num_upvals - | mvn r1, #0 // -1 - | lcall extern lua_rawgeti - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | mov r2, #num_upvals-1 // usr value - | mvn r1, #i // -i-1, stack is upval table, func, i-1 args - | lcall extern lua_rawgeti - | load32 r2, mt - | mvn r1, #0 // -1 - | lcall extern push_cdata - | ldr r2, [DATA], #4 - | str r2, [r0] - | mvn r1, #1 // -2 - | lcall extern lua_remove // remove the usr value - - } else { - switch (mt->type) { - case INT64_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - | lcall extern lua_pushnil - | load32 r2, mt - | mvn r1, #0 // -1 - | lcall extern push_cdata - | ldr r2, [DATA], #4 - | ldr r3, [DATA], #4 - | str r2, [r0] - | str r3, [r0, #4] - | mvn r1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - break; - - case INTPTR_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - | lcall extern lua_pushnil - | load32 r2, mt - | mvn r1, #0 // -1 - | lcall extern push_cdata - | ldr r2, [DATA], #4 - | str r2, [r0] - | mvn r1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - break; - - case BOOL_TYPE: - lua_pop(L, 1); - | ldr r1, [DATA], #4 - | lcall extern lua_pushboolean - break; - - case INT8_TYPE: - lua_pop(L, 1); - | ldr r1, [DATA], #4 - | mov r1, r1, lsl #24 - if (mt->is_unsigned) { - | mov r1, r1, lsr #24 - } else { - | mov r1, r1, asr #24 - } - | lcall extern push_int - break; - - case INT16_TYPE: - lua_pop(L, 1); - | ldr r1, [DATA], #4 - | mov r1, r1, lsl #16 - if (mt->is_unsigned) { - | mov r1, r1, lsr #16 - } else { - | mov r1, r1, asr #16 - } - | lcall extern push_int - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - | ldr r1, [DATA], #4 - | lcall extern push_int - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - | ldr r1, [DATA], #4 - | lcall extern push_float - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - | ldmia DATA!, {r1, r2} - | lcall extern lua_pushnumber - break; - - default: - luaL_error(L, "NYI: callback arg type"); - } - } - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - | mov r3, #0 - | mov r2, #((mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0) - | mov r1, #nargs - | lcall extern lua_callk - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | mov r2, #num_upvals-1 // usr value - | mvn r1, #1 // -2 stack is (upval table, ret val) - | lcall extern lua_rawgeti - | load32 r3, mt - | mov r2, #0 // -1 - ct_usr - | mvn r1, #1 // -2 - val - | lcall extern to_typed_pointer - | mov DATA, r0 - | mvn r1, #3 // -4 - remove 3 (upval table, ret val, usr value) - | lcall extern lua_settop - | mov r0, DATA - } else { - switch (mt->type) { - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | mov r2, #num_upvals-1 // usr value - | mvn r1, #1 // -2 stack is (upval table, ret val) - | lcall extern lua_rawgeti - | load32 r3, mt - | mvn r2, #0 // -1 - ct_usr - | mvn r1, #1 // -2 - val - | lcall extern to_enum - | mov DATA, r0 - | mvn r1, #3 // -4 - remove 3 (upval table, ret val, usr value) - | lcall extern lua_settop - | mov r0, DATA - break; - - case VOID_TYPE: - | mvn r1, #1 // -2 - | lcall extern lua_settop - lua_pop(L, 1); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - | mvn r1, #0 // -1 - if (mt->is_unsigned) { - | lcall extern check_uint32 - } else { - | lcall extern check_int32 - } - goto single; - - case INT64_TYPE: - | mvn r1, #0 // -1 - if (mt->is_unsigned) { - | lcall extern check_uint64 - } else { - | lcall extern check_int64 - } - goto dual; - - case INTPTR_TYPE: - | mvn r1, #0 // -1 - | lcall extern check_intptr - goto single; - - case FLOAT_TYPE: - | mvn r1, #0 // -1 - | lcall extern check_float - goto single; - - case DOUBLE_TYPE: - | mvn r1, #0 // -1 - | lcall extern check_double - goto dual; - - single: - | mov DATA, r0 - | mvn r1, #2 // -3 - | lcall extern lua_settop - | mov r0, DATA - lua_pop(L, 1); - break; - - dual: - | mov DATA, r0 - | mov DATA2, r1 - | mvn r1, #2 // -3 - | lcall extern lua_settop - | mov r0, DATA - | mov r1, DATA2 - lua_pop(L, 1); - break; - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - | ldmia sp, {TOP, L_ARG, DATA, DATA2, sp, pc} - - lua_pop(L, 1); /* upval table - already in registry */ - assert(lua_gettop(L) == top); - - { - void* p; - struct ctype ft; - cfunction func; - - func = compile(Dst, L, NULL, ref); - - ft = *ct; - ft.is_jitted = 1; - p = push_cdata(L, ct_usr, &ft); - *(cfunction*) p = func; - - assert(lua_gettop(L) == top + 1); - - return func; - } -} - -void compile_function(lua_State* L, cfunction func, int ct_usr, const struct ctype* ct) -{ - struct jit* Dst = get_jit(L);; - int i, nargs, num_upvals; - const struct ctype* mt; - void* p; - - int top = lua_gettop(L); - - ct_usr = lua_absindex(L, ct_usr); - nargs = (int) lua_rawlen(L, ct_usr); - - p = push_cdata(L, ct_usr, ct); - *(cfunction*) p = func; - num_upvals = 1; - - dasm_setup(Dst, build_actionlist); - - | mov r12, sp - | push {r0} - | push {TOP, L_ARG, DATA, DATA2, r11, r12, lr} - | sub r11, r12, #4 - | mov L_ARG, r0 - | lcall extern lua_gettop - | mov TOP, r0 - | cmp TOP, #nargs - | // these should really be in globals - but for some reason dynasm breaks when you do that - if (ct->has_var_arg) { - | bge >1 - | load32 r1, "too few arguments" - | lcall extern luaL_error - |1: - } else { - | beq >1 - | load32 r1, "incorrect number of arguments" - | lcall extern luaL_error - |1: - } - - /* reserve enough stack space for all of the arguments (8 bytes per - * argument for double and maintains alignment). Add an extra 16 bytes so - * that the pop {r0, r1, r2, r3} doesn't clean out our stack frame */ - | sub sp, sp, TOP, lsl #3 - | sub sp, sp, #16 - | mov DATA, sp - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference || mt->type == FUNCTION_PTR_TYPE || mt->type == ENUM_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - - | ldr r3, [pc, #4] - | ldr r2, [pc, #4] - | b >1 - |.long mt, lua_upvalueindex(num_upvals) - |1: - | mov r1, #i - | mov r0, L_ARG - - if (mt->pointers || mt->is_reference) { - | bl extern to_typed_pointer - } else if (mt->type == FUNCTION_PTR_TYPE) { - | bl extern to_typed_function - } else if (mt->type == ENUM_TYPE) { - | bl extern to_enum - } - - | str r0, [DATA], #4 - - } else { - lua_pop(L, 1); - | mov r1, #i - - switch (mt->type) { - case INT8_TYPE: - | lcall extern check_int32 - if (mt->is_unsigned) { - | and r0, r0, #0xFF - } else { - | mov r0, r0, lsl #24 - | mov r0, r0, asr #24 - } - | str r0, [DATA], #4 - break; - - case INT16_TYPE: - | lcall extern check_int32 - if (mt->is_unsigned) { - | mov r0, r0, lsl #16 - | mov r0, r0, lsr #16 - } else { - | mov r0, r0, lsl #16 - | mov r0, r0, asr #16 - } - | str r0, [DATA], #4 - break; - - case INT32_TYPE: - if (mt->is_unsigned) { - | lcall extern check_uint32 - } else { - | lcall extern check_int32 - } - | str r0, [DATA], #4 - break; - - case INT64_TYPE: - if (mt->is_unsigned) { - | lcall extern check_uint64 - } else { - | lcall extern check_int64 - } - | str r0, [DATA], #4 - | str r1, [DATA], #4 - break; - - case DOUBLE_TYPE: - | lcall extern check_double - | str r0, [DATA], #4 - | str r1, [DATA], #4 - break; - - case INTPTR_TYPE: - | lcall extern check_intptr - | str r0, [DATA], #4 - break; - - case FLOAT_TYPE: - | lcall extern check_float - | str r0, [DATA], #4 - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { - | mov r3, DATA - | mov r2, TOP - | mov r1, #nargs+1 - | lcall extern unpack_varargs_stack - } - - | load32 r0, &Dst->last_errno - | ldr r0, [r0] - | bl extern SetLastError - - | pop {r0, r1, r2, r3} // this pop is balanced with the sub sp, #16 - | bl extern FUNCTION - - |.macro get_errno - | bl extern GetLastError - | load32 r1, &Dst->last_errno - | str r0, [r1] - |.endmacro - - |.macro return - | ldmdb r11, {TOP, L_ARG, DATA, r11, sp, pc} - |.endmacro - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - num_upvals += 2; - | mov DATA, r0 - | get_errno - | ldr r2, [pc, #4] - | ldr r1, [pc, #4] - | b >1 - |.long mt, lua_upvalueindex(num_upvals) - |1: - | lcall extern push_cdata - | str DATA, [r0] - | mov r0, #1 - | return - - } else { - switch (mt->type) { - case INT64_TYPE: - num_upvals++; - | mov DATA, r0 - | mov DATA2, r1 - | get_errno - | lcall extern lua_pushnil - | load32 r2, mt - | mvn r1, #0 // -1 - | lcall extern push_cdata - | str DATA, [r0] - | str DATA2, [r0, #4] - | mov r0, #1 - | return - break; - - case INTPTR_TYPE: - num_upvals++; - | mov DATA, r0 - | get_errno - | lcall extern lua_pushnil - | load32 r2, mt - | mvn r1, #0 // -1 - | lcall extern push_cdata - | str DATA, [r0] - | mov r0, #1 - | return - break; - - case VOID_TYPE: - lua_pop(L, 1); - | get_errno - | mov r0, #0 - | return - break; - - case BOOL_TYPE: - lua_pop(L, 1); - | mov DATA, r0 - | get_errno - | mov r1, DATA - | lcall extern lua_pushboolean - | mov r0, #1 - | return - break; - - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - | mov DATA, r0 - | get_errno - | mov r1, DATA - if (mt->is_unsigned) { - | lcall extern push_uint - } else { - | lcall extern push_int - } - | mov r0, #1 - | return - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - | mov DATA, r0 - | get_errno - | mov r1, DATA - | lcall extern push_float - | mov r0, #1 - | return - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - | mov DATA, r0 - | mov DATA2, r1 - | get_errno - | mov r2, DATA2 - | mov r1, DATA - | lcall extern lua_pushnumber - | mov r0, #1 - | return - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - lua_pushcclosure(L, (lua_CFunction) compile(Dst, L, func, LUA_NOREF), num_upvals); -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call_arm.h b/Build/source/texk/web2c/luatexdir/luaffi/call_arm.h deleted file mode 100644 index efe7f9567e3..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call_arm.h +++ /dev/null @@ -1,1013 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM arm version 1.3.0 -** DO NOT EDIT! The original file is in "call_arm.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -static const unsigned int build_actionlist[546] = { -0xe1a0c00d, -0xe92d000f, -0xe92d50f0, -0xe24c6010, -0xe59f5008, -0xe59f2008, -0xe59f1008, -0xea000000, -0x00050001, -0x00090000, -0x00090000, -0x00090000, -0x0006000b, -0xe1a00005, -0xeb000000, -0x00030000, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030000, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00005, -0xeb000000, -0x00030000, -0xe59f2000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030001, -0xe4962004, -0xe5802000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x00030002, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030003, -0xe59f2000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030001, -0xe4962004, -0xe4963004, -0xe5802000, -0xe5803004, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x00030002, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030003, -0xe59f2000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030001, -0xe4962004, -0xe5802000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x00030002, -0x00000000, -0xe4961004, -0xe1a00005, -0xeb000000, -0x00030004, -0x00000000, -0xe4961004, -0xe1a01c01, -0x00000000, -0xe1a01c21, -0x00000000, -0xe1a01c41, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030005, -0x00000000, -0xe4961004, -0xe1a01801, -0x00000000, -0xe1a01821, -0x00000000, -0xe1a01841, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030005, -0x00000000, -0xe4961004, -0xe1a00005, -0xeb000000, -0x00030005, -0x00000000, -0xe4961004, -0xe1a00005, -0xeb000000, -0x00030006, -0x00000000, -0xe8b60006, -0xe1a00005, -0xeb000000, -0x00030007, -0x00000000, -0xe3a03000, -0xe3a02000, -0x000b0000, -0xe3a01000, -0x000b0000, -0xe1a00005, -0xeb000000, -0x00030008, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x00030000, -0xe59f3000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3a02000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x00030009, -0xe1a06000, -0xe3e01003, -0xe1a00005, -0xeb000000, -0x0003000a, -0xe1a00006, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x00030000, -0xe59f3000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3e02000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x0003000b, -0xe1a06000, -0xe3e01003, -0xe1a00005, -0xeb000000, -0x0003000a, -0xe1a00006, -0x00000000, -0xe3e01001, -0xe1a00005, -0xeb000000, -0x0003000a, -0x00000000, -0xe3e01000, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000c, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000d, -0x00000000, -0xe3e01000, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000e, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000f, -0x00000000, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030010, -0x00000000, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030011, -0x00000000, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030012, -0x00000000, -0xe1a06000, -0xe3e01002, -0xe1a00005, -0xeb000000, -0x0003000a, -0xe1a00006, -0x00000000, -0xe1a06000, -0xe1a07001, -0xe3e01002, -0xe1a00005, -0xeb000000, -0x0003000a, -0xe1a00006, -0xe1a01007, -0x00000000, -0xe89da0f0, -0x00000000, -0xe1a0c00d, -0xe92d0001, -0xe92d58f0, -0xe24cb004, -0xe1a05000, -0xe1a00005, -0xeb000000, -0x00030013, -0xe1a04000, -0xe3540000, -0x000b0000, -0x00000000, -0xaa000000, -0x00050001, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe1a00005, -0xeb000000, -0x00030014, -0x0006000b, -0x00000000, -0x0a000000, -0x00050001, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe1a00005, -0xeb000000, -0x00030014, -0x0006000b, -0x00000000, -0xe04dd184, -0xe24dd010, -0xe1a0600d, -0x00000000, -0xe59f3004, -0xe59f2004, -0xea000000, -0x00050001, -0x00090000, -0x00090000, -0x0006000b, -0xe3a01000, -0x000b0000, -0xe1a00005, -0x00000000, -0xeb000000, -0x00030009, -0x00000000, -0xeb000000, -0x00030015, -0x00000000, -0xeb000000, -0x0003000b, -0x00000000, -0xe4860004, -0x00000000, -0xe3a01000, -0x000b0000, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000d, -0x00000000, -0xe20000ff, -0x00000000, -0xe1a00c00, -0xe1a00c40, -0x00000000, -0xe4860004, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000d, -0x00000000, -0xe1a00800, -0xe1a00820, -0x00000000, -0xe1a00800, -0xe1a00840, -0x00000000, -0xe4860004, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000c, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000d, -0x00000000, -0xe4860004, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000e, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003000f, -0x00000000, -0xe4860004, -0xe4861004, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030012, -0xe4860004, -0xe4861004, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030010, -0xe4860004, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030011, -0xe4860004, -0x00000000, -0xe1a03006, -0xe1a02004, -0xe3a01000, -0x000b0000, -0xe1a00005, -0xeb000000, -0x00030016, -0x00000000, -0xe59f0000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5900000, -0xeb000000, -0x00030017, -0x00000000, -0xe8bd000f, -0xeb000000, -0x00030018, -0x00000000, -0xe1a06000, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe59f2004, -0xe59f1004, -0xea000000, -0x00050001, -0x00090000, -0x00090000, -0x0006000b, -0xe1a00005, -0xeb000000, -0x00030001, -0xe5806000, -0xe3a00001, -0xe91ba870, -0x00000000, -0xe1a06000, -0xe1a07001, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe1a00005, -0xeb000000, -0x00030003, -0xe59f2000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030001, -0xe5806000, -0xe5807004, -0xe3a00001, -0xe91ba870, -0x00000000, -0xe1a06000, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe1a00005, -0xeb000000, -0x00030003, -0xe59f2000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe3e01000, -0xe1a00005, -0xeb000000, -0x00030001, -0xe5806000, -0xe3a00001, -0xe91ba870, -0x00000000, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe3a00000, -0xe91ba870, -0x00000000, -0xe1a06000, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe1a01006, -0xe1a00005, -0xeb000000, -0x00030004, -0xe3a00001, -0xe91ba870, -0x00000000, -0xe1a06000, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe1a01006, -0x00000000, -0xe1a00005, -0xeb000000, -0x0003001a, -0x00000000, -0xe1a00005, -0xeb000000, -0x00030005, -0x00000000, -0xe3a00001, -0xe91ba870, -0x00000000, -0xe1a06000, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe1a01006, -0xe1a00005, -0xeb000000, -0x00030006, -0xe3a00001, -0xe91ba870, -0x00000000, -0xe1a06000, -0xe1a07001, -0xeb000000, -0x00030019, -0xe59f1000, -0xea000000, -0x00050005, -0x00090000, -0x0006000f, -0xe5810000, -0xe1a02007, -0xe1a01006, -0xe1a00005, -0xeb000000, -0x00030007, -0xe3a00001, -0xe91ba870, -0x00000000 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "lua_rawgeti", - "push_cdata", - "lua_remove", - "lua_pushnil", - "lua_pushboolean", - "push_int", - "push_float", - "lua_pushnumber", - "lua_callk", - "to_typed_pointer", - "lua_settop", - "to_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_intptr", - "check_float", - "check_double", - "lua_gettop", - "luaL_error", - "to_typed_function", - "unpack_varargs_stack", - "SetLastError", - "FUNCTION", - "GetLastError", - "push_uint", - (const char *)0 -}; - -#define JUMP_SIZE 8 -#define MIN_BRANCH ((INT32_MIN) >> 8) -#define MAX_BRANCH ((INT32_MAX) >> 8) -#define BRANCH_OFF 4 - -static void compile_extern_jump(struct jit* jit, lua_State* L, cfunction func, uint8_t* code) -{ - /* The jump code is the function pointer followed by a stub to call the - * function pointer. The stub exists so we can jump to functions with an - * offset greater than 32MB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state. - */ - *(cfunction*) code = func; - /* ldr pc, [pc - 12] */ - *(uint32_t*) &code[4] = 0xE51FF00CU; -} - - - - -void compile_globals(struct jit* jit, lua_State* L) -{ - (void) jit; -} - -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct) -{ - struct jit* Dst = get_jit(L);; - int i, nargs, num_upvals, ref; - const struct ctype* mt; - - int top = lua_gettop(L); - - ct_usr = lua_absindex(L, ct_usr); - fidx = lua_absindex(L, fidx); - nargs = (int) lua_rawlen(L, ct_usr); - - dasm_setup(Dst, build_actionlist); - - lua_newtable(L); - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - num_upvals = 0; - - if (ct->has_var_arg) { - luaL_error(L, "can't create callbacks with varargs"); - } - - /* prolog and get the upval table */ - dasm_put(Dst, 0, (uintptr_t)(L), (uintptr_t)(ref), (uintptr_t)(LUA_REGISTRYINDEX)); - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - dasm_put(Dst, 17, num_upvals); - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 24, num_upvals-1, i, (uintptr_t)(mt)); - - } else { - switch (mt->type) { - case INT64_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 47, (uintptr_t)(mt)); - break; - - case INTPTR_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 68, (uintptr_t)(mt)); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 87); - break; - - case INT8_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 92); - if (mt->is_unsigned) { - dasm_put(Dst, 95); - } else { - dasm_put(Dst, 97); - } - dasm_put(Dst, 99); - break; - - case INT16_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 103); - if (mt->is_unsigned) { - dasm_put(Dst, 106); - } else { - dasm_put(Dst, 108); - } - dasm_put(Dst, 110); - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 114); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 119); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 124); - break; - - default: - luaL_error(L, "NYI: callback arg type"); - } - } - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - dasm_put(Dst, 129, ((mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0), nargs); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 138, num_upvals-1, (uintptr_t)(mt)); - } else { - switch (mt->type) { - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 161, num_upvals-1, (uintptr_t)(mt)); - break; - - case VOID_TYPE: - dasm_put(Dst, 184); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - dasm_put(Dst, 189); - if (mt->is_unsigned) { - dasm_put(Dst, 191); - } else { - dasm_put(Dst, 195); - } - goto single; - - case INT64_TYPE: - dasm_put(Dst, 199); - if (mt->is_unsigned) { - dasm_put(Dst, 201); - } else { - dasm_put(Dst, 205); - } - goto dual; - - case INTPTR_TYPE: - dasm_put(Dst, 209); - goto single; - - case FLOAT_TYPE: - dasm_put(Dst, 214); - goto single; - - case DOUBLE_TYPE: - dasm_put(Dst, 219); - goto dual; - - single: - dasm_put(Dst, 224); - lua_pop(L, 1); - break; - - dual: - dasm_put(Dst, 231); - lua_pop(L, 1); - break; - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 240); - - lua_pop(L, 1); /* upval table - already in registry */ - assert(lua_gettop(L) == top); - - { - void* p; - struct ctype ft; - cfunction func; - - func = compile(Dst, L, NULL, ref); - - ft = *ct; - ft.is_jitted = 1; - p = push_cdata(L, ct_usr, &ft); - *(cfunction*) p = func; - - assert(lua_gettop(L) == top + 1); - - return func; - } -} - -void compile_function(lua_State* L, cfunction func, int ct_usr, const struct ctype* ct) -{ - struct jit* Dst = get_jit(L);; - int i, nargs, num_upvals; - const struct ctype* mt; - void* p; - - int top = lua_gettop(L); - - ct_usr = lua_absindex(L, ct_usr); - nargs = (int) lua_rawlen(L, ct_usr); - - p = push_cdata(L, ct_usr, ct); - *(cfunction*) p = func; - num_upvals = 1; - - dasm_setup(Dst, build_actionlist); - - dasm_put(Dst, 242, nargs); - if (ct->has_var_arg) { - dasm_put(Dst, 254, (uintptr_t)("too few arguments")); - } else { - dasm_put(Dst, 266, (uintptr_t)("incorrect number of arguments")); - } - - /* reserve enough stack space for all of the arguments (8 bytes per - * argument for double and maintains alignment). Add an extra 16 bytes so - * that the pop {r0, r1, r2, r3} doesn't clean out our stack frame */ - dasm_put(Dst, 278); - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference || mt->type == FUNCTION_PTR_TYPE || mt->type == ENUM_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - - dasm_put(Dst, 282, (uintptr_t)(mt), (uintptr_t)(lua_upvalueindex(num_upvals)), i); - - if (mt->pointers || mt->is_reference) { - dasm_put(Dst, 293); - } else if (mt->type == FUNCTION_PTR_TYPE) { - dasm_put(Dst, 296); - } else if (mt->type == ENUM_TYPE) { - dasm_put(Dst, 299); - } - - dasm_put(Dst, 302); - - } else { - lua_pop(L, 1); - dasm_put(Dst, 304, i); - - switch (mt->type) { - case INT8_TYPE: - dasm_put(Dst, 307); - if (mt->is_unsigned) { - dasm_put(Dst, 311); - } else { - dasm_put(Dst, 313); - } - dasm_put(Dst, 316); - break; - - case INT16_TYPE: - dasm_put(Dst, 318); - if (mt->is_unsigned) { - dasm_put(Dst, 322); - } else { - dasm_put(Dst, 325); - } - dasm_put(Dst, 328); - break; - - case INT32_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 330); - } else { - dasm_put(Dst, 334); - } - dasm_put(Dst, 338); - break; - - case INT64_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 340); - } else { - dasm_put(Dst, 344); - } - dasm_put(Dst, 348); - break; - - case DOUBLE_TYPE: - dasm_put(Dst, 351); - break; - - case INTPTR_TYPE: - dasm_put(Dst, 357); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 362); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { - dasm_put(Dst, 367, nargs+1); - } - - dasm_put(Dst, 375, (uintptr_t)(&Dst->last_errno)); - - dasm_put(Dst, 384); - - - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 388, (uintptr_t)(&Dst->last_errno), (uintptr_t)(mt), (uintptr_t)(lua_upvalueindex(num_upvals))); - - } else { - switch (mt->type) { - case INT64_TYPE: - num_upvals++; - dasm_put(Dst, 411, (uintptr_t)(&Dst->last_errno), (uintptr_t)(mt)); - break; - - case INTPTR_TYPE: - num_upvals++; - dasm_put(Dst, 438, (uintptr_t)(&Dst->last_errno), (uintptr_t)(mt)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 463, (uintptr_t)(&Dst->last_errno)); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 474, (uintptr_t)(&Dst->last_errno)); - break; - - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 490, (uintptr_t)(&Dst->last_errno)); - if (mt->is_unsigned) { - dasm_put(Dst, 501); - } else { - dasm_put(Dst, 505); - } - dasm_put(Dst, 509); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 512, (uintptr_t)(&Dst->last_errno)); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 528, (uintptr_t)(&Dst->last_errno)); - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - lua_pushcclosure(L, (lua_CFunction) compile(Dst, L, func, LUA_NOREF), num_upvals); -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call_x64.h b/Build/source/texk/web2c/luatexdir/luaffi/call_x64.h deleted file mode 100644 index 5cf89a0fc03..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call_x64.h +++ /dev/null @@ -1,1204 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM x64 version 1.3.0 -** DO NOT EDIT! The original file is in "call_x86.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -static const unsigned char build_actionlist[2157] = { - 72,139,141,233,255,72,137,132,253,36,233,255,221,133,233,255,217,133,233, - 255,252,243,15,126,133,233,255,252,243,15,90,133,233,255,221,156,253,36,233, - 255,217,156,253,36,233,255,102,15,214,132,253,36,233,255,252,242,15,90,192, - 102,15,214,132,253,36,233,255,252,242,15,90,192,102,15,126,132,253,36,233, - 255,85,72,137,229,65,84,72,129,252,236,239,102,15,214,69,252,240,102,15,214, - 77,232,102,15,214,85,224,102,15,214,93,216,102,15,214,101,208,102,15,214, - 109,200,102,15,214,117,192,102,15,214,125,184,72,137,125,176,72,137,117,168, - 72,137,85,160,72,137,77,152,76,137,69,144,76,137,77,136,255,73,188,237,237, - 255,72,199,194,237,72,199,198,237,76,137,231,232,251,1,0,255,72,199,194,237, - 72,199,198,252,255,252,255,252,255,252,255,76,137,231,232,251,1,0,255,72, - 199,194,237,72,199,198,237,76,137,231,232,251,1,0,72,186,237,237,72,199,198, - 252,255,252,255,252,255,252,255,76,137,231,232,251,1,1,255,72,137,8,72,199, - 198,252,254,252,255,252,255,252,255,76,137,231,232,251,1,2,255,72,186,237, - 237,72,199,198,0,0,0,0,76,137,231,232,251,1,1,255,72,137,8,255,102,15,214, - 0,255,217,24,255,217,88,4,255,102,15,214,64,8,255,76,137,231,232,251,1,3, - 255,15,182,201,72,137,206,76,137,231,232,251,1,4,255,15,182,201,255,15,190, - 201,255,72,137,206,76,137,231,232,251,1,5,255,15,183,201,255,15,191,201,255, - 72,137,206,76,137,231,232,251,1,6,255,72,185,237,237,72,199,194,237,72,199, - 198,237,76,137,231,232,251,1,7,255,72,199,194,237,72,199,198,252,254,252, - 255,252,255,252,255,76,137,231,232,251,1,0,72,185,237,237,72,199,194,252, - 255,252,255,252,255,252,255,72,199,198,252,254,252,255,252,255,252,255,76, - 137,231,232,251,1,8,72,137,68,36,32,72,199,198,252,252,252,255,252,255,252, - 255,76,137,231,232,251,1,9,72,139,68,36,32,255,72,199,194,237,72,199,198, - 252,254,252,255,252,255,252,255,76,137,231,232,251,1,0,72,185,237,237,72, - 199,194,252,255,252,255,252,255,252,255,72,199,198,252,254,252,255,252,255, - 252,255,76,137,231,232,251,1,10,137,68,36,32,72,199,198,252,252,252,255,252, - 255,252,255,76,137,231,232,251,1,9,139,68,36,32,255,72,199,198,252,254,252, - 255,252,255,252,255,76,137,231,232,251,1,9,255,72,199,198,252,255,252,255, - 252,255,252,255,76,137,231,232,251,1,11,255,72,199,198,252,255,252,255,252, - 255,252,255,76,137,231,232,251,1,12,255,137,68,36,32,72,199,198,252,253,252, - 255,252,255,252,255,76,137,231,232,251,1,9,139,68,36,32,255,72,199,198,252, - 255,252,255,252,255,252,255,76,137,231,232,251,1,13,255,72,199,198,252,255, - 252,255,252,255,252,255,76,137,231,232,251,1,14,255,72,137,68,36,32,72,199, - 198,252,253,252,255,252,255,252,255,76,137,231,232,251,1,9,72,139,68,36,32, - 255,72,199,198,252,255,252,255,252,255,252,255,76,137,231,232,251,1,15,72, - 137,68,36,32,72,199,198,252,253,252,255,252,255,252,255,76,137,231,232,251, - 1,9,72,139,68,36,32,255,72,199,198,252,255,252,255,252,255,252,255,76,137, - 231,232,251,1,16,102,15,214,68,36,32,72,199,198,252,253,252,255,252,255,252, - 255,76,137,231,232,251,1,9,255,252,242,15,90,68,36,32,255,252,243,15,126, - 68,36,32,255,72,199,198,252,255,252,255,252,255,252,255,76,137,231,232,251, - 1,17,102,15,214,68,36,32,72,199,198,252,253,252,255,252,255,252,255,76,137, - 231,232,251,1,9,252,243,15,126,68,36,32,255,72,199,198,252,255,252,255,252, - 255,252,255,76,137,231,232,251,1,18,102,15,214,68,36,32,102,15,214,76,36, - 40,72,199,198,252,253,252,255,252,255,252,255,76,137,231,232,251,1,9,252, - 243,15,126,68,36,32,252,243,15,126,76,36,40,255,72,139,141,233,72,199,194, - 252,255,252,255,252,255,252,255,76,137,230,72,137,207,232,251,1,18,72,131, - 252,236,4,72,199,198,252,253,252,255,252,255,252,255,76,137,231,232,251,1, - 9,255,76,139,101,252,248,72,137,252,236,93,194,236,255,85,72,137,229,65,84, - 65,85,73,137,252,252,76,137,231,232,251,1,19,73,137,197,72,129,252,248,239, - 255,15,141,244,248,102,184,0,0,72,190,237,237,76,137,231,232,251,1,20,248, - 2,15,142,244,247,102,184,0,0,72,190,237,237,76,137,231,232,251,1,20,255,15, - 141,244,247,102,184,0,0,72,190,237,237,76,137,231,232,251,1,20,255,248,1, - 255,72,193,224,4,72,41,196,72,129,252,236,239,255,72,186,237,237,72,199,198, - 0,0,0,0,76,137,231,232,251,1,1,72,131,252,236,16,255,72,185,237,237,72,199, - 194,237,72,199,198,237,76,137,231,232,251,1,8,255,72,185,237,237,72,199,194, - 237,72,199,198,237,76,137,231,232,251,1,21,255,72,185,237,237,72,199,194, - 237,72,199,198,237,76,137,231,232,251,1,10,255,72,199,198,237,76,137,231, - 232,251,1,12,255,15,182,192,255,15,190,192,255,15,183,192,255,15,191,192, - 255,72,199,198,237,76,137,231,232,251,1,12,131,252,248,0,15,149,208,15,182, - 192,255,72,199,198,237,76,137,231,232,251,1,11,255,72,199,198,237,76,137, - 231,232,251,1,15,255,72,199,198,237,76,137,231,232,251,1,13,255,72,199,198, - 237,76,137,231,232,251,1,14,255,72,199,198,237,76,137,231,232,251,1,16,255, - 72,199,198,237,76,137,231,232,251,1,18,255,252,243,15,126,193,255,72,141, - 132,253,36,233,72,131,252,236,4,72,199,194,237,76,137,230,72,137,199,232, - 251,1,18,255,72,199,198,237,76,137,231,232,251,1,17,255,72,199,198,237,76, - 137,231,232,251,1,17,137,4,36,217,4,36,255,137,20,36,217,4,36,255,72,137, - 224,72,129,192,239,73,137,192,72,199,193,237,76,137,252,234,72,199,198,237, - 76,137,231,232,251,1,22,255,72,137,224,72,129,192,239,73,137,192,72,199,193, - 237,76,137,252,234,72,199,198,237,76,137,231,232,251,1,23,255,72,137,224, - 72,129,192,239,73,137,193,73,199,192,237,72,199,193,237,76,137,252,234,72, - 199,198,237,76,137,231,232,251,1,24,255,72,185,237,237,139,1,72,137,199,232, - 251,1,25,255,72,131,196,32,255,252,243,15,126,188,253,36,233,255,252,243, - 15,126,180,253,36,233,255,252,243,15,126,172,253,36,233,255,252,243,15,126, - 164,253,36,233,255,252,243,15,126,156,253,36,233,255,252,243,15,126,148,253, - 36,233,255,252,243,15,126,140,253,36,233,255,252,243,15,126,132,253,36,233, - 255,76,139,140,253,36,233,255,76,139,132,253,36,233,255,72,139,140,253,36, - 233,255,72,139,148,253,36,233,255,72,139,180,253,36,233,255,72,139,60,36, - 255,72,129,196,239,255,176,8,255,232,251,1,26,72,131,252,236,48,255,72,137, - 68,36,32,232,251,1,27,72,185,237,237,137,1,72,186,237,237,72,199,198,237, - 76,137,231,232,251,1,1,72,139,76,36,32,72,137,8,184,1,0,0,0,76,139,109,252, - 240,76,139,101,252,248,72,137,252,236,93,195,255,72,137,68,36,32,232,251, - 1,27,72,185,237,237,137,1,72,139,68,36,32,72,137,198,76,137,231,232,251,1, - 28,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252,236,93,195, - 255,72,137,68,36,32,232,251,1,27,72,185,237,237,137,1,72,186,237,237,72,199, - 198,0,0,0,0,76,137,231,232,251,1,1,72,139,76,36,32,72,137,8,184,1,0,0,0,76, - 139,109,252,240,76,139,101,252,248,72,137,252,236,93,195,255,102,15,214,68, - 36,32,232,251,1,27,72,185,237,237,137,1,72,186,237,237,72,199,198,237,76, - 137,231,232,251,1,1,72,139,76,36,32,72,137,8,184,1,0,0,0,76,139,109,252,240, - 76,139,101,252,248,72,137,252,236,93,195,255,102,15,214,76,36,40,102,15,214, - 68,36,32,232,251,1,27,72,185,237,237,137,1,72,186,237,237,72,199,198,237, - 76,137,231,232,251,1,1,72,139,76,36,40,72,137,72,8,72,139,76,36,32,72,137, - 8,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252,236,93,195, - 255,232,251,1,27,72,185,237,237,137,1,184,0,0,0,0,76,139,109,252,240,76,139, - 101,252,248,72,137,252,236,93,195,255,15,182,192,137,68,36,32,232,251,1,27, - 72,185,237,237,137,1,139,68,36,32,72,137,198,76,137,231,232,251,1,4,184,1, - 0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252,236,93,195,255,137, - 68,36,32,232,251,1,27,72,185,237,237,137,1,139,68,36,32,72,137,198,76,137, - 231,232,251,1,5,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137, - 252,236,93,195,255,137,68,36,32,232,251,1,27,72,185,237,237,137,1,139,68, - 36,32,72,137,198,76,137,231,232,251,1,6,184,1,0,0,0,76,139,109,252,240,76, - 139,101,252,248,72,137,252,236,93,195,255,252,243,15,90,192,102,15,214,68, - 36,32,232,251,1,27,72,185,237,237,137,1,252,243,15,126,68,36,32,76,137,231, - 232,251,1,3,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252, - 236,93,195,255 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "lua_rawgeti", - "push_cdata", - "lua_remove", - "lua_pushnumber", - "lua_pushboolean", - "push_int", - "push_uint", - "lua_callk", - "check_typed_pointer", - "lua_settop", - "check_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_uintptr", - "check_double", - "check_complex_float", - "check_complex_double", - "lua_gettop", - "luaL_error", - "check_typed_cfunction", - "unpack_varargs_float", - "unpack_varargs_int", - "unpack_varargs_stack_skip", - "SetLastError", - "FUNCTION", - "GetLastError", - "lua_pushinteger", - (const char *)0 -}; - - - - - - - - - - - - - - - - - -#if defined _WIN64 || defined __amd64__ -#define JUMP_SIZE 14 -#else -#define JUMP_SIZE 4 -#endif - -#define MIN_BRANCH INT32_MIN -#define MAX_BRANCH INT32_MAX -#define BRANCH_OFF 4 - -static void compile_extern_jump(struct jit* jit, lua_State* L, cfunction func, uint8_t* code) -{ - /* The jump code is the function pointer followed by a stub to call the - * function pointer. The stub exists in 64 bit so we can jump to functions - * with an offset greater than 2 GB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state and dynasm doesn't support rip relative addressing. - * - * eg on 64 bit: - * 0-8: function ptr - * 8-14: jmp aword [rip-14] - * - * for 32 bit we only set the function ptr as it can always fit in a 32 - * bit displacement - */ -#if defined _WIN64 || defined __amd64__ - *(cfunction*) code = func; - code[8] = 0xFF; /* FF /4 operand for jmp */ - code[9] = 0x25; /* RIP displacement */ - *(int32_t*) &code[10] = -14; -#else - *(cfunction*) code = func; -#endif -} - -void compile_globals(struct jit* jit, lua_State* L) -{ - struct jit* Dst = jit; - int* perr = &jit->last_errno; - dasm_setup(Dst, build_actionlist); - - /* Note: since the return code uses EBP to reset the stack pointer, we - * don't have to track the amount of stack space used. It also means we - * can handle stdcall and cdecl with the same code. - */ - - /* Note the various call_* functions want 32 bytes of 16 byte aligned - * stack - */ - - compile(Dst, L, NULL, LUA_NOREF); -} - -int x86_return_size(lua_State* L, int usr, const struct ctype* ct) -{ - int ret = 0; - const struct ctype* mt; - - if (ct->calling_convention != C_CALL) { - size_t i; - size_t argn = lua_rawlen(L, usr); - for (i = 1; i <= argn; i++) { - lua_rawgeti(L, usr, (int) i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - ret += sizeof(void*); - } else { - switch (mt->type) { - case DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case INT64_TYPE: - ret += 8; - break; - case COMPLEX_DOUBLE_TYPE: - ret += 16; - break; - case INTPTR_TYPE: - ret += sizeof(intptr_t); - break; - case FUNCTION_PTR_TYPE: - ret += sizeof(cfunction); - break; - case BOOL_TYPE: - case FLOAT_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE: - ret += 4; - break; - default: - return luaL_error(L, "NYI - argument type"); - } - } - - lua_pop(L, 1); - } - } - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - ret += sizeof(void*); - } - lua_pop(L, 1); -#endif - - return ret; -} - -#ifdef _WIN64 -#define MAX_REGISTERS(ct) 4 /* rcx, rdx, r8, r9 */ - -#elif defined __amd64__ -#define MAX_INT_REGISTERS(ct) 6 /* rdi, rsi, rdx, rcx, r8, r9 */ -#define MAX_FLOAT_REGISTERS(ct) 8 /* xmm0-7 */ - -#else -#define MAX_INT_REGISTERS(ct) ((ct)->calling_convention == FAST_CALL ? 2 /* ecx, edx */ : 0) -#define MAX_FLOAT_REGISTERS(ct) 0 -#endif - -struct reg_alloc { -#ifdef _WIN64 - int regs; - int is_float[4]; - int is_int[4]; -#else - int floats; - int ints; -#endif - int off; -}; - -#ifdef _WIN64 -#define REGISTER_STACK_SPACE(ct) (4*8) -#elif defined __amd64__ -#define REGISTER_STACK_SPACE(ct) (14*8) -#else -#define REGISTER_STACK_SPACE(ct) ALIGN_UP(((ct)->calling_convention == FAST_CALL ? 2*4 : 0), 15) -#endif - -/* Fastcall: - * Uses ecx, edx as first two int registers - * Everything else on stack (include 64bit ints) - * No overflow stack space - * Pops the stack before returning - * Returns int in eax, float in ST0 - * We use the same register allocation logic as posix x64 with 2 int regs and 0 float regs - */ - -static void get_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ - /* grab the register from the shadow space */ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - dasm_put(Dst, 0, 16 + 8*reg->regs); - reg->regs++; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 0, - 80 - 8*reg->ints); - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 1, - 8 - 4*reg->ints); - reg->ints++; - } -#endif - else if (is_int64) { - dasm_put(Dst, 0, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 1, reg->off); - reg->off += 4; - } -} - -static void add_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - dasm_put(Dst, 5, 32 + 8*(reg->regs)); - reg->is_int[reg->regs++] = 1; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 5, 32 + 8*reg->ints); - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 5, 32 + 4*reg->ints); - reg->ints++; - } -#endif - else { -#if defined _WIN64 || defined __amd64__ - if (reg->off % 8 != 0) { - reg->off += 8 - (reg->off % 8); - } -#endif - if (is_int64) { - dasm_put(Dst, 5, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 6, reg->off); - reg->off += 4; - } - } -} - -static void get_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - dasm_put(Dst, 12, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 16, reg->off); - reg->off += 4; - } -#else - int off; - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - off = -16 - 8*reg->regs; - reg->regs++; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - off = -16 - 8*reg->floats; - reg->floats++; - } -#endif - else { - off = reg->off; - reg->off += is_double ? 8 : 4; - } - - if (is_double) { - dasm_put(Dst, 20, off); - } else { - dasm_put(Dst, 27, off); - } -#endif -} - -static void add_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - dasm_put(Dst, 34, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 40, reg->off); - reg->off += 4; - } -#else - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - if (is_double) { - dasm_put(Dst, 46, 32 + 8*(reg->regs)); - } else { - dasm_put(Dst, 54, 32 + 8*(reg->regs)); - } - reg->is_float[reg->regs++] = 1; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - if (is_double) { - dasm_put(Dst, 46, 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)); - } else { - dasm_put(Dst, 54, 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)); - } - reg->floats++; - } -#endif - - else if (is_double) { - dasm_put(Dst, 46, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 67, reg->off); - reg->off += 4; - } -#endif -} - -#if defined _WIN64 || defined __amd64__ -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 1) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 1) -#else -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 0) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 0) -#endif - -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct) -{ - int i, nargs; - cfunction* pf; - struct ctype ct2 = *ct; - const struct ctype* mt; - struct reg_alloc reg; - int num_upvals = 0; - int top = lua_gettop(L); - struct jit* Dst = get_jit(L); - int ref; - int hidden_arg_off = 0; - - ct_usr = lua_absindex(L, ct_usr); - fidx = lua_absindex(L, fidx); - - assert(lua_isnil(L, fidx) || lua_isfunction(L, fidx)); - - memset(®, 0, sizeof(reg)); -#ifdef _WIN64 - reg.off = 16 + REGISTER_STACK_SPACE(ct); /* stack registers are above the shadow space */ -#elif __amd64__ - reg.off = 16; -#else - reg.off = 8; -#endif - - dasm_setup(Dst, build_actionlist); - - // add a table to store ctype and function upvalues - // callback_set assumes the first value is the lua function - nargs = (int) lua_rawlen(L, ct_usr); - lua_newtable(L); - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - - if (ct->has_var_arg) { - luaL_error(L, "can't create callbacks with varargs"); - } - - // setup a stack frame to hold args for the call into lua_call - - dasm_put(Dst, 80, 8 + 16 + 32 + REGISTER_STACK_SPACE(ct)); - if (ct->calling_convention == FAST_CALL) { - } - - // hardcode the lua_State* value into the assembly - dasm_put(Dst, 157, (unsigned int)((uintptr_t)(L)), (unsigned int)(((uintptr_t)(L))>>32)); - - /* get the upval table */ - dasm_put(Dst, 162, ref, LUA_REGISTRYINDEX); - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - assert(num_upvals == CALLBACK_FUNC_USR_IDX); - dasm_put(Dst, 178, num_upvals); - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - hidden_arg_off = reg.off; - reg.off += sizeof(void*); - } - lua_pop(L, 1); -#else - (void) hidden_arg_off; -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - /* on the lua stack in the callback: - * upval tbl, lua func, i-1 args - */ - dasm_put(Dst, 201, num_upvals-1, -i-1, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_pointer(Dst, ct, ®); - dasm_put(Dst, 239); - } else { - switch (mt->type) { - case INT64_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - dasm_put(Dst, 261, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_int(Dst, ct, ®, 1); - dasm_put(Dst, 280); - break; - - case INTPTR_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - dasm_put(Dst, 261, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_pointer(Dst, ct, ®); - dasm_put(Dst, 280); - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if defined _WIN64 || defined __amd64__ - /* complex floats are two floats packed into a double */ - dasm_put(Dst, 261, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 284); -#else - /* complex floats are real followed by imag on the stack */ - dasm_put(Dst, 261, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_float(Dst, ct, ®, 0); - dasm_put(Dst, 289); - get_float(Dst, ct, ®, 0); - dasm_put(Dst, 292); -#endif - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 261, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - /* real */ - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 284); - /* imag */ - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 296); - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - get_float(Dst, ct, ®, mt->type == DOUBLE_TYPE); - dasm_put(Dst, 302); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - dasm_put(Dst, 310); - break; - - case INT8_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 324); - } else { - dasm_put(Dst, 328); - } - dasm_put(Dst, 332); - break; - - case INT16_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 343); - } else { - dasm_put(Dst, 347); - } - dasm_put(Dst, 332); - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 351); - } else { - dasm_put(Dst, 332); - } - break; - - default: - luaL_error(L, "NYI: callback arg type"); - } - } - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - dasm_put(Dst, 362, (unsigned int)((uintptr_t)(0)), (unsigned int)(((uintptr_t)(0))>>32), (mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0, nargs); - - // Unpack the return argument if not "void", also clean-up the lua stack - // to remove the return argument and bind table. Use lua_settop rather - // than lua_pop as lua_pop is implemented as a macro. - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 382, num_upvals-1, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - - } else { - switch (mt->type) { - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 466, num_upvals-1, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 548); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - if (mt->is_unsigned) { - dasm_put(Dst, 567); - } else { - dasm_put(Dst, 586); - } - dasm_put(Dst, 605); - break; - - case INT64_TYPE: - lua_pop(L, 1); - - if (mt->is_unsigned) { - dasm_put(Dst, 632); - } else { - dasm_put(Dst, 651); - } - - dasm_put(Dst, 670); - break; - - case INTPTR_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 699); - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 746); - if (mt->type == FLOAT_TYPE) { - dasm_put(Dst, 789); - } else { - dasm_put(Dst, 797); - } - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit complex floats are two floats packed into a double, - * on 32 bit returned complex floats use eax and edx */ - dasm_put(Dst, 805); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored which is popped by the called - * function */ -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 855); -#else - dasm_put(Dst, 918, hidden_arg_off); -#endif - break; - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 967, x86_return_size(L, ct_usr, ct)); - - lua_pop(L, 1); /* upval table - already in registry */ - assert(lua_gettop(L) == top); - - ct2.is_jitted = 1; - pf = (cfunction*) push_cdata(L, ct_usr, &ct2); - *pf = compile(Dst, L, NULL, ref); - - assert(lua_gettop(L) == top + 1); - - return *pf; -} - -void compile_function(lua_State* L, cfunction func, int ct_usr, const struct ctype* ct) -{ - size_t i, nargs; - int num_upvals; - const struct ctype* mbr_ct; - struct jit* Dst = get_jit(L); - struct reg_alloc reg; - void* p; - int top = lua_gettop(L); - int* perr = &Dst->last_errno; - - ct_usr = lua_absindex(L, ct_usr); - - memset(®, 0, sizeof(reg)); - reg.off = 32 + REGISTER_STACK_SPACE(ct); - - dasm_setup(Dst, build_actionlist); - - p = push_cdata(L, ct_usr, ct); - *(cfunction*) p = func; - num_upvals = 1; - - nargs = lua_rawlen(L, ct_usr); - - if (ct->calling_convention != C_CALL && ct->has_var_arg) { - luaL_error(L, "vararg is only allowed with the c calling convention"); - } - - dasm_put(Dst, 980, nargs); - if (!ct->has_var_arg) { - dasm_put(Dst, 1008, (unsigned int)((uintptr_t)(&"too few arguments")), (unsigned int)(((uintptr_t)(&"too few arguments"))>>32), (unsigned int)((uintptr_t)(&"too many arguments")), (unsigned int)(((uintptr_t)(&"too many arguments"))>>32)); - } else { - dasm_put(Dst, 1049, (unsigned int)((uintptr_t)(&"too few arguments")), (unsigned int)(((uintptr_t)(&"too few arguments"))>>32)); - } - - dasm_put(Dst, 1069); - - /* no need to zero extend eax returned by lua_gettop to rax as x86-64 - * preguarentees that the upper 32 bits will be zero */ - dasm_put(Dst, 1072, 32 + REGISTER_STACK_SPACE(ct)); - -#if !defined _WIN64 && !defined __amd64__ - /* Returned complex doubles require a hidden first parameter where the - * data is stored, which is popped by the calling code. */ - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - if (!mbr_ct->pointers && !mbr_ct->is_reference && mbr_ct->type == COMPLEX_DOUBLE_TYPE) { - /* we can allocate more space for arguments as long as no add_* - * function has been called yet, mbr_ct will be added as an upvalue in - * the return processing later */ - dasm_put(Dst, 1085, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32)); - add_pointer(Dst, ct, ®); - } - lua_pop(L, 1); -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, (int) i); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1109, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals), i); - add_pointer(Dst, ct, ®); - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1129, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals), i); - add_pointer(Dst, ct, ®); - break; - - case ENUM_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1149, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals), i); - add_int(Dst, ct, ®, 0); - break; - - case INT8_TYPE: - dasm_put(Dst, 1169, i); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1181); - } else { - dasm_put(Dst, 1185); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT16_TYPE: - dasm_put(Dst, 1169, i); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1189); - } else { - dasm_put(Dst, 1193); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - dasm_put(Dst, 1197, i); - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT32_TYPE: - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1219, i); - } else { - dasm_put(Dst, 1169, i); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INTPTR_TYPE: - dasm_put(Dst, 1231, i); - add_pointer(Dst, ct, ®); - lua_pop(L, 1); - break; - - case INT64_TYPE: - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1243, i); - } else { - dasm_put(Dst, 1255, i); - } - add_int(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case DOUBLE_TYPE: - dasm_put(Dst, 1267, i); - add_float(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case COMPLEX_DOUBLE_TYPE: - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored (this is popped by the called - * function) */ -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 1279, i); - add_float(Dst, ct, ®, 1); - dasm_put(Dst, 1291); - add_float(Dst, ct, ®, 1); -#else - dasm_put(Dst, 1297, reg.off, i); - reg.off += 16; -#endif - lua_pop(L, 1); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 1267, i); - add_float(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case COMPLEX_FLOAT_TYPE: -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 1323, i); - /* complex floats are two floats packed into a double */ - add_float(Dst, ct, ®, 1); -#else - /* returned complex floats use eax and edx */ - dasm_put(Dst, 1335, i); - add_float(Dst, ct, ®, 0); - dasm_put(Dst, 1353); - add_float(Dst, ct, ®, 0); -#endif - lua_pop(L, 1); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { -#ifdef _WIN64 - if (reg.regs < MAX_REGISTERS(ct)) { - assert(reg.regs == nargs); - } else { - } - - for (i = nargs; i < MAX_REGISTERS(ct); i++) { - reg.is_int[i] = reg.is_float[i] = 1; - } - reg.regs = MAX_REGISTERS(ct); -#elif defined __amd64__ - if (reg.floats < MAX_FLOAT_REGISTERS(ct)) { - dasm_put(Dst, 1360, 32 + 8*(MAX_INT_REGISTERS(ct) + reg.floats), MAX_FLOAT_REGISTERS(ct) - reg.floats, nargs+1); - } - - if (reg.ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 1390, 32 + 8*(reg.ints), MAX_INT_REGISTERS(ct) - reg.ints, nargs+1); - } - - dasm_put(Dst, 1420, reg.off, MAX_FLOAT_REGISTERS(ct) - reg.floats, MAX_INT_REGISTERS(ct) - reg.ints, nargs+1); - - reg.floats = MAX_FLOAT_REGISTERS(ct); - reg.ints = MAX_INT_REGISTERS(ct); -#else -#endif - } - - dasm_put(Dst, 1454, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - - /* remove the stack space to call local functions */ - dasm_put(Dst, 1468); - -#ifdef _WIN64 - switch (reg.regs) { - case 4: - if (reg.is_float[3]) { - } - if (reg.is_int[3]) { - } - case 3: - if (reg.is_float[2]) { - } - if (reg.is_int[2]) { - } - case 2: - if (reg.is_float[1]) { - } - if (reg.is_int[1]) { - } - case 1: - if (reg.is_float[0]) { - } - if (reg.is_int[0]) { - } - case 0: - break; - } - - /* don't remove the space for the registers as we need 32 bytes of register overflow space */ - assert(REGISTER_STACK_SPACE(ct) == 32); - -#elif defined __amd64__ - switch (reg.floats) { - case 8: - dasm_put(Dst, 1473, 8*(MAX_INT_REGISTERS(ct)+7)); - case 7: - dasm_put(Dst, 1482, 8*(MAX_INT_REGISTERS(ct)+6)); - case 6: - dasm_put(Dst, 1491, 8*(MAX_INT_REGISTERS(ct)+5)); - case 5: - dasm_put(Dst, 1500, 8*(MAX_INT_REGISTERS(ct)+4)); - case 4: - dasm_put(Dst, 1509, 8*(MAX_INT_REGISTERS(ct)+3)); - case 3: - dasm_put(Dst, 1518, 8*(MAX_INT_REGISTERS(ct)+2)); - case 2: - dasm_put(Dst, 1527, 8*(MAX_INT_REGISTERS(ct)+1)); - case 1: - dasm_put(Dst, 1536, 8*(MAX_INT_REGISTERS(ct))); - case 0: - break; - } - - switch (reg.ints) { - case 6: - dasm_put(Dst, 1545, 8*5); - case 5: - dasm_put(Dst, 1552, 8*4); - case 4: - dasm_put(Dst, 1559, 8*3); - case 3: - dasm_put(Dst, 1566, 8*2); - case 2: - dasm_put(Dst, 1573, 8*1); - case 1: - dasm_put(Dst, 1580); - case 0: - break; - } - - dasm_put(Dst, 1585, REGISTER_STACK_SPACE(ct)); -#else - if (ct->calling_convention == FAST_CALL) { - switch (reg.ints) { - case 2: - case 1: - case 0: - break; - } - - } -#endif - -#ifdef __amd64__ - if (ct->has_var_arg) { - /* al stores an upper limit on the number of float register, note that - * its allowed to be more than the actual number of float registers used as - * long as its 0-8 */ - dasm_put(Dst, 1590); - } -#endif - - dasm_put(Dst, 1593); - - /* note on windows X86 the stack may be only aligned to 4 (stdcall will - * have popped a multiple of 4 bytes), but we don't need 16 byte alignment on - * that platform - */ - - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference || mbr_ct->type == INTPTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1603, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1603, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - break; - - case INT64_TYPE: -#if LUA_VERSION_NUM == 503 - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1663, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } else { - dasm_put(Dst, 1663, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } -#else - num_upvals++; - dasm_put(Dst, 1715, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32)); -#endif - break; - - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1778, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1839, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1915, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1947, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case INT8_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1181); - } else { - dasm_put(Dst, 1185); - } - dasm_put(Dst, 2000, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case INT16_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1189); - } else { - dasm_put(Dst, 1193); - } - dasm_put(Dst, 2000, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 2050, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } else { - dasm_put(Dst, 2000, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 2100, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 2105, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, func, LUA_NOREF); - /* add a callback as an upval so that the jitted code gets cleaned up when - * the function gets gc'd */ - push_callback(L, f, func); - lua_pushcclosure(L, (lua_CFunction) f, num_upvals+1); - } -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call_x64win.h b/Build/source/texk/web2c/luatexdir/luaffi/call_x64win.h deleted file mode 100644 index 337266ff351..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call_x64win.h +++ /dev/null @@ -1,1191 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM x64 version 1.3.0 -** DO NOT EDIT! The original file is in "call_x86.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -static const unsigned char build_actionlist[2100] = { - 72,139,141,233,255,72,137,132,253,36,233,255,221,133,233,255,217,133,233, - 255,252,243,15,126,133,233,255,252,243,15,90,133,233,255,221,156,253,36,233, - 255,217,156,253,36,233,255,102,15,214,132,253,36,233,255,252,242,15,90,192, - 102,15,214,132,253,36,233,255,252,242,15,90,192,102,15,126,132,253,36,233, - 255,85,72,137,229,65,84,72,129,252,236,239,72,137,77,16,72,137,85,24,76,137, - 69,32,76,137,77,40,102,15,214,69,252,240,102,15,214,77,232,102,15,214,85, - 224,102,15,214,93,216,255,73,188,237,237,255,73,199,192,237,72,199,194,237, - 76,137,225,232,251,1,0,255,73,199,192,237,72,199,194,252,255,252,255,252, - 255,252,255,76,137,225,232,251,1,0,255,73,199,192,237,72,199,194,237,76,137, - 225,232,251,1,0,73,184,237,237,72,199,194,252,255,252,255,252,255,252,255, - 76,137,225,232,251,1,1,255,72,137,8,72,199,194,252,254,252,255,252,255,252, - 255,76,137,225,232,251,1,2,255,73,184,237,237,72,199,194,0,0,0,0,76,137,225, - 232,251,1,1,255,72,137,8,255,102,15,214,0,255,217,24,255,217,88,4,255,102, - 15,214,64,8,255,252,243,15,126,200,76,137,225,232,251,1,3,255,15,182,201, - 72,137,202,76,137,225,232,251,1,4,255,15,182,201,255,15,190,201,255,72,137, - 202,76,137,225,232,251,1,5,255,15,183,201,255,15,191,201,255,72,137,202,76, - 137,225,232,251,1,6,255,73,185,237,237,73,199,192,237,72,199,194,237,76,137, - 225,232,251,1,7,255,73,199,192,237,72,199,194,252,254,252,255,252,255,252, - 255,76,137,225,232,251,1,0,73,185,237,237,73,199,192,252,255,252,255,252, - 255,252,255,72,199,194,252,254,252,255,252,255,252,255,76,137,225,232,251, - 1,8,72,137,68,36,32,72,199,194,252,252,252,255,252,255,252,255,76,137,225, - 232,251,1,9,72,139,68,36,32,255,73,199,192,237,72,199,194,252,254,252,255, - 252,255,252,255,76,137,225,232,251,1,0,73,185,237,237,73,199,192,252,255, - 252,255,252,255,252,255,72,199,194,252,254,252,255,252,255,252,255,76,137, - 225,232,251,1,10,137,68,36,32,72,199,194,252,252,252,255,252,255,252,255, - 76,137,225,232,251,1,9,139,68,36,32,255,72,199,194,252,254,252,255,252,255, - 252,255,76,137,225,232,251,1,9,255,72,199,194,252,255,252,255,252,255,252, - 255,76,137,225,232,251,1,11,255,72,199,194,252,255,252,255,252,255,252,255, - 76,137,225,232,251,1,12,255,137,68,36,32,72,199,194,252,253,252,255,252,255, - 252,255,76,137,225,232,251,1,9,139,68,36,32,255,72,199,194,252,255,252,255, - 252,255,252,255,76,137,225,232,251,1,13,255,72,199,194,252,255,252,255,252, - 255,252,255,76,137,225,232,251,1,14,255,72,137,68,36,32,72,199,194,252,253, - 252,255,252,255,252,255,76,137,225,232,251,1,9,72,139,68,36,32,255,72,199, - 194,252,255,252,255,252,255,252,255,76,137,225,232,251,1,15,72,137,68,36, - 32,72,199,194,252,253,252,255,252,255,252,255,76,137,225,232,251,1,9,72,139, - 68,36,32,255,72,199,194,252,255,252,255,252,255,252,255,76,137,225,232,251, - 1,16,102,15,214,68,36,32,72,199,194,252,253,252,255,252,255,252,255,76,137, - 225,232,251,1,9,255,252,242,15,90,68,36,32,255,252,243,15,126,68,36,32,255, - 72,199,194,252,255,252,255,252,255,252,255,76,137,225,232,251,1,17,102,15, - 214,68,36,32,72,199,194,252,253,252,255,252,255,252,255,76,137,225,232,251, - 1,9,252,243,15,126,68,36,32,255,72,199,194,252,255,252,255,252,255,252,255, - 76,137,225,232,251,1,18,102,15,214,68,36,32,102,15,214,76,36,40,72,199,194, - 252,253,252,255,252,255,252,255,76,137,225,232,251,1,9,252,243,15,126,68, - 36,32,252,243,15,126,76,36,40,255,72,139,141,233,73,199,192,252,255,252,255, - 252,255,252,255,76,137,226,72,137,201,232,251,1,18,72,131,252,236,4,72,199, - 194,252,253,252,255,252,255,252,255,76,137,225,232,251,1,9,255,76,139,101, - 252,248,72,137,252,236,93,194,236,255,85,72,137,229,65,84,65,85,73,137,204, - 72,131,252,236,32,76,137,225,232,251,1,19,73,137,197,72,129,252,248,239,255, - 15,141,244,248,102,184,0,0,72,186,237,237,76,137,225,232,251,1,20,248,2,15, - 142,244,247,102,184,0,0,72,186,237,237,76,137,225,232,251,1,20,255,15,141, - 244,247,102,184,0,0,72,186,237,237,76,137,225,232,251,1,20,255,248,1,255, - 72,193,224,4,72,41,196,72,129,252,236,239,255,73,184,237,237,72,199,194,0, - 0,0,0,76,137,225,232,251,1,1,72,131,252,236,16,255,73,185,237,237,73,199, - 192,237,72,199,194,237,76,137,225,232,251,1,8,255,73,185,237,237,73,199,192, - 237,72,199,194,237,76,137,225,232,251,1,21,255,73,185,237,237,73,199,192, - 237,72,199,194,237,76,137,225,232,251,1,10,255,72,199,194,237,76,137,225, - 232,251,1,12,255,15,182,192,255,15,190,192,255,15,183,192,255,15,191,192, - 255,72,199,194,237,76,137,225,232,251,1,12,131,252,248,0,15,149,208,15,182, - 192,255,72,199,194,237,76,137,225,232,251,1,11,255,72,199,194,237,76,137, - 225,232,251,1,15,255,72,199,194,237,76,137,225,232,251,1,13,255,72,199,194, - 237,76,137,225,232,251,1,14,255,72,199,194,237,76,137,225,232,251,1,16,255, - 72,199,194,237,76,137,225,232,251,1,18,255,252,243,15,126,193,255,72,141, - 132,253,36,233,72,131,252,236,4,73,199,192,237,76,137,226,72,137,193,232, - 251,1,18,255,72,199,194,237,76,137,225,232,251,1,17,255,72,199,194,237,76, - 137,225,232,251,1,17,137,4,36,217,4,36,255,137,20,36,217,4,36,255,73,129, - 252,253,239,15,142,244,247,72,137,224,72,129,192,239,73,137,193,77,137,232, - 72,199,194,237,76,137,225,232,251,1,22,72,137,224,72,129,192,239,73,137,193, - 73,199,192,237,72,199,194,237,76,137,225,232,251,1,23,252,233,244,248,248, - 1,72,137,224,72,129,192,239,73,137,193,77,137,232,72,199,194,237,76,137,225, - 232,251,1,23,248,2,255,72,137,224,72,129,192,239,73,137,193,77,137,232,72, - 199,194,237,76,137,225,232,251,1,22,255,72,185,237,237,139,1,72,137,193,232, - 251,1,24,255,72,131,196,32,255,252,243,15,126,156,253,36,233,255,76,139,140, - 253,36,233,255,252,243,15,126,148,253,36,233,255,76,139,132,253,36,233,255, - 252,243,15,126,140,253,36,233,255,72,139,148,253,36,233,255,252,243,15,126, - 4,36,255,72,139,12,36,255,232,251,1,25,72,131,252,236,48,255,72,137,68,36, - 32,232,251,1,26,72,185,237,237,137,1,73,184,237,237,72,199,194,237,76,137, - 225,232,251,1,1,72,139,76,36,32,72,137,8,184,1,0,0,0,76,139,109,252,240,76, - 139,101,252,248,72,137,252,236,93,195,255,72,137,68,36,32,232,251,1,26,72, - 185,237,237,137,1,72,139,68,36,32,72,137,194,76,137,225,232,251,1,27,184, - 1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252,236,93,195,255,72, - 137,68,36,32,232,251,1,26,72,185,237,237,137,1,73,184,237,237,72,199,194, - 0,0,0,0,76,137,225,232,251,1,1,72,139,76,36,32,72,137,8,184,1,0,0,0,76,139, - 109,252,240,76,139,101,252,248,72,137,252,236,93,195,255,102,15,214,68,36, - 32,232,251,1,26,72,185,237,237,137,1,73,184,237,237,72,199,194,237,76,137, - 225,232,251,1,1,72,139,76,36,32,72,137,8,184,1,0,0,0,76,139,109,252,240,76, - 139,101,252,248,72,137,252,236,93,195,255,102,15,214,76,36,40,102,15,214, - 68,36,32,232,251,1,26,72,185,237,237,137,1,73,184,237,237,72,199,194,237, - 76,137,225,232,251,1,1,72,139,76,36,40,72,137,72,8,72,139,76,36,32,72,137, - 8,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252,236,93,195, - 255,232,251,1,26,72,185,237,237,137,1,184,0,0,0,0,76,139,109,252,240,76,139, - 101,252,248,72,137,252,236,93,195,255,15,182,192,137,68,36,32,232,251,1,26, - 72,185,237,237,137,1,139,68,36,32,72,137,194,76,137,225,232,251,1,4,184,1, - 0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252,236,93,195,255,137, - 68,36,32,232,251,1,26,72,185,237,237,137,1,139,68,36,32,72,137,194,76,137, - 225,232,251,1,5,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137, - 252,236,93,195,255,137,68,36,32,232,251,1,26,72,185,237,237,137,1,139,68, - 36,32,72,137,194,76,137,225,232,251,1,6,184,1,0,0,0,76,139,109,252,240,76, - 139,101,252,248,72,137,252,236,93,195,255,252,243,15,90,192,102,15,214,68, - 36,32,232,251,1,26,72,185,237,237,137,1,252,243,15,126,76,36,32,76,137,225, - 232,251,1,3,184,1,0,0,0,76,139,109,252,240,76,139,101,252,248,72,137,252, - 236,93,195,255 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "lua_rawgeti", - "push_cdata", - "lua_remove", - "lua_pushnumber", - "lua_pushboolean", - "push_int", - "push_uint", - "lua_callk", - "check_typed_pointer", - "lua_settop", - "check_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_uintptr", - "check_double", - "check_complex_float", - "check_complex_double", - "lua_gettop", - "luaL_error", - "check_typed_cfunction", - "unpack_varargs_stack", - "unpack_varargs_reg", - "SetLastError", - "FUNCTION", - "GetLastError", - "lua_pushinteger", - (const char *)0 -}; - - - - - - - - - - - - - - - - - -#if defined _WIN64 || defined __amd64__ -#define JUMP_SIZE 14 -#else -#define JUMP_SIZE 4 -#endif - -#define MIN_BRANCH INT32_MIN -#define MAX_BRANCH INT32_MAX -#define BRANCH_OFF 4 - -static void compile_extern_jump(struct jit* jit, lua_State* L, cfunction func, uint8_t* code) -{ - /* The jump code is the function pointer followed by a stub to call the - * function pointer. The stub exists in 64 bit so we can jump to functions - * with an offset greater than 2 GB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state and dynasm doesn't support rip relative addressing. - * - * eg on 64 bit: - * 0-8: function ptr - * 8-14: jmp aword [rip-14] - * - * for 32 bit we only set the function ptr as it can always fit in a 32 - * bit displacement - */ -#if defined _WIN64 || defined __amd64__ - *(cfunction*) code = func; - code[8] = 0xFF; /* FF /4 operand for jmp */ - code[9] = 0x25; /* RIP displacement */ - *(int32_t*) &code[10] = -14; -#else - *(cfunction*) code = func; -#endif -} - -void compile_globals(struct jit* jit, lua_State* L) -{ - struct jit* Dst = jit; - int* perr = &jit->last_errno; - dasm_setup(Dst, build_actionlist); - - /* Note: since the return code uses EBP to reset the stack pointer, we - * don't have to track the amount of stack space used. It also means we - * can handle stdcall and cdecl with the same code. - */ - - /* Note the various call_* functions want 32 bytes of 16 byte aligned - * stack - */ - - compile(Dst, L, NULL, LUA_NOREF); -} - -int x86_return_size(lua_State* L, int usr, const struct ctype* ct) -{ - int ret = 0; - const struct ctype* mt; - - if (ct->calling_convention != C_CALL) { - size_t i; - size_t argn = lua_rawlen(L, usr); - for (i = 1; i <= argn; i++) { - lua_rawgeti(L, usr, (int) i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - ret += sizeof(void*); - } else { - switch (mt->type) { - case DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case INT64_TYPE: - ret += 8; - break; - case COMPLEX_DOUBLE_TYPE: - ret += 16; - break; - case INTPTR_TYPE: - ret += sizeof(intptr_t); - break; - case FUNCTION_PTR_TYPE: - ret += sizeof(cfunction); - break; - case BOOL_TYPE: - case FLOAT_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE: - ret += 4; - break; - default: - return luaL_error(L, "NYI - argument type"); - } - } - - lua_pop(L, 1); - } - } - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - ret += sizeof(void*); - } - lua_pop(L, 1); -#endif - - return ret; -} - -#ifdef _WIN64 -#define MAX_REGISTERS(ct) 4 /* rcx, rdx, r8, r9 */ - -#elif defined __amd64__ -#define MAX_INT_REGISTERS(ct) 6 /* rdi, rsi, rdx, rcx, r8, r9 */ -#define MAX_FLOAT_REGISTERS(ct) 8 /* xmm0-7 */ - -#else -#define MAX_INT_REGISTERS(ct) ((ct)->calling_convention == FAST_CALL ? 2 /* ecx, edx */ : 0) -#define MAX_FLOAT_REGISTERS(ct) 0 -#endif - -struct reg_alloc { -#ifdef _WIN64 - int regs; - int is_float[4]; - int is_int[4]; -#else - int floats; - int ints; -#endif - int off; -}; - -#ifdef _WIN64 -#define REGISTER_STACK_SPACE(ct) (4*8) -#elif defined __amd64__ -#define REGISTER_STACK_SPACE(ct) (14*8) -#else -#define REGISTER_STACK_SPACE(ct) ALIGN_UP(((ct)->calling_convention == FAST_CALL ? 2*4 : 0), 15) -#endif - -/* Fastcall: - * Uses ecx, edx as first two int registers - * Everything else on stack (include 64bit ints) - * No overflow stack space - * Pops the stack before returning - * Returns int in eax, float in ST0 - * We use the same register allocation logic as posix x64 with 2 int regs and 0 float regs - */ - -static void get_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ - /* grab the register from the shadow space */ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - dasm_put(Dst, 0, 16 + 8*reg->regs); - reg->regs++; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 0, - 80 - 8*reg->ints); - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 1, - 8 - 4*reg->ints); - reg->ints++; - } -#endif - else if (is_int64) { - dasm_put(Dst, 0, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 1, reg->off); - reg->off += 4; - } -} - -static void add_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - dasm_put(Dst, 5, 32 + 8*(reg->regs)); - reg->is_int[reg->regs++] = 1; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 5, 32 + 8*reg->ints); - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 5, 32 + 4*reg->ints); - reg->ints++; - } -#endif - else { -#if defined _WIN64 || defined __amd64__ - if (reg->off % 8 != 0) { - reg->off += 8 - (reg->off % 8); - } -#endif - if (is_int64) { - dasm_put(Dst, 5, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 6, reg->off); - reg->off += 4; - } - } -} - -static void get_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - dasm_put(Dst, 12, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 16, reg->off); - reg->off += 4; - } -#else - int off; - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - off = -16 - 8*reg->regs; - reg->regs++; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - off = -16 - 8*reg->floats; - reg->floats++; - } -#endif - else { - off = reg->off; - reg->off += is_double ? 8 : 4; - } - - if (is_double) { - dasm_put(Dst, 20, off); - } else { - dasm_put(Dst, 27, off); - } -#endif -} - -static void add_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - dasm_put(Dst, 34, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 40, reg->off); - reg->off += 4; - } -#else - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - if (is_double) { - dasm_put(Dst, 46, 32 + 8*(reg->regs)); - } else { - dasm_put(Dst, 54, 32 + 8*(reg->regs)); - } - reg->is_float[reg->regs++] = 1; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - if (is_double) { - dasm_put(Dst, 46, 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)); - } else { - dasm_put(Dst, 54, 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)); - } - reg->floats++; - } -#endif - - else if (is_double) { - dasm_put(Dst, 46, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 67, reg->off); - reg->off += 4; - } -#endif -} - -#if defined _WIN64 || defined __amd64__ -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 1) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 1) -#else -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 0) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 0) -#endif - -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct) -{ - int i, nargs; - cfunction* pf; - struct ctype ct2 = *ct; - const struct ctype* mt; - struct reg_alloc reg; - int num_upvals = 0; - int top = lua_gettop(L); - struct jit* Dst = get_jit(L); - int ref; - int hidden_arg_off = 0; - - ct_usr = lua_absindex(L, ct_usr); - fidx = lua_absindex(L, fidx); - - assert(lua_isnil(L, fidx) || lua_isfunction(L, fidx)); - - memset(®, 0, sizeof(reg)); -#ifdef _WIN64 - reg.off = 16 + REGISTER_STACK_SPACE(ct); /* stack registers are above the shadow space */ -#elif __amd64__ - reg.off = 16; -#else - reg.off = 8; -#endif - - dasm_setup(Dst, build_actionlist); - - // add a table to store ctype and function upvalues - // callback_set assumes the first value is the lua function - nargs = (int) lua_rawlen(L, ct_usr); - lua_newtable(L); - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - - if (ct->has_var_arg) { - luaL_error(L, "can't create callbacks with varargs"); - } - - // setup a stack frame to hold args for the call into lua_call - - dasm_put(Dst, 80, 8 + 16 + 32 + REGISTER_STACK_SPACE(ct)); - if (ct->calling_convention == FAST_CALL) { - } - - // hardcode the lua_State* value into the assembly - dasm_put(Dst, 129, (unsigned int)((uintptr_t)(L)), (unsigned int)(((uintptr_t)(L))>>32)); - - /* get the upval table */ - dasm_put(Dst, 134, ref, LUA_REGISTRYINDEX); - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - assert(num_upvals == CALLBACK_FUNC_USR_IDX); - dasm_put(Dst, 150, num_upvals); - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - hidden_arg_off = reg.off; - reg.off += sizeof(void*); - } - lua_pop(L, 1); -#else - (void) hidden_arg_off; -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - /* on the lua stack in the callback: - * upval tbl, lua func, i-1 args - */ - dasm_put(Dst, 173, num_upvals-1, -i-1, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_pointer(Dst, ct, ®); - dasm_put(Dst, 211); - } else { - switch (mt->type) { - case INT64_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - dasm_put(Dst, 233, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_int(Dst, ct, ®, 1); - dasm_put(Dst, 252); - break; - - case INTPTR_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - dasm_put(Dst, 233, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_pointer(Dst, ct, ®); - dasm_put(Dst, 252); - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if defined _WIN64 || defined __amd64__ - /* complex floats are two floats packed into a double */ - dasm_put(Dst, 233, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 256); -#else - /* complex floats are real followed by imag on the stack */ - dasm_put(Dst, 233, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - get_float(Dst, ct, ®, 0); - dasm_put(Dst, 261); - get_float(Dst, ct, ®, 0); - dasm_put(Dst, 264); -#endif - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 233, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - /* real */ - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 256); - /* imag */ - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 268); - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - get_float(Dst, ct, ®, mt->type == DOUBLE_TYPE); - dasm_put(Dst, 274); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - dasm_put(Dst, 287); - break; - - case INT8_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 301); - } else { - dasm_put(Dst, 305); - } - dasm_put(Dst, 309); - break; - - case INT16_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 320); - } else { - dasm_put(Dst, 324); - } - dasm_put(Dst, 309); - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 328); - } else { - dasm_put(Dst, 309); - } - break; - - default: - luaL_error(L, "NYI: callback arg type"); - } - } - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - dasm_put(Dst, 339, (unsigned int)((uintptr_t)(0)), (unsigned int)(((uintptr_t)(0))>>32), (mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0, nargs); - - // Unpack the return argument if not "void", also clean-up the lua stack - // to remove the return argument and bind table. Use lua_settop rather - // than lua_pop as lua_pop is implemented as a macro. - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 359, num_upvals-1, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - - } else { - switch (mt->type) { - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 443, num_upvals-1, (unsigned int)((uintptr_t)(mt)), (unsigned int)(((uintptr_t)(mt))>>32)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 525); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - if (mt->is_unsigned) { - dasm_put(Dst, 544); - } else { - dasm_put(Dst, 563); - } - dasm_put(Dst, 582); - break; - - case INT64_TYPE: - lua_pop(L, 1); - - if (mt->is_unsigned) { - dasm_put(Dst, 609); - } else { - dasm_put(Dst, 628); - } - - dasm_put(Dst, 647); - break; - - case INTPTR_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 676); - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 723); - if (mt->type == FLOAT_TYPE) { - dasm_put(Dst, 766); - } else { - dasm_put(Dst, 774); - } - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit complex floats are two floats packed into a double, - * on 32 bit returned complex floats use eax and edx */ - dasm_put(Dst, 782); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored which is popped by the called - * function */ -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 832); -#else - dasm_put(Dst, 895, hidden_arg_off); -#endif - break; - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 944, x86_return_size(L, ct_usr, ct)); - - lua_pop(L, 1); /* upval table - already in registry */ - assert(lua_gettop(L) == top); - - ct2.is_jitted = 1; - pf = (cfunction*) push_cdata(L, ct_usr, &ct2); - *pf = compile(Dst, L, NULL, ref); - - assert(lua_gettop(L) == top + 1); - - return *pf; -} - -void compile_function(lua_State* L, cfunction func, int ct_usr, const struct ctype* ct) -{ - size_t i, nargs; - int num_upvals; - const struct ctype* mbr_ct; - struct jit* Dst = get_jit(L); - struct reg_alloc reg; - void* p; - int top = lua_gettop(L); - int* perr = &Dst->last_errno; - - ct_usr = lua_absindex(L, ct_usr); - - memset(®, 0, sizeof(reg)); - reg.off = 32 + REGISTER_STACK_SPACE(ct); - - dasm_setup(Dst, build_actionlist); - - p = push_cdata(L, ct_usr, ct); - *(cfunction*) p = func; - num_upvals = 1; - - nargs = lua_rawlen(L, ct_usr); - - if (ct->calling_convention != C_CALL && ct->has_var_arg) { - luaL_error(L, "vararg is only allowed with the c calling convention"); - } - - dasm_put(Dst, 957, nargs); - if (!ct->has_var_arg) { - dasm_put(Dst, 989, (unsigned int)((uintptr_t)(&"too few arguments")), (unsigned int)(((uintptr_t)(&"too few arguments"))>>32), (unsigned int)((uintptr_t)(&"too many arguments")), (unsigned int)(((uintptr_t)(&"too many arguments"))>>32)); - } else { - dasm_put(Dst, 1030, (unsigned int)((uintptr_t)(&"too few arguments")), (unsigned int)(((uintptr_t)(&"too few arguments"))>>32)); - } - - dasm_put(Dst, 1050); - - /* no need to zero extend eax returned by lua_gettop to rax as x86-64 - * preguarentees that the upper 32 bits will be zero */ - dasm_put(Dst, 1053, 32 + REGISTER_STACK_SPACE(ct)); - -#if !defined _WIN64 && !defined __amd64__ - /* Returned complex doubles require a hidden first parameter where the - * data is stored, which is popped by the calling code. */ - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - if (!mbr_ct->pointers && !mbr_ct->is_reference && mbr_ct->type == COMPLEX_DOUBLE_TYPE) { - /* we can allocate more space for arguments as long as no add_* - * function has been called yet, mbr_ct will be added as an upvalue in - * the return processing later */ - dasm_put(Dst, 1066, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32)); - add_pointer(Dst, ct, ®); - } - lua_pop(L, 1); -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, (int) i); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1090, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals), i); - add_pointer(Dst, ct, ®); - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1110, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals), i); - add_pointer(Dst, ct, ®); - break; - - case ENUM_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1130, (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals), i); - add_int(Dst, ct, ®, 0); - break; - - case INT8_TYPE: - dasm_put(Dst, 1150, i); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1162); - } else { - dasm_put(Dst, 1166); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT16_TYPE: - dasm_put(Dst, 1150, i); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1170); - } else { - dasm_put(Dst, 1174); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - dasm_put(Dst, 1178, i); - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT32_TYPE: - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1200, i); - } else { - dasm_put(Dst, 1150, i); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INTPTR_TYPE: - dasm_put(Dst, 1212, i); - add_pointer(Dst, ct, ®); - lua_pop(L, 1); - break; - - case INT64_TYPE: - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1224, i); - } else { - dasm_put(Dst, 1236, i); - } - add_int(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case DOUBLE_TYPE: - dasm_put(Dst, 1248, i); - add_float(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case COMPLEX_DOUBLE_TYPE: - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored (this is popped by the called - * function) */ -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 1260, i); - add_float(Dst, ct, ®, 1); - dasm_put(Dst, 1272); - add_float(Dst, ct, ®, 1); -#else - dasm_put(Dst, 1278, reg.off, i); - reg.off += 16; -#endif - lua_pop(L, 1); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 1248, i); - add_float(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case COMPLEX_FLOAT_TYPE: -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 1304, i); - /* complex floats are two floats packed into a double */ - add_float(Dst, ct, ®, 1); -#else - /* returned complex floats use eax and edx */ - dasm_put(Dst, 1316, i); - add_float(Dst, ct, ®, 0); - dasm_put(Dst, 1334); - add_float(Dst, ct, ®, 0); -#endif - lua_pop(L, 1); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { -#ifdef _WIN64 - if (reg.regs < MAX_REGISTERS(ct)) { - assert(reg.regs == nargs); - dasm_put(Dst, 1341, MAX_REGISTERS(ct), 32 + 8*MAX_REGISTERS(ct), MAX_REGISTERS(ct)+1, 32 + 8*(reg.regs), MAX_REGISTERS(ct), nargs+1, 32 + 8*(reg.regs), nargs+1); - } else { - dasm_put(Dst, 1432, reg.off, nargs+1); - } - - for (i = nargs; i < MAX_REGISTERS(ct); i++) { - reg.is_int[i] = reg.is_float[i] = 1; - } - reg.regs = MAX_REGISTERS(ct); -#elif defined __amd64__ - if (reg.floats < MAX_FLOAT_REGISTERS(ct)) { - } - - if (reg.ints < MAX_INT_REGISTERS(ct)) { - } - - - reg.floats = MAX_FLOAT_REGISTERS(ct); - reg.ints = MAX_INT_REGISTERS(ct); -#else -#endif - } - - dasm_put(Dst, 1457, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - - /* remove the stack space to call local functions */ - dasm_put(Dst, 1471); - -#ifdef _WIN64 - switch (reg.regs) { - case 4: - if (reg.is_float[3]) { - dasm_put(Dst, 1476, 8*3); - } - if (reg.is_int[3]) { - dasm_put(Dst, 1485, 8*3); - } - case 3: - if (reg.is_float[2]) { - dasm_put(Dst, 1492, 8*2); - } - if (reg.is_int[2]) { - dasm_put(Dst, 1501, 8*2); - } - case 2: - if (reg.is_float[1]) { - dasm_put(Dst, 1508, 8*1); - } - if (reg.is_int[1]) { - dasm_put(Dst, 1517, 8*1); - } - case 1: - if (reg.is_float[0]) { - dasm_put(Dst, 1524); - } - if (reg.is_int[0]) { - dasm_put(Dst, 1531); - } - case 0: - break; - } - - /* don't remove the space for the registers as we need 32 bytes of register overflow space */ - assert(REGISTER_STACK_SPACE(ct) == 32); - -#elif defined __amd64__ - switch (reg.floats) { - case 8: - case 7: - case 6: - case 5: - case 4: - case 3: - case 2: - case 1: - case 0: - break; - } - - switch (reg.ints) { - case 6: - case 5: - case 4: - case 3: - case 2: - case 1: - case 0: - break; - } - -#else - if (ct->calling_convention == FAST_CALL) { - switch (reg.ints) { - case 2: - case 1: - case 0: - break; - } - - } -#endif - -#ifdef __amd64__ - if (ct->has_var_arg) { - /* al stores an upper limit on the number of float register, note that - * its allowed to be more than the actual number of float registers used as - * long as its 0-8 */ - } -#endif - - dasm_put(Dst, 1536); - - /* note on windows X86 the stack may be only aligned to 4 (stdcall will - * have popped a multiple of 4 bytes), but we don't need 16 byte alignment on - * that platform - */ - - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference || mbr_ct->type == INTPTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1546, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1546, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - break; - - case INT64_TYPE: -#if LUA_VERSION_NUM == 503 - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1606, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } else { - dasm_put(Dst, 1606, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } -#else - num_upvals++; - dasm_put(Dst, 1658, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32)); -#endif - break; - - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1721, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1782, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32), (unsigned int)((uintptr_t)(mbr_ct)), (unsigned int)(((uintptr_t)(mbr_ct))>>32), lua_upvalueindex(num_upvals)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1858, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1890, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case INT8_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1162); - } else { - dasm_put(Dst, 1166); - } - dasm_put(Dst, 1943, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case INT16_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1170); - } else { - dasm_put(Dst, 1174); - } - dasm_put(Dst, 1943, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1993, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } else { - dasm_put(Dst, 1943, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - } - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 2043, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 2048, (unsigned int)((uintptr_t)(perr)), (unsigned int)(((uintptr_t)(perr))>>32)); - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, func, LUA_NOREF); - /* add a callback as an upval so that the jitted code gets cleaned up when - * the function gets gc'd */ - push_callback(L, f, func); - lua_pushcclosure(L, (lua_CFunction) f, num_upvals+1); - } -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call_x86.dasc b/Build/source/texk/web2c/luatexdir/luaffi/call_x86.dasc deleted file mode 100644 index 4a72b98e4ad..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call_x86.dasc +++ /dev/null @@ -1,1640 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -|.if X64 -|.arch x64 -|.else -|.arch x86 -|.endif - -|.actionlist build_actionlist -|.globalnames globnames -|.externnames extnames - -|.if not X64 -|.define RET_H, edx // for int64_t returns -|.define RET_L, eax -|.endif - -|.if X64 -|.define L_ARG, r12 -|.define TOP, r13 -|.else -|.define L_ARG, rdi -|.define TOP, rsi -|.endif - -|.if X64WIN -| -|.macro call_rrrp, func, arg0, arg1, arg2, arg3 -| mov64 r9, arg3 -| mov r8, arg2 -| mov rdx, arg1 -| mov rcx, arg0 -| call func -|.endmacro -|.macro call_rrrr, func, arg0, arg1, arg2, arg3 -| mov r9, arg3 -| mov r8, arg2 -| mov rdx, arg1 -| mov rcx, arg0 -| call func -|.endmacro -| -|.macro call_rrp, func, arg0, arg1, arg2 -| mov64 r8, arg2 -| mov rdx, arg1 -| mov rcx, arg0 -| call func -|.endmacro -|.macro call_rrr, func, arg0, arg1, arg2 -| mov r8, arg2 -| mov rdx, arg1 -| mov rcx, arg0 -| call func -|.endmacro -| -|.macro call_rp, func, arg0, arg1 -| mov64 rdx, arg1 -| mov rcx, arg0 -| call func -|.endmacro -|.macro call_rr, func, arg0, arg1 -| mov rdx, arg1 -| mov rcx, arg0 -| call func -|.endmacro -| -|.macro call_r, func, arg0 -| mov rcx, arg0 -| call func -|.endmacro -| -|.elif X64 -| -| // the 5 and 6 arg forms are only used on posix x64 -|.macro call_rrrrrr, func, arg0, arg1, arg2, arg3, arg4, arg5 -| mov r9, arg5 -| mov r8, arg4 -| mov rcx, arg3 -| mov rdx, arg2 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -|.macro call_rrrrr, func, arg0, arg1, arg2, arg3, arg4 -| mov r8, arg4 -| mov rcx, arg3 -| mov rdx, arg2 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -| -|.macro call_rrrp, func, arg0, arg1, arg2, arg3 -| mov64 rcx, arg3 -| mov rdx, arg2 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -|.macro call_rrrr, func, arg0, arg1, arg2, arg3 -| mov rcx, arg3 -| mov rdx, arg2 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -| -|.macro call_rrp, func, arg0, arg1, arg2 -| mov64 rdx, arg2 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -|.macro call_rrr, func, arg0, arg1, arg2 -| mov rdx, arg2 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -| -|.macro call_rp, func, arg0, arg1 -| mov64 rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -|.macro call_rr, func, arg0, arg1 -| mov rsi, arg1 -| mov rdi, arg0 -| call func -|.endmacro -| -|.macro call_r, func, arg0 -| mov rdi, arg0 -| call func -|.endmacro -| -|.else -| // define the 64bit registers to the 32 bit counterparts, so the common -| // code can use r*x for all pointers -|.define rax, eax -|.define rcx, ecx -|.define rdx, edx -|.define rsp, esp -|.define rbp, ebp -|.define rdi, edi -|.define rsi, esi -|.define mov64, mov -| -|.macro call_rrrr, func, arg0, arg1, arg2, arg3 -| mov dword [rsp+12], arg3 -| mov dword [rsp+8], arg2 -| mov dword [rsp+4], arg1 -| mov dword [rsp], arg0 -| call func -|.endmacro -|.macro call_rrr, func, arg0, arg1, arg2 -| mov dword [rsp+8], arg2 -| mov dword [rsp+4], arg1 -| mov dword [rsp], arg0 -| call func -|.endmacro -|.macro call_rr, func, arg0, arg1 -| mov dword [rsp+4], arg1 -| mov dword [rsp], arg0 -| call func -|.endmacro -|.macro call_r, func, arg0 -| mov dword [rsp], arg0 -| call func -|.endmacro -| -|.define call_rrrp, call_rrrr -|.define call_rrp, call_rrr -|.define call_rp, call_rr -| -|.endif - -|.macro epilog -|.if X64 -| mov TOP, [rbp-16] -| mov L_ARG, [rbp-8] -|.else -| mov TOP, [rbp-8] -| mov L_ARG, [rbp-4] -|.endif -| mov rsp, rbp -| pop rbp -| ret -|.endmacro - -|.macro get_errno // note trashes registers -| call extern GetLastError -| mov64 rcx, perr -| mov dword [rcx], eax -|.endmacro - -|.macro too_few_arguments -| mov ax, 0 -| call_rp extern luaL_error, L_ARG, &"too few arguments" -|.endmacro - -|.macro too_many_arguments -| mov ax, 0 -| call_rp extern luaL_error, L_ARG, &"too many arguments" -|.endmacro - -|.macro lua_return_arg -| mov eax, 1 -| epilog -|.endmacro - -|.macro lua_return_void -| get_errno -| mov eax, 0 -| epilog -|.endmacro - -|.macro lua_return_double -|.if X64 -| movq qword [rsp+32], xmm0 -|.else -| fstp qword [rsp+4] // note get_errno doesn't require any stack on x86 -|.endif -| -| get_errno -| -|.if X64WIN -| movq xmm1, qword [rsp+32] -| mov rcx, L_ARG -|.elif X64 -| movq xmm0, qword [rsp+32] -| mov rdi, L_ARG -|.else -| mov [rsp], L_ARG -|.endif -| call extern lua_pushnumber -| lua_return_arg -|.endmacro - -|.macro lua_return_bool -| movzx eax, al -| mov [rsp+32], eax -| get_errno -| mov eax, [rsp+32] -| call_rr extern lua_pushboolean, L_ARG, rax -| lua_return_arg -|.endmacro - -|.macro lua_return_int -| mov [rsp+32], eax -| get_errno -| mov eax, [rsp+32] -| call_rr extern push_int, L_ARG, rax -| lua_return_arg -|.endmacro - -|.macro lua_return_uint -| mov [rsp+32], eax -| get_errno -| mov eax, [rsp+32] -| call_rr extern push_uint, L_ARG, rax -| lua_return_arg -|.endmacro - -|.macro lua_return_long -| mov [rsp+32], rax -| get_errno -| mov rax, [rsp+32] -| call_rr extern lua_pushinteger, L_ARG, rax -| lua_return_arg -|.endmacro - -|.macro lua_return_ulong -| mov [rsp+32], rax -| get_errno -| mov rax, [rsp+32] -| call_rr extern lua_pushinteger, L_ARG, rax -| lua_return_arg -|.endmacro - -|.macro save_registers -| // use rbp relative so we store values in the outer stack frame -|.if X64WIN -| // use the provided shadow space for int registers above prev rbp and -| // return address -| mov [rbp+16], rcx -| mov [rbp+24], rdx -| mov [rbp+32], r8 -| mov [rbp+40], r9 -| // use the extra space we added for float registers -| // -16 to store underneath previous value of L_ARG -| movq qword [rbp-16], xmm0 -| movq qword [rbp-24], xmm1 -| movq qword [rbp-32], xmm2 -| movq qword [rbp-40], xmm3 -|.elif X64 -| movq qword [rbp-16], xmm0 -| movq qword [rbp-24], xmm1 -| movq qword [rbp-32], xmm2 -| movq qword [rbp-40], xmm3 -| movq qword [rbp-48], xmm4 -| movq qword [rbp-56], xmm5 -| movq qword [rbp-64], xmm6 -| movq qword [rbp-72], xmm7 -| mov [rbp-80], rdi -| mov [rbp-88], rsi -| mov [rbp-96], rdx -| mov [rbp-104], rcx -| mov [rbp-112], r8 -| mov [rbp-120], r9 -|.else -| // fastcall, -8 to store underneath previous value of L_ARG -| mov [rbp-8], ecx -| mov [rbp-12], edx -|.endif -|.endmacro - -#if defined _WIN64 || defined __amd64__ -#define JUMP_SIZE 14 -#else -#define JUMP_SIZE 4 -#endif - -#define MIN_BRANCH INT32_MIN -#define MAX_BRANCH INT32_MAX -#define BRANCH_OFF 4 - -static void compile_extern_jump(struct jit* jit, lua_State* L, cfunction func, uint8_t* code) -{ - /* The jump code is the function pointer followed by a stub to call the - * function pointer. The stub exists in 64 bit so we can jump to functions - * with an offset greater than 2 GB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state and dynasm doesn't support rip relative addressing. - * - * eg on 64 bit: - * 0-8: function ptr - * 8-14: jmp aword [rip-14] - * - * for 32 bit we only set the function ptr as it can always fit in a 32 - * bit displacement - */ -#if defined _WIN64 || defined __amd64__ - *(cfunction*) code = func; - code[8] = 0xFF; /* FF /4 operand for jmp */ - code[9] = 0x25; /* RIP displacement */ - *(int32_t*) &code[10] = -14; -#else - *(cfunction*) code = func; -#endif -} - -void compile_globals(struct jit* jit, lua_State* L) -{ - struct jit* Dst = jit; - int* perr = &jit->last_errno; - dasm_setup(Dst, build_actionlist); - - /* Note: since the return code uses EBP to reset the stack pointer, we - * don't have to track the amount of stack space used. It also means we - * can handle stdcall and cdecl with the same code. - */ - - /* Note the various call_* functions want 32 bytes of 16 byte aligned - * stack - */ - - - - compile(Dst, L, NULL, LUA_NOREF); -} - -int x86_return_size(lua_State* L, int usr, const struct ctype* ct) -{ - int ret = 0; - const struct ctype* mt; - - if (ct->calling_convention != C_CALL) { - size_t i; - size_t argn = lua_rawlen(L, usr); - for (i = 1; i <= argn; i++) { - lua_rawgeti(L, usr, (int) i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - ret += sizeof(void*); - } else { - switch (mt->type) { - case DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case INT64_TYPE: - ret += 8; - break; - case COMPLEX_DOUBLE_TYPE: - ret += 16; - break; - case INTPTR_TYPE: - ret += sizeof(intptr_t); - break; - case FUNCTION_PTR_TYPE: - ret += sizeof(cfunction); - break; - case BOOL_TYPE: - case FLOAT_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE: - ret += 4; - break; - default: - return luaL_error(L, "NYI - argument type"); - } - } - - lua_pop(L, 1); - } - } - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - ret += sizeof(void*); - } - lua_pop(L, 1); -#endif - - return ret; -} - -#ifdef _WIN64 -#define MAX_REGISTERS(ct) 4 /* rcx, rdx, r8, r9 */ - -#elif defined __amd64__ -#define MAX_INT_REGISTERS(ct) 6 /* rdi, rsi, rdx, rcx, r8, r9 */ -#define MAX_FLOAT_REGISTERS(ct) 8 /* xmm0-7 */ - -#else -#define MAX_INT_REGISTERS(ct) ((ct)->calling_convention == FAST_CALL ? 2 /* ecx, edx */ : 0) -#define MAX_FLOAT_REGISTERS(ct) 0 -#endif - -struct reg_alloc { -#ifdef _WIN64 - int regs; - int is_float[4]; - int is_int[4]; -#else - int floats; - int ints; -#endif - int off; -}; - -#ifdef _WIN64 -#define REGISTER_STACK_SPACE(ct) (4*8) -#elif defined __amd64__ -#define REGISTER_STACK_SPACE(ct) (14*8) -#else -#define REGISTER_STACK_SPACE(ct) ALIGN_UP(((ct)->calling_convention == FAST_CALL ? 2*4 : 0), 15) -#endif - -/* Fastcall: - * Uses ecx, edx as first two int registers - * Everything else on stack (include 64bit ints) - * No overflow stack space - * Pops the stack before returning - * Returns int in eax, float in ST0 - * We use the same register allocation logic as posix x64 with 2 int regs and 0 float regs - */ - -static void get_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ - /* grab the register from the shadow space */ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - | mov rcx, [rbp + 16 + 8*reg->regs] - reg->regs++; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - | mov rcx, [rbp - 80 - 8*reg->ints] - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - | mov ecx, [rbp - 8 - 4*reg->ints] - reg->ints++; - } -#endif - else if (is_int64) { - |.if X64 - | mov rcx, [rbp + reg->off] - |.else - | mov rcx, [rbp + reg->off] - | mov rdx, [rbp + reg->off + 4] - |.endif - reg->off += 8; - } else { - | mov ecx, [rbp + reg->off] - reg->off += 4; - } -} - -static void add_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - | mov [rsp + 32 + 8*(reg->regs)], rax - reg->is_int[reg->regs++] = 1; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - | mov [rsp + 32 + 8*reg->ints], rax - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - | mov [rsp + 32 + 4*reg->ints], rax - reg->ints++; - } -#endif - else { -#if defined _WIN64 || defined __amd64__ - if (reg->off % 8 != 0) { - reg->off += 8 - (reg->off % 8); - } -#endif - if (is_int64) { - |.if X64 - | mov [rsp + reg->off], rax - |.else - | mov [rsp + reg->off], RET_L - | mov [rsp + reg->off + 4], RET_H - |.endif - reg->off += 8; - } else { - | mov [rsp+reg->off], eax - reg->off += 4; - } - } -} - -static void get_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - | fld qword [rbp + reg->off] - reg->off += 8; - } else { - | fld dword [rbp + reg->off] - reg->off += 4; - } -#else - int off; - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - off = -16 - 8*reg->regs; - reg->regs++; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - off = -16 - 8*reg->floats; - reg->floats++; - } -#endif - else { - off = reg->off; - reg->off += is_double ? 8 : 4; - } - - if (is_double) { - | movq xmm0, qword [rbp + off] - } else { - | cvtss2sd xmm0, dword [rbp + off] - } -#endif -} - -static void add_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - | fstp qword [rsp + reg->off] - reg->off += 8; - } else { - | fstp dword [rsp + reg->off] - reg->off += 4; - } -#else - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - if (is_double) { - | movq qword [rsp + 32 + 8*(reg->regs)], xmm0 - } else { - | cvtsd2ss xmm0, xmm0 - | movq qword [rsp + 32 + 8*(reg->regs)], xmm0 - } - reg->is_float[reg->regs++] = 1; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - if (is_double) { - | movq qword [rsp + 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)], xmm0 - } else { - | cvtsd2ss xmm0, xmm0 - | movq qword [rsp + 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)], xmm0 - } - reg->floats++; - } -#endif - - else if (is_double) { - | movq qword [rsp + reg->off], xmm0 - reg->off += 8; - } else { - | cvtsd2ss xmm0, xmm0 - | movd dword [rsp + reg->off], xmm0 - reg->off += 4; - } -#endif -} - -#if defined _WIN64 || defined __amd64__ -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 1) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 1) -#else -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 0) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 0) -#endif - -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct) -{ - int i, nargs; - cfunction* pf; - struct ctype ct2 = *ct; - const struct ctype* mt; - struct reg_alloc reg; - int num_upvals = 0; - int top = lua_gettop(L); - struct jit* Dst = get_jit(L); - int ref; - int hidden_arg_off = 0; - - ct_usr = lua_absindex(L, ct_usr); - fidx = lua_absindex(L, fidx); - - assert(lua_isnil(L, fidx) || lua_isfunction(L, fidx)); - - memset(®, 0, sizeof(reg)); -#ifdef _WIN64 - reg.off = 16 + REGISTER_STACK_SPACE(ct); /* stack registers are above the shadow space */ -#elif __amd64__ - reg.off = 16; -#else - reg.off = 8; -#endif - - dasm_setup(Dst, build_actionlist); - - // add a table to store ctype and function upvalues - // callback_set assumes the first value is the lua function - nargs = (int) lua_rawlen(L, ct_usr); - lua_newtable(L); - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - - if (ct->has_var_arg) { - luaL_error(L, "can't create callbacks with varargs"); - } - - // setup a stack frame to hold args for the call into lua_call - - | push rbp - | mov rbp, rsp - | push L_ARG - | // stack is 4 or 8 (mod 16) (L_ARG, rbp, rip) - |.if X64 - | // 8 to realign, 16 for return vars, 32 for local calls, rest to save registers - | sub rsp, 8 + 16 + 32 + REGISTER_STACK_SPACE(ct) - | save_registers - |.else - | // 4 to realign, 16 for return vars, 32 for local calls, rest to save registers - | sub rsp, 4 + 16 + 32 + REGISTER_STACK_SPACE(ct) - if (ct->calling_convention == FAST_CALL) { - | save_registers - } - |.endif - - // hardcode the lua_State* value into the assembly - | mov64 L_ARG, L - - /* get the upval table */ - | call_rrr extern lua_rawgeti, L_ARG, LUA_REGISTRYINDEX, ref - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - assert(num_upvals == CALLBACK_FUNC_USR_IDX); - | call_rrr extern lua_rawgeti, L_ARG, -1, num_upvals - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - hidden_arg_off = reg.off; - reg.off += sizeof(void*); - } - lua_pop(L, 1); -#else - (void) hidden_arg_off; -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - /* on the lua stack in the callback: - * upval tbl, lua func, i-1 args - */ - | call_rrr extern lua_rawgeti, L_ARG, -i-1, num_upvals-1 - | call_rrp extern push_cdata, L_ARG, -1, mt - get_pointer(Dst, ct, ®); - | mov [rax], rcx - | call_rr, extern lua_remove, L_ARG, -2 - } else { - switch (mt->type) { - case INT64_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - | call_rrp extern push_cdata, L_ARG, 0, mt - get_int(Dst, ct, ®, 1); - |.if X64 - | mov [rax], rcx - |.else - | mov [rax], ecx - | mov [rax+4], edx - |.endif - break; - - case INTPTR_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - | call_rrp extern push_cdata, L_ARG, 0, mt - get_pointer(Dst, ct, ®); - | mov [rax], rcx - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if defined _WIN64 || defined __amd64__ - /* complex floats are two floats packed into a double */ - | call_rrp extern push_cdata, L_ARG, 0, mt - get_float(Dst, ct, ®, 1); - | movq qword [rax], xmm0 -#else - /* complex floats are real followed by imag on the stack */ - | call_rrp extern push_cdata, L_ARG, 0, mt - get_float(Dst, ct, ®, 0); - | fstp dword [rax] - get_float(Dst, ct, ®, 0); - | fstp dword [rax+4] -#endif - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); - | call_rrp extern push_cdata, L_ARG, 0, mt - /* real */ - get_float(Dst, ct, ®, 1); - |.if X64 - | movq qword [rax], xmm0 - |.else - | fstp qword [rax] - |.endif - /* imag */ - get_float(Dst, ct, ®, 1); - |.if X64 - | movq qword [rax+8], xmm0 - |.else - | fstp qword [rax+8] - |.endif - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - get_float(Dst, ct, ®, mt->type == DOUBLE_TYPE); - |.if X64WIN - | movq xmm1, xmm0 - | mov rcx, L_ARG - |.elif X64 - | // for 64bit xmm0 is already set - | mov rdi, L_ARG - |.else - | fstp qword [rsp+4] - | mov [rsp], L_ARG - |.endif - | call extern lua_pushnumber - break; - - case BOOL_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - | movzx ecx, cl - | call_rr extern lua_pushboolean, L_ARG, rcx - break; - - case INT8_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - | movzx ecx, cl - } else { - | movsx ecx, cl - } - | call_rr extern push_int, L_ARG, rcx - break; - - case INT16_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - | movzx ecx, cx - } else { - | movsx ecx, cx - } - | call_rr extern push_int, L_ARG, rcx - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - | call_rr extern push_uint, L_ARG, rcx - } else { - | call_rr extern push_int, L_ARG, rcx - } - break; - - default: - luaL_error(L, "NYI: callback arg type"); - } - } - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - | call_rrrp extern lua_callk, L_ARG, nargs, (mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0, 0 - - // Unpack the return argument if not "void", also clean-up the lua stack - // to remove the return argument and bind table. Use lua_settop rather - // than lua_pop as lua_pop is implemented as a macro. - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - | call_rrr extern lua_rawgeti, L_ARG, -2, num_upvals-1 - | call_rrrp extern check_typed_pointer, L_ARG, -2, -1, mt - | mov [rsp+32], rax - | call_rr extern lua_settop, L_ARG, -4 - | mov rax, [rsp+32] - - } else { - switch (mt->type) { - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - | call_rrr extern lua_rawgeti, L_ARG, -2, num_upvals-1 - | call_rrrp, extern check_enum, L_ARG, -2, -1, mt - | mov [rsp+32], eax - | call_rr extern lua_settop, L_ARG, -4 - | mov eax, [rsp+32] - break; - - case VOID_TYPE: - lua_pop(L, 1); - | call_rr extern lua_settop, L_ARG, -2 - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - if (mt->is_unsigned) { - | call_rr extern check_uint32, L_ARG, -1 - } else { - | call_rr extern check_int32, L_ARG, -1 - } - | mov [rsp+32], eax - | call_rr extern lua_settop, L_ARG, -3 - | mov eax, [rsp+32] - break; - - case INT64_TYPE: - lua_pop(L, 1); - - if (mt->is_unsigned) { - | call_rr extern check_uint64, L_ARG, -1 - } else { - | call_rr extern check_int64, L_ARG, -1 - } - - |.if X64 - | mov [rsp+32], rax - |.else - | mov [rsp+32], RET_L - | mov [rsp+36], RET_H - |.endif - | call_rr extern lua_settop, L_ARG, -3 - |.if X64 - | mov rax, [rsp+32] - |.else - | mov RET_L, [rsp+32] - | mov RET_H, [rsp+36] - |.endif - break; - - case INTPTR_TYPE: - lua_pop(L, 1); - | call_rr extern check_uintptr, L_ARG, -1 - | mov [rsp+32], rax - | call_rr extern lua_settop, L_ARG, -3 - | mov rax, [rsp+32] - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - | call_rr extern check_double, L_ARG, -1 - |.if X64 - | movq qword [rsp+32], xmm0 - | call_rr extern lua_settop, L_ARG, -3 - if (mt->type == FLOAT_TYPE) { - | cvtsd2ss xmm0, qword [rsp+32] - } else { - | movq xmm0, qword [rsp+32] - } - |.else - | fstp qword [rsp+32] - | call_rr extern lua_settop, L_ARG, -3 - | fld qword [rsp+32] - |.endif - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit complex floats are two floats packed into a double, - * on 32 bit returned complex floats use eax and edx */ - | call_rr extern check_complex_float, L_ARG, -1 - | - |.if X64 - | movq qword [rsp+32], xmm0 - |.else - | mov [rsp+32], eax - | mov [rsp+36], edx - |.endif - | - | call_rr extern lua_settop, L_ARG, -3 - | - |.if X64 - | movq xmm0, qword [rsp+32] - |.else - | mov eax, [rsp+32] - | mov edx, [rsp+36] - |.endif - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored which is popped by the called - * function */ -#if defined _WIN64 || defined __amd64__ - | call_rr extern check_complex_double, L_ARG, -1 - | movq qword [rsp+32], xmm0 - | movq qword [rsp+40], xmm1 - | call_rr extern lua_settop, L_ARG, -3 - | movq xmm0, qword [rsp+32] - | movq xmm1, qword [rsp+40] -#else - | mov rcx, [rbp + hidden_arg_off] - | call_rrr extern check_complex_double, rcx, L_ARG, -1 - | sub rsp, 4 // to realign from popped hidden arg - | call_rr extern lua_settop, L_ARG, -3 -#endif - break; - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - |.if X64 - | mov L_ARG, [rbp-8] - |.else - | mov L_ARG, [rbp-4] - |.endif - | mov rsp, rbp - | pop rbp - | ret x86_return_size(L, ct_usr, ct) - - lua_pop(L, 1); /* upval table - already in registry */ - assert(lua_gettop(L) == top); - - ct2.is_jitted = 1; - pf = (cfunction*) push_cdata(L, ct_usr, &ct2); - *pf = compile(Dst, L, NULL, ref); - - assert(lua_gettop(L) == top + 1); - - return *pf; -} - -void compile_function(lua_State* L, cfunction func, int ct_usr, const struct ctype* ct) -{ - size_t i, nargs; - int num_upvals; - const struct ctype* mbr_ct; - struct jit* Dst = get_jit(L); - struct reg_alloc reg; - void* p; - int top = lua_gettop(L); - int* perr = &Dst->last_errno; - - ct_usr = lua_absindex(L, ct_usr); - - memset(®, 0, sizeof(reg)); - reg.off = 32 + REGISTER_STACK_SPACE(ct); - - dasm_setup(Dst, build_actionlist); - - p = push_cdata(L, ct_usr, ct); - *(cfunction*) p = func; - num_upvals = 1; - - nargs = lua_rawlen(L, ct_usr); - - if (ct->calling_convention != C_CALL && ct->has_var_arg) { - luaL_error(L, "vararg is only allowed with the c calling convention"); - } - - | push rbp - | mov rbp, rsp - | push L_ARG - | push TOP - | // stack is 0 (mod 16) (TOP, L_ARG, rbp, rip) - | - | // Get L from our arguments and allocate some stack for lua_gettop - |.if X64WIN - | mov L_ARG, rcx - | sub rsp, 32 // shadow space - |.elif X64 - | mov L_ARG, rdi - |.else - | mov L_ARG, [rbp + 8] - | sub rsp, 16 - |.endif - | - | call_r extern lua_gettop, L_ARG - | mov TOP, rax // no need for movzxd rax, eax - high word guarenteed to be zero by x86-64 - | cmp rax, nargs - if (!ct->has_var_arg) { - | jge >2 - | too_few_arguments - | 2: - | jle >1 - | too_many_arguments - } else { - | jge >1 - | too_few_arguments - } - - | 1: - - /* no need to zero extend eax returned by lua_gettop to rax as x86-64 - * preguarentees that the upper 32 bits will be zero */ - | shl rax, 4 // reserve 16 bytes per argument - this maintains the alignment mod 16 - | sub rsp, rax - | sub rsp, 32 + REGISTER_STACK_SPACE(ct) // reserve an extra 32 to call local functions - -#if !defined _WIN64 && !defined __amd64__ - /* Returned complex doubles require a hidden first parameter where the - * data is stored, which is popped by the calling code. */ - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - if (!mbr_ct->pointers && !mbr_ct->is_reference && mbr_ct->type == COMPLEX_DOUBLE_TYPE) { - /* we can allocate more space for arguments as long as no add_* - * function has been called yet, mbr_ct will be added as an upvalue in - * the return processing later */ - | call_rrp extern push_cdata, L_ARG, 0, mbr_ct - | sub rsp, 16 - add_pointer(Dst, ct, ®); - } - lua_pop(L, 1); -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, (int) i); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference) { - lua_getuservalue(L, -1); - num_upvals += 2; - | call_rrrp extern check_typed_pointer, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct - add_pointer(Dst, ct, ®); - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - | call_rrrp extern check_typed_cfunction, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct - add_pointer(Dst, ct, ®); - break; - - case ENUM_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - | call_rrrp, extern check_enum, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct - add_int(Dst, ct, ®, 0); - break; - - case INT8_TYPE: - | call_rr extern check_int32, L_ARG, i - if (mbr_ct->is_unsigned) { - | movzx eax, al - } else { - | movsx eax, al - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT16_TYPE: - | call_rr extern check_int32, L_ARG, i - if (mbr_ct->is_unsigned) { - | movzx eax, ax - } else { - | movsx eax, ax - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - | call_rr extern check_int32, L_ARG, i - | cmp eax, 0 - | setne al - | movzx eax, al - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT32_TYPE: - if (mbr_ct->is_unsigned) { - | call_rr extern check_uint32, L_ARG, i - } else { - | call_rr extern check_int32, L_ARG, i - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INTPTR_TYPE: - | call_rr extern check_uintptr, L_ARG, i - add_pointer(Dst, ct, ®); - lua_pop(L, 1); - break; - - case INT64_TYPE: - if (mbr_ct->is_unsigned) { - | call_rr extern check_uint64, L_ARG, i - } else { - | call_rr extern check_int64, L_ARG, i - } - add_int(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case DOUBLE_TYPE: - | call_rr extern check_double, L_ARG, i - add_float(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case COMPLEX_DOUBLE_TYPE: - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored (this is popped by the called - * function) */ -#if defined _WIN64 || defined __amd64__ - | call_rr extern check_complex_double, L_ARG, i - add_float(Dst, ct, ®, 1); - | movq xmm0, xmm1 - add_float(Dst, ct, ®, 1); -#else - | lea rax, [rsp+reg.off] - | sub rsp, 4 - | call_rrr extern check_complex_double, rax, L_ARG, i - reg.off += 16; -#endif - lua_pop(L, 1); - break; - - case FLOAT_TYPE: - | call_rr extern check_double, L_ARG, i - add_float(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case COMPLEX_FLOAT_TYPE: -#if defined _WIN64 || defined __amd64__ - | call_rr extern check_complex_float, L_ARG, i - /* complex floats are two floats packed into a double */ - add_float(Dst, ct, ®, 1); -#else - /* returned complex floats use eax and edx */ - | call_rr extern check_complex_float, L_ARG, i - | mov [rsp], eax - | fld dword [rsp] - add_float(Dst, ct, ®, 0); - | mov [rsp], edx - | fld dword [rsp] - add_float(Dst, ct, ®, 0); -#endif - lua_pop(L, 1); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { -#ifdef _WIN64 - |.if X64WIN - if (reg.regs < MAX_REGISTERS(ct)) { - assert(reg.regs == nargs); - | cmp TOP, MAX_REGISTERS(ct) - | jle >1 - | // unpack onto stack - | mov rax, rsp - | add rax, 32 + 8*MAX_REGISTERS(ct) - | call_rrrr extern unpack_varargs_stack, L_ARG, MAX_REGISTERS(ct)+1, TOP, rax - | // unpack to registers - | mov rax, rsp - | add rax, 32 + 8*(reg.regs) - | call_rrrr extern unpack_varargs_reg, L_ARG, nargs+1, MAX_REGISTERS(ct), rax - | jmp >2 - |1: - | // unpack just to registers - | mov rax, rsp - | add rax, 32 + 8*(reg.regs) - | call_rrrr extern unpack_varargs_reg, L_ARG, nargs+1, TOP, rax - |2: - } else { - | // unpack just to stack - | mov rax, rsp - | add rax, reg.off - | call_rrrr extern unpack_varargs_stack, L_ARG, nargs+1, TOP, rax - } - - for (i = nargs; i < MAX_REGISTERS(ct); i++) { - reg.is_int[i] = reg.is_float[i] = 1; - } - reg.regs = MAX_REGISTERS(ct); -#elif defined __amd64__ - |.elif X64 - if (reg.floats < MAX_FLOAT_REGISTERS(ct)) { - | mov rax, rsp - | add rax, 32 + 8*(MAX_INT_REGISTERS(ct) + reg.floats) - | call_rrrrr extern unpack_varargs_float, L_ARG, nargs+1, TOP, MAX_FLOAT_REGISTERS(ct) - reg.floats, rax - } - - if (reg.ints < MAX_INT_REGISTERS(ct)) { - | mov rax, rsp - | add rax, 32 + 8*(reg.ints) - | call_rrrrr extern unpack_varargs_int, L_ARG, nargs+1, TOP, MAX_INT_REGISTERS(ct) - reg.ints, rax - } - - | mov rax, rsp - | add rax, reg.off - | call_rrrrrr extern unpack_varargs_stack_skip, L_ARG, nargs+1, TOP, MAX_INT_REGISTERS(ct) - reg.ints, MAX_FLOAT_REGISTERS(ct) - reg.floats, rax - - reg.floats = MAX_FLOAT_REGISTERS(ct); - reg.ints = MAX_INT_REGISTERS(ct); -#else - |.else - | mov rax, rsp - | add rax, reg.off - | call_rrrr extern unpack_varargs_stack, L_ARG, nargs+1, TOP, rax - |.endif -#endif - } - - | mov64 rcx, perr - | mov eax, dword [rcx] - | call_r extern SetLastError, rax - - /* remove the stack space to call local functions */ - |.if X32WIN - | add rsp, 28 // SetLastError will have already popped 4 - |.else - | add rsp, 32 - |.endif - -#ifdef _WIN64 - |.if X64WIN - switch (reg.regs) { - case 4: - if (reg.is_float[3]) { - | movq xmm3, qword [rsp + 8*3] - } - if (reg.is_int[3]) { - | mov r9, [rsp + 8*3] - } - case 3: - if (reg.is_float[2]) { - | movq xmm2, qword [rsp + 8*2] - } - if (reg.is_int[2]) { - | mov r8, [rsp + 8*2] - } - case 2: - if (reg.is_float[1]) { - | movq xmm1, qword [rsp + 8*1] - } - if (reg.is_int[1]) { - | mov rdx, [rsp + 8*1] - } - case 1: - if (reg.is_float[0]) { - | movq xmm0, qword [rsp] - } - if (reg.is_int[0]) { - | mov rcx, [rsp] - } - case 0: - break; - } - - /* don't remove the space for the registers as we need 32 bytes of register overflow space */ - assert(REGISTER_STACK_SPACE(ct) == 32); - -#elif defined __amd64__ - |.elif X64 - switch (reg.floats) { - case 8: - | movq xmm7, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+7)] - case 7: - | movq xmm6, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+6)] - case 6: - | movq xmm5, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+5)] - case 5: - | movq xmm4, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+4)] - case 4: - | movq xmm3, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+3)] - case 3: - | movq xmm2, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+2)] - case 2: - | movq xmm1, qword [rsp + 8*(MAX_INT_REGISTERS(ct)+1)] - case 1: - | movq xmm0, qword [rsp + 8*(MAX_INT_REGISTERS(ct))] - case 0: - break; - } - - switch (reg.ints) { - case 6: - | mov r9, [rsp + 8*5] - case 5: - | mov r8, [rsp + 8*4] - case 4: - | mov rcx, [rsp + 8*3] - case 3: - | mov rdx, [rsp + 8*2] - case 2: - | mov rsi, [rsp + 8*1] - case 1: - | mov rdi, [rsp] - case 0: - break; - } - - | add rsp, REGISTER_STACK_SPACE(ct) -#else - |.else - if (ct->calling_convention == FAST_CALL) { - switch (reg.ints) { - case 2: - | mov edx, [rsp + 4] - case 1: - | mov ecx, [rsp] - case 0: - break; - } - - | add rsp, REGISTER_STACK_SPACE(ct) - } - |.endif -#endif - -#ifdef __amd64__ - if (ct->has_var_arg) { - /* al stores an upper limit on the number of float register, note that - * its allowed to be more than the actual number of float registers used as - * long as its 0-8 */ - |.if X64 and not X64WIN - | mov al, 8 - |.endif - } -#endif - - | call extern FUNCTION - | sub rsp, 48 // 32 to be able to call local functions, 16 so we can store some local variables - - /* note on windows X86 the stack may be only aligned to 4 (stdcall will - * have popped a multiple of 4 bytes), but we don't need 16 byte alignment on - * that platform - */ - - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference || mbr_ct->type == INTPTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - | mov [rsp+32], rax // save the pointer - | get_errno - | call_rrp extern push_cdata, L_ARG, lua_upvalueindex(num_upvals), mbr_ct - | mov rcx, [rsp+32] - | mov [rax], rcx // *(void**) cdata = val - | lua_return_arg - - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - | mov [rsp+32], rax // save the function pointer - | get_errno - | call_rrp extern push_cdata, L_ARG, lua_upvalueindex(num_upvals), mbr_ct - | mov rcx, [rsp+32] - | mov [rax], rcx // *(cfunction**) cdata = val - | lua_return_arg - break; - - case INT64_TYPE: -#if LUA_VERSION_NUM == 503 - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - | lua_return_ulong - } else { - | lua_return_long - } -#else - num_upvals++; - | // save the return value - |.if X64 - | mov [rsp+32], rax - |.else - | mov [rsp+36], edx // high - | mov [rsp+32], eax // low - |.endif - | - | get_errno - | call_rrp extern push_cdata, L_ARG, 0, mbr_ct - | - | // *(int64_t*) cdata = val - |.if X64 - | mov rcx, [rsp+32] - | mov [rax], rcx - |.else - | mov rcx, [rsp+36] - | mov rdx, [rsp+32] - | mov [rax+4], rcx - | mov [rax], rdx - |.endif - | - | lua_return_arg -#endif - break; - - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - |.if X64 - | // complex floats are returned as two floats packed into xmm0 - | movq qword [rsp+32], xmm0 - |.else - | // complex floats are returned as floats in eax and edx - | mov [rsp+32], eax - | mov [rsp+36], edx - |.endif - | - | get_errno - | call_rrp extern push_cdata, L_ARG, lua_upvalueindex(num_upvals), mbr_ct - | - | // ((complex_float*) cdata) = val - |.if X64 - | mov rcx, [rsp+32] - | mov [rax], rcx - |.else - | mov ecx, [rsp+32] - | mov [rax], ecx - | mov ecx, [rsp+36] - | mov [rax+4], ecx - |.endif - | - | lua_return_arg - break; - - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - |.if X64 - | // complex doubles are returned as xmm0 and xmm1 - | movq qword [rsp+40], xmm1 - | movq qword [rsp+32], xmm0 - | - | get_errno - | call_rrp extern push_cdata, L_ARG, lua_upvalueindex(num_upvals), mbr_ct - | - | // ((complex_double*) cdata)->real = val0 - | // ((complex_double*) cdata)->imag = val1 - | mov rcx, [rsp+40] - | mov [rax+8], rcx - | mov rcx, [rsp+32] - | mov [rax], rcx - | - |.else - | // On 32 bit we have already handled this by pushing a new cdata - | // and handing the cdata ptr in as the hidden first param, but - | // still need to add mbr_ct as an upval as its used earlier. - | // Hidden param was popped by called function, we need to realign. - | sub rsp, 4 - | get_errno - |.endif - | - | lua_return_arg - break; - - case VOID_TYPE: - lua_pop(L, 1); - | lua_return_void - break; - - case BOOL_TYPE: - lua_pop(L, 1); - | lua_return_bool - break; - - case INT8_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - | movzx eax, al - } else { - | movsx eax, al - } - | lua_return_int - break; - - case INT16_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - | movzx eax, ax - } else { - | movsx eax, ax - } - | lua_return_int - break; - - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - | lua_return_uint - } else { - | lua_return_int - } - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - |.if X64 - | cvtss2sd xmm0, xmm0 - |.endif - | lua_return_double - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - | lua_return_double - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, func, LUA_NOREF); - /* add a callback as an upval so that the jitted code gets cleaned up when - * the function gets gc'd */ - push_callback(L, f, func); - lua_pushcclosure(L, (lua_CFunction) f, num_upvals+1); - } -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call_x86.h b/Build/source/texk/web2c/luatexdir/luaffi/call_x86.h deleted file mode 100644 index 4611a3cec02..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/call_x86.h +++ /dev/null @@ -1,1172 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM x86 version 1.3.0 -** DO NOT EDIT! The original file is in "call_x86.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -static const unsigned char build_actionlist[1915] = { - 139,141,233,255,139,141,233,139,149,233,255,137,132,253,36,233,255,137,132, - 253,36,233,137,148,253,36,233,255,221,133,233,255,217,133,233,255,252,243, - 15,126,133,233,255,252,243,15,90,133,233,255,221,156,253,36,233,255,217,156, - 253,36,233,255,102,15,214,132,253,36,233,255,252,242,15,90,192,102,15,214, - 132,253,36,233,255,252,242,15,90,192,102,15,126,132,253,36,233,255,85,137, - 229,87,129,252,236,239,255,137,77,252,248,137,85,252,244,255,191,237,255, - 199,68,36,8,237,199,68,36,4,237,137,60,36,232,251,1,0,255,199,68,36,8,237, - 199,68,36,4,252,255,252,255,252,255,252,255,137,60,36,232,251,1,0,255,199, - 68,36,8,237,199,68,36,4,237,137,60,36,232,251,1,0,199,68,36,8,237,199,68, - 36,4,252,255,252,255,252,255,252,255,137,60,36,232,251,1,1,255,137,8,199, - 68,36,4,252,254,252,255,252,255,252,255,137,60,36,232,251,1,2,255,199,68, - 36,8,237,199,68,36,4,0,0,0,0,137,60,36,232,251,1,1,255,137,8,137,80,4,255, - 137,8,255,102,15,214,0,255,217,24,255,217,88,4,255,221,24,255,221,88,8,255, - 221,92,36,4,137,60,36,232,251,1,3,255,15,182,201,137,76,36,4,137,60,36,232, - 251,1,4,255,15,182,201,255,15,190,201,255,137,76,36,4,137,60,36,232,251,1, - 5,255,15,183,201,255,15,191,201,255,137,76,36,4,137,60,36,232,251,1,6,255, - 199,68,36,12,0,0,0,0,199,68,36,8,237,199,68,36,4,237,137,60,36,232,251,1, - 7,255,199,68,36,8,237,199,68,36,4,252,254,252,255,252,255,252,255,137,60, - 36,232,251,1,0,199,68,36,12,237,199,68,36,8,252,255,252,255,252,255,252,255, - 199,68,36,4,252,254,252,255,252,255,252,255,137,60,36,232,251,1,8,137,68, - 36,32,199,68,36,4,252,252,252,255,252,255,252,255,137,60,36,232,251,1,9,139, - 68,36,32,255,199,68,36,8,237,199,68,36,4,252,254,252,255,252,255,252,255, - 137,60,36,232,251,1,0,199,68,36,12,237,199,68,36,8,252,255,252,255,252,255, - 252,255,199,68,36,4,252,254,252,255,252,255,252,255,137,60,36,232,251,1,10, - 137,68,36,32,199,68,36,4,252,252,252,255,252,255,252,255,137,60,36,232,251, - 1,9,139,68,36,32,255,199,68,36,4,252,254,252,255,252,255,252,255,137,60,36, - 232,251,1,9,255,199,68,36,4,252,255,252,255,252,255,252,255,137,60,36,232, - 251,1,11,255,199,68,36,4,252,255,252,255,252,255,252,255,137,60,36,232,251, - 1,12,255,137,68,36,32,199,68,36,4,252,253,252,255,252,255,252,255,137,60, - 36,232,251,1,9,139,68,36,32,255,199,68,36,4,252,255,252,255,252,255,252,255, - 137,60,36,232,251,1,13,255,199,68,36,4,252,255,252,255,252,255,252,255,137, - 60,36,232,251,1,14,255,137,68,36,32,137,84,36,36,199,68,36,4,252,253,252, - 255,252,255,252,255,137,60,36,232,251,1,9,139,68,36,32,139,84,36,36,255,199, - 68,36,4,252,255,252,255,252,255,252,255,137,60,36,232,251,1,15,137,68,36, - 32,199,68,36,4,252,253,252,255,252,255,252,255,137,60,36,232,251,1,9,139, - 68,36,32,255,199,68,36,4,252,255,252,255,252,255,252,255,137,60,36,232,251, - 1,16,255,221,92,36,32,199,68,36,4,252,253,252,255,252,255,252,255,137,60, - 36,232,251,1,9,221,68,36,32,255,199,68,36,4,252,255,252,255,252,255,252,255, - 137,60,36,232,251,1,17,137,68,36,32,137,84,36,36,199,68,36,4,252,253,252, - 255,252,255,252,255,137,60,36,232,251,1,9,139,68,36,32,139,84,36,36,255,199, - 68,36,4,252,255,252,255,252,255,252,255,137,60,36,232,251,1,18,102,15,214, - 68,36,32,102,15,214,76,36,40,199,68,36,4,252,253,252,255,252,255,252,255, - 137,60,36,232,251,1,9,252,243,15,126,68,36,32,252,243,15,126,76,36,40,255, - 139,141,233,199,68,36,8,252,255,252,255,252,255,252,255,137,124,36,4,137, - 12,36,232,251,1,18,131,252,236,4,199,68,36,4,252,253,252,255,252,255,252, - 255,137,60,36,232,251,1,9,255,139,125,252,252,137,252,236,93,194,236,255, - 85,137,229,87,86,139,189,233,131,252,236,16,137,60,36,232,251,1,19,137,198, - 129,252,248,239,255,15,141,244,248,102,184,0,0,199,68,36,4,237,137,60,36, - 232,251,1,20,248,2,15,142,244,247,102,184,0,0,199,68,36,4,237,137,60,36,232, - 251,1,20,255,15,141,244,247,102,184,0,0,199,68,36,4,237,137,60,36,232,251, - 1,20,255,248,1,255,193,224,4,41,196,129,252,236,239,255,199,68,36,8,237,199, - 68,36,4,0,0,0,0,137,60,36,232,251,1,1,131,252,236,16,255,199,68,36,12,237, - 199,68,36,8,237,199,68,36,4,237,137,60,36,232,251,1,8,255,199,68,36,12,237, - 199,68,36,8,237,199,68,36,4,237,137,60,36,232,251,1,21,255,199,68,36,12,237, - 199,68,36,8,237,199,68,36,4,237,137,60,36,232,251,1,10,255,199,68,36,4,237, - 137,60,36,232,251,1,12,255,15,182,192,255,15,190,192,255,15,183,192,255,15, - 191,192,255,199,68,36,4,237,137,60,36,232,251,1,12,131,252,248,0,15,149,208, - 15,182,192,255,199,68,36,4,237,137,60,36,232,251,1,11,255,199,68,36,4,237, - 137,60,36,232,251,1,15,255,199,68,36,4,237,137,60,36,232,251,1,13,255,199, - 68,36,4,237,137,60,36,232,251,1,14,255,199,68,36,4,237,137,60,36,232,251, - 1,16,255,199,68,36,4,237,137,60,36,232,251,1,18,255,252,243,15,126,193,255, - 141,132,253,36,233,131,252,236,4,199,68,36,8,237,137,124,36,4,137,4,36,232, - 251,1,18,255,199,68,36,4,237,137,60,36,232,251,1,17,255,199,68,36,4,237,137, - 60,36,232,251,1,17,137,4,36,217,4,36,255,137,20,36,217,4,36,255,137,224,129, - 192,239,137,68,36,12,137,116,36,8,199,68,36,4,237,137,60,36,232,251,1,22, - 255,185,237,139,1,137,4,36,232,251,1,23,255,131,196,32,255,139,148,253,36, - 233,255,139,12,36,255,129,196,239,255,232,251,1,24,131,252,236,48,255,137, - 68,36,32,232,251,1,25,185,237,137,1,199,68,36,8,237,199,68,36,4,237,137,60, - 36,232,251,1,1,139,76,36,32,137,8,184,1,0,0,0,139,117,252,248,139,125,252, - 252,137,252,236,93,195,255,137,68,36,32,232,251,1,25,185,237,137,1,139,68, - 36,32,137,68,36,4,137,60,36,232,251,1,26,184,1,0,0,0,139,117,252,248,139, - 125,252,252,137,252,236,93,195,255,137,84,36,36,137,68,36,32,232,251,1,25, - 185,237,137,1,199,68,36,8,237,199,68,36,4,0,0,0,0,137,60,36,232,251,1,1,139, - 76,36,36,139,84,36,32,137,72,4,137,16,184,1,0,0,0,139,117,252,248,139,125, - 252,252,137,252,236,93,195,255,137,68,36,32,137,84,36,36,232,251,1,25,185, - 237,137,1,199,68,36,8,237,199,68,36,4,237,137,60,36,232,251,1,1,139,76,36, - 32,137,8,139,76,36,36,137,72,4,184,1,0,0,0,139,117,252,248,139,125,252,252, - 137,252,236,93,195,255,131,252,236,4,232,251,1,25,185,237,137,1,184,1,0,0, - 0,139,117,252,248,139,125,252,252,137,252,236,93,195,255,232,251,1,25,185, - 237,137,1,184,0,0,0,0,139,117,252,248,139,125,252,252,137,252,236,93,195, - 255,15,182,192,137,68,36,32,232,251,1,25,185,237,137,1,139,68,36,32,137,68, - 36,4,137,60,36,232,251,1,4,184,1,0,0,0,139,117,252,248,139,125,252,252,137, - 252,236,93,195,255,137,68,36,32,232,251,1,25,185,237,137,1,139,68,36,32,137, - 68,36,4,137,60,36,232,251,1,5,184,1,0,0,0,139,117,252,248,139,125,252,252, - 137,252,236,93,195,255,137,68,36,32,232,251,1,25,185,237,137,1,139,68,36, - 32,137,68,36,4,137,60,36,232,251,1,6,184,1,0,0,0,139,117,252,248,139,125, - 252,252,137,252,236,93,195,255,221,92,36,4,232,251,1,25,185,237,137,1,137, - 60,36,232,251,1,3,184,1,0,0,0,139,117,252,248,139,125,252,252,137,252,236, - 93,195,255 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "lua_rawgeti", - "push_cdata", - "lua_remove", - "lua_pushnumber", - "lua_pushboolean", - "push_int", - "push_uint", - "lua_callk", - "check_typed_pointer", - "lua_settop", - "check_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_uintptr", - "check_double", - "check_complex_float", - "check_complex_double", - "lua_gettop", - "luaL_error", - "check_typed_cfunction", - "unpack_varargs_stack", - "SetLastError", - "FUNCTION", - "GetLastError", - "lua_pushinteger", - (const char *)0 -}; - - - - - - - - - - - - - - - - - -#if defined _WIN64 || defined __amd64__ -#define JUMP_SIZE 14 -#else -#define JUMP_SIZE 4 -#endif - -#define MIN_BRANCH INT32_MIN -#define MAX_BRANCH INT32_MAX -#define BRANCH_OFF 4 - -static void compile_extern_jump(struct jit* jit, lua_State* L, cfunction func, uint8_t* code) -{ - /* The jump code is the function pointer followed by a stub to call the - * function pointer. The stub exists in 64 bit so we can jump to functions - * with an offset greater than 2 GB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state and dynasm doesn't support rip relative addressing. - * - * eg on 64 bit: - * 0-8: function ptr - * 8-14: jmp aword [rip-14] - * - * for 32 bit we only set the function ptr as it can always fit in a 32 - * bit displacement - */ -#if defined _WIN64 || defined __amd64__ - *(cfunction*) code = func; - code[8] = 0xFF; /* FF /4 operand for jmp */ - code[9] = 0x25; /* RIP displacement */ - *(int32_t*) &code[10] = -14; -#else - *(cfunction*) code = func; -#endif -} - -void compile_globals(struct jit* jit, lua_State* L) -{ - struct jit* Dst = jit; - int* perr = &jit->last_errno; - dasm_setup(Dst, build_actionlist); - - /* Note: since the return code uses EBP to reset the stack pointer, we - * don't have to track the amount of stack space used. It also means we - * can handle stdcall and cdecl with the same code. - */ - - /* Note the various call_* functions want 32 bytes of 16 byte aligned - * stack - */ - - compile(Dst, L, NULL, LUA_NOREF); -} - -int x86_return_size(lua_State* L, int usr, const struct ctype* ct) -{ - int ret = 0; - const struct ctype* mt; - - if (ct->calling_convention != C_CALL) { - size_t i; - size_t argn = lua_rawlen(L, usr); - for (i = 1; i <= argn; i++) { - lua_rawgeti(L, usr, (int) i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - ret += sizeof(void*); - } else { - switch (mt->type) { - case DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case INT64_TYPE: - ret += 8; - break; - case COMPLEX_DOUBLE_TYPE: - ret += 16; - break; - case INTPTR_TYPE: - ret += sizeof(intptr_t); - break; - case FUNCTION_PTR_TYPE: - ret += sizeof(cfunction); - break; - case BOOL_TYPE: - case FLOAT_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE: - ret += 4; - break; - default: - return luaL_error(L, "NYI - argument type"); - } - } - - lua_pop(L, 1); - } - } - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - ret += sizeof(void*); - } - lua_pop(L, 1); -#endif - - return ret; -} - -#ifdef _WIN64 -#define MAX_REGISTERS(ct) 4 /* rcx, rdx, r8, r9 */ - -#elif defined __amd64__ -#define MAX_INT_REGISTERS(ct) 6 /* rdi, rsi, rdx, rcx, r8, r9 */ -#define MAX_FLOAT_REGISTERS(ct) 8 /* xmm0-7 */ - -#else -#define MAX_INT_REGISTERS(ct) ((ct)->calling_convention == FAST_CALL ? 2 /* ecx, edx */ : 0) -#define MAX_FLOAT_REGISTERS(ct) 0 -#endif - -struct reg_alloc { -#ifdef _WIN64 - int regs; - int is_float[4]; - int is_int[4]; -#else - int floats; - int ints; -#endif - int off; -}; - -#ifdef _WIN64 -#define REGISTER_STACK_SPACE(ct) (4*8) -#elif defined __amd64__ -#define REGISTER_STACK_SPACE(ct) (14*8) -#else -#define REGISTER_STACK_SPACE(ct) ALIGN_UP(((ct)->calling_convention == FAST_CALL ? 2*4 : 0), 15) -#endif - -/* Fastcall: - * Uses ecx, edx as first two int registers - * Everything else on stack (include 64bit ints) - * No overflow stack space - * Pops the stack before returning - * Returns int in eax, float in ST0 - * We use the same register allocation logic as posix x64 with 2 int regs and 0 float regs - */ - -static void get_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ - /* grab the register from the shadow space */ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - dasm_put(Dst, 0, 16 + 8*reg->regs); - reg->regs++; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 0, - 80 - 8*reg->ints); - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 0, - 8 - 4*reg->ints); - reg->ints++; - } -#endif - else if (is_int64) { - dasm_put(Dst, 4, reg->off, reg->off + 4); - reg->off += 8; - } else { - dasm_put(Dst, 0, reg->off); - reg->off += 4; - } -} - -static void add_int(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_int64) -{ -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - dasm_put(Dst, 11, 32 + 8*(reg->regs)); - reg->is_int[reg->regs++] = 1; - } -#elif __amd64__ - if (reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 11, 32 + 8*reg->ints); - reg->ints++; - } -#else - if (!is_int64 && reg->ints < MAX_INT_REGISTERS(ct)) { - dasm_put(Dst, 11, 32 + 4*reg->ints); - reg->ints++; - } -#endif - else { -#if defined _WIN64 || defined __amd64__ - if (reg->off % 8 != 0) { - reg->off += 8 - (reg->off % 8); - } -#endif - if (is_int64) { - dasm_put(Dst, 17, reg->off, reg->off + 4); - reg->off += 8; - } else { - dasm_put(Dst, 11, reg->off); - reg->off += 4; - } - } -} - -static void get_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - dasm_put(Dst, 28, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 32, reg->off); - reg->off += 4; - } -#else - int off; - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - off = -16 - 8*reg->regs; - reg->regs++; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - off = -16 - 8*reg->floats; - reg->floats++; - } -#endif - else { - off = reg->off; - reg->off += is_double ? 8 : 4; - } - - if (is_double) { - dasm_put(Dst, 36, off); - } else { - dasm_put(Dst, 43, off); - } -#endif -} - -static void add_float(Dst_DECL, const struct ctype* ct, struct reg_alloc* reg, int is_double) -{ -#if !defined _WIN64 && !defined __amd64__ - assert(MAX_FLOAT_REGISTERS(ct) == 0); - if (is_double) { - dasm_put(Dst, 50, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 56, reg->off); - reg->off += 4; - } -#else - -#ifdef _WIN64 - if (reg->regs < MAX_REGISTERS(ct)) { - if (is_double) { - dasm_put(Dst, 62, 32 + 8*(reg->regs)); - } else { - dasm_put(Dst, 70, 32 + 8*(reg->regs)); - } - reg->is_float[reg->regs++] = 1; - } -#else - if (reg->floats < MAX_FLOAT_REGISTERS(ct)) { - if (is_double) { - dasm_put(Dst, 62, 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)); - } else { - dasm_put(Dst, 70, 32 + 8*(MAX_INT_REGISTERS(ct) + reg->floats)); - } - reg->floats++; - } -#endif - - else if (is_double) { - dasm_put(Dst, 62, reg->off); - reg->off += 8; - } else { - dasm_put(Dst, 83, reg->off); - reg->off += 4; - } -#endif -} - -#if defined _WIN64 || defined __amd64__ -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 1) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 1) -#else -#define add_pointer(jit, ct, reg) add_int(jit, ct, reg, 0) -#define get_pointer(jit, ct, reg) get_int(jit, ct, reg, 0) -#endif - -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct) -{ - int i, nargs; - cfunction* pf; - struct ctype ct2 = *ct; - const struct ctype* mt; - struct reg_alloc reg; - int num_upvals = 0; - int top = lua_gettop(L); - struct jit* Dst = get_jit(L); - int ref; - int hidden_arg_off = 0; - - ct_usr = lua_absindex(L, ct_usr); - fidx = lua_absindex(L, fidx); - - assert(lua_isnil(L, fidx) || lua_isfunction(L, fidx)); - - memset(®, 0, sizeof(reg)); -#ifdef _WIN64 - reg.off = 16 + REGISTER_STACK_SPACE(ct); /* stack registers are above the shadow space */ -#elif __amd64__ - reg.off = 16; -#else - reg.off = 8; -#endif - - dasm_setup(Dst, build_actionlist); - - // add a table to store ctype and function upvalues - // callback_set assumes the first value is the lua function - nargs = (int) lua_rawlen(L, ct_usr); - lua_newtable(L); - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - - if (ct->has_var_arg) { - luaL_error(L, "can't create callbacks with varargs"); - } - - // setup a stack frame to hold args for the call into lua_call - - dasm_put(Dst, 96, 4 + 16 + 32 + REGISTER_STACK_SPACE(ct)); - if (ct->calling_convention == FAST_CALL) { - dasm_put(Dst, 105); - } - - // hardcode the lua_State* value into the assembly - dasm_put(Dst, 114, L); - - /* get the upval table */ - dasm_put(Dst, 117, ref, LUA_REGISTRYINDEX); - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - assert(num_upvals == CALLBACK_FUNC_USR_IDX); - dasm_put(Dst, 135, num_upvals); - -#if !defined _WIN64 && !defined __amd64__ - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers && !mt->is_reference && mt->type == COMPLEX_DOUBLE_TYPE) { - hidden_arg_off = reg.off; - reg.off += sizeof(void*); - } - lua_pop(L, 1); -#else - (void) hidden_arg_off; -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - /* on the lua stack in the callback: - * upval tbl, lua func, i-1 args - */ - dasm_put(Dst, 160, num_upvals-1, -i-1, mt); - get_pointer(Dst, ct, ®); - dasm_put(Dst, 202); - } else { - switch (mt->type) { - case INT64_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - dasm_put(Dst, 224, mt); - get_int(Dst, ct, ®, 1); - dasm_put(Dst, 245); - break; - - case INTPTR_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* mt */ - lua_pop(L, 1); - dasm_put(Dst, 224, mt); - get_pointer(Dst, ct, ®); - dasm_put(Dst, 251); - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if defined _WIN64 || defined __amd64__ - /* complex floats are two floats packed into a double */ - dasm_put(Dst, 224, mt); - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 254); -#else - /* complex floats are real followed by imag on the stack */ - dasm_put(Dst, 224, mt); - get_float(Dst, ct, ®, 0); - dasm_put(Dst, 259); - get_float(Dst, ct, ®, 0); - dasm_put(Dst, 262); -#endif - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 224, mt); - /* real */ - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 266); - /* imag */ - get_float(Dst, ct, ®, 1); - dasm_put(Dst, 269); - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - get_float(Dst, ct, ®, mt->type == DOUBLE_TYPE); - dasm_put(Dst, 273); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - dasm_put(Dst, 285); - break; - - case INT8_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 300); - } else { - dasm_put(Dst, 304); - } - dasm_put(Dst, 308); - break; - - case INT16_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 320); - } else { - dasm_put(Dst, 324); - } - dasm_put(Dst, 308); - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - get_int(Dst, ct, ®, 0); - if (mt->is_unsigned) { - dasm_put(Dst, 328); - } else { - dasm_put(Dst, 308); - } - break; - - default: - luaL_error(L, "NYI: callback arg type"); - } - } - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - dasm_put(Dst, 340, (mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0, nargs); - - // Unpack the return argument if not "void", also clean-up the lua stack - // to remove the return argument and bind table. Use lua_settop rather - // than lua_pop as lua_pop is implemented as a macro. - if (mt->pointers || mt->is_reference) { - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 366, num_upvals-1, mt); - - } else { - switch (mt->type) { - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 454, num_upvals-1, mt); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 542); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - if (mt->is_unsigned) { - dasm_put(Dst, 562); - } else { - dasm_put(Dst, 582); - } - dasm_put(Dst, 602); - break; - - case INT64_TYPE: - lua_pop(L, 1); - - if (mt->is_unsigned) { - dasm_put(Dst, 630); - } else { - dasm_put(Dst, 650); - } - - dasm_put(Dst, 670); - break; - - case INTPTR_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 706); - break; - - case FLOAT_TYPE: - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 753); - if (mt->type == FLOAT_TYPE) { - } else { - } - dasm_put(Dst, 773); - break; - - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit complex floats are two floats packed into a double, - * on 32 bit returned complex floats use eax and edx */ - dasm_put(Dst, 801); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); -#if !defined HAVE_COMPLEX - luaL_error(L, "ffi lib compiled without complex number support"); -#endif - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored which is popped by the called - * function */ -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 856); -#else - dasm_put(Dst, 921, hidden_arg_off); -#endif - break; - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 971, x86_return_size(L, ct_usr, ct)); - - lua_pop(L, 1); /* upval table - already in registry */ - assert(lua_gettop(L) == top); - - ct2.is_jitted = 1; - pf = (cfunction*) push_cdata(L, ct_usr, &ct2); - *pf = compile(Dst, L, NULL, ref); - - assert(lua_gettop(L) == top + 1); - - return *pf; -} - -void compile_function(lua_State* L, cfunction func, int ct_usr, const struct ctype* ct) -{ - size_t i, nargs; - int num_upvals; - const struct ctype* mbr_ct; - struct jit* Dst = get_jit(L); - struct reg_alloc reg; - void* p; - int top = lua_gettop(L); - int* perr = &Dst->last_errno; - - ct_usr = lua_absindex(L, ct_usr); - - memset(®, 0, sizeof(reg)); - reg.off = 32 + REGISTER_STACK_SPACE(ct); - - dasm_setup(Dst, build_actionlist); - - p = push_cdata(L, ct_usr, ct); - *(cfunction*) p = func; - num_upvals = 1; - - nargs = lua_rawlen(L, ct_usr); - - if (ct->calling_convention != C_CALL && ct->has_var_arg) { - luaL_error(L, "vararg is only allowed with the c calling convention"); - } - - dasm_put(Dst, 982, 8, nargs); - if (!ct->has_var_arg) { - dasm_put(Dst, 1008, (ptrdiff_t)("too few arguments"), (ptrdiff_t)("too many arguments")); - } else { - dasm_put(Dst, 1051, (ptrdiff_t)("too few arguments")); - } - - dasm_put(Dst, 1072); - - /* no need to zero extend eax returned by lua_gettop to rax as x86-64 - * preguarentees that the upper 32 bits will be zero */ - dasm_put(Dst, 1075, 32 + REGISTER_STACK_SPACE(ct)); - -#if !defined _WIN64 && !defined __amd64__ - /* Returned complex doubles require a hidden first parameter where the - * data is stored, which is popped by the calling code. */ - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - if (!mbr_ct->pointers && !mbr_ct->is_reference && mbr_ct->type == COMPLEX_DOUBLE_TYPE) { - /* we can allocate more space for arguments as long as no add_* - * function has been called yet, mbr_ct will be added as an upvalue in - * the return processing later */ - dasm_put(Dst, 1085, mbr_ct); - add_pointer(Dst, ct, ®); - } - lua_pop(L, 1); -#endif - - for (i = 1; i <= nargs; i++) { - lua_rawgeti(L, ct_usr, (int) i); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1110, mbr_ct, lua_upvalueindex(num_upvals), i); - add_pointer(Dst, ct, ®); - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1133, mbr_ct, lua_upvalueindex(num_upvals), i); - add_pointer(Dst, ct, ®); - break; - - case ENUM_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1156, mbr_ct, lua_upvalueindex(num_upvals), i); - add_int(Dst, ct, ®, 0); - break; - - case INT8_TYPE: - dasm_put(Dst, 1179, i); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1192); - } else { - dasm_put(Dst, 1196); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT16_TYPE: - dasm_put(Dst, 1179, i); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1200); - } else { - dasm_put(Dst, 1204); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - dasm_put(Dst, 1208, i); - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INT32_TYPE: - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1231, i); - } else { - dasm_put(Dst, 1179, i); - } - add_int(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case INTPTR_TYPE: - dasm_put(Dst, 1244, i); - add_pointer(Dst, ct, ®); - lua_pop(L, 1); - break; - - case INT64_TYPE: - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1257, i); - } else { - dasm_put(Dst, 1270, i); - } - add_int(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case DOUBLE_TYPE: - dasm_put(Dst, 1283, i); - add_float(Dst, ct, ®, 1); - lua_pop(L, 1); - break; - - case COMPLEX_DOUBLE_TYPE: - /* on 64 bit, returned complex doubles use xmm0, xmm1, on 32 bit - * there is a hidden first parameter that points to 16 bytes where - * the returned arg is stored (this is popped by the called - * function) */ -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 1296, i); - add_float(Dst, ct, ®, 1); - dasm_put(Dst, 1309); - add_float(Dst, ct, ®, 1); -#else - dasm_put(Dst, 1315, reg.off, i); - reg.off += 16; -#endif - lua_pop(L, 1); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 1283, i); - add_float(Dst, ct, ®, 0); - lua_pop(L, 1); - break; - - case COMPLEX_FLOAT_TYPE: -#if defined _WIN64 || defined __amd64__ - dasm_put(Dst, 1341, i); - /* complex floats are two floats packed into a double */ - add_float(Dst, ct, ®, 1); -#else - /* returned complex floats use eax and edx */ - dasm_put(Dst, 1354, i); - add_float(Dst, ct, ®, 0); - dasm_put(Dst, 1373); - add_float(Dst, ct, ®, 0); -#endif - lua_pop(L, 1); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { -#ifdef _WIN64 - if (reg.regs < MAX_REGISTERS(ct)) { - assert(reg.regs == nargs); - } else { - } - - for (i = nargs; i < MAX_REGISTERS(ct); i++) { - reg.is_int[i] = reg.is_float[i] = 1; - } - reg.regs = MAX_REGISTERS(ct); -#elif defined __amd64__ - if (reg.floats < MAX_FLOAT_REGISTERS(ct)) { - } - - if (reg.ints < MAX_INT_REGISTERS(ct)) { - } - - - reg.floats = MAX_FLOAT_REGISTERS(ct); - reg.ints = MAX_INT_REGISTERS(ct); -#else - dasm_put(Dst, 1380, reg.off, nargs+1); -#endif - } - - dasm_put(Dst, 1406, perr); - - /* remove the stack space to call local functions */ - dasm_put(Dst, 1418); - -#ifdef _WIN64 - switch (reg.regs) { - case 4: - if (reg.is_float[3]) { - } - if (reg.is_int[3]) { - } - case 3: - if (reg.is_float[2]) { - } - if (reg.is_int[2]) { - } - case 2: - if (reg.is_float[1]) { - } - if (reg.is_int[1]) { - } - case 1: - if (reg.is_float[0]) { - } - if (reg.is_int[0]) { - } - case 0: - break; - } - - /* don't remove the space for the registers as we need 32 bytes of register overflow space */ - assert(REGISTER_STACK_SPACE(ct) == 32); - -#elif defined __amd64__ - switch (reg.floats) { - case 8: - case 7: - case 6: - case 5: - case 4: - case 3: - case 2: - case 1: - case 0: - break; - } - - switch (reg.ints) { - case 6: - case 5: - case 4: - case 3: - case 2: - case 1: - case 0: - break; - } - -#else - if (ct->calling_convention == FAST_CALL) { - switch (reg.ints) { - case 2: - dasm_put(Dst, 1422, 4); - case 1: - dasm_put(Dst, 1428); - case 0: - break; - } - - dasm_put(Dst, 1432, REGISTER_STACK_SPACE(ct)); - } -#endif - -#ifdef __amd64__ - if (ct->has_var_arg) { - /* al stores an upper limit on the number of float register, note that - * its allowed to be more than the actual number of float registers used as - * long as its 0-8 */ - } -#endif - - dasm_put(Dst, 1436); - - /* note on windows X86 the stack may be only aligned to 4 (stdcall will - * have popped a multiple of 4 bytes), but we don't need 16 byte alignment on - * that platform - */ - - lua_rawgeti(L, ct_usr, 0); - mbr_ct = (const struct ctype*) lua_touserdata(L, -1); - - if (mbr_ct->pointers || mbr_ct->is_reference || mbr_ct->type == INTPTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1445, perr, mbr_ct, lua_upvalueindex(num_upvals)); - - } else { - switch (mbr_ct->type) { - case FUNCTION_PTR_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1445, perr, mbr_ct, lua_upvalueindex(num_upvals)); - break; - - case INT64_TYPE: -#if LUA_VERSION_NUM == 503 - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1499, perr); - } else { - dasm_put(Dst, 1499, perr); - } -#else - num_upvals++; - dasm_put(Dst, 1545, perr, mbr_ct); -#endif - break; - - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1613, perr, mbr_ct, lua_upvalueindex(num_upvals)); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 1678, perr); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1709, perr); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1736, perr); - break; - - case INT8_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1192); - } else { - dasm_put(Dst, 1196); - } - dasm_put(Dst, 1785, perr); - break; - - case INT16_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1200); - } else { - dasm_put(Dst, 1204); - } - dasm_put(Dst, 1785, perr); - break; - - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - if (mbr_ct->is_unsigned) { - dasm_put(Dst, 1831, perr); - } else { - dasm_put(Dst, 1785, perr); - } - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1877, perr); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 1877, perr); - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, func, LUA_NOREF); - /* add a callback as an upval so that the jitted code gets cleaned up when - * the function gets gc'd */ - push_callback(L, f, func); - lua_pushcclosure(L, (lua_CFunction) f, num_upvals+1); - } -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/ctype.c b/Build/source/texk/web2c/luatexdir/luaffi/ctype.c deleted file mode 100644 index f477ea5bc31..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/ctype.c +++ /dev/null @@ -1,274 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#include "ffi.h" - -static int to_define_key; - -static void update_on_definition(lua_State* L, int ct_usr, int ct_idx) -{ - ct_usr = lua_absindex(L, ct_usr); - ct_idx = lua_absindex(L, ct_idx); - - lua_pushlightuserdata(L, &to_define_key); - lua_rawget(L, ct_usr); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop the nil */ - - /* {} */ - lua_newtable(L); - - /* {__mode='k'} */ - lua_newtable(L); - lua_pushliteral(L, "k"); - lua_setfield(L, -2, "__mode"); - - /* setmetatable({}, {__mode='k'}) */ - lua_setmetatable(L, -2); - - /* usr[TO_UPDATE_KEY] = setmetatable({}, {__mode='k'}) */ - lua_pushlightuserdata(L, &to_define_key); - lua_pushvalue(L, -2); - lua_rawset(L, ct_usr); - - /* leave the table on the stack */ - } - - /* to_update[ctype or cdata] = true */ - lua_pushvalue(L, ct_idx); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - - /* pop the to_update table */ - lua_pop(L, 1); -} - -void set_defined(lua_State* L, int ct_usr, struct ctype* ct) -{ - ct_usr = lua_absindex(L, ct_usr); - - ct->is_defined = 1; - - /* update ctypes and cdatas that were created before the definition came in */ - lua_pushlightuserdata(L, &to_define_key); - lua_rawget(L, ct_usr); - - if (!lua_isnil(L, -1)) { - lua_pushnil(L); - - while (lua_next(L, -2)) { - struct ctype* upd = (struct ctype*) lua_touserdata(L, -2); - upd->base_size = ct->base_size; - upd->align_mask = ct->align_mask; - upd->is_defined = 1; - upd->is_variable_struct = ct->is_variable_struct; - upd->variable_increment = ct->variable_increment; - assert(!upd->variable_size_known); - lua_pop(L, 1); - } - - lua_pop(L, 1); - /* usr[TO_UPDATE_KEY] = nil */ - lua_pushlightuserdata(L, &to_define_key); - lua_pushnil(L); - lua_rawset(L, ct_usr); - } else { - lua_pop(L, 1); - } -} - -struct ctype* push_ctype(lua_State* L, int ct_usr, const struct ctype* ct) -{ - struct ctype* ret; - ct_usr = lua_absindex(L, ct_usr); - - ret = (struct ctype*) lua_newuserdata(L, sizeof(struct ctype)); - *ret = *ct; - - push_upval(L, &ctype_mt_key); - lua_setmetatable(L, -2); - -#if LUA_VERSION_NUM == 501 - if (!ct_usr || lua_isnil(L, ct_usr)) { - push_upval(L, &niluv_key); - lua_setfenv(L, -2); - } -#endif - - if (ct_usr && !lua_isnil(L, ct_usr)) { - lua_pushvalue(L, ct_usr); - lua_setuservalue(L, -2); - } - - if (!ct->is_defined && ct_usr && !lua_isnil(L, ct_usr)) { - update_on_definition(L, ct_usr, -1); - } - - return ret; -} - -size_t ctype_size(lua_State* L, const struct ctype* ct) -{ - if (ct->pointers - ct->is_array) { - return sizeof(void*) * (ct->is_array ? ct->array_size : 1); - - } else if (!ct->is_defined || ct->type == VOID_TYPE) { - return luaL_error(L, "can't calculate size of an undefined type"); - - } else if (ct->variable_size_known) { - assert(ct->is_variable_struct && !ct->is_array); - return ct->base_size + ct->variable_increment; - - } else if (ct->is_variable_array || ct->is_variable_struct) { - return luaL_error(L, "internal error: calc size of variable type with unknown size"); - - } else { - return ct->base_size * (ct->is_array ? ct->array_size : 1); - } -} - -void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct) -{ - struct cdata* cd; - size_t sz = ct->is_reference ? sizeof(void*) : ctype_size(L, ct); - ct_usr = lua_absindex(L, ct_usr); - - /* This is to stop valgrind from complaining. Bitfields are accessed in 8 - * byte chunks so that the code doesn't have to deal with different access - * patterns, but this means that occasionally it will read past the end of - * the struct. As its not setting the bits past the end (only reading and - * then writing the bits back) and the read is aligned its a non-issue, - * but valgrind complains nonetheless. - */ - if (ct->has_bitfield) { - sz = ALIGN_UP(sz, 7); - } - - cd = (struct cdata*) lua_newuserdata(L, sizeof(struct cdata) + sz); - *(struct ctype*) &cd->type = *ct; - memset(cd+1, 0, sz); - - /* TODO: handle cases where lua_newuserdata returns a pointer that is not - * aligned */ -#if 0 - assert((uintptr_t) (cd + 1) % 8 == 0); -#endif - -#if LUA_VERSION_NUM == 501 - if (!ct_usr || lua_isnil(L, ct_usr)) { - push_upval(L, &niluv_key); - lua_setfenv(L, -2); - } -#endif - - if (ct_usr && !lua_isnil(L, ct_usr)) { - lua_pushvalue(L, ct_usr); - lua_setuservalue(L, -2); - } - - push_upval(L, &cdata_mt_key); - lua_setmetatable(L, -2); - - if (!ct->is_defined && ct_usr && !lua_isnil(L, ct_usr)) { - update_on_definition(L, ct_usr, -1); - } - - return cd+1; -} - -void push_callback(lua_State* L, cfunction luafunc, cfunction cfunc) -{ - cfunction* pf = (cfunction*) lua_newuserdata(L, 2 * sizeof(cfunction)); - pf[0] = luafunc; - pf[1] = cfunc; - - push_upval(L, &callback_mt_key); - lua_setmetatable(L, -2); -} - -/* returns the value as a ctype, pushes the user value onto the stack */ -void check_ctype(lua_State* L, int idx, struct ctype* ct) -{ - if (lua_isstring(L, idx)) { - struct parser P; - P.line = 1; - P.prev = P.next = lua_tostring(L, idx); - P.align_mask = DEFAULT_ALIGN_MASK; - parse_type(L, &P, ct); - parse_argument(L, &P, -1, ct, NULL, NULL); - lua_remove(L, -2); /* remove the user value from parse_type */ - - } else if (lua_getmetatable(L, idx)) { - if (!equals_upval(L, -1, &ctype_mt_key) - && !equals_upval(L, -1, &cdata_mt_key)) { - goto err; - } - - lua_pop(L, 1); /* pop the metatable */ - *ct = *(struct ctype*) lua_touserdata(L, idx); - lua_getuservalue(L, idx); - - } else { - goto err; - } - - return; - -err: - luaL_error(L, "expected cdata, ctype or string for arg #%d", idx); -} - -/* to_cdata returns the struct cdata* and pushes the user value onto the - * stack. If the index is not a ctype then ct is set to the zero value such - * that ct->type is INVALID_TYPE, a nil is pushed, and NULL is returned. */ -void* to_cdata(lua_State* L, int idx, struct ctype* ct) -{ - struct cdata* cd; - - memset(ct, 0, sizeof(struct ctype)); - if (!lua_isuserdata(L, idx) || !lua_getmetatable(L, idx)) { - lua_pushnil(L); - return NULL; - } - - if (!equals_upval(L, -1, &cdata_mt_key)) { - lua_pop(L, 1); /* mt */ - lua_pushnil(L); - return NULL; - } - - lua_pop(L, 1); /* mt */ - cd = (struct cdata*) lua_touserdata(L, idx); - - if (!cd) {lua_pushnil(L);return NULL;} - *ct = cd->type; - lua_getuservalue(L, idx); - - if (ct->is_reference) { - return *(void**) (cd+1); - - } else if (ct->pointers && !ct->is_array) { - return *(void**) (cd+1); - - } else { - return cd + 1; - } -} - -/* check_cdata returns the struct cdata* and pushes the user value onto the - * stack. Also dereferences references. */ -void* check_cdata(lua_State* L, int idx, struct ctype* ct) -{ - void* p = to_cdata(L, idx, ct); - if (ct->type == INVALID_TYPE) { - luaL_error(L, "expected cdata for arg #%d", idx); - } - return p; -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_arm.h b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_arm.h deleted file mode 100644 index 71a4979193f..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_arm.h +++ /dev/null @@ -1,455 +0,0 @@ -/* -** DynASM ARM encoding engine. -** Copyright (C) 2005-2011 Mike Pall. All rights reserved. -** Released under the MIT/X license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "arm" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. */ -enum { - DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, - /* The following actions need a buffer position. */ - DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, - /* The following actions also have an argument. */ - DASM_REL_PC, DASM_LABEL_PC, - DASM_LONG, DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, - DASM__MAX -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_REL 0x15000000 -#define DASM_S_UNDEF_LG 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned int *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -static int dasm_imm12(unsigned int n) -{ - int i; - for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30)) - if (n <= 255) return (int)(n + (i << 8)); - return -1; -} - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - if (action >= DASM__MAX) { - ofs += 4; - } else { - int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; - switch (action) { - case DASM_STOP: goto stop; - case DASM_SECTION: - n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); - D->section = &D->sections[n]; goto stop; - case DASM_ESC: p++; ofs += 4; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; - case DASM_REL_LG: - n = (ins & 2047) - 10; pl = D->lglabels + n; - if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ - pl += 10; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - break; - case DASM_LABEL_LG: - pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; - } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_LONG: - ofs += 4; - b[pos++] = n; - break; - case DASM_IMM: - case DASM_IMM16: -#ifdef DASM_CHECKS - CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); - if ((ins & 0x8000)) - CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); - else - CK((n>>((ins>>5)&31)) == 0, RANGE_I); -#endif - b[pos++] = n; - break; - case DASM_IMML8: - case DASM_IMML12: - CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) : - (((-n)>>((ins>>5)&31)) == 0), RANGE_I); - b[pos++] = n; - break; - case DASM_IMM12: - CK(dasm_imm12((unsigned int)n) != -1, RANGE_I); - b[pos++] = n; - break; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: p++; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; - case DASM_REL_LG: case DASM_REL_PC: pos++; break; - case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; - case DASM_LONG: case DASM_IMM: case DASM_IMM12: case DASM_IMM16: - case DASM_IMML8: case DASM_IMML12: pos++; break; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) -#else -#define CK(x, st) ((void)0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - char *base = (char *)buffer; - unsigned int *cp = (unsigned int *)buffer; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: *cp++ = *p++; break; - case DASM_REL_EXT: - n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048)); - goto patchrel; - case DASM_ALIGN: - ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; - break; - case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); - case DASM_REL_PC: - CK(n >= 0, UNDEF_PC); - n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4; - patchrel: - if ((ins & 0x800) == 0) { - CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL); - cp[-1] |= ((n >> 2) & 0x00ffffff); - } else if ((ins & 0x1000)) { - CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL); - goto patchimml8; - } else { - CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL); - goto patchimml12; - } - break; - case DASM_LABEL_LG: - ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); - break; - case DASM_LABEL_PC: break; - case DASM_LONG: - *cp++ = n; - break; - case DASM_IMM: - cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31); - break; - case DASM_IMM12: - cp[-1] |= dasm_imm12((unsigned int)n); - break; - case DASM_IMM16: - cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); - break; - case DASM_IMML8: patchimml8: - cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : - ((-n & 0x0f) | ((-n & 0xf0) << 4)); - break; - case DASM_IMML12: patchimml12: - cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); - break; - default: *cp++ = ins; break; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != (char *)cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} -#undef CK - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(D->section-D->sections); - return D->status; -} -#endif - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_arm.lua b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_arm.lua deleted file mode 100644 index a54230db370..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_arm.lua +++ /dev/null @@ -1,952 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM ARM module. --- --- Copyright (C) 2005-2011 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - --- Module information: -local _info = { - arch = "arm", - description = "DynASM ARM module", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, setmetatable, rawget = assert, setmetatable, rawget -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub -local concat, sort, insert = table.concat, table.sort, table.insert - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - "STOP", "SECTION", "ESC", "REL_EXT", - "ALIGN", "REL_LG", "LABEL_LG", - "REL_PC", "LABEL_PC", "LONG", "IMM", "IMM12", "IMM16", "IMML8", "IMML12", -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number. -local map_action = {} -for n,name in ipairs(action_names) do - map_action[name] = n-1 -end - --- Action list buffer. -local actlist = {} - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Return 8 digit hex number. -local function tohex(x) - return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. -end - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - if nn == 0 then nn = 1; actlist[0] = map_action.STOP end - out:write("static const unsigned int ", name, "[", nn, "] = {\n") - for i = 1,nn-1 do - assert(out:write("0x", tohex(actlist[i]), ",\n")) - end - assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) -end - ------------------------------------------------------------------------------- - --- Add word to action list. -local function wputxw(n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, val, a, num) - local w = assert(map_action[action], "bad action name `"..action.."'") - wputxw(w * 0x10000 + (val or 0)) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - if #actlist == actargs[1] then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped word. -local function wputw(n) - if n <= 0x000fffff then waction("ESC") end - wputxw(n) -end - --- Reserve position for word. -local function wpos() - local pos = #actlist+1 - actlist[pos] = "" - return pos -end - --- Store word to reserved position. -local function wputpos(pos, n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - if n <= 0x000fffff then - insert(actlist, pos+1, n) - n = map_action.ESC * 0x10000 - end - actlist[pos] = n -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 20 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end - local n = next_global - if n > 2047 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=20,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=20,next_global-1 do - out:write(" ", prefix, t[i], ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=20,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = 0 -local map_extern_ = {} -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n > 2047 then werror("too many extern labels") end - next_extern = n + 1 - t[name] = n - map_extern_[n] = name - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - out:write("Extern labels:\n") - for i=0,next_extern-1 do - out:write(format(" %s\n", map_extern_[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - out:write("static const char *const ", name, "[] = {\n") - for i=0,next_extern-1 do - out:write(" \"", map_extern_[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. - --- Ext. register name -> int. name. -local map_archdef = { sp = "r13", lr = "r14", pc = "r15", } - --- Int. register name -> ext. name. -local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", } - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for Dt... macros). - --- Reverse defines for registers. -function _M.revdef(s) - return map_reg_rev[s] or s -end - -local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, } - -local map_cond = { - eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7, - hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14, - hs = 2, lo = 3, -} - ------------------------------------------------------------------------------- - --- Template strings for ARM instructions. -local map_op = { - -- Basic data processing instructions. - and_3 = "e0000000DNPs", - eor_3 = "e0200000DNPs", - sub_3 = "e0400000DNPs", - rsb_3 = "e0600000DNPs", - add_3 = "e0800000DNPs", - adc_3 = "e0a00000DNPs", - sbc_3 = "e0c00000DNPs", - rsc_3 = "e0e00000DNPs", - tst_2 = "e1100000NP", - teq_2 = "e1300000NP", - cmp_2 = "e1500000NP", - cmn_2 = "e1700000NP", - orr_3 = "e1800000DNPs", - mov_2 = "e1a00000DPs", - bic_3 = "e1c00000DNPs", - mvn_2 = "e1e00000DPs", - - and_4 = "e0000000DNMps", - eor_4 = "e0200000DNMps", - sub_4 = "e0400000DNMps", - rsb_4 = "e0600000DNMps", - add_4 = "e0800000DNMps", - adc_4 = "e0a00000DNMps", - sbc_4 = "e0c00000DNMps", - rsc_4 = "e0e00000DNMps", - tst_3 = "e1100000NMp", - teq_3 = "e1300000NMp", - cmp_3 = "e1500000NMp", - cmn_3 = "e1700000NMp", - orr_4 = "e1800000DNMps", - mov_3 = "e1a00000DMps", - bic_4 = "e1c00000DNMps", - mvn_3 = "e1e00000DMps", - - lsl_3 = "e1a00000DMws", - lsr_3 = "e1a00020DMws", - asr_3 = "e1a00040DMws", - ror_3 = "e1a00060DMws", - rrx_2 = "e1a00060DMs", - - -- Multiply and multiply-accumulate. - mul_3 = "e0000090NMSs", - mla_4 = "e0200090NMSDs", - umaal_4 = "e0400090DNMSs", -- v6 - mls_4 = "e0600090DNMSs", -- v6T2 - umull_4 = "e0800090DNMSs", - umlal_4 = "e0a00090DNMSs", - smull_4 = "e0c00090DNMSs", - smlal_4 = "e0e00090DNMSs", - - -- Halfword multiply and multiply-accumulate. - smlabb_4 = "e1000080NMSD", -- v5TE - smlatb_4 = "e10000a0NMSD", -- v5TE - smlabt_4 = "e10000c0NMSD", -- v5TE - smlatt_4 = "e10000e0NMSD", -- v5TE - smlawb_4 = "e1200080NMSD", -- v5TE - smulwb_3 = "e12000a0NMS", -- v5TE - smlawt_4 = "e12000c0NMSD", -- v5TE - smulwt_3 = "e12000e0NMS", -- v5TE - smlalbb_4 = "e1400080NMSD", -- v5TE - smlaltb_4 = "e14000a0NMSD", -- v5TE - smlalbt_4 = "e14000c0NMSD", -- v5TE - smlaltt_4 = "e14000e0NMSD", -- v5TE - smulbb_3 = "e1600080NMS", -- v5TE - smultb_3 = "e16000a0NMS", -- v5TE - smulbt_3 = "e16000c0NMS", -- v5TE - smultt_3 = "e16000e0NMS", -- v5TE - - -- Miscellaneous data processing instructions. - clz_2 = "e16f0f10DM", -- v5T - rev_2 = "e6bf0f30DM", -- v6 - rev16_2 = "e6bf0fb0DM", -- v6 - revsh_2 = "e6ff0fb0DM", -- v6 - sel_3 = "e6800fb0DNM", -- v6 - usad8_3 = "e780f010NMS", -- v6 - usada8_4 = "e7800010NMSD", -- v6 - rbit_2 = "e6ff0f30DM", -- v6T2 - movw_2 = "e3000000DW", -- v6T2 - movt_2 = "e3400000DW", -- v6T2 - -- Note: the X encodes width-1, not width. - sbfx_4 = "e7a00050DMvX", -- v6T2 - ubfx_4 = "e7e00050DMvX", -- v6T2 - -- Note: the X encodes the msb field, not the width. - bfc_3 = "e7c0001fDvX", -- v6T2 - bfi_4 = "e7c00010DMvX", -- v6T2 - - -- Packing and unpacking instructions. - pkhbt_3 = "e6800010DNM", pkhbt_4 = "e6800010DNMv", -- v6 - pkhtb_3 = "e6800050DNM", pkhtb_4 = "e6800050DNMv", -- v6 - sxtab_3 = "e6a00070DNM", sxtab_4 = "e6a00070DNMv", -- v6 - sxtab16_3 = "e6800070DNM", sxtab16_4 = "e6800070DNMv", -- v6 - sxtah_3 = "e6b00070DNM", sxtah_4 = "e6b00070DNMv", -- v6 - sxtb_2 = "e6af0070DM", sxtb_3 = "e6af0070DMv", -- v6 - sxtb16_2 = "e68f0070DM", sxtb16_3 = "e68f0070DMv", -- v6 - sxth_2 = "e6bf0070DM", sxth_3 = "e6bf0070DMv", -- v6 - uxtab_3 = "e6e00070DNM", uxtab_4 = "e6e00070DNMv", -- v6 - uxtab16_3 = "e6c00070DNM", uxtab16_4 = "e6c00070DNMv", -- v6 - uxtah_3 = "e6f00070DNM", uxtah_4 = "e6f00070DNMv", -- v6 - uxtb_2 = "e6ef0070DM", uxtb_3 = "e6ef0070DMv", -- v6 - uxtb16_2 = "e6cf0070DM", uxtb16_3 = "e6cf0070DMv", -- v6 - uxth_2 = "e6ff0070DM", uxth_3 = "e6ff0070DMv", -- v6 - - -- Saturating instructions. - qadd_3 = "e1000050DMN", -- v5TE - qsub_3 = "e1200050DMN", -- v5TE - qdadd_3 = "e1400050DMN", -- v5TE - qdsub_3 = "e1600050DMN", -- v5TE - -- Note: the X for ssat* encodes sat_imm-1, not sat_imm. - ssat_3 = "e6a00010DXM", ssat_4 = "e6a00010DXMp", -- v6 - usat_3 = "e6e00010DXM", usat_4 = "e6e00010DXMp", -- v6 - ssat16_3 = "e6a00f30DXM", -- v6 - usat16_3 = "e6e00f30DXM", -- v6 - - -- Parallel addition and subtraction. - sadd16_3 = "e6100f10DNM", -- v6 - sasx_3 = "e6100f30DNM", -- v6 - ssax_3 = "e6100f50DNM", -- v6 - ssub16_3 = "e6100f70DNM", -- v6 - sadd8_3 = "e6100f90DNM", -- v6 - ssub8_3 = "e6100ff0DNM", -- v6 - qadd16_3 = "e6200f10DNM", -- v6 - qasx_3 = "e6200f30DNM", -- v6 - qsax_3 = "e6200f50DNM", -- v6 - qsub16_3 = "e6200f70DNM", -- v6 - qadd8_3 = "e6200f90DNM", -- v6 - qsub8_3 = "e6200ff0DNM", -- v6 - shadd16_3 = "e6300f10DNM", -- v6 - shasx_3 = "e6300f30DNM", -- v6 - shsax_3 = "e6300f50DNM", -- v6 - shsub16_3 = "e6300f70DNM", -- v6 - shadd8_3 = "e6300f90DNM", -- v6 - shsub8_3 = "e6300ff0DNM", -- v6 - uadd16_3 = "e6500f10DNM", -- v6 - uasx_3 = "e6500f30DNM", -- v6 - usax_3 = "e6500f50DNM", -- v6 - usub16_3 = "e6500f70DNM", -- v6 - uadd8_3 = "e6500f90DNM", -- v6 - usub8_3 = "e6500ff0DNM", -- v6 - uqadd16_3 = "e6600f10DNM", -- v6 - uqasx_3 = "e6600f30DNM", -- v6 - uqsax_3 = "e6600f50DNM", -- v6 - uqsub16_3 = "e6600f70DNM", -- v6 - uqadd8_3 = "e6600f90DNM", -- v6 - uqsub8_3 = "e6600ff0DNM", -- v6 - uhadd16_3 = "e6700f10DNM", -- v6 - uhasx_3 = "e6700f30DNM", -- v6 - uhsax_3 = "e6700f50DNM", -- v6 - uhsub16_3 = "e6700f70DNM", -- v6 - uhadd8_3 = "e6700f90DNM", -- v6 - uhsub8_3 = "e6700ff0DNM", -- v6 - - -- Load/store instructions. - str_2 = "e4000000DL", str_3 = "e4000000DL", str_4 = "e4000000DL", - strb_2 = "e4400000DL", strb_3 = "e4400000DL", strb_4 = "e4400000DL", - ldr_2 = "e4100000DL", ldr_3 = "e4100000DL", ldr_4 = "e4100000DL", - ldrb_2 = "e4500000DL", ldrb_3 = "e4500000DL", ldrb_4 = "e4500000DL", - strh_2 = "e00000b0DL", strh_3 = "e00000b0DL", - ldrh_2 = "e01000b0DL", ldrh_3 = "e01000b0DL", - ldrd_2 = "e00000d0DL", ldrd_3 = "e00000d0DL", -- v5TE - ldrsb_2 = "e01000d0DL", ldrsb_3 = "e01000d0DL", - strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE - ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL", - - ldm_2 = "e8900000nR", ldmia_2 = "e8900000nR", ldmfd_2 = "e8900000nR", - ldmda_2 = "e8100000nR", ldmfa_2 = "e8100000nR", - ldmdb_2 = "e9100000nR", ldmea_2 = "e9100000nR", - ldmib_2 = "e9900000nR", ldmed_2 = "e9900000nR", - stm_2 = "e8800000nR", stmia_2 = "e8800000nR", stmfd_2 = "e8800000nR", - stmda_2 = "e8000000nR", stmfa_2 = "e8000000nR", - stmdb_2 = "e9000000nR", stmea_2 = "e9000000nR", - stmib_2 = "e9800000nR", stmed_2 = "e9800000nR", - pop_1 = "e8bd0000R", push_1 = "e92d0000R", - - -- Branch instructions. - b_1 = "ea000000B", - bl_1 = "eb000000B", - blx_1 = "e12fff30C", - bx_1 = "e12fff10M", - - -- Miscellaneous instructions. - nop_0 = "e1a00000", - mrs_1 = "e10f0000D", - bkpt_1 = "e1200070K", -- v5T - svc_1 = "ef000000T", swi_1 = "ef000000T", - ud_0 = "e7f001f0", - - -- NYI: Advanced SIMD and VFP instructions. - - -- NYI instructions, since I have no need for them right now: - -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh - -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe - -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb - -- stc, ldc, mcr, mcr2, mrc, mrc2, mcrr, mcrr2, mrrc, mrrc2, cdp, cdp2 -} - --- Add mnemonics for "s" variants. -do - local t = {} - for k,v in pairs(map_op) do - if sub(v, -1) == "s" then - local v2 = sub(v, 1, 2)..char(byte(v, 3)+1)..sub(v, 4, -2) - t[sub(k, 1, -3).."s"..sub(k, -2)] = v2 - end - end - for k,v in pairs(t) do - map_op[k] = v - end -end - ------------------------------------------------------------------------------- - -local function parse_gpr(expr) - local tname, ovreg = match(expr, "^([%w_]+):(r1?[0-9])$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - if not reg then - werror("type `"..(tname or expr).."' needs a register override") - end - expr = reg - end - local r = match(expr, "^r(1?[0-9])$") - if r then - r = tonumber(r) - if r <= 15 then return r, tp end - end - werror("bad register name `"..expr.."'") -end - -local function parse_gpr_pm(expr) - local pm, expr2 = match(expr, "^([+-]?)(.*)$") - return parse_gpr(expr2), (pm == "-") -end - -local function parse_reglist(reglist) - reglist = match(reglist, "^{%s*([^}]*)}$") - if not reglist then werror("register list expected") end - local rr = 0 - for p in gmatch(reglist..",", "%s*([^,]*),") do - local rbit = 2^parse_gpr(gsub(p, "%s+$", "")) - if ((rr - (rr % rbit)) / rbit) % 2 ~= 0 then - werror("duplicate register `"..p.."'") - end - rr = rr + rbit - end - return rr -end - -local function parse_imm(imm, bits, shift, scale, signed) - imm = match(imm, "^#(.*)$") - if not imm then werror("expected immediate operand") end - local n = tonumber(imm) - if n then - if n % 2^scale == 0 then - n = n / 2^scale - if signed then - if n >= 0 then - if n < 2^(bits-1) then return n*2^shift end - else - if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end - end - else - if n >= 0 and n <= 2^bits-1 then return n*2^shift end - end - end - werror("out of range immediate `"..imm.."'") - else - waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) - return 0 - end -end - -local function parse_imm12(imm) - local n = tonumber(imm) - if n then - local m = n - for i=0,-15,-1 do - if m >= 0 and m <= 255 and n % 1 == 0 then return m + (i%16) * 256 end - local t = m % 4 - m = (m - t) / 4 + t * 2^30 - end - werror("out of range immediate `"..imm.."'") - else - waction("IMM12", 0, imm) - return 0 - end -end - -local function parse_imm16(imm) - imm = match(imm, "^#(.*)$") - if not imm then werror("expected immediate operand") end - local n = tonumber(imm) - if n then - if n >= 0 and n <= 65535 and n % 1 == 0 then - local t = n % 4096 - return (n - t) * 16 + t - end - werror("out of range immediate `"..imm.."'") - else - waction("IMM16", 32*16, imm) - return 0 - end -end - -local function parse_imm_load(imm, ext) - local n = tonumber(imm) - if n then - if ext then - if n >= -255 and n <= 255 then - local up = 0x00800000 - if n < 0 then n = -n; up = 0 end - return (n-(n%16))*16+(n%16) + up - end - else - if n >= -4095 and n <= 4095 then - if n >= 0 then return n+0x00800000 end - return -n - end - end - werror("out of range immediate `"..imm.."'") - else - waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), imm) - return 0 - end -end - -local function parse_shift(shift, gprok) - if shift == "rrx" then - return 3 * 32 - else - local s, s2 = match(shift, "^(%S+)%s*(.*)$") - s = map_shift[s] - if not s then werror("expected shift operand") end - if sub(s2, 1, 1) == "#" then - return parse_imm(s2, 5, 7, 0, false) + s * 32 - else - if not gprok then werror("expected immediate shift operand") end - return parse_gpr(s2) * 256 + s * 32 + 16 - end - end -end - -local function parse_label(label, def) - local prefix = sub(label, 1, 2) - -- =>label (pc label reference) - if prefix == "=>" then - return "PC", 0, sub(label, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "LG", map_global[sub(label, 3)] - end - if def then - -- [1-9] (local label definition) - if match(label, "^[1-9]$") then - return "LG", 10+tonumber(label) - end - else - -- [<>][1-9] (local label reference) - local dir, lnum = match(label, "^([<>])([1-9])$") - if dir then -- Fwd: 1-9, Bkwd: 11-19. - return "LG", lnum + (dir == ">" and 0 or 10) - end - -- extern label (extern label reference) - local extname = match(label, "^extern%s+(%S+)$") - if extname then - return "EXT", map_extern[extname] - end - end - werror("bad label `"..label.."'") -end - -local function parse_load(params, nparams, n, op) - local oplo = op % 256 - local ext, ldrd = (oplo ~= 0), (oplo == 208) - local d - if (ldrd or oplo == 240) then - d = ((op - (op % 4096)) / 4096) % 16 - if d % 2 ~= 0 then werror("odd destination register") end - end - local pn = params[n] - local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") - local p2 = params[n+1] - if not p1 then - if not p2 then - if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then - local mode, n, s = parse_label(pn, false) - waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1) - return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0) - end - local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local d, tp = parse_gpr(reg) - if tp then - waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), - format(tp.ctypefmt, tailr)) - return op + d * 65536 + 0x01000000 + (ext and 0x00400000 or 0) - end - end - end - werror("expected address operand") - end - if wb == "!" then op = op + 0x00200000 end - if p2 then - if wb == "!" then werror("bad use of '!'") end - local p3 = params[n+2] - op = op + parse_gpr(p1) * 65536 - local imm = match(p2, "^#(.*)$") - if imm then - local m = parse_imm_load(imm, ext) - if p3 then werror("too many parameters") end - op = op + m + (ext and 0x00400000 or 0) - else - local m, neg = parse_gpr_pm(p2) - if ldrd and (m == d or m-1 == d) then werror("register conflict") end - op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000) - if p3 then op = op + parse_shift(p3) end - end - else - local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$") - op = op + parse_gpr(p1a) * 65536 + 0x01000000 - if p2 ~= "" then - local imm = match(p2, "^,%s*#(.*)$") - if imm then - local m = parse_imm_load(imm, ext) - op = op + m + (ext and 0x00400000 or 0) - else - local p2a, p3 = match(p2, "^,%s*([^,%s]*)%s*,?%s*(.*)$") - local m, neg = parse_gpr_pm(p2a) - if ldrd and (m == d or m-1 == d) then werror("register conflict") end - op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000) - if p3 ~= "" then - if ext then werror("too many parameters") end - op = op + parse_shift(p3) - end - end - else - if wb == "!" then werror("bad use of '!'") end - op = op + (ext and 0x00c00000 or 0x00800000) - end - end - return op -end - ------------------------------------------------------------------------------- - --- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) - if not params then return sub(template, 9) end - local op = tonumber(sub(template, 1, 8), 16) - local n = 1 - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 3 positions. - if secpos+3 > maxsecpos then wflush() end - local pos = wpos() - - -- Process each character. - for p in gmatch(sub(template, 9), ".") do - if p == "D" then - op = op + parse_gpr(params[n]) * 4096; n = n + 1 - elseif p == "N" then - op = op + parse_gpr(params[n]) * 65536; n = n + 1 - elseif p == "S" then - op = op + parse_gpr(params[n]) * 256; n = n + 1 - elseif p == "M" then - op = op + parse_gpr(params[n]); n = n + 1 - elseif p == "P" then - local imm = match(params[n], "^#(.*)$") - if imm then - op = op + parse_imm12(imm) + 0x02000000 - else - op = op + parse_gpr(params[n]) - end - n = n + 1 - elseif p == "p" then - op = op + parse_shift(params[n], true); n = n + 1 - elseif p == "L" then - op = parse_load(params, nparams, n, op) - elseif p == "B" then - local mode, n, s = parse_label(params[n], false) - waction("REL_"..mode, n, s, 1) - elseif p == "C" then -- blx gpr vs. blx label. - local p = params[n] - if match(p, "^([%w_]+):(r1?[0-9])$") or match(p, "^r(1?[0-9])$") then - op = op + parse_gpr(p) - else - if op < 0xe0000000 then werror("unconditional instruction") end - local mode, n, s = parse_label(p, false) - waction("REL_"..mode, n, s, 1) - op = 0xfa000000 - end - elseif p == "n" then - local r, wb = match(params[n], "^([^!]*)(!?)$") - op = op + parse_gpr(r) * 65536 + (wb == "!" and 0x00200000 or 0) - n = n + 1 - elseif p == "R" then - op = op + parse_reglist(params[n]); n = n + 1 - elseif p == "W" then - op = op + parse_imm16(params[n]); n = n + 1 - elseif p == "v" then - op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 - elseif p == "w" then - local imm = match(params[n], "^#(.*)$") - if imm then - op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 - else - op = op + parse_gpr(params[n]) * 256 + 16 - end - elseif p == "X" then - op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 - elseif p == "K" then - local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1 - if not imm or imm % 1 ~= 0 or imm < 0 or imm > 0xffff then - werror("bad immediate operand") - end - local t = imm % 16 - op = op + (imm - t) * 16 + t - elseif p == "T" then - op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1 - elseif p == "s" then - -- Ignored. - else - assert(false) - end - end - wputpos(pos, op) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_1"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr" end - if secpos+1 > maxsecpos then wflush() end - local mode, n, s = parse_label(params[1], true) - if mode == "EXT" then werror("bad label definition") end - waction("LABEL_"..mode, n, s, 1) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -map_op[".long_*"] = function(params) - if not params then return "imm..." end - for _,p in ipairs(params) do - local n = tonumber(p) - if n then - if n < 0 then n = n + 2^32 end - wputw(n) - if secpos+2 > maxsecpos then wflush() end - else - waction("LONG", 0, format("(uintptr_t)(%s)", p)) - end - end -end - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION", num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = function(t, k) - local v = map_coreop[k] - if v then return v end - local cc = sub(k, -4, -3) - local cv = map_cond[cc] - if cv then - local v = rawget(t, sub(k, 1, -5)..sub(k, -2)) - if type(v) == "string" then return format("%x%s", cv, sub(v, 2)) end - end - end }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_ppc.h b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_ppc.h deleted file mode 100644 index e928ffedd38..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_ppc.h +++ /dev/null @@ -1,408 +0,0 @@ -/* -** DynASM PPC encoding engine. -** Copyright (C) 2005-2011 Mike Pall. All rights reserved. -** Released under the MIT/X license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "ppc" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. */ -enum { - DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, - /* The following actions need a buffer position. */ - DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, - /* The following actions also have an argument. */ - DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, - DASM__MAX -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_REL 0x15000000 -#define DASM_S_UNDEF_LG 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned int *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - if (action >= DASM__MAX) { - ofs += 4; - } else { - int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; - switch (action) { - case DASM_STOP: goto stop; - case DASM_SECTION: - n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); - D->section = &D->sections[n]; goto stop; - case DASM_ESC: p++; ofs += 4; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; - case DASM_REL_LG: - n = (ins & 2047) - 10; pl = D->lglabels + n; - if (n >= 0) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ - pl += 10; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - break; - case DASM_LABEL_LG: - pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; - } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_IMM: -#ifdef DASM_CHECKS - CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); - if (ins & 0x8000) - CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); - else - CK((n>>((ins>>5)&31)) == 0, RANGE_I); -#endif - b[pos++] = n; - break; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: p++; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; - case DASM_REL_LG: case DASM_REL_PC: pos++; break; - case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; - case DASM_IMM: pos++; break; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) -#else -#define CK(x, st) ((void)0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - char *base = (char *)buffer; - unsigned int *cp = (unsigned int *)buffer; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: *cp++ = *p++; break; - case DASM_REL_EXT: - n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1); - goto patchrel; - case DASM_ALIGN: - ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; - break; - case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); - case DASM_REL_PC: - CK(n >= 0, UNDEF_PC); - n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); - patchrel: - CK((n & 3) == 0 && - (((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >> - ((ins & 2048) ? 16 : 26)) == 0, RANGE_REL); - cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc)); - break; - case DASM_LABEL_LG: - ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); - break; - case DASM_LABEL_PC: break; - case DASM_IMM: - cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31); - break; - default: *cp++ = ins; break; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != (char *)cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} -#undef CK - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(D->section-D->sections); - return D->status; -} -#endif - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_ppc.lua b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_ppc.lua deleted file mode 100644 index bb6de01e2ba..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_ppc.lua +++ /dev/null @@ -1,1225 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM PPC module. --- --- Copyright (C) 2005-2011 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - --- Module information: -local _info = { - arch = "ppc", - description = "DynASM PPC module", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, setmetatable = assert, setmetatable -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local match, gmatch = _s.match, _s.gmatch -local concat, sort = table.concat, table.sort - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - "STOP", "SECTION", "ESC", "REL_EXT", - "ALIGN", "REL_LG", "LABEL_LG", - "REL_PC", "LABEL_PC", "IMM", -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number. -local map_action = {} -for n,name in ipairs(action_names) do - map_action[name] = n-1 -end - --- Action list buffer. -local actlist = {} - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Return 8 digit hex number. -local function tohex(x) - return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. -end - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - if nn == 0 then nn = 1; actlist[0] = map_action.STOP end - out:write("static const unsigned int ", name, "[", nn, "] = {\n") - for i = 1,nn-1 do - assert(out:write("0x", tohex(actlist[i]), ",\n")) - end - assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) -end - ------------------------------------------------------------------------------- - --- Add word to action list. -local function wputxw(n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, val, a, num) - local w = assert(map_action[action], "bad action name `"..action.."'") - wputxw(w * 0x10000 + (val or 0)) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - if #actlist == actargs[1] then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped word. -local function wputw(n) - if n <= 0xffffff then waction("ESC") end - wputxw(n) -end - --- Reserve position for word. -local function wpos() - local pos = #actlist+1 - actlist[pos] = "" - return pos -end - --- Store word to reserved position. -local function wputpos(pos, n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[pos] = n -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 20 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end - local n = next_global - if n > 2047 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=20,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=20,next_global-1 do - out:write(" ", prefix, t[i], ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=20,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = 0 -local map_extern_ = {} -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n > 2047 then werror("too many extern labels") end - next_extern = n + 1 - t[name] = n - map_extern_[n] = name - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - out:write("Extern labels:\n") - for i=0,next_extern-1 do - out:write(format(" %s\n", map_extern_[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - out:write("static const char *const ", name, "[] = {\n") - for i=0,next_extern-1 do - out:write(" \"", map_extern_[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. -local map_archdef = { sp = "r1" } -- Ext. register name -> int. name. - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for Dt... macros). - --- Reverse defines for registers. -function _M.revdef(s) - if s == "r1" then return "sp" end - return s -end - -local map_cond = { - lt = 0, gt = 1, eq = 2, so = 3, - ge = 4, le = 5, ne = 6, ns = 7, -} - ------------------------------------------------------------------------------- - --- Template strings for PPC instructions. -local map_op = { - tdi_3 = "08000000ARI", - twi_3 = "0c000000ARI", - mulli_3 = "1c000000RRI", - subfic_3 = "20000000RRI", - cmplwi_3 = "28000000XRU", - cmplwi_2 = "28000000-RU", - cmpldi_3 = "28200000XRU", - cmpldi_2 = "28200000-RU", - cmpwi_3 = "2c000000XRI", - cmpwi_2 = "2c000000-RI", - cmpdi_3 = "2c200000XRI", - cmpdi_2 = "2c200000-RI", - addic_3 = "30000000RRI", - ["addic._3"] = "34000000RRI", - addi_3 = "38000000RR0I", - li_2 = "38000000RI", - la_2 = "38000000RD", - addis_3 = "3c000000RR0I", - lis_2 = "3c000000RI", - lus_2 = "3c000000RU", - bc_3 = "40000000AAK", - bcl_3 = "40000001AAK", - bdnz_1 = "42000000K", - bdz_1 = "42400000K", - sc_0 = "44000000", - b_1 = "48000000J", - bl_1 = "48000001J", - rlwimi_5 = "50000000RR~AAA.", - rlwinm_5 = "54000000RR~AAA.", - rlwnm_5 = "5c000000RR~RAA.", - ori_3 = "60000000RR~U", - nop_0 = "60000000", - oris_3 = "64000000RR~U", - xori_3 = "68000000RR~U", - xoris_3 = "6c000000RR~U", - ["andi._3"] = "70000000RR~U", - ["andis._3"] = "74000000RR~U", - lwz_2 = "80000000RD", - lwzu_2 = "84000000RD", - lbz_2 = "88000000RD", - lbzu_2 = "8c000000RD", - stw_2 = "90000000RD", - stwu_2 = "94000000RD", - stb_2 = "98000000RD", - stbu_2 = "9c000000RD", - lhz_2 = "a0000000RD", - lhzu_2 = "a4000000RD", - lha_2 = "a8000000RD", - lhau_2 = "ac000000RD", - sth_2 = "b0000000RD", - sthu_2 = "b4000000RD", - lmw_2 = "b8000000RD", - stmw_2 = "bc000000RD", - lfs_2 = "c0000000FD", - lfsu_2 = "c4000000FD", - lfd_2 = "c8000000FD", - lfdu_2 = "cc000000FD", - stfs_2 = "d0000000FD", - stfsu_2 = "d4000000FD", - stfd_2 = "d8000000FD", - stfdu_2 = "dc000000FD", - ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4. - ldu_2 = "e8000001RD", - lwa_2 = "e8000002RD", - std_2 = "f8000000RD", - stdu_2 = "f8000001RD", - - -- Primary opcode 19: - mcrf_2 = "4c000000XX", - isync_0 = "4c00012c", - crnor_3 = "4c000042CCC", - crnot_2 = "4c000042CC=", - crandc_3 = "4c000102CCC", - crxor_3 = "4c000182CCC", - crclr_1 = "4c000182C==", - crnand_3 = "4c0001c2CCC", - crand_3 = "4c000202CCC", - creqv_3 = "4c000242CCC", - crset_1 = "4c000242C==", - crorc_3 = "4c000342CCC", - cror_3 = "4c000382CCC", - crmove_2 = "4c000382CC=", - bclr_2 = "4c000020AA", - bclrl_2 = "4c000021AA", - bcctr_2 = "4c000420AA", - bcctrl_2 = "4c000421AA", - blr_0 = "4e800020", - blrl_0 = "4e800021", - bctr_0 = "4e800420", - bctrl_0 = "4e800421", - - -- Primary opcode 31: - cmpw_3 = "7c000000XRR", - cmpw_2 = "7c000000-RR", - cmpd_3 = "7c200000XRR", - cmpd_2 = "7c200000-RR", - tw_3 = "7c000008ARR", - subfc_3 = "7c000010RRR.", - subc_3 = "7c000010RRR~.", - mulhdu_3 = "7c000012RRR.", - addc_3 = "7c000014RRR.", - mulhwu_3 = "7c000016RRR.", - isel_4 = "7c00001eRRRC", - isellt_3 = "7c00001eRRR", - iselgt_3 = "7c00005eRRR", - iseleq_3 = "7c00009eRRR", - mfcr_1 = "7c000026R", - -- NYI: mtcrf, mtocrf, mfocrf - lwarx_3 = "7c000028RR0R", - ldx_3 = "7c00002aRR0R", - lwzx_3 = "7c00002eRR0R", - slw_3 = "7c000030RR~R.", - cntlzw_2 = "7c000034RR~", - sld_3 = "7c000036RR~R.", - and_3 = "7c000038RR~R.", - cmplw_3 = "7c000040XRR", - cmplw_2 = "7c000040-RR", - cmpld_3 = "7c200040XRR", - cmpld_2 = "7c200040-RR", - subf_3 = "7c000050RRR.", - sub_3 = "7c000050RRR~.", - ldux_3 = "7c00006aRR0R", - dcbst_2 = "7c00006c-RR", - lwzux_3 = "7c00006eRR0R", - cntlzd_2 = "7c000074RR~", - andc_3 = "7c000078RR~R.", - td_3 = "7c000088ARR", - mulhd_3 = "7c000092RRR.", - mulhw_3 = "7c000096RRR.", - ldarx_3 = "7c0000a8RR0R", - dcbf_2 = "7c0000ac-RR", - lbzx_3 = "7c0000aeRR0R", - neg_2 = "7c0000d0RR.", - lbzux_3 = "7c0000eeRR0R", - popcntb_2 = "7c0000f4RR~", - not_2 = "7c0000f8RR~%.", - nor_3 = "7c0000f8RR~R.", - subfe_3 = "7c000110RRR.", - sube_3 = "7c000110RRR~.", - adde_3 = "7c000114RRR.", - stdx_3 = "7c00012aRR0R", - stwcx_3 = "7c00012cRR0R.", - stwx_3 = "7c00012eRR0R", - prtyw_2 = "7c000134RR~", - stdux_3 = "7c00016aRR0R", - stwux_3 = "7c00016eRR0R", - prtyd_2 = "7c000174RR~", - subfze_2 = "7c000190RR.", - addze_2 = "7c000194RR.", - stdcx_3 = "7c0001acRR0R.", - stbx_3 = "7c0001aeRR0R", - subfme_2 = "7c0001d0RR.", - mulld_3 = "7c0001d2RRR.", - addme_2 = "7c0001d4RR.", - mullw_3 = "7c0001d6RRR.", - dcbtst_2 = "7c0001ec-RR", - stbux_3 = "7c0001eeRR0R", - add_3 = "7c000214RRR.", - dcbt_2 = "7c00022c-RR", - lhzx_3 = "7c00022eRR0R", - eqv_3 = "7c000238RR~R.", - eciwx_3 = "7c00026cRR0R", - lhzux_3 = "7c00026eRR0R", - xor_3 = "7c000278RR~R.", - mfspefscr_1 = "7c0082a6R", - mfxer_1 = "7c0102a6R", - mflr_1 = "7c0802a6R", - mfctr_1 = "7c0902a6R", - lwax_3 = "7c0002aaRR0R", - lhax_3 = "7c0002aeRR0R", - mftb_1 = "7c0c42e6R", - mftbu_1 = "7c0d42e6R", - lwaux_3 = "7c0002eaRR0R", - lhaux_3 = "7c0002eeRR0R", - sthx_3 = "7c00032eRR0R", - orc_3 = "7c000338RR~R.", - ecowx_3 = "7c00036cRR0R", - sthux_3 = "7c00036eRR0R", - or_3 = "7c000378RR~R.", - mr_2 = "7c000378RR~%.", - divdu_3 = "7c000392RRR.", - divwu_3 = "7c000396RRR.", - mtspefscr_1 = "7c0083a6R", - mtxer_1 = "7c0103a6R", - mtlr_1 = "7c0803a6R", - mtctr_1 = "7c0903a6R", - dcbi_2 = "7c0003ac-RR", - nand_3 = "7c0003b8RR~R.", - divd_3 = "7c0003d2RRR.", - divw_3 = "7c0003d6RRR.", - cmpb_3 = "7c0003f8RR~R.", - mcrxr_1 = "7c000400X", - subfco_3 = "7c000410RRR.", - subco_3 = "7c000410RRR~.", - addco_3 = "7c000414RRR.", - ldbrx_3 = "7c000428RR0R", - lswx_3 = "7c00042aRR0R", - lwbrx_3 = "7c00042cRR0R", - lfsx_3 = "7c00042eFR0R", - srw_3 = "7c000430RR~R.", - srd_3 = "7c000436RR~R.", - subfo_3 = "7c000450RRR.", - subo_3 = "7c000450RRR~.", - lfsux_3 = "7c00046eFR0R", - lswi_3 = "7c0004aaRR0A", - sync_0 = "7c0004ac", - lwsync_0 = "7c2004ac", - ptesync_0 = "7c4004ac", - lfdx_3 = "7c0004aeFR0R", - nego_2 = "7c0004d0RR.", - lfdux_3 = "7c0004eeFR0R", - subfeo_3 = "7c000510RRR.", - subeo_3 = "7c000510RRR~.", - addeo_3 = "7c000514RRR.", - stdbrx_3 = "7c000528RR0R", - stswx_3 = "7c00052aRR0R", - stwbrx_3 = "7c00052cRR0R", - stfsx_3 = "7c00052eFR0R", - stfsux_3 = "7c00056eFR0R", - subfzeo_2 = "7c000590RR.", - addzeo_2 = "7c000594RR.", - stswi_3 = "7c0005aaRR0A", - stfdx_3 = "7c0005aeFR0R", - subfmeo_2 = "7c0005d0RR.", - mulldo_3 = "7c0005d2RRR.", - addmeo_2 = "7c0005d4RR.", - mullwo_3 = "7c0005d6RRR.", - dcba_2 = "7c0005ec-RR", - stfdux_3 = "7c0005eeFR0R", - addo_3 = "7c000614RRR.", - lhbrx_3 = "7c00062cRR0R", - sraw_3 = "7c000630RR~R.", - srad_3 = "7c000634RR~R.", - srawi_3 = "7c000670RR~A.", - eieio_0 = "7c0006ac", - lfiwax_3 = "7c0006aeFR0R", - sthbrx_3 = "7c00072cRR0R", - extsh_2 = "7c000734RR~.", - extsb_2 = "7c000774RR~.", - divduo_3 = "7c000792RRR.", - divwou_3 = "7c000796RRR.", - icbi_2 = "7c0007ac-RR", - stfiwx_3 = "7c0007aeFR0R", - extsw_2 = "7c0007b4RR~.", - divdo_3 = "7c0007d2RRR.", - divwo_3 = "7c0007d6RRR.", - dcbz_2 = "7c0007ec-RR", - - -- Primary opcode 59: - fdivs_3 = "ec000024FFF.", - fsubs_3 = "ec000028FFF.", - fadds_3 = "ec00002aFFF.", - fsqrts_2 = "ec00002cF-F.", - fres_2 = "ec000030F-F.", - fmuls_3 = "ec000032FF-F.", - frsqrtes_2 = "ec000034F-F.", - fmsubs_4 = "ec000038FFFF~.", - fmadds_4 = "ec00003aFFFF~.", - fnmsubs_4 = "ec00003cFFFF~.", - fnmadds_4 = "ec00003eFFFF~.", - - -- Primary opcode 63: - fdiv_3 = "fc000024FFF.", - fsub_3 = "fc000028FFF.", - fadd_3 = "fc00002aFFF.", - fsqrt_2 = "fc00002cF-F.", - fsel_4 = "fc00002eFFFF~.", - fre_2 = "fc000030F-F.", - fmul_3 = "fc000032FF-F.", - frsqrte_2 = "fc000034F-F.", - fmsub_4 = "fc000038FFFF~.", - fmadd_4 = "fc00003aFFFF~.", - fnmsub_4 = "fc00003cFFFF~.", - fnmadd_4 = "fc00003eFFFF~.", - fcmpu_3 = "fc000000XFF", - fcpsgn_3 = "fc000010FFF.", - fcmpo_3 = "fc000040XFF", - mtfsb1_1 = "fc00004cA", - fneg_2 = "fc000050F-F.", - mcrfs_2 = "fc000080XX", - mtfsb0_1 = "fc00008cA", - fmr_2 = "fc000090F-F.", - frsp_2 = "fc000018F-F.", - fctiw_2 = "fc00001cF-F.", - fctiwz_2 = "fc00001eF-F.", - mtfsfi_2 = "fc00010cAA", -- NYI: upshift. - fnabs_2 = "fc000110F-F.", - fabs_2 = "fc000210F-F.", - frin_2 = "fc000310F-F.", - friz_2 = "fc000350F-F.", - frip_2 = "fc000390F-F.", - frim_2 = "fc0003d0F-F.", - mffs_1 = "fc00048eF.", - mtfsf_1 = "fc00058eF.", - fctid_2 = "fc00065cF-F.", - fctidz_2 = "fc00065eF-F.", - fcfid_2 = "fc00069cF-F.", - - -- Primary opcode 4, SPE APU extension: - evaddw_3 = "10000200RRR", - evaddiw_3 = "10000202RAR~", - evsubw_3 = "10000204RRR~", - evsubiw_3 = "10000206RAR~", - evabs_2 = "10000208RR", - evneg_2 = "10000209RR", - evextsb_2 = "1000020aRR", - evextsh_2 = "1000020bRR", - evrndw_2 = "1000020cRR", - evcntlzw_2 = "1000020dRR", - evcntlsw_2 = "1000020eRR", - brinc_3 = "1000020fRRR", - evand_3 = "10000211RRR", - evandc_3 = "10000212RRR", - evxor_3 = "10000216RRR", - evor_3 = "10000217RRR", - evmr_2 = "10000217RR=", - evnor_3 = "10000218RRR", - evnot_2 = "10000218RR=", - eveqv_3 = "10000219RRR", - evorc_3 = "1000021bRRR", - evnand_3 = "1000021eRRR", - evsrwu_3 = "10000220RRR", - evsrws_3 = "10000221RRR", - evsrwiu_3 = "10000222RRA", - evsrwis_3 = "10000223RRA", - evslw_3 = "10000224RRR", - evslwi_3 = "10000226RRA", - evrlw_3 = "10000228RRR", - evsplati_2 = "10000229RS", - evrlwi_3 = "1000022aRRA", - evsplatfi_2 = "1000022bRS", - evmergehi_3 = "1000022cRRR", - evmergelo_3 = "1000022dRRR", - evcmpgtu_3 = "10000230XRR", - evcmpgtu_2 = "10000230-RR", - evcmpgts_3 = "10000231XRR", - evcmpgts_2 = "10000231-RR", - evcmpltu_3 = "10000232XRR", - evcmpltu_2 = "10000232-RR", - evcmplts_3 = "10000233XRR", - evcmplts_2 = "10000233-RR", - evcmpeq_3 = "10000234XRR", - evcmpeq_2 = "10000234-RR", - evsel_4 = "10000278RRRW", - evsel_3 = "10000278RRR", - evfsadd_3 = "10000280RRR", - evfssub_3 = "10000281RRR", - evfsabs_2 = "10000284RR", - evfsnabs_2 = "10000285RR", - evfsneg_2 = "10000286RR", - evfsmul_3 = "10000288RRR", - evfsdiv_3 = "10000289RRR", - evfscmpgt_3 = "1000028cXRR", - evfscmpgt_2 = "1000028c-RR", - evfscmplt_3 = "1000028dXRR", - evfscmplt_2 = "1000028d-RR", - evfscmpeq_3 = "1000028eXRR", - evfscmpeq_2 = "1000028e-RR", - evfscfui_2 = "10000290R-R", - evfscfsi_2 = "10000291R-R", - evfscfuf_2 = "10000292R-R", - evfscfsf_2 = "10000293R-R", - evfsctui_2 = "10000294R-R", - evfsctsi_2 = "10000295R-R", - evfsctuf_2 = "10000296R-R", - evfsctsf_2 = "10000297R-R", - evfsctuiz_2 = "10000298R-R", - evfsctsiz_2 = "1000029aR-R", - evfststgt_3 = "1000029cXRR", - evfststgt_2 = "1000029c-RR", - evfststlt_3 = "1000029dXRR", - evfststlt_2 = "1000029d-RR", - evfststeq_3 = "1000029eXRR", - evfststeq_2 = "1000029e-RR", - efsadd_3 = "100002c0RRR", - efssub_3 = "100002c1RRR", - efsabs_2 = "100002c4RR", - efsnabs_2 = "100002c5RR", - efsneg_2 = "100002c6RR", - efsmul_3 = "100002c8RRR", - efsdiv_3 = "100002c9RRR", - efscmpgt_3 = "100002ccXRR", - efscmpgt_2 = "100002cc-RR", - efscmplt_3 = "100002cdXRR", - efscmplt_2 = "100002cd-RR", - efscmpeq_3 = "100002ceXRR", - efscmpeq_2 = "100002ce-RR", - efscfd_2 = "100002cfR-R", - efscfui_2 = "100002d0R-R", - efscfsi_2 = "100002d1R-R", - efscfuf_2 = "100002d2R-R", - efscfsf_2 = "100002d3R-R", - efsctui_2 = "100002d4R-R", - efsctsi_2 = "100002d5R-R", - efsctuf_2 = "100002d6R-R", - efsctsf_2 = "100002d7R-R", - efsctuiz_2 = "100002d8R-R", - efsctsiz_2 = "100002daR-R", - efststgt_3 = "100002dcXRR", - efststgt_2 = "100002dc-RR", - efststlt_3 = "100002ddXRR", - efststlt_2 = "100002dd-RR", - efststeq_3 = "100002deXRR", - efststeq_2 = "100002de-RR", - efdadd_3 = "100002e0RRR", - efdsub_3 = "100002e1RRR", - efdcfuid_2 = "100002e2R-R", - efdcfsid_2 = "100002e3R-R", - efdabs_2 = "100002e4RR", - efdnabs_2 = "100002e5RR", - efdneg_2 = "100002e6RR", - efdmul_3 = "100002e8RRR", - efddiv_3 = "100002e9RRR", - efdctuidz_2 = "100002eaR-R", - efdctsidz_2 = "100002ebR-R", - efdcmpgt_3 = "100002ecXRR", - efdcmpgt_2 = "100002ec-RR", - efdcmplt_3 = "100002edXRR", - efdcmplt_2 = "100002ed-RR", - efdcmpeq_3 = "100002eeXRR", - efdcmpeq_2 = "100002ee-RR", - efdcfs_2 = "100002efR-R", - efdcfui_2 = "100002f0R-R", - efdcfsi_2 = "100002f1R-R", - efdcfuf_2 = "100002f2R-R", - efdcfsf_2 = "100002f3R-R", - efdctui_2 = "100002f4R-R", - efdctsi_2 = "100002f5R-R", - efdctuf_2 = "100002f6R-R", - efdctsf_2 = "100002f7R-R", - efdctuiz_2 = "100002f8R-R", - efdctsiz_2 = "100002faR-R", - efdtstgt_3 = "100002fcXRR", - efdtstgt_2 = "100002fc-RR", - efdtstlt_3 = "100002fdXRR", - efdtstlt_2 = "100002fd-RR", - efdtsteq_3 = "100002feXRR", - efdtsteq_2 = "100002fe-RR", - evlddx_3 = "10000300RR0R", - evldd_2 = "10000301R8", - evldwx_3 = "10000302RR0R", - evldw_2 = "10000303R8", - evldhx_3 = "10000304RR0R", - evldh_2 = "10000305R8", - evlwhex_3 = "10000310RR0R", - evlwhe_2 = "10000311R4", - evlwhoux_3 = "10000314RR0R", - evlwhou_2 = "10000315R4", - evlwhosx_3 = "10000316RR0R", - evlwhos_2 = "10000317R4", - evstddx_3 = "10000320RR0R", - evstdd_2 = "10000321R8", - evstdwx_3 = "10000322RR0R", - evstdw_2 = "10000323R8", - evstdhx_3 = "10000324RR0R", - evstdh_2 = "10000325R8", - evstwhex_3 = "10000330RR0R", - evstwhe_2 = "10000331R4", - evstwhox_3 = "10000334RR0R", - evstwho_2 = "10000335R4", - evstwwex_3 = "10000338RR0R", - evstwwe_2 = "10000339R4", - evstwwox_3 = "1000033cRR0R", - evstwwo_2 = "1000033dR4", - evmhessf_3 = "10000403RRR", - evmhossf_3 = "10000407RRR", - evmheumi_3 = "10000408RRR", - evmhesmi_3 = "10000409RRR", - evmhesmf_3 = "1000040bRRR", - evmhoumi_3 = "1000040cRRR", - evmhosmi_3 = "1000040dRRR", - evmhosmf_3 = "1000040fRRR", - evmhessfa_3 = "10000423RRR", - evmhossfa_3 = "10000427RRR", - evmheumia_3 = "10000428RRR", - evmhesmia_3 = "10000429RRR", - evmhesmfa_3 = "1000042bRRR", - evmhoumia_3 = "1000042cRRR", - evmhosmia_3 = "1000042dRRR", - evmhosmfa_3 = "1000042fRRR", - evmwhssf_3 = "10000447RRR", - evmwlumi_3 = "10000448RRR", - evmwhumi_3 = "1000044cRRR", - evmwhsmi_3 = "1000044dRRR", - evmwhsmf_3 = "1000044fRRR", - evmwssf_3 = "10000453RRR", - evmwumi_3 = "10000458RRR", - evmwsmi_3 = "10000459RRR", - evmwsmf_3 = "1000045bRRR", - evmwhssfa_3 = "10000467RRR", - evmwlumia_3 = "10000468RRR", - evmwhumia_3 = "1000046cRRR", - evmwhsmia_3 = "1000046dRRR", - evmwhsmfa_3 = "1000046fRRR", - evmwssfa_3 = "10000473RRR", - evmwumia_3 = "10000478RRR", - evmwsmia_3 = "10000479RRR", - evmwsmfa_3 = "1000047bRRR", - evmra_2 = "100004c4RR", - evdivws_3 = "100004c6RRR", - evdivwu_3 = "100004c7RRR", - evmwssfaa_3 = "10000553RRR", - evmwumiaa_3 = "10000558RRR", - evmwsmiaa_3 = "10000559RRR", - evmwsmfaa_3 = "1000055bRRR", - evmwssfan_3 = "100005d3RRR", - evmwumian_3 = "100005d8RRR", - evmwsmian_3 = "100005d9RRR", - evmwsmfan_3 = "100005dbRRR", - evmergehilo_3 = "1000022eRRR", - evmergelohi_3 = "1000022fRRR", - evlhhesplatx_3 = "10000308RR0R", - evlhhesplat_2 = "10000309R2", - evlhhousplatx_3 = "1000030cRR0R", - evlhhousplat_2 = "1000030dR2", - evlhhossplatx_3 = "1000030eRR0R", - evlhhossplat_2 = "1000030fR2", - evlwwsplatx_3 = "10000318RR0R", - evlwwsplat_2 = "10000319R4", - evlwhsplatx_3 = "1000031cRR0R", - evlwhsplat_2 = "1000031dR4", - evaddusiaaw_2 = "100004c0RR", - evaddssiaaw_2 = "100004c1RR", - evsubfusiaaw_2 = "100004c2RR", - evsubfssiaaw_2 = "100004c3RR", - evaddumiaaw_2 = "100004c8RR", - evaddsmiaaw_2 = "100004c9RR", - evsubfumiaaw_2 = "100004caRR", - evsubfsmiaaw_2 = "100004cbRR", - evmheusiaaw_3 = "10000500RRR", - evmhessiaaw_3 = "10000501RRR", - evmhessfaaw_3 = "10000503RRR", - evmhousiaaw_3 = "10000504RRR", - evmhossiaaw_3 = "10000505RRR", - evmhossfaaw_3 = "10000507RRR", - evmheumiaaw_3 = "10000508RRR", - evmhesmiaaw_3 = "10000509RRR", - evmhesmfaaw_3 = "1000050bRRR", - evmhoumiaaw_3 = "1000050cRRR", - evmhosmiaaw_3 = "1000050dRRR", - evmhosmfaaw_3 = "1000050fRRR", - evmhegumiaa_3 = "10000528RRR", - evmhegsmiaa_3 = "10000529RRR", - evmhegsmfaa_3 = "1000052bRRR", - evmhogumiaa_3 = "1000052cRRR", - evmhogsmiaa_3 = "1000052dRRR", - evmhogsmfaa_3 = "1000052fRRR", - evmwlusiaaw_3 = "10000540RRR", - evmwlssiaaw_3 = "10000541RRR", - evmwlumiaaw_3 = "10000548RRR", - evmwlsmiaaw_3 = "10000549RRR", - evmheusianw_3 = "10000580RRR", - evmhessianw_3 = "10000581RRR", - evmhessfanw_3 = "10000583RRR", - evmhousianw_3 = "10000584RRR", - evmhossianw_3 = "10000585RRR", - evmhossfanw_3 = "10000587RRR", - evmheumianw_3 = "10000588RRR", - evmhesmianw_3 = "10000589RRR", - evmhesmfanw_3 = "1000058bRRR", - evmhoumianw_3 = "1000058cRRR", - evmhosmianw_3 = "1000058dRRR", - evmhosmfanw_3 = "1000058fRRR", - evmhegumian_3 = "100005a8RRR", - evmhegsmian_3 = "100005a9RRR", - evmhegsmfan_3 = "100005abRRR", - evmhogumian_3 = "100005acRRR", - evmhogsmian_3 = "100005adRRR", - evmhogsmfan_3 = "100005afRRR", - evmwlusianw_3 = "100005c0RRR", - evmwlssianw_3 = "100005c1RRR", - evmwlumianw_3 = "100005c8RRR", - evmwlsmianw_3 = "100005c9RRR", - - -- NYI: some 64 bit PowerPC and Book E instructions: - -- rldicl, rldicr, rldic, rldimi, rldcl, rldcr, sradi, 64 bit ext. add/sub, - -- extended addressing branches, cache management, loads and stores -} - --- Add mnemonics for "." variants. -do - local t = {} - for k,v in pairs(map_op) do - if sub(v, -1) == "." then - local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2) - t[sub(k, 1, -3).."."..sub(k, -2)] = v2 - end - end - for k,v in pairs(t) do - map_op[k] = v - end -end - --- Add more branch mnemonics. -for cond,c in pairs(map_cond) do - local b1 = "b"..cond - local c1 = (c%4)*0x00010000 + (c < 4 and 0x01000000 or 0) - -- bX[l] - map_op[b1.."_1"] = tohex(0x40800000 + c1).."K" - map_op[b1.."l_1"] = tohex(0x40800001 + c1).."K" - map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK" - map_op[b1.."l_2"] = tohex(0x40800001 + c1).."-XK" - -- bXlr[l] - map_op[b1.."lr_0"] = tohex(0x4c800020 + c1) - map_op[b1.."lrl_0"] = tohex(0x4c800021 + c1) - map_op[b1.."ctr_0"] = tohex(0x4c800420 + c1) - map_op[b1.."ctrl_0"] = tohex(0x4c800421 + c1) - -- bXctr[l] - map_op[b1.."lr_1"] = tohex(0x4c800020 + c1).."-X" - map_op[b1.."lrl_1"] = tohex(0x4c800021 + c1).."-X" - map_op[b1.."ctr_1"] = tohex(0x4c800420 + c1).."-X" - map_op[b1.."ctrl_1"] = tohex(0x4c800421 + c1).."-X" -end - ------------------------------------------------------------------------------- - -local function parse_gpr(expr) - local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - if not reg then - werror("type `"..(tname or expr).."' needs a register override") - end - expr = reg - end - local r = match(expr, "^r([1-3]?[0-9])$") - if r then - r = tonumber(r) - if r <= 31 then return r, tp end - end - werror("bad register name `"..expr.."'") -end - -local function parse_fpr(expr) - local r = match(expr, "^f([1-3]?[0-9])$") - if r then - r = tonumber(r) - if r <= 31 then return r end - end - werror("bad register name `"..expr.."'") -end - -local function parse_cr(expr) - local r = match(expr, "^cr([0-7])$") - if r then return tonumber(r) end - werror("bad condition register name `"..expr.."'") -end - -local function parse_cond(expr) - local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$") - if r then - r = tonumber(r) - local c = map_cond[cond] - if c and c < 4 then return r*4+c end - end - werror("bad condition bit name `"..expr.."'") -end - -local function parse_imm(imm, bits, shift, scale, signed) - local n = tonumber(imm) - if n then - if n % 2^scale == 0 then - n = n / 2^scale - if signed then - if n >= 0 then - if n < 2^(bits-1) then return n*2^shift end - else - if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end - end - else - if n >= 0 and n <= 2^bits-1 then return n*2^shift end - end - end - werror("out of range immediate `"..imm.."'") - elseif match(imm, "^r([1-3]?[0-9])$") or - match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then - werror("expected immediate operand, got register") - else - waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) - return 0 - end -end - -local function parse_disp(disp) - local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") - if imm then - local r = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - return r*65536 + parse_imm(imm, 16, 0, 0, true) - end - local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local r, tp = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - if tp then - waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) - return r*65536 - end - end - werror("bad displacement `"..disp.."'") -end - -local function parse_u5disp(disp, scale) - local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") - if imm then - local r = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - return r*65536 + parse_imm(imm, 5, 11, scale, false) - end - local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local r, tp = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - if tp then - waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr)) - return r*65536 - end - end - werror("bad displacement `"..disp.."'") -end - -local function parse_label(label, def) - local prefix = sub(label, 1, 2) - -- =>label (pc label reference) - if prefix == "=>" then - return "PC", 0, sub(label, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "LG", map_global[sub(label, 3)] - end - if def then - -- [1-9] (local label definition) - if match(label, "^[1-9]$") then - return "LG", 10+tonumber(label) - end - else - -- [<>][1-9] (local label reference) - local dir, lnum = match(label, "^([<>])([1-9])$") - if dir then -- Fwd: 1-9, Bkwd: 11-19. - return "LG", lnum + (dir == ">" and 0 or 10) - end - -- extern label (extern label reference) - local extname = match(label, "^extern%s+(%S+)$") - if extname then - return "EXT", map_extern[extname] - end - end - werror("bad label `"..label.."'") -end - ------------------------------------------------------------------------------- - --- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) - if not params then return sub(template, 9) end - local op = tonumber(sub(template, 1, 8), 16) - local n, rs = 1, 26 - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 3 positions (rlwinm). - if secpos+3 > maxsecpos then wflush() end - local pos = wpos() - - -- Process each character. - for p in gmatch(sub(template, 9), ".") do - if p == "R" then - rs = rs - 5; op = op + parse_gpr(params[n]) * 2^rs; n = n + 1 - elseif p == "F" then - rs = rs - 5; op = op + parse_fpr(params[n]) * 2^rs; n = n + 1 - elseif p == "A" then - rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1 - elseif p == "S" then - rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, true); n = n + 1 - elseif p == "I" then - op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 - elseif p == "U" then - op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 - elseif p == "D" then - op = op + parse_disp(params[n]); n = n + 1 - elseif p == "2" then - op = op + parse_u5disp(params[n], 1); n = n + 1 - elseif p == "4" then - op = op + parse_u5disp(params[n], 2); n = n + 1 - elseif p == "8" then - op = op + parse_u5disp(params[n], 3); n = n + 1 - elseif p == "C" then - rs = rs - 5; op = op + parse_cond(params[n]) * 2^rs; n = n + 1 - elseif p == "X" then - rs = rs - 5; op = op + parse_cr(params[n]) * 2^(rs+2); n = n + 1 - elseif p == "W" then - op = op + parse_cr(params[n]); n = n + 1 - elseif p == "J" or p == "K" then - local mode, n, s = parse_label(params[n], false) - if p == "K" then n = n + 2048 end - waction("REL_"..mode, n, s, 1) - n = n + 1 - elseif p == "0" then - local mm = 2^rs - local t = op % mm - if ((op - t) / mm) % 32 == 0 then werror("cannot use r0") end - elseif p == "=" or p == "%" then - local mm = 2^(rs + (p == "%" and 5 or 0)) - local t = ((op - op % mm) / mm) % 32 - rs = rs - 5 - op = op + t * 2^rs - elseif p == "~" then - local mm = 2^rs - local t1l = op % mm - local t1h = (op - t1l) / mm - local t2l = t1h % 32 - local t2h = (t1h - t2l) / 32 - local t3l = t2h % 32 - op = ((t2h - t3l + t2l)*32 + t3l)*mm + t1l - elseif p == "-" then - rs = rs - 5 - elseif p == "." then - -- Ignored. - else - assert(false) - end - end - wputpos(pos, op) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_1"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr" end - if secpos+1 > maxsecpos then wflush() end - local mode, n, s = parse_label(params[1], true) - if mode == "EXT" then werror("bad label definition") end - waction("LABEL_"..mode, n, s, 1) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -map_op[".long_*"] = function(params) - if not params then return "imm..." end - for _,p in ipairs(params) do - local n = tonumber(p) - if not n then werror("bad immediate `"..p.."'") end - if n < 0 then n = n + 2^32 end - wputw(n) - if secpos+2 > maxsecpos then wflush() end - end -end - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION", num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = map_coreop }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_proto.h b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_proto.h deleted file mode 100644 index dc9ed51067f..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_proto.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** DynASM encoding engine prototypes. -** Copyright (C) 2005-2011 Mike Pall. All rights reserved. -** Released under the MIT/X license. See dynasm.lua for full copyright notice. -*/ - -#ifndef _DASM_PROTO_H -#define _DASM_PROTO_H - -#include <stddef.h> -#include <stdarg.h> - -#define DASM_IDENT "DynASM 1.3.0" -#define DASM_VERSION 10300 /* 1.3.0 */ - -#ifndef Dst_DECL -#define Dst_DECL dasm_State **Dst -#endif - -#ifndef Dst_REF -#define Dst_REF (*Dst) -#endif - -#ifndef DASM_FDEF -#define DASM_FDEF extern -#endif - -#ifndef DASM_M_GROW -#define DASM_M_GROW(ctx, t, p, sz, need) \ - do { \ - size_t _sz = (sz), _need = (need); \ - if (_sz < _need) { \ - if (_sz < 16) _sz = 16; \ - while (_sz < _need) _sz += _sz; \ - (p) = (t *)realloc((p), _sz); \ - if ((p) == NULL) exit(1); \ - (sz) = _sz; \ - } \ - } while(0) -#endif - -#ifndef DASM_M_FREE -#define DASM_M_FREE(ctx, p, sz) free(p) -#endif - -/* Internal DynASM encoder state. */ -typedef struct dasm_State dasm_State; - - -/* Initialize and free DynASM state. */ -DASM_FDEF void dasm_init(Dst_DECL, int maxsection); -DASM_FDEF void dasm_free(Dst_DECL); - -/* Setup global array. Must be called before dasm_setup(). */ -DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl); - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc); - -/* Setup encoder. */ -DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist); - -/* Feed encoder with actions. Calls are generated by pre-processor. */ -DASM_FDEF void dasm_put(Dst_DECL, int start, ...); - -/* Link sections and return the resulting size. */ -DASM_FDEF int dasm_link(Dst_DECL, size_t *szp); - -/* Encode sections into buffer. */ -DASM_FDEF int dasm_encode(Dst_DECL, void *buffer); - -/* Get PC label offset. */ -DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc); - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch); -#else -#define dasm_checkstep(a, b) 0 -#endif - - -#endif /* _DASM_PROTO_H */ diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x64.lua b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x64.lua deleted file mode 100644 index 73e01e919ac..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x64.lua +++ /dev/null @@ -1,12 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM x64 module. --- --- Copyright (C) 2005-2011 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- --- This module just sets 64 bit mode for the combined x86/x64 module. --- All the interesting stuff is there. ------------------------------------------------------------------------------- - -x64 = true -- Using a global is an ugly, but effective solution. -return require("dasm_x86") diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x86.h b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x86.h deleted file mode 100644 index 23e213cb6e6..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x86.h +++ /dev/null @@ -1,470 +0,0 @@ -/* -** DynASM x86 encoding engine. -** Copyright (C) 2005-2011 Mike Pall. All rights reserved. -** Released under the MIT/X license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "x86" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. DASM_STOP must be 255. */ -enum { - DASM_DISP = 233, - DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB, - DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC, - DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN, - DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_VREG 0x15000000 -#define DASM_S_UNDEF_L 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned char *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs, mrm = 4; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - int action = *p++; - if (action < DASM_DISP) { - ofs++; - } else if (action <= DASM_REL_A) { - int n = va_arg(ap, int); - b[pos++] = n; - switch (action) { - case DASM_DISP: - if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; } - case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; - case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ - case DASM_IMM_D: ofs += 4; break; - case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob; - case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break; - case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; - case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; - case DASM_SPACE: p++; ofs += n; break; - case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */ - case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG); - if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue; - } - mrm = 4; - } else { - int *pl, n; - switch (action) { - case DASM_REL_LG: - case DASM_IMM_LG: - n = *p++; pl = D->lglabels + n; - if (n <= 246) { CKPL(lg, LG); goto putrel; } /* Bkwd rel or global. */ - pl -= 246; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - ofs += 4; /* Maximum offset needed. */ - if (action == DASM_REL_LG || action == DASM_REL_PC) - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_ALIGN: - ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_EXTERN: p += 2; ofs += 4; break; - case DASM_ESC: p++; ofs++; break; - case DASM_MARK: mrm = p[-2]; break; - case DASM_SECTION: - n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n]; - case DASM_STOP: goto stop; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - int op, action = *p++; - switch (action) { - case DASM_REL_LG: p++; op = p[-3]; goto rel_pc; - case DASM_REL_PC: op = p[-2]; rel_pc: { - int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0); - if (shrink) { /* Shrinkable branch opcode? */ - int lofs, lpos = b[pos]; - if (lpos < 0) goto noshrink; /* Ext global? */ - lofs = *DASM_POS2PTR(D, lpos); - if (lpos > pos) { /* Fwd label: add cumulative section offsets. */ - int i; - for (i = secnum; i < DASM_POS2SEC(lpos); i++) - lofs += D->sections[i].ofs; - } else { - lofs -= ofs; /* Bkwd label: unfix offset. */ - } - lofs -= b[pos+1]; /* Short branch ok? */ - if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */ - else { noshrink: shrink = 0; } /* No, cannot shrink op. */ - } - b[pos+1] = shrink; - pos += 2; - break; - } - case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++; - case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W: - case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB: - case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break; - case DASM_LABEL_LG: p++; - case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */ - case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */ - case DASM_EXTERN: p += 2; break; - case DASM_ESC: p++; break; - case DASM_MARK: break; - case DASM_SECTION: case DASM_STOP: goto stop; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#define dasmb(x) *cp++ = (unsigned char)(x) -#ifndef DASM_ALIGNED_WRITES -#define dasmw(x) \ - do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) -#define dasmd(x) \ - do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) -#else -#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) -#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - unsigned char *base = (unsigned char *)buffer; - unsigned char *cp = base; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - unsigned char *mark = NULL; - while (1) { - int action = *p++; - int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0; - switch (action) { - case DASM_DISP: if (!mark) mark = cp; { - unsigned char *mm = mark; - if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL; - if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7; - if (mrm != 5) { mm[-1] -= 0x80; break; } } - if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40; - } - case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break; - case DASM_IMM_DB: if (((n+128)&-256) == 0) { - db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb; - } else mark = NULL; - case DASM_IMM_D: wd: dasmd(n); break; - case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; - case DASM_IMM_W: dasmw(n); break; - case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; } - case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; - b++; n = (int)(ptrdiff_t)D->globals[-n]; - case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */ - case DASM_REL_PC: rel_pc: { - int shrink = *b++; - int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; } - n = *pb - ((int)(cp-base) + 4-shrink); - if (shrink == 0) goto wd; - if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb; - goto wb; - } - case DASM_IMM_LG: - p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } - case DASM_IMM_PC: { - int *pb = DASM_POS2PTR(D, n); - n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); - goto wd; - } - case DASM_LABEL_LG: { - int idx = *p++; - if (idx >= 10) - D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n)); - break; - } - case DASM_LABEL_PC: case DASM_SETLABEL: break; - case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; } - case DASM_ALIGN: - n = *p++; - while (((cp-base) & n)) *cp++ = 0x90; /* nop */ - break; - case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd; - case DASM_MARK: mark = cp; break; - case DASM_ESC: action = *p++; - default: *cp++ = action; break; - case DASM_SECTION: case DASM_STOP: goto stop; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections); - return D->status; -} -#endif - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x86.lua b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x86.lua deleted file mode 100644 index f5c8c5208d7..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dasm_x86.lua +++ /dev/null @@ -1,1931 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM x86/x64 module. --- --- Copyright (C) 2005-2011 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - -local x64 = x64 - --- Module information: -local _info = { - arch = x64 and "x64" or "x86", - description = "DynASM x86/x64 module", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, unpack, setmetatable = assert, unpack or table.unpack, setmetatable -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub -local concat, sort = table.concat, table.sort - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - -- int arg, 1 buffer pos: - "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB", - -- action arg (1 byte), int arg, 1 buffer pos (reg/num): - "VREG", "SPACE", -- !x64: VREG support NYI. - -- ptrdiff_t arg, 1 buffer pos (address): !x64 - "SETLABEL", "REL_A", - -- action arg (1 byte) or int arg, 2 buffer pos (link, offset): - "REL_LG", "REL_PC", - -- action arg (1 byte) or int arg, 1 buffer pos (link): - "IMM_LG", "IMM_PC", - -- action arg (1 byte) or int arg, 1 buffer pos (offset): - "LABEL_LG", "LABEL_PC", - -- action arg (1 byte), 1 buffer pos (offset): - "ALIGN", - -- action args (2 bytes), no buffer pos. - "EXTERN", - -- action arg (1 byte), no buffer pos. - "ESC", - -- no action arg, no buffer pos. - "MARK", - -- action arg (1 byte), no buffer pos, terminal action: - "SECTION", - -- no args, no buffer pos, terminal action: - "STOP" -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number (dynamically generated below). -local map_action = {} --- First action number. Everything below does not need to be escaped. -local actfirst = 256-#action_names - --- Action list buffer and string (only used to remove dupes). -local actlist = {} -local actstr = "" - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Compute action numbers for action names. -for n,name in ipairs(action_names) do - local num = actfirst + n - 1 - map_action[name] = num -end - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - local last = actlist[nn] or 255 - actlist[nn] = nil -- Remove last byte. - if nn == 0 then nn = 1 end - out:write("static const unsigned char ", name, "[", nn, "] = {\n") - local s = " " - for n,b in ipairs(actlist) do - s = s..b.."," - if #s >= 75 then - assert(out:write(s, "\n")) - s = " " - end - end - out:write(s, last, "\n};\n\n") -- Add last byte back. -end - ------------------------------------------------------------------------------- - --- Add byte to action list. -local function wputxb(n) - assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, a, num) - wputxb(assert(map_action[action], "bad action name `"..action.."'")) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Add call to embedded DynASM C code. -local function wcall(func, args) - wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true) -end - --- Delete duplicate action list chunks. A tad slow, but so what. -local function dedupechunk(offset) - local al, as = actlist, actstr - local chunk = char(unpack(al, offset+1, #al)) - local orig = find(as, chunk, 1, true) - if orig then - actargs[1] = orig-1 -- Replace with original offset. - for i=offset+1,#al do al[i] = nil end -- Kill dupe. - else - actstr = as..chunk - end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - local offset = actargs[1] - if #actlist == offset then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - dedupechunk(offset) - wcall("put", actargs) -- Add call to dasm_put(). - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped byte. -local function wputb(n) - if n >= actfirst then waction("ESC") end -- Need to escape byte. - wputxb(n) -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 10 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_@]*$") then werror("bad global label") end - local n = next_global - if n > 246 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=10,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=10,next_global-1 do - out:write(" ", prefix, gsub(t[i], "@.*", ""), ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=10,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = -1 -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n < -256 then werror("too many extern labels") end - next_extern = n - 1 - t[name] = n - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - local t = {} - for name, n in pairs(map_extern) do t[-n] = name end - out:write("Extern labels:\n") - for i=1,-next_extern-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - local t = {} - for name, n in pairs(map_extern) do t[-n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=1,-next_extern-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. -local map_archdef = {} -- Ext. register name -> int. name. -local map_reg_rev = {} -- Int. register name -> ext. name. -local map_reg_num = {} -- Int. register name -> register number. -local map_reg_opsize = {} -- Int. register name -> operand size. -local map_reg_valid_base = {} -- Int. register name -> valid base register? -local map_reg_valid_index = {} -- Int. register name -> valid index register? -local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex. -local reg_list = {} -- Canonical list of int. register names. - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for _PTx macros). - -local addrsize = x64 and "q" or "d" -- Size for address operands. - --- Helper functions to fill register maps. -local function mkrmap(sz, cl, names) - local cname = format("@%s", sz) - reg_list[#reg_list+1] = cname - map_archdef[cl] = cname - map_reg_rev[cname] = cl - map_reg_num[cname] = -1 - map_reg_opsize[cname] = sz - if sz == addrsize or sz == "d" then - map_reg_valid_base[cname] = true - map_reg_valid_index[cname] = true - end - if names then - for n,name in ipairs(names) do - local iname = format("@%s%x", sz, n-1) - reg_list[#reg_list+1] = iname - map_archdef[name] = iname - map_reg_rev[iname] = name - map_reg_num[iname] = n-1 - map_reg_opsize[iname] = sz - if sz == "b" and n > 4 then map_reg_needrex[iname] = false end - if sz == addrsize or sz == "d" then - map_reg_valid_base[iname] = true - map_reg_valid_index[iname] = true - end - end - end - for i=0,(x64 and sz ~= "f") and 15 or 7 do - local needrex = sz == "b" and i > 3 - local iname = format("@%s%x%s", sz, i, needrex and "R" or "") - if needrex then map_reg_needrex[iname] = true end - local name - if sz == "o" then name = format("xmm%d", i) - elseif sz == "f" then name = format("st%d", i) - else name = format("r%d%s", i, sz == addrsize and "" or sz) end - map_archdef[name] = iname - if not map_reg_rev[iname] then - reg_list[#reg_list+1] = iname - map_reg_rev[iname] = name - map_reg_num[iname] = i - map_reg_opsize[iname] = sz - if sz == addrsize or sz == "d" then - map_reg_valid_base[iname] = true - map_reg_valid_index[iname] = true - end - end - end - reg_list[#reg_list+1] = "" -end - --- Integer registers (qword, dword, word and byte sized). -if x64 then - mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"}) -end -mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}) -mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}) -mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}) -map_reg_valid_index[map_archdef.esp] = false -if x64 then map_reg_valid_index[map_archdef.rsp] = false end -map_archdef["Ra"] = "@"..addrsize - --- FP registers (internally tword sized, but use "f" as operand size). -mkrmap("f", "Rf") - --- SSE registers (oword sized, but qword and dword accessible). -mkrmap("o", "xmm") - --- Operand size prefixes to codes. -local map_opsize = { - byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t", - aword = addrsize, -} - --- Operand size code to number. -local map_opsizenum = { - b = 1, w = 2, d = 4, q = 8, o = 16, t = 10, -} - --- Operand size code to name. -local map_opsizename = { - b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword", - f = "fpword", -} - --- Valid index register scale factors. -local map_xsc = { - ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3, -} - --- Condition codes. -local map_cc = { - o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7, - s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15, - c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7, - pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15, -} - - --- Reverse defines for registers. -function _M.revdef(s) - return gsub(s, "@%w+", map_reg_rev) -end - --- Dump register names and numbers -local function dumpregs(out) - out:write("Register names, sizes and internal numbers:\n") - for _,reg in ipairs(reg_list) do - if reg == "" then - out:write("\n") - else - local name = map_reg_rev[reg] - local num = map_reg_num[reg] - local opsize = map_opsizename[map_reg_opsize[reg]] - out:write(format(" %-5s %-8s %s\n", name, opsize, - num < 0 and "(variable)" or num)) - end - end -end - ------------------------------------------------------------------------------- - --- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC). -local function wputlabel(aprefix, imm, num) - if type(imm) == "number" then - if imm < 0 then - waction("EXTERN") - wputxb(aprefix == "IMM_" and 0 or 1) - imm = -imm-1 - else - waction(aprefix.."LG", nil, num); - end - wputxb(imm) - else - waction(aprefix.."PC", imm, num) - end -end - --- Put signed byte or arg. -local function wputsbarg(n) - if type(n) == "number" then - if n < -128 or n > 127 then - werror("signed immediate byte out of range") - end - if n < 0 then n = n + 256 end - wputb(n) - else waction("IMM_S", n) end -end - --- Put unsigned byte or arg. -local function wputbarg(n) - if type(n) == "number" then - if n < 0 or n > 255 then - werror("unsigned immediate byte out of range") - end - wputb(n) - else waction("IMM_B", n) end -end - --- Put unsigned word or arg. -local function wputwarg(n) - if type(n) == "number" then - if n < 0 or n > 65535 then - werror("unsigned immediate word out of range") - end - local r = n%256; n = (n-r)/256; wputb(r); wputb(n); - else waction("IMM_W", n) end -end - --- Put signed or unsigned dword or arg. -local function wputdarg(n) - local tn = type(n) - if tn == "number" then - if n < 0 then n = n + 4294967296 end - local r = n%256; n = (n-r)/256; wputb(r); - r = n%256; n = (n-r)/256; wputb(r); - r = n%256; n = (n-r)/256; wputb(r); wputb(n); - elseif tn == "table" then - wputlabel("IMM_", n[1], 1) - else - waction("IMM_D", n) - end -end - --- Put operand-size dependent number or arg (defaults to dword). -local function wputszarg(sz, n) - if not sz or sz == "d" or sz == "q" then wputdarg(n) - elseif sz == "w" then wputwarg(n) - elseif sz == "b" then wputbarg(n) - elseif sz == "s" then wputsbarg(n) - else werror("bad operand size") end -end - --- Put multi-byte opcode with operand-size dependent modifications. -local function wputop(sz, op, rex) - local r - if rex ~= 0 and not x64 then werror("bad operand size") end - if sz == "w" then wputb(102) end - -- Needs >32 bit numbers, but only for crc32 eax, word [ebx] - if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end - if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end - if op >= 65536 then - if rex ~= 0 then - local opc3 = op - op % 256 - if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then - wputb(64 + rex % 16); rex = 0 - end - end - r = op % 65536 wputb((op-r) / 65536) op = r - end - if op >= 256 then - r = op % 256 - local b = (op-r) / 256 - if b == 15 and rex ~= 0 then wputb(64 + rex % 16); rex = 0 end - wputb(b) - op = r - end - if rex ~= 0 then wputb(64 + rex % 16) end - if sz == "b" then op = op - 1 end - wputb(op) -end - --- Put ModRM or SIB formatted byte. -local function wputmodrm(m, s, rm, vs, vrm) - assert(m < 4 and s < 16 and rm < 16, "bad modrm operands") - wputb(64*m + 8*(s%8) + (rm%8)) -end - --- Put ModRM/SIB plus optional displacement. -local function wputmrmsib(t, imark, s, vsreg) - local vreg, vxreg - local reg, xreg = t.reg, t.xreg - if reg and reg < 0 then reg = 0; vreg = t.vreg end - if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end - if s < 0 then s = 0 end - - -- Register mode. - if sub(t.mode, 1, 1) == "r" then - wputmodrm(3, s, reg) - if vsreg then waction("VREG", vsreg); wputxb(2) end - if vreg then waction("VREG", vreg); wputxb(0) end - return - end - - local disp = t.disp - local tdisp = type(disp) - -- No base register? - if not reg then - local riprel = false - if xreg then - -- Indexed mode with index register only. - -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp) - wputmodrm(0, s, 4) - if imark == "I" then waction("MARK") end - if vsreg then waction("VREG", vsreg); wputxb(2) end - wputmodrm(t.xsc, xreg, 5) - if vxreg then waction("VREG", vxreg); wputxb(3) end - else - -- Pure 32 bit displacement. - if x64 and tdisp ~= "table" then - wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp) - if imark == "I" then waction("MARK") end - wputmodrm(0, 4, 5) - else - riprel = x64 - wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp) - if imark == "I" then waction("MARK") end - end - if vsreg then waction("VREG", vsreg); wputxb(2) end - end - if riprel then -- Emit rip-relative displacement. - if match("UWSiI", imark) then - werror("NYI: rip-relative displacement followed by immediate") - end - -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f. - wputlabel("REL_", disp[1], 2) - else - wputdarg(disp) - end - return - end - - local m - if tdisp == "number" then -- Check displacement size at assembly time. - if disp == 0 and (reg%8) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too) - if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0] - elseif disp >= -128 and disp <= 127 then m = 1 - else m = 2 end - elseif tdisp == "table" then - m = 2 - end - - -- Index register present or esp as base register: need SIB encoding. - if xreg or (reg%8) == 4 then - wputmodrm(m or 2, s, 4) -- ModRM. - if m == nil or imark == "I" then waction("MARK") end - if vsreg then waction("VREG", vsreg); wputxb(2) end - wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB. - if vxreg then waction("VREG", vxreg); wputxb(3) end - if vreg then waction("VREG", vreg); wputxb(1) end - else - wputmodrm(m or 2, s, reg) -- ModRM. - if (imark == "I" and (m == 1 or m == 2)) or - (m == nil and (vsreg or vreg)) then waction("MARK") end - if vsreg then waction("VREG", vsreg); wputxb(2) end - if vreg then waction("VREG", vreg); wputxb(1) end - end - - -- Put displacement. - if m == 1 then wputsbarg(disp) - elseif m == 2 then wputdarg(disp) - elseif m == nil then waction("DISP", disp) end -end - ------------------------------------------------------------------------------- - --- Return human-readable operand mode string. -local function opmodestr(op, args) - local m = {} - for i=1,#args do - local a = args[i] - m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?") - end - return op.." "..concat(m, ",") -end - --- Convert number to valid integer or nil. -local function toint(expr) - local n = tonumber(expr) - if n then - if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then - werror("bad integer number `"..expr.."'") - end - return n - end -end - --- Parse immediate expression. -local function immexpr(expr) - -- &expr (pointer) - if sub(expr, 1, 1) == "&" then - return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2)) - end - - local prefix = sub(expr, 1, 2) - -- =>expr (pc label reference) - if prefix == "=>" then - return "iJ", sub(expr, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "iJ", map_global[sub(expr, 3)] - end - - -- [<>][1-9] (local label reference) - local dir, lnum = match(expr, "^([<>])([1-9])$") - if dir then -- Fwd: 247-255, Bkwd: 1-9. - return "iJ", lnum + (dir == ">" and 246 or 0) - end - - local extname = match(expr, "^extern%s+(%S+)$") - if extname then - return "iJ", map_extern[extname] - end - - -- expr (interpreted as immediate) - return "iI", expr -end - --- Parse displacement expression: +-num, +-expr, +-opsize*num -local function dispexpr(expr) - local disp = expr == "" and 0 or toint(expr) - if disp then return disp end - local c, dispt = match(expr, "^([+-])%s*(.+)$") - if c == "+" then - expr = dispt - elseif not c then - werror("bad displacement expression `"..expr.."'") - end - local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$") - local ops, imm = map_opsize[opsize], toint(tailops) - if ops and imm then - if c == "-" then imm = -imm end - return imm*map_opsizenum[ops] - end - local mode, iexpr = immexpr(dispt) - if mode == "iJ" then - if c == "-" then werror("cannot invert label reference") end - return { iexpr } - end - return expr -- Need to return original signed expression. -end - --- Parse register or type expression. -local function rtexpr(expr) - if not expr then return end - local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - local rnum = map_reg_num[reg] - if not rnum then - werror("type `"..(tname or expr).."' needs a register override") - end - if not map_reg_valid_base[reg] then - werror("bad base register override `"..(map_reg_rev[reg] or reg).."'") - end - return reg, rnum, tp - end - return expr, map_reg_num[expr] -end - --- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. -local function parseoperand(param) - local t = {} - - local expr = param - local opsize, tailops = match(param, "^(%w+)%s*(.+)$") - if opsize then - t.opsize = map_opsize[opsize] - if t.opsize then expr = tailops end - end - - local br = match(expr, "^%[%s*(.-)%s*%]$") - repeat - if br then - t.mode = "xm" - - -- [disp] - t.disp = toint(br) - if t.disp then - t.mode = x64 and "xm" or "xmO" - break - end - - -- [reg...] - local tp - local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$") - reg, t.reg, tp = rtexpr(reg) - if not t.reg then - -- [expr] - t.mode = x64 and "xm" or "xmO" - t.disp = dispexpr("+"..br) - break - end - - if t.reg == -1 then - t.vreg, tailr = match(tailr, "^(%b())(.*)$") - if not t.vreg then werror("bad variable register expression") end - end - - -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr] - local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$") - if xsc then - if not map_reg_valid_index[reg] then - werror("bad index register `"..map_reg_rev[reg].."'") - end - t.xsc = map_xsc[xsc] - t.xreg = t.reg - t.vxreg = t.vreg - t.reg = nil - t.vreg = nil - t.disp = dispexpr(tailsc) - break - end - if not map_reg_valid_base[reg] then - werror("bad base register `"..map_reg_rev[reg].."'") - end - - -- [reg] or [reg+-disp] - t.disp = toint(tailr) or (tailr == "" and 0) - if t.disp then break end - - -- [reg+xreg...] - local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$") - xreg, t.xreg, tp = rtexpr(xreg) - if not t.xreg then - -- [reg+-expr] - t.disp = dispexpr(tailr) - break - end - if not map_reg_valid_index[xreg] then - werror("bad index register `"..map_reg_rev[xreg].."'") - end - - if t.xreg == -1 then - t.vxreg, tailx = match(tailx, "^(%b())(.*)$") - if not t.vxreg then werror("bad variable register expression") end - end - - -- [reg+xreg*xsc...] - local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$") - if xsc then - t.xsc = map_xsc[xsc] - tailx = tailsc - end - - -- [...] or [...+-disp] or [...+-expr] - t.disp = dispexpr(tailx) - else - -- imm or opsize*imm - local imm = toint(expr) - if not imm and sub(expr, 1, 1) == "*" and t.opsize then - imm = toint(sub(expr, 2)) - if imm then - imm = imm * map_opsizenum[t.opsize] - t.opsize = nil - end - end - if imm then - if t.opsize then werror("bad operand size override") end - local m = "i" - if imm == 1 then m = m.."1" end - if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end - if imm >= -128 and imm <= 127 then m = m.."S" end - t.imm = imm - t.mode = m - break - end - - local tp - local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$") - reg, t.reg, tp = rtexpr(reg) - if t.reg then - if t.reg == -1 then - t.vreg, tailr = match(tailr, "^(%b())(.*)$") - if not t.vreg then werror("bad variable register expression") end - end - -- reg - if tailr == "" then - if t.opsize then werror("bad operand size override") end - t.opsize = map_reg_opsize[reg] - if t.opsize == "f" then - t.mode = t.reg == 0 and "fF" or "f" - else - if reg == "@w4" or (x64 and reg == "@d4") then - wwarn("bad idea, try again with `"..(x64 and "rsp'" or "esp'")) - end - t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm") - end - t.needrex = map_reg_needrex[reg] - break - end - - -- type[idx], type[idx].field, type->field -> [reg+offset_expr] - if not tp then werror("bad operand `"..param.."'") end - t.mode = "xm" - t.disp = format(tp.ctypefmt, tailr) - else - t.mode, t.imm = immexpr(expr) - if sub(t.mode, -1) == "J" then - if t.opsize and t.opsize ~= addrsize then - werror("bad operand size override") - end - t.opsize = addrsize - end - end - end - until true - return t -end - ------------------------------------------------------------------------------- --- x86 Template String Description --- =============================== --- --- Each template string is a list of [match:]pattern pairs, --- separated by "|". The first match wins. No match means a --- bad or unsupported combination of operand modes or sizes. --- --- The match part and the ":" is omitted if the operation has --- no operands. Otherwise the first N characters are matched --- against the mode strings of each of the N operands. --- --- The mode string for each operand type is (see parseoperand()): --- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl --- FP register: "f", +"F" for st0 --- Index operand: "xm", +"O" for [disp] (pure offset) --- Immediate: "i", +"S" for signed 8 bit, +"1" for 1, --- +"I" for arg, +"P" for pointer --- Any: +"J" for valid jump targets --- --- So a match character "m" (mixed) matches both an integer register --- and an index operand (to be encoded with the ModRM/SIB scheme). --- But "r" matches only a register and "x" only an index operand --- (e.g. for FP memory access operations). --- --- The operand size match string starts right after the mode match --- characters and ends before the ":". "dwb" or "qdwb" is assumed, if empty. --- The effective data size of the operation is matched against this list. --- --- If only the regular "b", "w", "d", "q", "t" operand sizes are --- present, then all operands must be the same size. Unspecified sizes --- are ignored, but at least one operand must have a size or the pattern --- won't match (use the "byte", "word", "dword", "qword", "tword" --- operand size overrides. E.g.: mov dword [eax], 1). --- --- If the list has a "1" or "2" prefix, the operand size is taken --- from the respective operand and any other operand sizes are ignored. --- If the list contains only ".", all operand sizes are ignored. --- If the list has a "/" prefix, the concatenated (mixed) operand sizes --- are compared to the match. --- --- E.g. "rrdw" matches for either two dword registers or two word --- registers. "Fx2dq" matches an st0 operand plus an index operand --- pointing to a dword (float) or qword (double). --- --- Every character after the ":" is part of the pattern string: --- Hex chars are accumulated to form the opcode (left to right). --- "n" disables the standard opcode mods --- (otherwise: -1 for "b", o16 prefix for "w", rex.w for "q") --- "X" Force REX.W. --- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode. --- "m"/"M" generates ModRM/SIB from the 1st/2nd operand. --- The spare 3 bits are either filled with the last hex digit or --- the result from a previous "r"/"R". The opcode is restored. --- --- All of the following characters force a flush of the opcode: --- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand. --- "S" stores a signed 8 bit immediate from the last operand. --- "U" stores an unsigned 8 bit immediate from the last operand. --- "W" stores an unsigned 16 bit immediate from the last operand. --- "i" stores an operand sized immediate from the last operand. --- "I" dito, but generates an action code to optionally modify --- the opcode (+2) for a signed 8 bit immediate. --- "J" generates one of the REL action codes from the last operand. --- ------------------------------------------------------------------------------- - --- Template strings for x86 instructions. Ordered by first opcode byte. --- Unimplemented opcodes (deliberate omissions) are marked with *. -local map_op = { - -- 00-05: add... - -- 06: *push es - -- 07: *pop es - -- 08-0D: or... - -- 0E: *push cs - -- 0F: two byte opcode prefix - -- 10-15: adc... - -- 16: *push ss - -- 17: *pop ss - -- 18-1D: sbb... - -- 1E: *push ds - -- 1F: *pop ds - -- 20-25: and... - es_0 = "26", - -- 27: *daa - -- 28-2D: sub... - cs_0 = "2E", - -- 2F: *das - -- 30-35: xor... - ss_0 = "36", - -- 37: *aaa - -- 38-3D: cmp... - ds_0 = "3E", - -- 3F: *aas - inc_1 = x64 and "m:FF0m" or "rdw:40r|m:FF0m", - dec_1 = x64 and "m:FF1m" or "rdw:48r|m:FF1m", - push_1 = (x64 and "rq:n50r|rw:50r|mq:nFF6m|mw:FF6m" or - "rdw:50r|mdw:FF6m").."|S.:6AS|ib:n6Ai|i.:68i", - pop_1 = x64 and "rq:n58r|rw:58r|mq:n8F0m|mw:8F0m" or "rdw:58r|mdw:8F0m", - -- 60: *pusha, *pushad, *pushaw - -- 61: *popa, *popad, *popaw - -- 62: *bound rdw,x - -- 63: x86: *arpl mw,rw - movsxd_2 = x64 and "rm/qd:63rM", - fs_0 = "64", - gs_0 = "65", - o16_0 = "66", - a16_0 = not x64 and "67" or nil, - a32_0 = x64 and "67", - -- 68: push idw - -- 69: imul rdw,mdw,idw - -- 6A: push ib - -- 6B: imul rdw,mdw,S - -- 6C: *insb - -- 6D: *insd, *insw - -- 6E: *outsb - -- 6F: *outsd, *outsw - -- 70-7F: jcc lb - -- 80: add... mb,i - -- 81: add... mdw,i - -- 82: *undefined - -- 83: add... mdw,S - test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi", - -- 86: xchg rb,mb - -- 87: xchg rdw,mdw - -- 88: mov mb,r - -- 89: mov mdw,r - -- 8A: mov r,mb - -- 8B: mov r,mdw - -- 8C: *mov mdw,seg - lea_2 = "rx1dq:8DrM", - -- 8E: *mov seg,mdw - -- 8F: pop mdw - nop_0 = "90", - xchg_2 = "Rrqdw:90R|rRqdw:90r|rm:87rM|mr:87Rm", - cbw_0 = "6698", - cwde_0 = "98", - cdqe_0 = "4898", - cwd_0 = "6699", - cdq_0 = "99", - cqo_0 = "4899", - -- 9A: *call iw:idw - wait_0 = "9B", - fwait_0 = "9B", - pushf_0 = "9C", - pushfd_0 = not x64 and "9C", - pushfq_0 = x64 and "9C", - popf_0 = "9D", - popfd_0 = not x64 and "9D", - popfq_0 = x64 and "9D", - sahf_0 = "9E", - lahf_0 = "9F", - mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi", - movsb_0 = "A4", - movsw_0 = "66A5", - movsd_0 = "A5", - cmpsb_0 = "A6", - cmpsw_0 = "66A7", - cmpsd_0 = "A7", - -- A8: test Rb,i - -- A9: test Rdw,i - stosb_0 = "AA", - stosw_0 = "66AB", - stosd_0 = "AB", - lodsb_0 = "AC", - lodsw_0 = "66AD", - lodsd_0 = "AD", - scasb_0 = "AE", - scasw_0 = "66AF", - scasd_0 = "AF", - -- B0-B7: mov rb,i - -- B8-BF: mov rdw,i - -- C0: rol... mb,i - -- C1: rol... mdw,i - ret_1 = "i.:nC2W", - ret_0 = "C3", - -- C4: *les rdw,mq - -- C5: *lds rdw,mq - -- C6: mov mb,i - -- C7: mov mdw,i - -- C8: *enter iw,ib - leave_0 = "C9", - -- CA: *retf iw - -- CB: *retf - int3_0 = "CC", - int_1 = "i.:nCDU", - into_0 = "CE", - -- CF: *iret - -- D0: rol... mb,1 - -- D1: rol... mdw,1 - -- D2: rol... mb,cl - -- D3: rol... mb,cl - -- D4: *aam ib - -- D5: *aad ib - -- D6: *salc - -- D7: *xlat - -- D8-DF: floating point ops - -- E0: *loopne - -- E1: *loope - -- E2: *loop - -- E3: *jcxz, *jecxz - -- E4: *in Rb,ib - -- E5: *in Rdw,ib - -- E6: *out ib,Rb - -- E7: *out ib,Rdw - call_1 = x64 and "mq:nFF2m|J.:E8nJ" or "md:FF2m|J.:E8J", - jmp_1 = x64 and "mq:nFF4m|J.:E9nJ" or "md:FF4m|J.:E9J", -- short: EB - -- EA: *jmp iw:idw - -- EB: jmp ib - -- EC: *in Rb,dx - -- ED: *in Rdw,dx - -- EE: *out dx,Rb - -- EF: *out dx,Rdw - -- F0: *lock - int1_0 = "F1", - repne_0 = "F2", - repnz_0 = "F2", - rep_0 = "F3", - repe_0 = "F3", - repz_0 = "F3", - -- F4: *hlt - cmc_0 = "F5", - -- F6: test... mb,i; div... mb - -- F7: test... mdw,i; div... mdw - clc_0 = "F8", - stc_0 = "F9", - -- FA: *cli - cld_0 = "FC", - std_0 = "FD", - -- FE: inc... mb - -- FF: inc... mdw - - -- misc ops - not_1 = "m:F72m", - neg_1 = "m:F73m", - mul_1 = "m:F74m", - imul_1 = "m:F75m", - div_1 = "m:F76m", - idiv_1 = "m:F77m", - - imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi", - imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi", - - movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:", - movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:", - - bswap_1 = "rqd:0FC8r", - bsf_2 = "rmqdw:0FBCrM", - bsr_2 = "rmqdw:0FBDrM", - bt_2 = "mrqdw:0FA3Rm|miqdw:0FBA4mU", - btc_2 = "mrqdw:0FBBRm|miqdw:0FBA7mU", - btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU", - bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU", - - rdtsc_0 = "0F31", -- P1+ - cpuid_0 = "0FA2", -- P1+ - - -- floating point ops - fst_1 = "ff:DDD0r|xd:D92m|xq:nDD2m", - fstp_1 = "ff:DDD8r|xd:D93m|xq:nDD3m|xt:DB7m", - fld_1 = "ff:D9C0r|xd:D90m|xq:nDD0m|xt:DB5m", - - fpop_0 = "DDD8", -- Alias for fstp st0. - - fist_1 = "xw:nDF2m|xd:DB2m", - fistp_1 = "xw:nDF3m|xd:DB3m|xq:nDF7m", - fild_1 = "xw:nDF0m|xd:DB0m|xq:nDF5m", - - fxch_0 = "D9C9", - fxch_1 = "ff:D9C8r", - fxch_2 = "fFf:D9C8r|Fff:D9C8R", - - fucom_1 = "ff:DDE0r", - fucom_2 = "Fff:DDE0R", - fucomp_1 = "ff:DDE8r", - fucomp_2 = "Fff:DDE8R", - fucomi_1 = "ff:DBE8r", -- P6+ - fucomi_2 = "Fff:DBE8R", -- P6+ - fucomip_1 = "ff:DFE8r", -- P6+ - fucomip_2 = "Fff:DFE8R", -- P6+ - fcomi_1 = "ff:DBF0r", -- P6+ - fcomi_2 = "Fff:DBF0R", -- P6+ - fcomip_1 = "ff:DFF0r", -- P6+ - fcomip_2 = "Fff:DFF0R", -- P6+ - fucompp_0 = "DAE9", - fcompp_0 = "DED9", - - fldcw_1 = "xw:nD95m", - fstcw_1 = "xw:n9BD97m", - fnstcw_1 = "xw:nD97m", - fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m", - fnstsw_1 = "Rw:nDFE0|xw:nDD7m", - fclex_0 = "9BDBE2", - fnclex_0 = "DBE2", - - fnop_0 = "D9D0", - -- D9D1-D9DF: unassigned - - fchs_0 = "D9E0", - fabs_0 = "D9E1", - -- D9E2: unassigned - -- D9E3: unassigned - ftst_0 = "D9E4", - fxam_0 = "D9E5", - -- D9E6: unassigned - -- D9E7: unassigned - fld1_0 = "D9E8", - fldl2t_0 = "D9E9", - fldl2e_0 = "D9EA", - fldpi_0 = "D9EB", - fldlg2_0 = "D9EC", - fldln2_0 = "D9ED", - fldz_0 = "D9EE", - -- D9EF: unassigned - - f2xm1_0 = "D9F0", - fyl2x_0 = "D9F1", - fptan_0 = "D9F2", - fpatan_0 = "D9F3", - fxtract_0 = "D9F4", - fprem1_0 = "D9F5", - fdecstp_0 = "D9F6", - fincstp_0 = "D9F7", - fprem_0 = "D9F8", - fyl2xp1_0 = "D9F9", - fsqrt_0 = "D9FA", - fsincos_0 = "D9FB", - frndint_0 = "D9FC", - fscale_0 = "D9FD", - fsin_0 = "D9FE", - fcos_0 = "D9FF", - - -- SSE, SSE2 - andnpd_2 = "rmo:660F55rM", - andnps_2 = "rmo:0F55rM", - andpd_2 = "rmo:660F54rM", - andps_2 = "rmo:0F54rM", - clflush_1 = "x.:0FAE7m", - cmppd_3 = "rmio:660FC2rMU", - cmpps_3 = "rmio:0FC2rMU", - cmpsd_3 = "rrio:F20FC2rMU|rxi/oq:", - cmpss_3 = "rrio:F30FC2rMU|rxi/od:", - comisd_2 = "rro:660F2FrM|rx/oq:", - comiss_2 = "rro:0F2FrM|rx/od:", - cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:", - cvtdq2ps_2 = "rmo:0F5BrM", - cvtpd2dq_2 = "rmo:F20FE6rM", - cvtpd2ps_2 = "rmo:660F5ArM", - cvtpi2pd_2 = "rx/oq:660F2ArM", - cvtpi2ps_2 = "rx/oq:0F2ArM", - cvtps2dq_2 = "rmo:660F5BrM", - cvtps2pd_2 = "rro:0F5ArM|rx/oq:", - cvtsd2si_2 = "rr/do:F20F2DrM|rr/qo:|rx/dq:|rxq:", - cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:", - cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM", - cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM", - cvtss2sd_2 = "rro:F30F5ArM|rx/od:", - cvtss2si_2 = "rr/do:F20F2CrM|rr/qo:|rxd:|rx/qd:", - cvttpd2dq_2 = "rmo:660FE6rM", - cvttps2dq_2 = "rmo:F30F5BrM", - cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:", - cvttss2si_2 = "rr/do:F30F2CrM|rr/qo:|rxd:|rx/qd:", - ldmxcsr_1 = "xd:0FAE2m", - lfence_0 = "0FAEE8", - maskmovdqu_2 = "rro:660FF7rM", - mfence_0 = "0FAEF0", - movapd_2 = "rmo:660F28rM|mro:660F29Rm", - movaps_2 = "rmo:0F28rM|mro:0F29Rm", - movd_2 = "rm/od:660F6ErM|rm/oq:660F6ErXM|mr/do:660F7ERm|mr/qo:", - movdqa_2 = "rmo:660F6FrM|mro:660F7FRm", - movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm", - movhlps_2 = "rro:0F12rM", - movhpd_2 = "rx/oq:660F16rM|xr/qo:n660F17Rm", - movhps_2 = "rx/oq:0F16rM|xr/qo:n0F17Rm", - movlhps_2 = "rro:0F16rM", - movlpd_2 = "rx/oq:660F12rM|xr/qo:n660F13Rm", - movlps_2 = "rx/oq:0F12rM|xr/qo:n0F13Rm", - movmskpd_2 = "rr/do:660F50rM", - movmskps_2 = "rr/do:0F50rM", - movntdq_2 = "xro:660FE7Rm", - movnti_2 = "xrqd:0FC3Rm", - movntpd_2 = "xro:660F2BRm", - movntps_2 = "xro:0F2BRm", - movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:n660FD6Rm", - movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:nF20F11Rm", - movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm", - movupd_2 = "rmo:660F10rM|mro:660F11Rm", - movups_2 = "rmo:0F10rM|mro:0F11Rm", - orpd_2 = "rmo:660F56rM", - orps_2 = "rmo:0F56rM", - packssdw_2 = "rmo:660F6BrM", - packsswb_2 = "rmo:660F63rM", - packuswb_2 = "rmo:660F67rM", - paddb_2 = "rmo:660FFCrM", - paddd_2 = "rmo:660FFErM", - paddq_2 = "rmo:660FD4rM", - paddsb_2 = "rmo:660FECrM", - paddsw_2 = "rmo:660FEDrM", - paddusb_2 = "rmo:660FDCrM", - paddusw_2 = "rmo:660FDDrM", - paddw_2 = "rmo:660FFDrM", - pand_2 = "rmo:660FDBrM", - pandn_2 = "rmo:660FDFrM", - pause_0 = "F390", - pavgb_2 = "rmo:660FE0rM", - pavgw_2 = "rmo:660FE3rM", - pcmpeqb_2 = "rmo:660F74rM", - pcmpeqd_2 = "rmo:660F76rM", - pcmpeqw_2 = "rmo:660F75rM", - pcmpgtb_2 = "rmo:660F64rM", - pcmpgtd_2 = "rmo:660F66rM", - pcmpgtw_2 = "rmo:660F65rM", - pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nrMU", -- Mem op: SSE4.1 only. - pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:", - pmaddwd_2 = "rmo:660FF5rM", - pmaxsw_2 = "rmo:660FEErM", - pmaxub_2 = "rmo:660FDErM", - pminsw_2 = "rmo:660FEArM", - pminub_2 = "rmo:660FDArM", - pmovmskb_2 = "rr/do:660FD7rM", - pmulhuw_2 = "rmo:660FE4rM", - pmulhw_2 = "rmo:660FE5rM", - pmullw_2 = "rmo:660FD5rM", - pmuludq_2 = "rmo:660FF4rM", - por_2 = "rmo:660FEBrM", - prefetchnta_1 = "xb:n0F180m", - prefetcht0_1 = "xb:n0F181m", - prefetcht1_1 = "xb:n0F182m", - prefetcht2_1 = "xb:n0F183m", - psadbw_2 = "rmo:660FF6rM", - pshufd_3 = "rmio:660F70rMU", - pshufhw_3 = "rmio:F30F70rMU", - pshuflw_3 = "rmio:F20F70rMU", - pslld_2 = "rmo:660FF2rM|rio:660F726mU", - pslldq_2 = "rio:660F737mU", - psllq_2 = "rmo:660FF3rM|rio:660F736mU", - psllw_2 = "rmo:660FF1rM|rio:660F716mU", - psrad_2 = "rmo:660FE2rM|rio:660F724mU", - psraw_2 = "rmo:660FE1rM|rio:660F714mU", - psrld_2 = "rmo:660FD2rM|rio:660F722mU", - psrldq_2 = "rio:660F733mU", - psrlq_2 = "rmo:660FD3rM|rio:660F732mU", - psrlw_2 = "rmo:660FD1rM|rio:660F712mU", - psubb_2 = "rmo:660FF8rM", - psubd_2 = "rmo:660FFArM", - psubq_2 = "rmo:660FFBrM", - psubsb_2 = "rmo:660FE8rM", - psubsw_2 = "rmo:660FE9rM", - psubusb_2 = "rmo:660FD8rM", - psubusw_2 = "rmo:660FD9rM", - psubw_2 = "rmo:660FF9rM", - punpckhbw_2 = "rmo:660F68rM", - punpckhdq_2 = "rmo:660F6ArM", - punpckhqdq_2 = "rmo:660F6DrM", - punpckhwd_2 = "rmo:660F69rM", - punpcklbw_2 = "rmo:660F60rM", - punpckldq_2 = "rmo:660F62rM", - punpcklqdq_2 = "rmo:660F6CrM", - punpcklwd_2 = "rmo:660F61rM", - pxor_2 = "rmo:660FEFrM", - rcpps_2 = "rmo:0F53rM", - rcpss_2 = "rro:F30F53rM|rx/od:", - rsqrtps_2 = "rmo:0F52rM", - rsqrtss_2 = "rmo:F30F52rM", - sfence_0 = "0FAEF8", - shufpd_3 = "rmio:660FC6rMU", - shufps_3 = "rmio:0FC6rMU", - stmxcsr_1 = "xd:0FAE3m", - ucomisd_2 = "rro:660F2ErM|rx/oq:", - ucomiss_2 = "rro:0F2ErM|rx/od:", - unpckhpd_2 = "rmo:660F15rM", - unpckhps_2 = "rmo:0F15rM", - unpcklpd_2 = "rmo:660F14rM", - unpcklps_2 = "rmo:0F14rM", - xorpd_2 = "rmo:660F57rM", - xorps_2 = "rmo:0F57rM", - - -- SSE3 ops - fisttp_1 = "xw:nDF1m|xd:DB1m|xq:nDD1m", - addsubpd_2 = "rmo:660FD0rM", - addsubps_2 = "rmo:F20FD0rM", - haddpd_2 = "rmo:660F7CrM", - haddps_2 = "rmo:F20F7CrM", - hsubpd_2 = "rmo:660F7DrM", - hsubps_2 = "rmo:F20F7DrM", - lddqu_2 = "rxo:F20FF0rM", - movddup_2 = "rmo:F20F12rM", - movshdup_2 = "rmo:F30F16rM", - movsldup_2 = "rmo:F30F12rM", - - -- SSSE3 ops - pabsb_2 = "rmo:660F381CrM", - pabsd_2 = "rmo:660F381ErM", - pabsw_2 = "rmo:660F381DrM", - palignr_3 = "rmio:660F3A0FrMU", - phaddd_2 = "rmo:660F3802rM", - phaddsw_2 = "rmo:660F3803rM", - phaddw_2 = "rmo:660F3801rM", - phsubd_2 = "rmo:660F3806rM", - phsubsw_2 = "rmo:660F3807rM", - phsubw_2 = "rmo:660F3805rM", - pmaddubsw_2 = "rmo:660F3804rM", - pmulhrsw_2 = "rmo:660F380BrM", - pshufb_2 = "rmo:660F3800rM", - psignb_2 = "rmo:660F3808rM", - psignd_2 = "rmo:660F380ArM", - psignw_2 = "rmo:660F3809rM", - - -- SSE4.1 ops - blendpd_3 = "rmio:660F3A0DrMU", - blendps_3 = "rmio:660F3A0CrMU", - blendvpd_3 = "rmRo:660F3815rM", - blendvps_3 = "rmRo:660F3814rM", - dppd_3 = "rmio:660F3A41rMU", - dpps_3 = "rmio:660F3A40rMU", - extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU", - insertps_3 = "rrio:660F3A41rMU|rxi/od:", - movntdqa_2 = "rmo:660F382ArM", - mpsadbw_3 = "rmio:660F3A42rMU", - packusdw_2 = "rmo:660F382BrM", - pblendvb_3 = "rmRo:660F3810rM", - pblendw_3 = "rmio:660F3A0ErMU", - pcmpeqq_2 = "rmo:660F3829rM", - pextrb_3 = "rri/do:660F3A14nRmU|rri/qo:|xri/bo:", - pextrd_3 = "mri/do:660F3A16RmU", - pextrq_3 = "mri/qo:660F3A16RmU", - -- pextrw is SSE2, mem operand is SSE4.1 only - phminposuw_2 = "rmo:660F3841rM", - pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:", - pinsrd_3 = "rmi/od:660F3A22rMU", - pinsrq_3 = "rmi/oq:660F3A22rXMU", - pmaxsb_2 = "rmo:660F383CrM", - pmaxsd_2 = "rmo:660F383DrM", - pmaxud_2 = "rmo:660F383FrM", - pmaxuw_2 = "rmo:660F383ErM", - pminsb_2 = "rmo:660F3838rM", - pminsd_2 = "rmo:660F3839rM", - pminud_2 = "rmo:660F383BrM", - pminuw_2 = "rmo:660F383ArM", - pmovsxbd_2 = "rro:660F3821rM|rx/od:", - pmovsxbq_2 = "rro:660F3822rM|rx/ow:", - pmovsxbw_2 = "rro:660F3820rM|rx/oq:", - pmovsxdq_2 = "rro:660F3825rM|rx/oq:", - pmovsxwd_2 = "rro:660F3823rM|rx/oq:", - pmovsxwq_2 = "rro:660F3824rM|rx/od:", - pmovzxbd_2 = "rro:660F3831rM|rx/od:", - pmovzxbq_2 = "rro:660F3832rM|rx/ow:", - pmovzxbw_2 = "rro:660F3830rM|rx/oq:", - pmovzxdq_2 = "rro:660F3835rM|rx/oq:", - pmovzxwd_2 = "rro:660F3833rM|rx/oq:", - pmovzxwq_2 = "rro:660F3834rM|rx/od:", - pmuldq_2 = "rmo:660F3828rM", - pmulld_2 = "rmo:660F3840rM", - ptest_2 = "rmo:660F3817rM", - roundpd_3 = "rmio:660F3A09rMU", - roundps_3 = "rmio:660F3A08rMU", - roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:", - roundss_3 = "rrio:660F3A0ArMU|rxi/od:", - - -- SSE4.2 ops - crc32_2 = "rmqd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0rM|rm/qb:", - pcmpestri_3 = "rmio:660F3A61rMU", - pcmpestrm_3 = "rmio:660F3A60rMU", - pcmpgtq_2 = "rmo:660F3837rM", - pcmpistri_3 = "rmio:660F3A63rMU", - pcmpistrm_3 = "rmio:660F3A62rMU", - popcnt_2 = "rmqdw:F30FB8rM", - - -- SSE4a - extrq_2 = "rro:660F79rM", - extrq_3 = "riio:660F780mUU", - insertq_2 = "rro:F20F79rM", - insertq_4 = "rriio:F20F78rMUU", - lzcnt_2 = "rmqdw:F30FBDrM", - movntsd_2 = "xr/qo:nF20F2BRm", - movntss_2 = "xr/do:F30F2BRm", - -- popcnt is also in SSE4.2 -} - ------------------------------------------------------------------------------- - --- Arithmetic ops. -for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3, - ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do - local n8 = n * 8 - map_op[name.."_2"] = format( - "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi", - 1+n8, 3+n8, n, n, 5+n8, n) -end - --- Shift ops. -for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3, - shl = 4, shr = 5, sar = 7, sal = 4 } do - map_op[name.."_2"] = format("m1:D1%Xm|mC1qdwb:D3%Xm|mi:C1%XmU", n, n, n) -end - --- Conditional ops. -for cc,n in pairs(map_cc) do - map_op["j"..cc.."_1"] = format("J.:n0F8%XJ", n) -- short: 7%X - map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n) - map_op["cmov"..cc.."_2"] = format("rmqdw:0F4%XrM", n) -- P6+ -end - --- FP arithmetic ops. -for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3, - sub = 4, subr = 5, div = 6, divr = 7 } do - local nc = 192 + n * 8 - local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8)) - local fn = "f"..name - map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n) - if n == 2 or n == 3 then - map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:nDC%XM", nc, n, n) - else - map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:nDC%XM", nc, nr, n, n) - map_op[fn.."p_1"] = format("ff:DE%02Xr", nr) - map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr) - end - map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n) -end - --- FP conditional moves. -for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do - local n4 = n % 4 - local nc = 56000 + n4 * 8 + (n-n4) * 64 - map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+ - map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+ -end - --- SSE FP arithmetic ops. -for name,n in pairs{ sqrt = 1, add = 8, mul = 9, - sub = 12, min = 13, div = 14, max = 15 } do - map_op[name.."ps_2"] = format("rmo:0F5%XrM", n) - map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n) - map_op[name.."pd_2"] = format("rmo:660F5%XrM", n) - map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n) -end - ------------------------------------------------------------------------------- - --- Process pattern string. -local function dopattern(pat, args, sz, op, needrex) - local digit, addin - local opcode = 0 - local szov = sz - local narg = 1 - local rex = 0 - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 5 positions. - if secpos+5 > maxsecpos then wflush() end - - -- Process each character. - for c in gmatch(pat.."|", ".") do - if match(c, "%x") then -- Hex digit. - digit = byte(c) - 48 - if digit > 48 then digit = digit - 39 - elseif digit > 16 then digit = digit - 7 end - opcode = opcode*16 + digit - addin = nil - elseif c == "n" then -- Disable operand size mods for opcode. - szov = nil - elseif c == "X" then -- Force REX.W. - rex = 8 - elseif c == "r" then -- Merge 1st operand regno. into opcode. - addin = args[1]; opcode = opcode + (addin.reg % 8) - if narg < 2 then narg = 2 end - elseif c == "R" then -- Merge 2nd operand regno. into opcode. - addin = args[2]; opcode = opcode + (addin.reg % 8) - narg = 3 - elseif c == "m" or c == "M" then -- Encode ModRM/SIB. - local s - if addin then - s = addin.reg - opcode = opcode - (s%8) -- Undo regno opcode merge. - else - s = opcode % 16 -- Undo last digit. - opcode = (opcode - s) / 16 - end - local nn = c == "m" and 1 or 2 - local t = args[nn] - if narg <= nn then narg = nn + 1 end - if szov == "q" and rex == 0 then rex = rex + 8 end - if t.reg and t.reg > 7 then rex = rex + 1 end - if t.xreg and t.xreg > 7 then rex = rex + 2 end - if s > 7 then rex = rex + 4 end - if needrex then rex = rex + 16 end - wputop(szov, opcode, rex); opcode = nil - local imark = sub(pat, -1) -- Force a mark (ugly). - -- Put ModRM/SIB with regno/last digit as spare. - wputmrmsib(t, imark, s, addin and addin.vreg) - addin = nil - else - if opcode then -- Flush opcode. - if szov == "q" and rex == 0 then rex = rex + 8 end - if needrex then rex = rex + 16 end - if addin and addin.reg == -1 then - wputop(szov, opcode - 7, rex) - waction("VREG", addin.vreg); wputxb(0) - else - if addin and addin.reg > 7 then rex = rex + 1 end - wputop(szov, opcode, rex) - end - opcode = nil - end - if c == "|" then break end - if c == "o" then -- Offset (pure 32 bit displacement). - wputdarg(args[1].disp); if narg < 2 then narg = 2 end - elseif c == "O" then - wputdarg(args[2].disp); narg = 3 - else - -- Anything else is an immediate operand. - local a = args[narg] - narg = narg + 1 - local mode, imm = a.mode, a.imm - if mode == "iJ" and not match("iIJ", c) then - werror("bad operand size for label") - end - if c == "S" then - wputsbarg(imm) - elseif c == "U" then - wputbarg(imm) - elseif c == "W" then - wputwarg(imm) - elseif c == "i" or c == "I" then - if mode == "iJ" then - wputlabel("IMM_", imm, 1) - elseif mode == "iI" and c == "I" then - waction(sz == "w" and "IMM_WB" or "IMM_DB", imm) - else - wputszarg(sz, imm) - end - elseif c == "J" then - if mode == "iPJ" then - waction("REL_A", imm) -- !x64 (secpos) - else - wputlabel("REL_", imm, 2) - end - else - werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'") - end - end - end - end -end - ------------------------------------------------------------------------------- - --- Mapping of operand modes to short names. Suppress output with '#'. -local map_modename = { - r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm", - f = "stx", F = "st0", J = "lbl", ["1"] = "1", - I = "#", S = "#", O = "#", -} - --- Return a table/string showing all possible operand modes. -local function templatehelp(template, nparams) - if nparams == 0 then return "" end - local t = {} - for tm in gmatch(template, "[^%|]+") do - local s = map_modename[sub(tm, 1, 1)] - s = s..gsub(sub(tm, 2, nparams), ".", function(c) - return ", "..map_modename[c] - end) - if not match(s, "#") then t[#t+1] = s end - end - return t -end - --- Match operand modes against mode match part of template. -local function matchtm(tm, args) - for i=1,#args do - if not match(args[i].mode, sub(tm, i, i)) then return end - end - return true -end - --- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) - if not params then return templatehelp(template, nparams) end - local args = {} - - -- Zero-operand opcodes have no match part. - if #params == 0 then - dopattern(template, args, "d", params.op, nil) - return - end - - -- Determine common operand size (coerce undefined size) or flag as mixed. - local sz, szmix, needrex - for i,p in ipairs(params) do - args[i] = parseoperand(p) - local nsz = args[i].opsize - if nsz then - if sz and sz ~= nsz then szmix = true else sz = nsz end - end - local nrex = args[i].needrex - if nrex ~= nil then - if needrex == nil then - needrex = nrex - elseif needrex ~= nrex then - werror("bad mix of byte-addressable registers") - end - end - end - - -- Try all match:pattern pairs (separated by '|'). - local gotmatch, lastpat - for tm in gmatch(template, "[^%|]+") do - -- Split off size match (starts after mode match) and pattern string. - local szm, pat = match(tm, "^(.-):(.*)$", #args+1) - if pat == "" then pat = lastpat else lastpat = pat end - if matchtm(tm, args) then - local prefix = sub(szm, 1, 1) - if prefix == "/" then -- Match both operand sizes. - if args[1].opsize == sub(szm, 2, 2) and - args[2].opsize == sub(szm, 3, 3) then - dopattern(pat, args, sz, params.op, needrex) -- Process pattern. - return - end - else -- Match common operand size. - local szp = sz - if szm == "" then szm = x64 and "qdwb" or "dwb" end -- Default sizes. - if prefix == "1" then szp = args[1].opsize; szmix = nil - elseif prefix == "2" then szp = args[2].opsize; szmix = nil end - if not szmix and (prefix == "." or match(szm, szp or "#")) then - dopattern(pat, args, szp, params.op, needrex) -- Process pattern. - return - end - end - gotmatch = true - end - end - - local msg = "bad operand mode" - if gotmatch then - if szmix then - msg = "mixed operand size" - else - msg = sz and "bad operand size" or "missing operand size" - end - end - - werror(msg.." in `"..opmodestr(params.op, args).."'") -end - ------------------------------------------------------------------------------- - --- x64-specific opcode for 64 bit immediates and displacements. -if x64 then - function map_op.mov64_2(params) - if not params then return { "reg, imm", "reg, [disp]", "[disp], reg" } end - if secpos+2 > maxsecpos then wflush() end - local opcode, op64, sz, rex - local op64 = match(params[1], "^%[%s*(.-)%s*%]$") - if op64 then - local a = parseoperand(params[2]) - if a.mode ~= "rmR" then werror("bad operand mode") end - sz = a.opsize - rex = sz == "q" and 8 or 0 - opcode = 0xa3 - else - op64 = match(params[2], "^%[%s*(.-)%s*%]$") - local a = parseoperand(params[1]) - if op64 then - if a.mode ~= "rmR" then werror("bad operand mode") end - sz = a.opsize - rex = sz == "q" and 8 or 0 - opcode = 0xa1 - else - if sub(a.mode, 1, 1) ~= "r" or a.opsize ~= "q" then - werror("bad operand mode") - end - op64 = params[2] - opcode = 0xb8 + (a.reg%8) -- !x64: no VREG support. - rex = a.reg > 7 and 9 or 8 - end - end - wputop(sz, opcode, rex) - waction("IMM_D", format("(unsigned int)((uintptr_t)(%s))", op64)) - waction("IMM_D", format("(unsigned int)(((uintptr_t)(%s))>>32)", op64)) - end -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -local function op_data(params) - if not params then return "imm..." end - local sz = sub(params.op, 2, 2) - if sz == "a" then sz = addrsize end - for _,p in ipairs(params) do - local a = parseoperand(p) - if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then - werror("bad mode or size in `"..p.."'") - end - if a.mode == "iJ" then - wputlabel("IMM_", a.imm, 1) - else - wputszarg(sz, a.imm) - end - if secpos+2 > maxsecpos then wflush() end - end -end - -map_op[".byte_*"] = op_data -map_op[".sbyte_*"] = op_data -map_op[".word_*"] = op_data -map_op[".dword_*"] = op_data -map_op[".aword_*"] = op_data - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_2"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end - if secpos+2 > maxsecpos then wflush() end - local a = parseoperand(params[1]) - local mode, imm = a.mode, a.imm - if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then - -- Local label (1: ... 9:) or global label (->global:). - waction("LABEL_LG", nil, 1) - wputxb(imm) - elseif mode == "iJ" then - -- PC label (=>pcexpr:). - waction("LABEL_PC", imm) - else - werror("bad label definition") - end - -- SETLABEL must immediately follow LABEL_LG/LABEL_PC. - local addr = params[2] - if addr then - local a = parseoperand(addr) - if a.mode == "iPJ" then - waction("SETLABEL", a.imm) - else - werror("bad label assignment") - end - end -end -map_op[".label_1"] = map_op[".label_2"] - ------------------------------------------------------------------------------- - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]] - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", nil, 1) - wputxb(align-1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - --- Spacing pseudo-opcode. -map_op[".space_2"] = function(params) - if not params then return "num [, filler]" end - if secpos+1 > maxsecpos then wflush() end - waction("SPACE", params[1]) - local fill = params[2] - if fill then - fill = tonumber(fill) - if not fill or fill < 0 or fill > 255 then werror("bad filler") end - end - wputxb(fill or 0) -end -map_op[".space_1"] = map_op[".space_2"] - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - if reg and not map_reg_valid_base[reg] then - werror("bad base register `"..(map_reg_rev[reg] or reg).."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg and map_reg_rev[tp.reg] or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION") - wputxb(num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpregs(out) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = map_coreop }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dynasm.lua b/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dynasm.lua deleted file mode 100644 index 2c5062d30a4..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/dynasm/dynasm.lua +++ /dev/null @@ -1,1096 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM. A dynamic assembler for code generation engines. --- Originally designed and implemented for LuaJIT. --- --- Copyright (C) 2005-2011 Mike Pall. All rights reserved. --- See below for full copyright notice. ------------------------------------------------------------------------------- - --- Application information. -local _info = { - name = "DynASM", - description = "A dynamic assembler for code generation engines", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - url = "http://luajit.org/dynasm.html", - license = "MIT", - copyright = [[ -Copyright (C) 2005-2011 Mike Pall. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[ MIT license: http://www.opensource.org/licenses/mit-license.php ] -]], -} - --- Cache library functions. -local type, pairs, ipairs = type, pairs, ipairs -local pcall, error, assert = pcall, error, assert -local _s = string -local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub -local format, rep, upper = _s.format, _s.rep, _s.upper -local _t = table -local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort -local exit = os.exit -local io = io -local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr - ------------------------------------------------------------------------------- - --- Program options. -local g_opt = {} - --- Global state for current file. -local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch -local g_errcount = 0 - --- Write buffer for output file. -local g_wbuffer, g_capbuffer - ------------------------------------------------------------------------------- - --- Write an output line (or callback function) to the buffer. -local function wline(line, needindent) - local buf = g_capbuffer or g_wbuffer - buf[#buf+1] = needindent and g_indent..line or line - g_synclineno = g_synclineno + 1 -end - --- Write assembler line as a comment, if requestd. -local function wcomment(aline) - if g_opt.comment then - wline(g_opt.comment..aline..g_opt.endcomment, true) - end -end - --- Resync CPP line numbers. -local function wsync() - if g_synclineno ~= g_lineno and g_opt.cpp then - wline("# "..g_lineno..' "'..g_fname..'"') - g_synclineno = g_lineno - end -end - --- Dummy action flush function. Replaced with arch-specific function later. -local function wflush(term) -end - --- Dump all buffered output lines. -local function wdumplines(out, buf) - for _,line in ipairs(buf) do - if type(line) == "string" then - assert(out:write(line, "\n")) - else - -- Special callback to dynamically insert lines after end of processing. - line(out) - end - end -end - ------------------------------------------------------------------------------- - --- Emit an error. Processing continues with next statement. -local function werror(msg) - if g_opt.vserror then - error(format("%s(%s) : error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0) - else - error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0) - end -end - --- Emit a fatal error. Processing stops. -local function wfatal(msg) - g_errcount = "fatal" - werror(msg) -end - --- Print a warning. Processing continues. -local function wwarn(msg) - stderr:write(format("%s:%s: warning: %s:\n%s\n", - g_fname, g_lineno, msg, g_curline)) -end - --- Print caught error message. But suppress excessive errors. -local function wprinterr(...) - if type(g_errcount) == "number" then - -- Regular error. - g_errcount = g_errcount + 1 - if g_errcount < 21 then -- Seems to be a reasonable limit. - stderr:write(...) - elseif g_errcount == 21 then - stderr:write(g_fname, - ":*: warning: too many errors (suppressed further messages).\n") - end - else - -- Fatal error. - stderr:write(...) - return true -- Stop processing. - end -end - ------------------------------------------------------------------------------- - --- Map holding all option handlers. -local opt_map = {} -local opt_current - --- Print error and exit with error status. -local function opterror(...) - stderr:write("dynasm.lua: ERROR: ", ...) - stderr:write("\n") - exit(1) -end - --- Get option parameter. -local function optparam(args) - local argn = args.argn - local p = args[argn] - if not p then - opterror("missing parameter for option `", opt_current, "'.") - end - args.argn = argn + 1 - return p -end - ------------------------------------------------------------------------------- - --- Core pseudo-opcodes. -local map_coreop = {} --- Dummy opcode map. Replaced by arch-specific map. -local map_op = {} - --- Forward declarations. -local dostmt -local readfile - ------------------------------------------------------------------------------- - --- Map for defines (initially empty, chains to arch-specific map). -local map_def = {} - --- Pseudo-opcode to define a substitution. -map_coreop[".define_2"] = function(params, nparams) - if not params then return nparams == 1 and "name" or "name, subst" end - local name, def = params[1], params[2] or "1" - if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end - map_def[name] = def -end -map_coreop[".define_1"] = map_coreop[".define_2"] - --- Define a substitution on the command line. -function opt_map.D(args) - local namesubst = optparam(args) - local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$") - if name then - map_def[name] = subst - elseif match(namesubst, "^[%a_][%w_]*$") then - map_def[namesubst] = "1" - else - opterror("bad define") - end -end - --- Undefine a substitution on the command line. -function opt_map.U(args) - local name = optparam(args) - if match(name, "^[%a_][%w_]*$") then - map_def[name] = nil - else - opterror("bad define") - end -end - --- Helper for definesubst. -local gotsubst - -local function definesubst_one(word) - local subst = map_def[word] - if subst then gotsubst = word; return subst else return word end -end - --- Iteratively substitute defines. -local function definesubst(stmt) - -- Limit number of iterations. - for i=1,100 do - gotsubst = false - stmt = gsub(stmt, "#?[%w_]+", definesubst_one) - if not gotsubst then break end - end - if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end - return stmt -end - --- Dump all defines. -local function dumpdefines(out, lvl) - local t = {} - for name in pairs(map_def) do - t[#t+1] = name - end - sort(t) - out:write("Defines:\n") - for _,name in ipairs(t) do - local subst = map_def[name] - if g_arch then subst = g_arch.revdef(subst) end - out:write(format(" %-20s %s\n", name, subst)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Support variables for conditional assembly. -local condlevel = 0 -local condstack = {} - -local function loadin(source, env) - if setfenv then - local func, err = loadstring(source) - if func then - setfenv(func, env) - end - return func, err - else - return load(source, nil, nil, env) - end -end - --- Evaluate condition with a Lua expression. Substitutions already performed. -local function cond_eval(cond) - -- No globals. All unknown identifiers evaluate to nil. - local func, err = loadin("return "..cond, {}) - if func then - local ok, res = pcall(func) - if ok then - if res == 0 then return false end -- Oh well. - return not not res - end - err = res - end - wfatal("bad condition: "..err) -end - --- Skip statements until next conditional pseudo-opcode at the same level. -local function stmtskip() - local dostmt_save = dostmt - local lvl = 0 - dostmt = function(stmt) - local op = match(stmt, "^%s*(%S+)") - if op == ".if" then - lvl = lvl + 1 - elseif lvl ~= 0 then - if op == ".endif" then lvl = lvl - 1 end - elseif op == ".elif" or op == ".else" or op == ".endif" then - dostmt = dostmt_save - dostmt(stmt) - end - end -end - --- Pseudo-opcodes for conditional assembly. -map_coreop[".if_1"] = function(params) - if not params then return "condition" end - local lvl = condlevel + 1 - local res = cond_eval(params[1]) - condlevel = lvl - condstack[lvl] = res - if not res then stmtskip() end -end - -map_coreop[".elif_1"] = function(params) - if not params then return "condition" end - if condlevel == 0 then wfatal(".elif without .if") end - local lvl = condlevel - local res = condstack[lvl] - if res then - if res == "else" then wfatal(".elif after .else") end - else - res = cond_eval(params[1]) - if res then - condstack[lvl] = res - return - end - end - stmtskip() -end - -map_coreop[".else_0"] = function(params) - if condlevel == 0 then wfatal(".else without .if") end - local lvl = condlevel - local res = condstack[lvl] - condstack[lvl] = "else" - if res then - if res == "else" then wfatal(".else after .else") end - stmtskip() - end -end - -map_coreop[".endif_0"] = function(params) - local lvl = condlevel - if lvl == 0 then wfatal(".endif without .if") end - condlevel = lvl - 1 -end - --- Check for unfinished conditionals. -local function checkconds() - if g_errcount ~= "fatal" and condlevel ~= 0 then - wprinterr(g_fname, ":*: error: unbalanced conditional\n") - end -end - ------------------------------------------------------------------------------- - --- Search for a file in the given path and open it for reading. -local function pathopen(path, name) - local dirsep = match(package.path, "\\") and "\\" or "/" - for _,p in ipairs(path) do - local fullname = p == "" and name or p..dirsep..name - local fin = io.open(fullname, "r") - if fin then - g_fname = fullname - return fin - end - end -end - --- Include a file. -map_coreop[".include_1"] = function(params) - if not params then return "filename" end - local name = params[1] - -- Save state. Ugly, I know. but upvalues are fast. - local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent - -- Read the included file. - local fatal = readfile(pathopen(g_opt.include, name) or - wfatal("include file `"..name.."' not found")) - -- Restore state. - g_synclineno = -1 - g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi - if fatal then wfatal("in include file") end -end - --- Make .include and conditionals initially available, too. -map_op[".include_1"] = map_coreop[".include_1"] -map_op[".if_1"] = map_coreop[".if_1"] -map_op[".elif_1"] = map_coreop[".elif_1"] -map_op[".else_0"] = map_coreop[".else_0"] -map_op[".endif_0"] = map_coreop[".endif_0"] - ------------------------------------------------------------------------------- - --- Support variables for macros. -local mac_capture, mac_lineno, mac_name -local mac_active = {} -local mac_list = {} - --- Pseudo-opcode to define a macro. -map_coreop[".macro_*"] = function(mparams) - if not mparams then return "name [, params...]" end - -- Split off and validate macro name. - local name = remove(mparams, 1) - if not name then werror("missing macro name") end - if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]+$")) then - wfatal("bad macro name `"..name.."'") - end - -- Validate macro parameter names. - local mdup = {} - for _,mp in ipairs(mparams) do - if not match(mp, "^[%a_][%w_]*$") then - wfatal("bad macro parameter name `"..mp.."'") - end - if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end - mdup[mp] = true - end - -- Check for duplicate or recursive macro definitions. - local opname = name.."_"..#mparams - if map_op[opname] or map_op[name.."_*"] then - wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)") - end - if mac_capture then wfatal("recursive macro definition") end - - -- Enable statement capture. - local lines = {} - mac_lineno = g_lineno - mac_name = name - mac_capture = function(stmt) -- Statement capture function. - -- Stop macro definition with .endmacro pseudo-opcode. - if not match(stmt, "^%s*.endmacro%s*$") then - lines[#lines+1] = stmt - return - end - mac_capture = nil - mac_lineno = nil - mac_name = nil - mac_list[#mac_list+1] = opname - -- Add macro-op definition. - map_op[opname] = function(params) - if not params then return mparams, lines end - -- Protect against recursive macro invocation. - if mac_active[opname] then wfatal("recursive macro invocation") end - mac_active[opname] = true - -- Setup substitution map. - local subst = {} - for i,mp in ipairs(mparams) do subst[mp] = params[i] end - local mcom - if g_opt.maccomment and g_opt.comment then - mcom = " MACRO "..name.." ("..#mparams..")" - wcomment("{"..mcom) - end - -- Loop through all captured statements - for _,stmt in ipairs(lines) do - -- Substitute macro parameters. - local st = gsub(stmt, "[%w_]+", subst) - st = definesubst(st) - st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b. - if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end - -- Emit statement. Use a protected call for better diagnostics. - local ok, err = pcall(dostmt, st) - if not ok then - -- Add the captured statement to the error. - wprinterr(err, "\n", g_indent, "| ", stmt, - "\t[MACRO ", name, " (", #mparams, ")]\n") - end - end - if mcom then wcomment("}"..mcom) end - mac_active[opname] = nil - end - end -end - --- An .endmacro pseudo-opcode outside of a macro definition is an error. -map_coreop[".endmacro_0"] = function(params) - wfatal(".endmacro without .macro") -end - --- Dump all macros and their contents (with -PP only). -local function dumpmacros(out, lvl) - sort(mac_list) - out:write("Macros:\n") - for _,opname in ipairs(mac_list) do - local name = sub(opname, 1, -3) - local params, lines = map_op[opname]() - out:write(format(" %-20s %s\n", name, concat(params, ", "))) - if lvl > 1 then - for _,line in ipairs(lines) do - out:write(" |", line, "\n") - end - out:write("\n") - end - end - out:write("\n") -end - --- Check for unfinished macro definitions. -local function checkmacros() - if mac_capture then - wprinterr(g_fname, ":", mac_lineno, - ": error: unfinished .macro `", mac_name ,"'\n") - end -end - ------------------------------------------------------------------------------- - --- Support variables for captures. -local cap_lineno, cap_name -local cap_buffers = {} -local cap_used = {} - --- Start a capture. -map_coreop[".capture_1"] = function(params) - if not params then return "name" end - wflush() - local name = params[1] - if not match(name, "^[%a_][%w_]*$") then - wfatal("bad capture name `"..name.."'") - end - if cap_name then - wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno) - end - cap_name = name - cap_lineno = g_lineno - -- Create or continue a capture buffer and start the output line capture. - local buf = cap_buffers[name] - if not buf then buf = {}; cap_buffers[name] = buf end - g_capbuffer = buf - g_synclineno = 0 -end - --- Stop a capture. -map_coreop[".endcapture_0"] = function(params) - wflush() - if not cap_name then wfatal(".endcapture without a valid .capture") end - cap_name = nil - cap_lineno = nil - g_capbuffer = nil - g_synclineno = 0 -end - --- Dump a capture buffer. -map_coreop[".dumpcapture_1"] = function(params) - if not params then return "name" end - wflush() - local name = params[1] - if not match(name, "^[%a_][%w_]*$") then - wfatal("bad capture name `"..name.."'") - end - cap_used[name] = true - wline(function(out) - local buf = cap_buffers[name] - if buf then wdumplines(out, buf) end - end) - g_synclineno = 0 -end - --- Dump all captures and their buffers (with -PP only). -local function dumpcaptures(out, lvl) - out:write("Captures:\n") - for name,buf in pairs(cap_buffers) do - out:write(format(" %-20s %4s)\n", name, "("..#buf)) - if lvl > 1 then - local bar = rep("=", 76) - out:write(" ", bar, "\n") - for _,line in ipairs(buf) do - out:write(" ", line, "\n") - end - out:write(" ", bar, "\n\n") - end - end - out:write("\n") -end - --- Check for unfinished or unused captures. -local function checkcaptures() - if cap_name then - wprinterr(g_fname, ":", cap_lineno, - ": error: unfinished .capture `", cap_name,"'\n") - return - end - for name in pairs(cap_buffers) do - if not cap_used[name] then - wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n") - end - end -end - ------------------------------------------------------------------------------- - --- Sections names. -local map_sections = {} - --- Pseudo-opcode to define code sections. --- TODO: Data sections, BSS sections. Needs extra C code and API. -map_coreop[".section_*"] = function(params) - if not params then return "name..." end - if #map_sections > 0 then werror("duplicate section definition") end - wflush() - for sn,name in ipairs(params) do - local opname = "."..name.."_0" - if not match(name, "^[%a][%w_]*$") or - map_op[opname] or map_op["."..name.."_*"] then - werror("bad section name `"..name.."'") - end - map_sections[#map_sections+1] = name - wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1)) - map_op[opname] = function(params) g_arch.section(sn-1) end - end - wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections)) -end - --- Dump all sections. -local function dumpsections(out, lvl) - out:write("Sections:\n") - for _,name in ipairs(map_sections) do - out:write(format(" %s\n", name)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Load architecture-specific module. -local function loadarch(arch) - if not match(arch, "^[%w_]+$") then return "bad arch name" end - local ok, m_arch = pcall(require, "dasm_"..arch) - if not ok then return "cannot load module: "..m_arch end - g_arch = m_arch - wflush = m_arch.passcb(wline, werror, wfatal, wwarn) - m_arch.setup(arch, g_opt) - map_op, map_def = m_arch.mergemaps(map_coreop, map_def) -end - --- Dump architecture description. -function opt_map.dumparch(args) - local name = optparam(args) - if not g_arch then - local err = loadarch(name) - if err then opterror(err) end - end - - local t = {} - for name in pairs(map_coreop) do t[#t+1] = name end - for name in pairs(map_op) do t[#t+1] = name end - sort(t) - - local out = stdout - local _arch = g_arch._info - out:write(format("%s version %s, released %s, %s\n", - _info.name, _info.version, _info.release, _info.url)) - g_arch.dumparch(out) - - local pseudo = true - out:write("Pseudo-Opcodes:\n") - for _,sname in ipairs(t) do - local name, nparam = match(sname, "^(.+)_([0-9%*])$") - if name then - if pseudo and sub(name, 1, 1) ~= "." then - out:write("\nOpcodes:\n") - pseudo = false - end - local f = map_op[sname] - local s - if nparam ~= "*" then nparam = nparam + 0 end - if nparam == 0 then - s = "" - elseif type(f) == "string" then - s = map_op[".template__"](nil, f, nparam) - else - s = f(nil, nparam) - end - if type(s) == "table" then - for _,s2 in ipairs(s) do - out:write(format(" %-12s %s\n", name, s2)) - end - else - out:write(format(" %-12s %s\n", name, s)) - end - end - end - out:write("\n") - exit(0) -end - --- Pseudo-opcode to set the architecture. --- Only initially available (map_op is replaced when called). -map_op[".arch_1"] = function(params) - if not params then return "name" end - local err = loadarch(params[1]) - if err then wfatal(err) end -end - --- Dummy .arch pseudo-opcode to improve the error report. -map_coreop[".arch_1"] = function(params) - if not params then return "name" end - wfatal("duplicate .arch statement") -end - ------------------------------------------------------------------------------- - --- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'. -map_coreop[".nop_*"] = function(params) - if not params then return "[ignored...]" end -end - --- Pseudo-opcodes to raise errors. -map_coreop[".error_1"] = function(params) - if not params then return "message" end - werror(params[1]) -end - -map_coreop[".fatal_1"] = function(params) - if not params then return "message" end - wfatal(params[1]) -end - --- Dump all user defined elements. -local function dumpdef(out) - local lvl = g_opt.dumpdef - if lvl == 0 then return end - dumpsections(out, lvl) - dumpdefines(out, lvl) - if g_arch then g_arch.dumpdef(out, lvl) end - dumpmacros(out, lvl) - dumpcaptures(out, lvl) -end - ------------------------------------------------------------------------------- - --- Helper for splitstmt. -local splitlvl - -local function splitstmt_one(c) - if c == "(" then - splitlvl = ")"..splitlvl - elseif c == "[" then - splitlvl = "]"..splitlvl - elseif c == "{" then - splitlvl = "}"..splitlvl - elseif c == ")" or c == "]" or c == "}" then - if sub(splitlvl, 1, 1) ~= c then werror("unbalanced (), [] or {}") end - splitlvl = sub(splitlvl, 2) - elseif splitlvl == "" then - return " \0 " - end - return c -end - --- Split statement into (pseudo-)opcode and params. -local function splitstmt(stmt) - -- Convert label with trailing-colon into .label statement. - local label = match(stmt, "^%s*(.+):%s*$") - if label then return ".label", {label} end - - -- Split at commas and equal signs, but obey parentheses and brackets. - splitlvl = "" - stmt = gsub(stmt, "[,%(%)%[%]{}]", splitstmt_one) - if splitlvl ~= "" then werror("unbalanced () or []") end - - -- Split off opcode. - local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$") - if not op then werror("bad statement syntax") end - - -- Split parameters. - local params = {} - for p in gmatch(other, "%s*(%Z+)%z?") do - params[#params+1] = gsub(p, "%s+$", "") - end - if #params > 16 then werror("too many parameters") end - - params.op = op - return op, params -end - --- Process a single statement. -dostmt = function(stmt) - -- Ignore empty statements. - if match(stmt, "^%s*$") then return end - - -- Capture macro defs before substitution. - if mac_capture then return mac_capture(stmt) end - stmt = definesubst(stmt) - - -- Emit C code without parsing the line. - if sub(stmt, 1, 1) == "|" then - local tail = sub(stmt, 2) - wflush() - if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end - return - end - - -- Split into (pseudo-)opcode and params. - local op, params = splitstmt(stmt) - - -- Get opcode handler (matching # of parameters or generic handler). - local f = map_op[op.."_"..#params] or map_op[op.."_*"] - if not f then - if not g_arch then wfatal("first statement must be .arch") end - -- Improve error report. - for i=0,9 do - if map_op[op.."_"..i] then - werror("wrong number of parameters for `"..op.."'") - end - end - werror("unknown statement `"..op.."'") - end - - -- Call opcode handler or special handler for template strings. - if type(f) == "string" then - map_op[".template__"](params, f) - else - f(params) - end -end - --- Process a single line. -local function doline(line) - if g_opt.flushline then wflush() end - - -- Assembler line? - local indent, aline = match(line, "^(%s*)%|(.*)$") - if not aline then - -- No, plain C code line, need to flush first. - wflush() - wsync() - wline(line, false) - return - end - - g_indent = indent -- Remember current line indentation. - - -- Emit C code (even from macros). Avoids echo and line parsing. - if sub(aline, 1, 1) == "|" then - if not mac_capture then - wsync() - elseif g_opt.comment then - wsync() - wcomment(aline) - end - dostmt(aline) - return - end - - -- Echo assembler line as a comment. - if g_opt.comment then - wsync() - wcomment(aline) - end - - -- Strip assembler comments. - aline = gsub(aline, "//.*$", "") - - -- Split line into statements at semicolons. - if match(aline, ";") then - for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end - else - dostmt(aline) - end -end - ------------------------------------------------------------------------------- - --- Write DynASM header. -local function dasmhead(out) - out:write(format([[ -/* -** This file has been pre-processed with DynASM. -** %s -** DynASM version %s, DynASM %s version %s -** DO NOT EDIT! The original file is in "%s". -*/ - -#if DASM_VERSION != %d -#error "Version mismatch between DynASM and included encoding engine" -#endif - -]], _info.url, - _info.version, g_arch._info.arch, g_arch._info.version, - g_fname, _info.vernum)) -end - --- Read input file. -readfile = function(fin) - g_indent = "" - g_lineno = 0 - g_synclineno = -1 - - -- Process all lines. - for line in fin:lines() do - g_lineno = g_lineno + 1 - g_curline = line - local ok, err = pcall(doline, line) - if not ok and wprinterr(err, "\n") then return true end - end - wflush() - - -- Close input file. - assert(fin == stdin or fin:close()) -end - --- Write output file. -local function writefile(outfile) - local fout - - -- Open output file. - if outfile == nil or outfile == "-" then - fout = stdout - else - fout = assert(io.open(outfile, "w")) - end - - -- Write all buffered lines - wdumplines(fout, g_wbuffer) - - -- Close output file. - assert(fout == stdout or fout:close()) - - -- Optionally dump definitions. - dumpdef(fout == stdout and stderr or stdout) -end - --- Translate an input file to an output file. -local function translate(infile, outfile) - g_wbuffer = {} - g_indent = "" - g_lineno = 0 - g_synclineno = -1 - - -- Put header. - wline(dasmhead) - - -- Read input file. - local fin - if infile == "-" then - g_fname = "(stdin)" - fin = stdin - else - g_fname = infile - fin = assert(io.open(infile, "r")) - end - readfile(fin) - - -- Check for errors. - if not g_arch then - wprinterr(g_fname, ":*: error: missing .arch directive\n") - end - checkconds() - checkmacros() - checkcaptures() - - if g_errcount ~= 0 then - stderr:write(g_fname, ":*: info: ", g_errcount, " error", - (type(g_errcount) == "number" and g_errcount > 1) and "s" or "", - " in input file -- no output file generated.\n") - dumpdef(stderr) - exit(1) - end - - -- Write output file. - writefile(outfile) -end - ------------------------------------------------------------------------------- - --- Print help text. -function opt_map.help() - stdout:write("DynASM -- ", _info.description, ".\n") - stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n") - stdout:write[[ - -Usage: dynasm [OPTION]... INFILE.dasc|- - - -h, --help Display this help text. - -V, --version Display version and copyright information. - - -o, --outfile FILE Output file name (default is stdout). - -I, --include DIR Add directory to the include search path. - - -c, --ccomment Use /* */ comments for assembler lines. - -C, --cppcomment Use // comments for assembler lines (default). - -N, --nocomment Suppress assembler lines in output. - -M, --maccomment Show macro expansions as comments (default off). - - -L, --nolineno Suppress CPP line number information in output. - -F, --flushline Flush action list for every line. - - -E, --vserror Use Visual Studio style errors file(line) vs file:line - - -D NAME[=SUBST] Define a substitution. - -U NAME Undefine a substitution. - - -P, --dumpdef Dump defines, macros, etc. Repeat for more output. - -A, --dumparch ARCH Load architecture ARCH and dump description. -]] - exit(0) -end - --- Print version information. -function opt_map.version() - stdout:write(format("%s version %s, released %s\n%s\n\n%s", - _info.name, _info.version, _info.release, _info.url, _info.copyright)) - exit(0) -end - --- Misc. options. -function opt_map.outfile(args) g_opt.outfile = optparam(args) end -function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end -function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end -function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end -function opt_map.nocomment() g_opt.comment = false end -function opt_map.maccomment() g_opt.maccomment = true end -function opt_map.nolineno() g_opt.cpp = false end -function opt_map.flushline() g_opt.flushline = true end -function opt_map.vserror() g_opt.vserror = true end -function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end - ------------------------------------------------------------------------------- - --- Short aliases for long options. -local opt_alias = { - h = "help", ["?"] = "help", V = "version", - o = "outfile", I = "include", - c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment", - L = "nolineno", F = "flushline", - E = "vserror", - P = "dumpdef", A = "dumparch", -} - --- Parse single option. -local function parseopt(opt, args) - opt_current = #opt == 1 and "-"..opt or "--"..opt - local f = opt_map[opt] or opt_map[opt_alias[opt]] - if not f then - opterror("unrecognized option `", opt_current, "'. Try `--help'.\n") - end - f(args) -end - --- Parse arguments. -local function parseargs(args) - -- Default options. - g_opt.comment = "//|" - g_opt.endcomment = "" - g_opt.cpp = true - g_opt.dumpdef = 0 - g_opt.include = { "" } - - -- Process all option arguments. - args.argn = 1 - repeat - local a = args[args.argn] - if not a then break end - local lopt, opt = match(a, "^%-(%-?)(.+)") - if not opt then break end - args.argn = args.argn + 1 - if lopt == "" then - -- Loop through short options. - for o in gmatch(opt, ".") do parseopt(o, args) end - else - -- Long option. - parseopt(opt, args) - end - until false - - -- Check for proper number of arguments. - local nargs = #args - args.argn + 1 - if nargs ~= 1 then - if nargs == 0 then - if g_opt.dumpdef > 0 then return dumpdef(stdout) end - end - opt_map.help() - end - - -- Translate a single input file to a single output file - -- TODO: Handle multiple files? - translate(args[args.argn], g_opt.outfile) -end - ------------------------------------------------------------------------------- - --- Add the directory dynasm.lua resides in to the Lua module search path. -local arg = arg -if arg and arg[0] then - local prefix = match(arg[0], "^(.*[/\\])") - if prefix then package.path = prefix.."?.lua;"..package.path end -end - --- Start DynASM. -parseargs{...} - ------------------------------------------------------------------------------- - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/ffi.c b/Build/source/texk/web2c/luatexdir/luaffi/ffi.c deleted file mode 100644 index 6d3c197e48e..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/ffi.c +++ /dev/null @@ -1,3619 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#include "ffi.h" -#include <math.h> -#include <inttypes.h> - -/* Set to 1 to get extra debugging on print */ -#define DEBUG_TOSTRING 0 - -int jit_key; -int ctype_mt_key; -int cdata_mt_key; -int callback_mt_key; -int cmodule_mt_key; -int constants_key; -int types_key; -int gc_key; -int callbacks_key; -int functions_key; -int abi_key; -int next_unnamed_key; -int niluv_key; -int asmname_key; - -void push_upval(lua_State* L, int* key) -{ - lua_pushlightuserdata(L, key); - lua_rawget(L, LUA_REGISTRYINDEX); -} - -void set_upval(lua_State* L, int* key) -{ - lua_pushlightuserdata(L, key); - lua_insert(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); -} - -int equals_upval(lua_State* L, int idx, int* key) -{ - int ret; - lua_pushvalue(L, idx); - push_upval(L, key); - ret = lua_rawequal(L, -2, -1); - lua_pop(L, 2); - return ret; -} - -struct jit* get_jit(lua_State* L) -{ - struct jit* jit; - push_upval(L, &jit_key); - jit = (struct jit*) lua_touserdata(L, -1); - jit->L = L; - lua_pop(L, 1); /* still in registry */ - return jit; -} - -static int type_error(lua_State* L, int idx, const char* to_type, int to_usr, const struct ctype* to_ct) -{ - luaL_Buffer B; - struct ctype ft; - - assert(to_type || (to_usr && to_ct)); - if (to_usr) { - to_usr = lua_absindex(L, to_usr); - } - - idx = lua_absindex(L, idx); - - luaL_buffinit(L, &B); - to_cdata(L, idx, &ft); - - if (ft.type != INVALID_TYPE) { - push_type_name(L, -1, &ft); - lua_pushfstring(L, "unable to convert argument %d from cdata<%s> to cdata<", idx, lua_tostring(L, -1)); - lua_remove(L, -2); - luaL_addvalue(&B); - } else { - lua_pushfstring(L, "unable to convert argument %d from lua<%s> to cdata<", idx, luaL_typename(L, idx)); - luaL_addvalue(&B); - } - - if (to_ct) { - push_type_name(L, to_usr, to_ct); - luaL_addvalue(&B); - } else { - luaL_addstring(&B, to_type); - } - - luaL_addchar(&B, '>'); - - luaL_pushresult(&B); - return lua_error(L); -} - -static void* userdata_toptr(lua_State* L, int idx) -{ - void* ptr = lua_touserdata(L, idx); - int isfile; - - // check for FILE* - lua_getmetatable(L, idx); - luaL_getmetatable(L, LUA_FILEHANDLE); - isfile = lua_rawequal(L, -1, -2); - lua_pop(L, 2); - - if (isfile) { -#if LUA_VERSION_NUM == 501 - FILE** stream = (FILE**) ptr; - return *stream; -#else - luaL_Stream* stream = (luaL_Stream*) ptr; - return stream->f; -#endif - } - - return ptr; -} - -static int cdata_tointeger(lua_State* L, int idx, ptrdiff_t* val) -{ - struct ctype ct; - void* addr = to_cdata(L, idx, &ct); - lua_pop(L, 1); - - if (ct.pointers) { - return 0; - } - - switch (ct.type) { - case INT8_TYPE: - *val = *(int8_t*)addr; - return 1; - case INT16_TYPE: - *val = *(int16_t*)addr; - return 1; - case INT32_TYPE: - *val = *(int32_t*)addr; - return 1; - case INT64_TYPE: - *val = *(int64_t*)addr; - return 1; - default: - return 0; - } -} - -static int64_t check_intptr(lua_State* L, int idx, void* p, struct ctype* ct) -{ - if (ct->type == INVALID_TYPE) { - int64_t ret; - memset(ct, 0, sizeof(*ct)); - ct->base_size = 8; - ct->type = INT64_TYPE; - ct->is_defined = 1; - ret = luaL_checknumber(L, idx); - return ret; - - } else if (ct->pointers) { - return (intptr_t) p; - } - - switch (ct->type) { - case INTPTR_TYPE: - case FUNCTION_PTR_TYPE: - return *(intptr_t*) p; - - case INT64_TYPE: - return *(int64_t*) p; - - case INT32_TYPE: - return ct->is_unsigned ? (int64_t) *(uint32_t*) p : (int64_t) *(int32_t*) p; - - case INT16_TYPE: - return ct->is_unsigned ? (int64_t) *(uint16_t*) p : (int64_t) *(int16_t*) p; - - case INT8_TYPE: - return ct->is_unsigned ? (int64_t) *(uint8_t*) p : (int64_t) *(int8_t*) p; - - default: - type_error(L, idx, "intptr_t", 0, NULL); - return 0; - } -} - -static int get_cfunction_address(lua_State* L, int idx, cfunction* addr); - -#define TO_NUMBER(TYPE, ALLOW_POINTERS, LUA_TONUMBER) \ - TYPE ret = 0; \ - void* p; \ - struct ctype ct; \ - cfunction f; \ - \ - switch (lua_type(L, idx)) { \ - case LUA_TBOOLEAN: \ - ret = (TYPE) lua_toboolean(L, idx); \ - break; \ - \ - case LUA_TNUMBER: \ - ret = (TYPE) LUA_TONUMBER(L, idx); \ - break; \ - \ - case LUA_TSTRING: \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) lua_tostring(L, idx); \ - break; \ - \ - case LUA_TLIGHTUSERDATA: \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) lua_topointer(L, idx); \ - break; \ - \ - case LUA_TFUNCTION: \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - if (!get_cfunction_address(L, idx, &f)) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) f; \ - break; \ - \ - case LUA_TUSERDATA: \ - p = to_cdata(L, idx, &ct); \ - \ - if (ct.type == INVALID_TYPE) { \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) userdata_toptr(L, idx); \ - } else if (ct.pointers || ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) {\ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) p; \ - } else if (ct.type == COMPLEX_DOUBLE_TYPE) { \ - ret = (TYPE) creal(*(complex_double*) p); \ - } else if (ct.type == COMPLEX_FLOAT_TYPE) { \ - ret = (TYPE) crealf(*(complex_float*) p); \ - } else if (ct.type == DOUBLE_TYPE) { \ - ret = (TYPE) *(double*) p; \ - } else if (ct.type == FLOAT_TYPE) { \ - ret = (TYPE) *(float*) p; \ - } else { \ - ret = check_intptr(L, idx, p, &ct); \ - } \ - lua_pop(L, 1); \ - break; \ - \ - case LUA_TNIL: \ - ret = (TYPE) 0; \ - break; \ - \ - default: \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - -static int64_t cast_int64(lua_State* L, int idx, int is_cast) -{ TO_NUMBER(int64_t, is_cast, lua_tointeger); return ret; } - -static uint64_t cast_uint64(lua_State* L, int idx, int is_cast) -{ TO_NUMBER(uint64_t, is_cast, lua_tointeger); return ret; } - -int32_t check_int32(lua_State* L, int idx) -{ return (int32_t) cast_int64(L, idx, 0); } - -uint32_t check_uint32(lua_State* L, int idx) -{ return (uint32_t) cast_uint64(L, idx, 0); } - -int64_t check_int64(lua_State* L, int idx) -{ return cast_int64(L, idx, 0); } - -uint64_t check_uint64(lua_State* L, int idx) -{ return cast_uint64(L, idx, 0); } - -double check_double(lua_State* L, int idx) -{ TO_NUMBER(double, 0, lua_tonumber); return ret; } - -float check_float(lua_State* L, int idx) -{ TO_NUMBER(double, 0, lua_tonumber); return ret; } - -uintptr_t check_uintptr(lua_State* L, int idx) -{ TO_NUMBER(uintptr_t, 1, lua_tointeger); return ret; } - -complex_double check_complex_double(lua_State* L, int idx) -{ - double real = 0, imag = 0; - void* p; - struct ctype ct; - - switch (lua_type(L, idx)) { - case LUA_TNUMBER: - real = (double) lua_tonumber(L, idx); - break; - case LUA_TTABLE: - lua_rawgeti(L, idx, 1); - real = check_double(L, -1); - lua_pop(L, 1); - - lua_rawgeti(L, idx, 2); - if (lua_isnil(L, -1)) { - imag = real; - } else { - imag = check_double(L, -1); - } - lua_pop(L, 1); - break; - case LUA_TUSERDATA: - p = to_cdata(L, idx, &ct); - if (ct.type == COMPLEX_DOUBLE_TYPE) { - real = creal(*(complex_double*) p); - imag = cimag(*(complex_double*) p); - } else if (ct.type == COMPLEX_FLOAT_TYPE) { - real = crealf(*(complex_float*) p); - imag = cimagf(*(complex_float*) p); - } else if (ct.type == DOUBLE_TYPE) { - real = *(double*) p; - } else if (ct.type == FLOAT_TYPE) { - real = *(float*) p; - } else { - real = check_intptr(L, idx, p, &ct); - } - lua_pop(L, 1); - break; - - default: - type_error(L, idx, "complex", 0, NULL); - } - - return mk_complex_double(real, imag); -} - -complex_float check_complex_float(lua_State* L, int idx) -{ - complex_double d = check_complex_double(L, idx); - return mk_complex_float(creal(d), cimag(d)); -} - -static size_t unpack_vararg(lua_State* L, int i, char* to) -{ - void* p; - struct ctype ct; - - switch (lua_type(L, i)) { - case LUA_TBOOLEAN: - *(int*) to = lua_toboolean(L, i); - return sizeof(int); - - case LUA_TNUMBER: - *(double*) to = lua_tonumber(L, i); // TODO in Lua 5.3: lua_tointeger sometimes should be here - return sizeof(double); - - case LUA_TSTRING: - *(const char**) to = lua_tostring(L, i); - return sizeof(const char*); - - case LUA_TLIGHTUSERDATA: - *(void**) to = lua_touserdata(L, i); - return sizeof(void*); - - case LUA_TUSERDATA: - p = to_cdata(L, i, &ct); - lua_pop(L, 1); - - if (ct.type == INVALID_TYPE) { - *(void**) to = userdata_toptr(L, i); - return sizeof(void*); - - } else if (ct.pointers || ct.type == INTPTR_TYPE) { - *(void**) to = p; - return sizeof(void*); - - } else if (ct.type == INT32_TYPE) { - *(int32_t*) to = *(int32_t*) p; - return sizeof(int32_t); - - } else if (ct.type == INT64_TYPE) { - *(int64_t*) to = *(int64_t*) p; - return sizeof(int64_t); - - } else if (ct.type == FUNCTION_PTR_TYPE) { - *(cfunction *) to = *(cfunction *)p; - return sizeof(cfunction); - } - - goto err; - - case LUA_TNIL: - *(void**) to = NULL; - return sizeof(void*); - - default: - goto err; - } - -err: - return type_error(L, i, "vararg", 0, NULL); -} - -void unpack_varargs_stack(lua_State* L, int first, int last, char* to) -{ - int i; - - for (i = first; i <= last; i++) { - to += unpack_vararg(L, i, to); - } -} - -void unpack_varargs_stack_skip(lua_State* L, int first, int last, int ints_to_skip, int floats_to_skip, char* to) -{ - int i; - - for (i = first; i <= last; i++) { - int type = lua_type(L, i); - - if (type == LUA_TNUMBER && --floats_to_skip >= 0) { - continue; - } else if (type != LUA_TNUMBER && --ints_to_skip >= 0) { - continue; - } - - to += unpack_vararg(L, i, to); - } -} - -void unpack_varargs_float(lua_State* L, int first, int last, int max, char* to) -{ - int i; - - for (i = first; i <= last && max > 0; i++) { - if (lua_type(L, i) == LUA_TNUMBER) { - unpack_vararg(L, i, to); - to += sizeof(double); - max--; - } - } -} - -void unpack_varargs_int(lua_State* L, int first, int last, int max, char* to) -{ - int i; - - for (i = first; i <= last && max > 0; i++) { - if (lua_type(L, i) != LUA_TNUMBER) { - unpack_vararg(L, i, to); - to += sizeof(void*); - max--; - } - } -} - -void unpack_varargs_reg(lua_State* L, int first, int last, char* to) -{ - int i; - - for (i = first; i <= last; i++) { - unpack_vararg(L, i, to); - to += sizeof(double); - } -} - -/* to_enum tries to convert a value at idx to the enum type indicated by to_ct - * and uv to_usr. For strings this means it will do a string lookup for the - * enum type. It leaves the stack unchanged. Will throw an error if the type - * at idx can't be conerted. - */ -int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* to_ct) -{ - int32_t ret; - - switch (lua_type(L, idx)) { - case LUA_TSTRING: - /* lookup string in to_usr to find value */ - to_usr = lua_absindex(L, to_usr); - lua_pushvalue(L, idx); - lua_rawget(L, to_usr); - - if (lua_isnil(L, -1)) { - goto err; - } - - ret = (int32_t) lua_tointeger(L, -1); - lua_pop(L, 1); - return ret; - - case LUA_TUSERDATA: - return check_int32(L, idx); - - case LUA_TNIL: - return (int32_t) 0; - - case LUA_TNUMBER: - return (int32_t) lua_tointeger(L, idx); - - default: - goto err; - } - -err: - return type_error(L, idx, NULL, to_usr, to_ct); -} - -/* to_pointer tries converts a value at idx to a pointer. It fills out ct and - * pushes the uv of the found type. It will throw a lua error if it can not - * convert the value to a pointer. */ -static void* check_pointer(lua_State* L, int idx, struct ctype* ct) -{ - void* p; - memset(ct, 0, sizeof(*ct)); - idx = lua_absindex(L, idx); - - switch (lua_type(L, idx)) { - case LUA_TNIL: - ct->type = VOID_TYPE; - ct->pointers = 1; - ct->is_null = 1; - lua_pushnil(L); - return NULL; - - case LUA_TNUMBER: - ct->type = INTPTR_TYPE; - ct->is_unsigned = 1; - ct->pointers = 0; - lua_pushnil(L); - return (void*) (uintptr_t) lua_tonumber(L, idx); // TODO in Lua 5.3: maybe change to lua_tointeger - - case LUA_TLIGHTUSERDATA: - ct->type = VOID_TYPE; - ct->pointers = 1; - lua_pushnil(L); - return lua_touserdata(L, idx); - - case LUA_TSTRING: - ct->type = INT8_TYPE; - ct->pointers = 1; - ct->is_unsigned = IS_CHAR_UNSIGNED; - ct->is_array = 1; - ct->base_size = 1; - ct->const_mask = 2; - lua_pushnil(L); - return (void*) lua_tolstring(L, idx, &ct->array_size); - - case LUA_TUSERDATA: - p = to_cdata(L, idx, ct); - - if (ct->type == INVALID_TYPE) { - /* some other type of user data */ - ct->type = VOID_TYPE; - ct->pointers = 1; - return userdata_toptr(L, idx); - } else if (ct->type == STRUCT_TYPE || ct->type == UNION_TYPE) { - return p; - } else { - return (void*) (intptr_t) check_intptr(L, idx, p, ct); - } - break; - } - - type_error(L, idx, "pointer", 0, NULL); - return NULL; -} - -static int is_void_ptr(const struct ctype* ct) -{ - return ct->type == VOID_TYPE - && ct->pointers == 1; -} - -static int is_same_type(lua_State* L, int usr1, int usr2, const struct ctype* t1, const struct ctype* t2) -{ - if (t1->type != t2->type) { - return 0; - } - -#if LUA_VERSION_NUM == 501 - if (lua_isnil(L, usr1) != lua_isnil(L, usr2)) { - int ret; - usr1 = lua_absindex(L, usr1); - usr2 = lua_absindex(L, usr2); - push_upval(L, &niluv_key); - - ret = lua_rawequal(L, usr1, -1) - || lua_rawequal(L, usr2, -1); - - lua_pop(L, 1); - - if (ret) { - return 1; - } - } -#endif - - return lua_rawequal(L, usr1, usr2); -} - -static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers); - -/* to_typed_pointer converts a value at idx to a type tt with target uv to_usr - * checking all types. May push a temporary value so that it can create - * structs on the fly. */ -void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt) -{ - struct ctype ft; - void* p; - - to_usr = lua_absindex(L, to_usr); - idx = lua_absindex(L, idx); - - if (tt->pointers == 1 && (tt->type == STRUCT_TYPE || tt->type == UNION_TYPE) && lua_type(L, idx) == LUA_TTABLE) { - /* need to construct a struct of the target type */ - struct ctype ct = *tt; - ct.pointers = ct.is_array = 0; - p = push_cdata(L, to_usr, &ct); - set_struct(L, idx, p, to_usr, &ct, 1); - return p; - } - - p = check_pointer(L, idx, &ft); - - if (tt->pointers == 1 && ft.pointers == 0 && (ft.type == STRUCT_TYPE || ft.type == UNION_TYPE)) { - /* auto dereference structs */ - ft.pointers = 1; - ft.const_mask <<= 1; - } - - if (is_void_ptr(tt)) { - /* any pointer can convert to void* */ - goto suc; - - } else if (is_void_ptr(&ft) && (ft.pointers || ft.is_reference)) { - /* void* can convert to any pointer */ - goto suc; - - } else if (ft.is_null) { - /* NULL can convert to any pointer */ - goto suc; - - } else if (!is_same_type(L, to_usr, -1, tt, &ft)) { - /* the base type is different */ - goto err; - - } else if (tt->pointers != ft.pointers) { - goto err; - - } else if (ft.const_mask & ~tt->const_mask) { - /* for every const in from it must be in to, there are further rules - * for const casting (see the c++ spec), but they are hard to test - * quickly */ - goto err; - } - -suc: - return p; - -err: - type_error(L, idx, NULL, to_usr, tt); - return NULL; -} - -/** - * gets the address of the wrapped C function for the lua function value at idx - * and returns 1 if it exists; otherwise returns 0 and nothing is pushed */ -static int get_cfunction_address(lua_State* L, int idx, cfunction* addr) -{ - int top, n; - cfunction* f; - if (!lua_isfunction(L, idx)) return 0; - - top = lua_gettop(L); - - // Get the last upvalue - n = 2; - while (lua_getupvalue(L, idx, n)) { - lua_pop(L, 1); - n++; - } - - if (!lua_getupvalue(L, idx, n - 1)) - return 0; - - if (!lua_isuserdata(L, -1) || !lua_getmetatable(L, -1)) { - lua_pop(L, 1); - return 0; - } - - push_upval(L, &callback_mt_key); - if (!lua_rawequal(L, -1, -2)) { - lua_pop(L, 3); - return 0; - } - - /* stack is: - * userdata upval - * metatable - * callback_mt - */ - - f = lua_touserdata(L, -3); - *addr = f[1]; - lua_pop(L, 3); - return 1; -} - -/* to_cfunction converts a value at idx with usr table at to_usr and type tt - * into a function. Leaves the stack unchanged. */ -static cfunction check_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt, int check_pointers) -{ - void* p; - struct ctype ft; - cfunction f; - int top = lua_gettop(L); - - idx = lua_absindex(L, idx); - to_usr = lua_absindex(L, to_usr); - - switch (lua_type(L, idx)) { - case LUA_TFUNCTION: - if (get_cfunction_address(L, idx, &f)) { - return f; - } - - /* Function cdatas are pinned and must be manually cleaned up by - * calling func:free(). */ - push_upval(L, &callbacks_key); - f = compile_callback(L, idx, to_usr, tt); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - lua_pop(L, 1); /* callbacks tbl */ - return f; - - case LUA_TNIL: - return NULL; - - case LUA_TLIGHTUSERDATA: - if (check_pointers) { - goto err; - } else { - return (cfunction) lua_touserdata(L, idx); - } - - case LUA_TUSERDATA: - p = to_cdata(L, idx, &ft); - assert(lua_gettop(L) == top + 1); - - if (ft.type == INVALID_TYPE) { - if (check_pointers) { - goto err; - } else { - lua_pop(L, 1); - return (cfunction) lua_touserdata(L, idx); - } - - } else if (ft.is_null) { - lua_pop(L, 1); - return NULL; - - } else if (!check_pointers && (ft.pointers || ft.type == INTPTR_TYPE)) { - lua_pop(L, 1); - return (cfunction) *(void**) p; - - } else if (ft.type != FUNCTION_PTR_TYPE) { - goto err; - - } else if (!check_pointers) { - lua_pop(L, 1); - return *(cfunction*) p; - - } else if (ft.calling_convention != tt->calling_convention) { - goto err; - - } else if (!is_same_type(L, -1, to_usr, &ft, tt)) { - goto err; - - } else { - lua_pop(L, 1); - return *(cfunction*) p; - } - - default: - goto err; - } - -err: - type_error(L, idx, NULL, to_usr, tt); - return NULL; -} - -/* to_type_cfunction converts a value at idx with uv at to_usr and type tt to - * a cfunction. Leaves the stack unchanged. */ -cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt) -{ return check_cfunction(L, idx, to_usr, tt, 1); } - -static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers); - -static void set_array(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers) -{ - size_t i, sz, esz; - struct ctype et; - - idx = lua_absindex(L, idx); - to_usr = lua_absindex(L, to_usr); - - switch (lua_type(L, idx)) { - case LUA_TSTRING: - if (tt->pointers == 1 && tt->type == INT8_TYPE) { - const char* str = lua_tolstring(L, idx, &sz); - - if (!tt->is_variable_array && sz >= tt->array_size) { - memcpy(to, str, tt->array_size); - } else { - /* include nul terminator */ - memcpy(to, str, sz+1); - } - } else { - goto err; - } - break; - - case LUA_TTABLE: - et = *tt; - et.pointers--; - et.const_mask >>= 1; - et.is_array = 0; - esz = et.pointers ? sizeof(void*) : et.base_size; - - lua_rawgeti(L, idx, 2); - - if (tt->is_variable_array) { - /* we have no idea how big the array is, so set values based off - * how many items were given to us */ - lua_pop(L, 1); - for (i = 0; i < lua_rawlen(L, idx); i++) { - lua_rawgeti(L, idx, (int) i + 1); - set_value(L, -1, (char*) to + esz * i, to_usr, &et, check_pointers); - lua_pop(L, 1); - } - - } else if (lua_isnil(L, -1)) { - /* there is no second element, so we set the whole array to the - * first element (or nil - ie 0) if there is no first element) */ - lua_pop(L, 1); - lua_rawgeti(L, idx, 1); - - if (lua_isnil(L, -1)) { - memset(to, 0, ctype_size(L, tt)); - } else { - /* if its still variable we have no idea how many values to set */ - for (i = 0; i < tt->array_size; i++) { - set_value(L, -1, (char*) to + esz * i, to_usr, &et, check_pointers); - } - } - - lua_pop(L, 1); - - } else { - /* there is a second element, so we set each element using the - * equiv index in the table initializer */ - lua_pop(L, 1); - for (i = 0; i < tt->array_size; i++) { - lua_rawgeti(L, idx, (int) (i+1)); - - if (lua_isnil(L, -1)) { - /* we've hit the end of the values provided in the - * initializer, so memset the rest to zero */ - lua_pop(L, 1); - memset((char*) to + esz * i, 0, (tt->array_size - i) * esz); - break; - - } else { - set_value(L, -1, (char*) to + esz * i, to_usr, &et, check_pointers); - lua_pop(L, 1); - } - } - } - break; - - default: - goto err; - } - - return; - -err: - type_error(L, idx, NULL, to_usr, tt); -} - -/* pops the member key from the stack, leaves the member user value on the - * stack. Returns the member offset. Returns -ve if the member can not be - * found. */ -static ptrdiff_t get_member(lua_State* L, int usr, const struct ctype* ct, struct ctype* mt) -{ - ptrdiff_t off; - lua_rawget(L, usr); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - return -1; - } - - *mt = *(const struct ctype*) lua_touserdata(L, -1); - lua_getuservalue(L, -1); - lua_replace(L, -2); - - if (mt->is_variable_array && ct->variable_size_known) { - /* eg char mbr[?] */ - size_t sz = (mt->pointers > 1) ? sizeof(void*) : mt->base_size; - assert(ct->is_variable_struct && mt->is_array); - mt->array_size = ct->variable_increment / sz; - mt->is_variable_array = 0; - - } else if (mt->is_variable_struct && ct->variable_size_known) { - /* eg struct {char a; char b[?]} mbr; */ - assert(ct->is_variable_struct); - mt->variable_size_known = 1; - mt->variable_increment = ct->variable_increment; - } - - off = mt->offset; - mt->offset = 0; - return off; -} - -static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers) -{ - int have_first = 0; - int have_other = 0; - struct ctype mt; - void* p; - - to_usr = lua_absindex(L, to_usr); - idx = lua_absindex(L, idx); - - switch (lua_type(L, idx)) { - case LUA_TTABLE: - /* match up to the members based off the table initializers key - this - * will match both numbered and named members in the user table - * we need a special case for when no entries in the initializer - - * zero initialize the c struct, and only one entry in the initializer - * - set all members to this value */ - memset(to, 0, ctype_size(L, tt)); - lua_pushnil(L); - while (lua_next(L, idx)) { - ptrdiff_t off; - - if (!have_first && lua_tonumber(L, -2) == 1 && lua_tonumber(L, -1) != 0) { - have_first = 1; - } else if (!have_other && (lua_type(L, -2) != LUA_TNUMBER || lua_tonumber(L, -2) != 1)) { - have_other = 1; - } - - lua_pushvalue(L, -2); - off = get_member(L, to_usr, tt, &mt); - assert(off >= 0); - set_value(L, -2, (char*) to + off, -1, &mt, check_pointers); - - /* initializer value, mt usr */ - lua_pop(L, 2); - } - - /* if we only had a single non zero value then initialize all members to that value */ - if (!have_other && have_first && tt->type != UNION_TYPE) { - size_t i, sz; - ptrdiff_t off; - lua_rawgeti(L, idx, 1); - sz = lua_rawlen(L, to_usr); - - for (i = 2; i < sz; i++) { - lua_pushinteger(L, i); - off = get_member(L, to_usr, tt, &mt); - assert(off >= 0); - set_value(L, -2, (char*) to + off, -1, &mt, check_pointers); - lua_pop(L, 1); /* mt usr */ - } - - lua_pop(L, 1); /* initializer table */ - } - break; - - case LUA_TUSERDATA: - if (check_pointers) { - p = check_typed_pointer(L, idx, to_usr, tt); - } else { - struct ctype ct; - p = check_pointer(L, idx, &ct); - } - memcpy(to, p, tt->base_size); - lua_pop(L, 1); - break; - - default: - goto err; - } - - return; - -err: - type_error(L, idx, NULL, to_usr, tt); -} - -static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers) -{ - int top = lua_gettop(L); - - if (tt->is_array) { - set_array(L, idx, to, to_usr, tt, check_pointers); - - } else if (tt->pointers || tt->is_reference) { - union { - uint8_t c[sizeof(void*)]; - void* p; - } u; - - if (lua_istable(L, idx)) { - luaL_error(L, "Can't set a pointer member to a struct that's about to be freed"); - } - - if (check_pointers) { - u.p = check_typed_pointer(L, idx, to_usr, tt); - } else { - struct ctype ct; - u.p = check_pointer(L, idx, &ct); - } - -#ifndef ALLOW_MISALIGNED_ACCESS - if ((uintptr_t) to & PTR_ALIGN_MASK) { - memcpy(to, u.c, sizeof(void*)); - } else -#endif - { - *(void**) to = u.p; - } - - lua_pop(L, 1); - - } else if (tt->is_bitfield) { - - uint64_t hi_mask = UINT64_C(0) - (UINT64_C(1) << (tt->bit_offset + tt->bit_size)); - uint64_t low_mask = (UINT64_C(1) << tt->bit_offset) - UINT64_C(1); - uint64_t val = check_uint64(L, idx); - val &= (UINT64_C(1) << tt->bit_size) - 1; - val <<= tt->bit_offset; - *(uint64_t*) to = val | (*(uint64_t*) to & (hi_mask | low_mask)); - - } else if (tt->type == STRUCT_TYPE || tt->type == UNION_TYPE) { - set_struct(L, idx, to, to_usr, tt, check_pointers); - - } else { - -#ifndef ALLOW_MISALIGNED_ACCESS - union { - uint8_t c[8]; - _Bool b; - uint64_t u64; - float f; - double d; - cfunction func; - } misalign; - - void* origto = to; - - if ((uintptr_t) origto & (tt->base_size - 1)) { - to = misalign.c; - } -#endif - - switch (tt->type) { - case BOOL_TYPE: - *(_Bool*) to = (cast_int64(L, idx, !check_pointers) != 0); - break; - case INT8_TYPE: - if (tt->is_unsigned) { - *(uint8_t*) to = (uint8_t) cast_uint64(L, idx, !check_pointers); - } else { - *(int8_t*) to = (int8_t) cast_int64(L, idx, !check_pointers); - } - break; - case INT16_TYPE: - if (tt->is_unsigned) { - *(uint16_t*) to = (uint16_t) cast_uint64(L, idx, !check_pointers); - } else { - *(int16_t*) to = (int16_t) cast_int64(L, idx, !check_pointers); - } - break; - case INT32_TYPE: - if (tt->is_unsigned) { - *(uint32_t*) to = (uint32_t) cast_uint64(L, idx, !check_pointers); - } else { - *(int32_t*) to = (int32_t) cast_int64(L, idx, !check_pointers); - } - break; - case INT64_TYPE: - if (tt->is_unsigned) { - *(uint64_t*) to = cast_uint64(L, idx, !check_pointers); - } else { - *(int64_t*) to = cast_int64(L, idx, !check_pointers); - } - break; - case FLOAT_TYPE: - *(float*) to = (float) check_double(L, idx); - break; - case DOUBLE_TYPE: - *(double*) to = check_double(L, idx); - break; - case COMPLEX_FLOAT_TYPE: - *(complex_float*) to = check_complex_float(L, idx); - break; - case COMPLEX_DOUBLE_TYPE: - *(complex_double*) to = check_complex_double(L, idx); - break; - case INTPTR_TYPE: - *(uintptr_t*) to = check_uintptr(L, idx); - break; - case ENUM_TYPE: - *(int32_t*) to = check_enum(L, idx, to_usr, tt); - break; - case FUNCTION_PTR_TYPE: - *(cfunction*) to = check_cfunction(L, idx, to_usr, tt, check_pointers); - break; - default: - goto err; - } - -#ifndef ALLOW_MISALIGNED_ACCESS - if ((uintptr_t) origto & (tt->base_size - 1)) { - memcpy(origto, misalign.c, tt->base_size); - } -#endif - } - - assert(lua_gettop(L) == top); - return; -err: - type_error(L, idx, NULL, to_usr, tt); -} - -static int ffi_typeof(lua_State* L) -{ - struct ctype ct; - check_ctype(L, 1, &ct); - push_ctype(L, -1, &ct); - return 1; -} - -static void setmintop(lua_State* L, int idx) -{ - if (lua_gettop(L) < idx) { - lua_settop(L, idx); - } -} - -/* warning: in the case that it finds an array size, it removes that index */ -static void get_variable_array_size(lua_State* L, int idx, struct ctype* ct) -{ - /* we only care about the variable buisness for the variable array - * directly ie ffi.new('char[?]') or the struct that contains the variable - * array ffi.new('struct {char v[?]}'). A pointer to the struct doesn't - * care about the variable size (it treats it as a zero sized array). */ - - if (ct->is_variable_array) { - assert(ct->is_array); - ct->array_size = (size_t) luaL_checknumber(L, idx); - ct->is_variable_array = 0; - lua_remove(L, idx); - - } else if (ct->is_variable_struct && !ct->variable_size_known) { - assert(ct->type == STRUCT_TYPE && !ct->is_array); - ct->variable_increment *= (size_t) luaL_checknumber(L, idx); - ct->variable_size_known = 1; - lua_remove(L, idx); - } -} - -static int is_scalar(struct ctype* ct) -{ - int type = ct->type; - if (ct->pointers || ct->is_reference) { - return !ct->is_array; - } - return type != STRUCT_TYPE && type != UNION_TYPE && !IS_COMPLEX(type); -} - -static int should_pack(lua_State *L, int ct_usr, struct ctype* ct, int idx) -{ - struct ctype argt; - int same; - ct_usr = lua_absindex(L, ct_usr); - - if (IS_COMPLEX(ct->type)) { - return 0; - } - - switch (lua_type(L, idx)) { - case LUA_TTABLE: - return 0; - case LUA_TSTRING: - return ct->type == STRUCT_TYPE; - case LUA_TUSERDATA: - // don't pack if the argument is a cdata with the same type - to_cdata(L, idx, &argt); - same = is_same_type(L, ct_usr, -1, ct, &argt); - lua_pop(L, 1); - return !same; - default: - return 1; - } -} - -static int do_new(lua_State* L, int is_cast) -{ - int cargs, i, scalar; - void* p; - struct ctype ct; - int check_ptrs = !is_cast; - - check_ctype(L, 1, &ct); - - /* don't push a callback when we have a c function, as cb:set needs a - * compiled callback from a lua function to work */ - if (!ct.pointers && ct.type == FUNCTION_PTR_TYPE && (lua_isnil(L, 2) || lua_isfunction(L, 2))) { - // Get the bound C function if this is a ffi lua function - cfunction func; - if (get_cfunction_address(L, 2, &func)) { - p = push_cdata(L, -1, &ct); - *(cfunction*) p = func; - return 1; - } - - /* Function cdatas are pinned and must be manually cleaned up by - * calling func:free(). */ - compile_callback(L, 2, -1, &ct); - push_upval(L, &callbacks_key); - lua_pushvalue(L, -2); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - lua_pop(L, 1); /* callbacks tbl */ - return 1; - } - - /* this removes the vararg argument if its needed, and errors if its invalid */ - if (!is_cast) { - get_variable_array_size(L, 2, &ct); - } - - p = push_cdata(L, -1, &ct); - - /* if the user mt has a __gc function then call ffi.gc on this value */ - if (push_user_mt(L, -2, &ct)) { - push_upval(L, &gc_key); - lua_pushvalue(L, -3); - - /* user_mt.__gc */ - lua_pushliteral(L, "__gc"); - lua_rawget(L, -4); - - lua_rawset(L, -3); /* gc_upval[cdata] = user_mt.__gc */ - lua_pop(L, 2); /* user_mt and gc_upval */ - } - - /* stack is: - * ctype arg - * ctor args ... 0+ - * ctype usr - * cdata - */ - - cargs = lua_gettop(L) - 3; - - if (cargs == 0) { - return 1; - } - - scalar = is_scalar(&ct); - if (scalar && cargs > 1) { - return luaL_error(L, "too many initializers"); - } - - if (cargs > 1 || (!scalar && should_pack(L, -2, &ct, 2))) { - lua_createtable(L, cargs, 0); - lua_replace(L, 1); - for (i = 1; i <= cargs; i++) { - lua_pushvalue(L, i + 1); - lua_rawseti(L, 1, i); - } - assert(lua_gettop(L) == cargs + 3); - set_value(L, 1, p, -2, &ct, check_ptrs); - return 1; - } - - set_value(L, 2, p, -2, &ct, check_ptrs); - return 1; -} - -static int ffi_new(lua_State* L) -{ return do_new(L, 0); } - -static int ffi_cast(lua_State* L) -{ return do_new(L, 1); } - -static int ctype_new(lua_State* L) -{ return do_new(L, 0); } - -static int ctype_call(lua_State* L) -{ - struct ctype ct; - int top = lua_gettop(L); - - check_ctype(L, 1, &ct); - - if (push_user_mt(L, -1, &ct)) { - lua_pushstring(L, "__new"); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - lua_insert(L, 1); // function at bottom of stack under args - lua_pop(L, 2); - lua_call(L, top, 1); - return 1; - } - lua_pop(L, 2); - } - lua_pop(L, 1); - - assert(lua_gettop(L) == top); - return do_new(L, 0); -} - -static int ffi_sizeof(lua_State* L) -{ - struct ctype ct; - check_ctype(L, 1, &ct); - get_variable_array_size(L, 2, &ct); - lua_pushinteger(L, ctype_size(L, &ct)); - return 1; -} - -static int ffi_alignof(lua_State* L) -{ - struct ctype ct, mt; - lua_settop(L, 2); - check_ctype(L, 1, &ct); - - /* if no member is specified then we return the alignment of the type */ - if (lua_isnil(L, 2)) { - lua_pushinteger(L, ct.align_mask + 1); - return 1; - } - - /* get the alignment of the member */ - lua_pushvalue(L, 2); - if (get_member(L, -2, &ct, &mt) < 0) { - push_type_name(L, 3, &ct); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); - } - - lua_pushinteger(L, mt.align_mask + 1); - return 1; -} - -static int ffi_offsetof(lua_State* L) -{ - ptrdiff_t off; - struct ctype ct, mt; - lua_settop(L, 2); - check_ctype(L, 1, &ct); - - lua_pushvalue(L, 2); - off = get_member(L, -2, &ct, &mt); /* this replaces the member key at -1 with the mbr usr value */ - if (off < 0) { - push_type_name(L, 3, &ct); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); - } - - lua_pushinteger(L, off); - - if (!mt.is_bitfield) { - return 1; - } - - lua_pushinteger(L, mt.bit_offset); - lua_pushinteger(L, mt.bit_size); - return 3; -} - -static int ffi_istype(lua_State* L) -{ - struct ctype tt, ft; - check_ctype(L, 1, &tt); - to_cdata(L, 2, &ft); - - if (ft.type == INVALID_TYPE) { - goto fail; - } - - if (!is_same_type(L, 3, 4, &tt, &ft)) { - goto fail; - } - - if (tt.pointers != ft.pointers) { - goto fail; - } - - if (tt.is_array != ft.is_array) { - goto fail; - } - - if (tt.is_array && tt.array_size != ft.array_size) { - goto fail; - } - - if (tt.calling_convention != ft.calling_convention) { - goto fail; - } - - lua_pushboolean(L, 1); - return 1; - -fail: - lua_pushboolean(L, 0); - return 1; -} - -static int cdata_gc(lua_State* L) -{ - struct ctype ct; - check_cdata(L, 1, &ct); - lua_settop(L, 1); - - /* call the gc func if there is any registered */ - lua_pushvalue(L, 1); - lua_rawget(L, lua_upvalueindex(2)); - if (!lua_isnil(L, -1)) { - lua_pushvalue(L, 1); - lua_pcall(L, 1, 0, 0); - } - - /* unset the closure */ - lua_pushvalue(L, 1); - lua_pushnil(L); - lua_rawset(L, lua_upvalueindex(1)); - - return 0; -} - -static int callback_free(lua_State* L) -{ - cfunction* p = (cfunction*) lua_touserdata(L, 1); - // FIXME: temporarily disabled to prevent SIGTRAP on exit - // free_code(get_jit(L), L, *p); - return 0; -} - -static int cdata_free(lua_State* L) -{ - struct ctype ct; - cfunction* p = (cfunction*) check_cdata(L, 1, &ct); - lua_settop(L, 1); - - /* unset the closure */ - lua_pushvalue(L, 1); - lua_pushnil(L); - lua_rawset(L, lua_upvalueindex(1)); - - if (ct.is_jitted) { - free_code(get_jit(L), L, *p); - *p = NULL; - } - - return 0; -} - -static int cdata_set(lua_State* L) -{ - struct ctype ct; - cfunction* p = (cfunction*) check_cdata(L, 1, &ct); - luaL_checktype(L, 2, LUA_TFUNCTION); - - if (!ct.is_jitted) { - luaL_error(L, "can't set the function for a non-lua callback"); - } - - if (*p == NULL) { - luaL_error(L, "can't set the function for a free'd callback"); - } - - push_func_ref(L, *p); - lua_pushvalue(L, 2); - lua_rawseti(L, -2, CALLBACK_FUNC_USR_IDX); - - /* remove the closure for this callback as it embeds the function pointer - * value */ - lua_pushvalue(L, 1); - lua_pushboolean(L, 1); - lua_rawset(L, lua_upvalueindex(1)); - - return 0; -} - -static int cdata_call(lua_State* L) -{ - struct ctype ct; - int top = lua_gettop(L); - cfunction* p = (cfunction*) check_cdata(L, 1, &ct); - - if (push_user_mt(L, -1, &ct)) { - lua_pushliteral(L, "__call"); - lua_rawget(L, -2); - - if (!lua_isnil(L, -1)) { - lua_insert(L, 1); - lua_pop(L, 2); /* ct_usr, user_mt */ - lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); - return lua_gettop(L); - } - } - if (ct.pointers || ct.type != FUNCTION_PTR_TYPE) { - return luaL_error(L, "only function callbacks are callable"); - } - - lua_pushvalue(L, 1); - lua_rawget(L, lua_upvalueindex(1)); - - if (!lua_isfunction(L, -1)) { - lua_pop(L, 1); - compile_function(L, *p, -1, &ct); - - assert(lua_gettop(L) == top + 2); /* uv, closure */ - - /* closures[func] = closure */ - lua_pushvalue(L, 1); - lua_pushvalue(L, -2); - lua_rawset(L, lua_upvalueindex(1)); - - lua_replace(L, 1); - } else { - lua_replace(L, 1); - } - - lua_pop(L, 1); /* uv */ - assert(lua_gettop(L) == top); - - lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); - return lua_gettop(L); -} - -static int user_mt_key; - -static int ffi_metatype(lua_State* L) -{ - struct ctype ct; - lua_settop(L, 2); - - check_ctype(L, 1, &ct); - if (lua_type(L, 2) != LUA_TTABLE && lua_type(L, 2) != LUA_TNIL) { - return luaL_argerror(L, 2, "metatable must be a table or nil"); - } - - lua_pushlightuserdata(L, &user_mt_key); - lua_pushvalue(L, 2); - lua_rawset(L, 3); /* user[user_mt_key] = mt */ - - /* return the passed in ctype */ - push_ctype(L, 3, &ct); - return 1; -} - -/* push_user_mt returns 1 if the type has a user metatable and pushes it onto - * the stack, otherwise it returns 0 and pushes nothing */ -int push_user_mt(lua_State* L, int ct_usr, const struct ctype* ct) -{ - if (ct->type != STRUCT_TYPE && ct->type != UNION_TYPE && !IS_COMPLEX(ct->type)) { - return 0; - } - if (!lua_istable(L, ct_usr)) { - return 0; - } - - ct_usr = lua_absindex(L, ct_usr); - lua_pushlightuserdata(L, &user_mt_key); - lua_rawget(L, ct_usr); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - return 0; - } - return 1; -} - -static int ffi_gc(lua_State* L) -{ - struct ctype ct; - lua_settop(L, 2); - check_cdata(L, 1, &ct); - - push_upval(L, &gc_key); - lua_pushvalue(L, 1); - lua_pushvalue(L, 2); - lua_rawset(L, -3); - - /* return the cdata back */ - lua_settop(L, 1); - return 1; -} - -/* lookup_cdata_index returns the offset of the found type and user value on - * the stack if valid. Otherwise returns -ve and doesn't touch the stack. - */ -static ptrdiff_t lookup_cdata_index(lua_State* L, int idx, int ct_usr, struct ctype* ct) -{ - struct ctype mt; - ptrdiff_t off; - int type; - - ct_usr = lua_absindex(L, ct_usr); - type = lua_type(L, idx); - - switch (type) { - case LUA_TNUMBER: - case LUA_TUSERDATA: - /* possibilities are array, pointer */ - - if (!ct->pointers || is_void_ptr(ct)) { - return -1; - } - - // unbox cdata - if (type == LUA_TUSERDATA) { - if (!cdata_tointeger(L, idx, &off)) { - return -1; - } - } else { - off = lua_tointeger(L, idx); - } - - ct->is_array = 0; - ct->pointers--; - ct->const_mask >>= 1; - ct->is_reference = 0; - - lua_pushvalue(L, ct_usr); - - return (ct->pointers ? sizeof(void*) : ct->base_size) * off; - - case LUA_TSTRING: - /* possibilities are struct/union, pointer to struct/union */ - - if ((ct->type != STRUCT_TYPE && ct->type != UNION_TYPE) || ct->is_array || ct->pointers > 1) { - return -1; - } - - lua_pushvalue(L, idx); - off = get_member(L, ct_usr, ct, &mt); - if (off < 0) { - return -1; - } - - *ct = mt; - return off; - - default: - return -1; - } -} - -static int cdata_newindex(lua_State* L) -{ - struct ctype tt; - char* to; - ptrdiff_t off; - - lua_settop(L, 3); - - to = (char*) check_cdata(L, 1, &tt); - off = lookup_cdata_index(L, 2, -1, &tt); - - if (off < 0) { - if (!push_user_mt(L, -1, &tt)) { - goto err; - } - - lua_pushliteral(L, "__newindex"); - lua_rawget(L, -2); - - if (lua_isnil(L, -1)) { - goto err; - } - - lua_insert(L, 1); - lua_settop(L, 4); - lua_call(L, 3, LUA_MULTRET); - return lua_gettop(L); - } - - if (tt.const_mask & 1) { - return luaL_error(L, "can't set const data"); - } - - set_value(L, 3, to + off, -1, &tt, 1); - return 0; - -err: - push_type_name(L, 4, &tt); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); -} - -static int cdata_index(lua_State* L) -{ - void* to; - struct ctype ct; - char* data; - ptrdiff_t off; - - lua_settop(L, 2); - data = (char*) check_cdata(L, 1, &ct); - assert(lua_gettop(L) == 3); - - if (!ct.pointers) { - switch (ct.type) { - case FUNCTION_PTR_TYPE: - /* Callbacks use the same metatable as standard cdata values, but have set - * and free members. So instead of mt.__index = mt, we do the equiv here. */ - lua_getmetatable(L, 1); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - return 1; - - /* This provides the .re and .im virtual members */ - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - if (!lua_isstring(L, 2)) { - luaL_error(L, "invalid member for complex number"); - - } else if (strcmp(lua_tostring(L, 2), "re") == 0) { - lua_pushnumber(L, ct.type == COMPLEX_DOUBLE_TYPE ? creal(*(complex_double*) data) : crealf(*(complex_float*) data)); - - } else if (strcmp(lua_tostring(L, 2), "im") == 0) { - lua_pushnumber(L, ct.type == COMPLEX_DOUBLE_TYPE ? cimag(*(complex_double*) data) : cimagf(*(complex_float*) data)); - - } else { - luaL_error(L, "invalid member for complex number"); - } - return 1; - } - } - - off = lookup_cdata_index(L, 2, -1, &ct); - - if (off < 0) { - assert(lua_gettop(L) == 3); - if (!push_user_mt(L, -1, &ct)) { - goto err; - } - - lua_pushliteral(L, "__index"); - lua_rawget(L, -2); - - if (lua_isnil(L, -1)) { - goto err; - } - - if (lua_istable(L, -1)) { - lua_pushvalue(L, 2); - lua_gettable(L, -2); - return 1; - } - - lua_insert(L, 1); - lua_settop(L, 3); - lua_call(L, 2, LUA_MULTRET); - return lua_gettop(L); - -err: - push_type_name(L, 3, &ct); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); - } - - assert(lua_gettop(L) == 4); /* ct, key, ct_usr, mbr_usr */ - data += off; - - if (ct.is_array) { - /* push a reference to the array */ - ct.is_reference = 1; - to = push_cdata(L, -1, &ct); - *(void**) to = data; - return 1; - - } else if (ct.is_bitfield) { - - if (ct.type == INT64_TYPE) { - struct ctype rt; - uint64_t val = *(uint64_t*) data; - val >>= ct.bit_offset; - val &= (UINT64_C(1) << ct.bit_size) - 1; - - memset(&rt, 0, sizeof(rt)); - rt.base_size = 8; - rt.type = INT64_TYPE; - rt.is_unsigned = 1; - rt.is_defined = 1; - - to = push_cdata(L, 0, &rt); - *(uint64_t*) to = val; - - return 1; - - } else if (ct.type == BOOL_TYPE) { - uint64_t val = *(uint64_t*) data; - lua_pushboolean(L, (int) (val & (UINT64_C(1) << ct.bit_offset))); - return 1; - - } else { - uint64_t val = *(uint64_t*) data; - val >>= ct.bit_offset; - val &= (UINT64_C(1) << ct.bit_size) - 1; - lua_pushinteger(L, val); - return 1; - } - - } else if (ct.pointers) { -#ifndef ALLOW_MISALIGNED_ACCESS - union { - uint8_t c[8]; - void* p; - } misalignbuf; - - if ((uintptr_t) data & PTR_ALIGN_MASK) { - memcpy(misalignbuf.c, data, sizeof(void*)); - data = misalignbuf.c; - } -#endif - to = push_cdata(L, -1, &ct); - *(void**) to = *(void**) data; - return 1; - - } else if (ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) { - /* push a reference to the member */ - ct.is_reference = 1; - to = push_cdata(L, -1, &ct); - *(void**) to = data; - return 1; - - } else if (ct.type == FUNCTION_PTR_TYPE) { - cfunction* pf = (cfunction*) push_cdata(L, -1, &ct); - *pf = *(cfunction*) data; - return 1; - - } else { -#ifndef ALLOW_MISALIGNED_ACCESS - union { - uint8_t c[8]; - double d; - float f; - uint64_t u64; - } misalignbuf; - - assert(ct.base_size <= 8); - - if ((uintptr_t) data & (ct.base_size - 1)) { - memcpy(misalignbuf.c, data, ct.base_size); - data = misalignbuf.c; - } -#endif - - switch (ct.type) { - case BOOL_TYPE: - lua_pushboolean(L, *(_Bool*) data); - break; - case INT8_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint8_t*) data : (lua_Integer) *(int8_t*) data); - break; - case INT16_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint16_t*) data : (lua_Integer) *(int16_t*) data); - break; - case ENUM_TYPE: - case INT32_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint32_t*) data : (lua_Integer) *(int32_t*) data); - break; - case INT64_TYPE: - to = push_cdata(L, -1, &ct); - *(int64_t*) to = *(int64_t*) data; - break; - case INTPTR_TYPE: - to = push_cdata(L, -1, &ct); - *(intptr_t*) to = *(intptr_t*) data; - break; - case FLOAT_TYPE: - lua_pushnumber(L, *(float*) data); - break; - case DOUBLE_TYPE: - lua_pushnumber(L, *(double*) data); - break; - case COMPLEX_DOUBLE_TYPE: - to = push_cdata(L, -1, &ct); - *(complex_double*) to = *(complex_double*) data; - break; - case COMPLEX_FLOAT_TYPE: - to = push_cdata(L, -1, &ct); - *(complex_float*) to = *(complex_float*) data; - break; - default: - luaL_error(L, "internal error: invalid member type"); - } - - return 1; - } -} - -static complex_double check_complex(lua_State* L, int idx, void* p, struct ctype* ct) -{ - if (ct->type == INVALID_TYPE) { - double d = luaL_checknumber(L, idx); -#ifdef HAVE_COMPLEX - return d; -#else - complex_double c; - c.real = d; - c.imag = 0; - return c; -#endif - } else if (ct->type == COMPLEX_DOUBLE_TYPE) { - return *(complex_double*) p; - } else if (ct->type == COMPLEX_FLOAT_TYPE) { - complex_float* f = (complex_float*) p; -#ifdef HAVE_COMPLEX - return *f; -#else - complex_double d; - d.real = f->real; - d.imag = f->imag; - return d; -#endif - } else { - complex_double dummy; - type_error(L, idx, "complex", 0, NULL); - memset(&dummy, 0, sizeof(dummy)); - return dummy; - } -} - -static int rank(const struct ctype* ct) -{ - if (ct->pointers) { - return 5; - } - - switch (ct->type) { - case COMPLEX_DOUBLE_TYPE: - return 7; - case COMPLEX_FLOAT_TYPE: - return 6; - case INTPTR_TYPE: - return sizeof(intptr_t) >= sizeof(int64_t) ? 4 : 1; - case INT64_TYPE: - return ct->is_unsigned ? 3 : 2; - case INT32_TYPE: - case INT16_TYPE: - case INT8_TYPE: - return 2; - default: - return 0; - } -} - -static void push_complex(lua_State* L, complex_double res, int ct_usr, const struct ctype* ct) -{ - if (ct->type == COMPLEX_DOUBLE_TYPE) { - complex_double* p = (complex_double*) push_cdata(L, ct_usr, ct); - *p = res; - } else { - complex_float* p = (complex_float*) push_cdata(L, ct_usr, ct); -#ifdef HAVE_COMPLEX - *p = (complex float) res; -#else - p->real = (float) res.real; - p->imag = (float) res.imag; -#endif - } -} - -static void push_number(lua_State* L, int64_t val, int ct_usr, const struct ctype* ct) -{ - if ((ct->pointers || ct->type == INTPTR_TYPE) && sizeof(intptr_t) != sizeof(int64_t)) { - intptr_t* p = (intptr_t*) push_cdata(L, ct_usr, ct); - *p = val; - } else { - int64_t* p = (int64_t*) push_cdata(L, ct_usr, ct); - *p = val; - } -} - -static int call_user_op(lua_State* L, const char* opfield, int idx, int ct_usr, const struct ctype* ct) -{ - idx = lua_absindex(L, idx); - - if (push_user_mt(L, ct_usr, ct)) { - lua_pushstring(L, opfield); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - int top = lua_gettop(L); - lua_pushvalue(L, idx); - lua_call(L, 1, LUA_MULTRET); - return lua_gettop(L) - top + 1; - } - lua_pop(L, 2); - } - return -1; -} - -static int cdata_unm(lua_State* L) -{ - struct ctype ct; - void* p; - int64_t val; - int ret; - - lua_settop(L, 1); - p = to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__unm", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - val = check_intptr(L, 1, p, &ct); - - if (ct.pointers) { - luaL_error(L, "can't negate a pointer value"); - } else { - memset(&ct, 0, sizeof(ct)); - ct.type = INT64_TYPE; - ct.base_size = 8; - ct.is_defined = 1; - push_number(L, -val, 0, &ct); - } - - return 1; -} - -/* returns -ve if no binop was called otherwise returns the number of return - * arguments */ -static int call_user_binop(lua_State* L, const char* opfield, int lidx, int lusr, const struct ctype* lt, int ridx, int rusr, const struct ctype* rt) -{ - lidx = lua_absindex(L, lidx); - ridx = lua_absindex(L, ridx); - - if (push_user_mt(L, lusr, lt)) { - lua_pushstring(L, opfield); - lua_rawget(L, -2); - - if (!lua_isnil(L, -1)) { - int top = lua_gettop(L); - lua_pushvalue(L, lidx); - lua_pushvalue(L, ridx); - lua_call(L, 2, LUA_MULTRET); - return lua_gettop(L) - top + 1; - } - - lua_pop(L, 2); /* user_mt and user_mt.op */ - } - - if (push_user_mt(L, rusr, rt)) { - lua_pushstring(L, opfield); - lua_rawget(L, -2); - - if (!lua_isnil(L, -1)) { - int top = lua_gettop(L); - lua_pushvalue(L, lidx); - lua_pushvalue(L, ridx); - lua_call(L, 2, LUA_MULTRET); - return lua_gettop(L) - top + 1; - } - - lua_pop(L, 2); /* user_mt and user_mt.op */ - } - - return -1; -} - -static int cdata_concat(lua_State* L) -{ - struct ctype lt, rt; - int ret; - - lua_settop(L, 2); - to_cdata(L, 1, <); - to_cdata(L, 2, &rt); - - ret = call_user_binop(L, "__concat", 1, 3, <, 2, 4, &rt); - if (ret >= 0) { - return ret; - } - - return luaL_error(L, "NYI"); -} - -static int cdata_len(lua_State* L) -{ - struct ctype ct; - int ret; - - lua_settop(L, 1); - to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__len", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - push_type_name(L, 2, &ct); - return luaL_error(L, "type %s does not implement the __len metamethod", lua_tostring(L, -1)); -} - -static int cdata_pairs(lua_State* L) -{ - struct ctype ct; - int ret; - - lua_settop(L, 1); - to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__pairs", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - push_type_name(L, 2, &ct); - return luaL_error(L, "type %s does not implement the __pairs metamethod", lua_tostring(L, -1)); -} - -static int cdata_ipairs(lua_State* L) -{ - struct ctype ct; - int ret; - - lua_settop(L, 1); - to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__ipairs", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - push_type_name(L, 2, &ct); - return luaL_error(L, "type %s does not implement the __ipairs metamethod", lua_tostring(L, -1)); -} - -static int cdata_add(lua_State* L) -{ - struct ctype lt, rt, ct; - void *lp, *rp; - int ct_usr; - int ret; - - lua_settop(L, 2); - - lp = to_cdata(L, 1, <); - rp = to_cdata(L, 2, &rt); - assert(lua_gettop(L) == 4); - - ret = call_user_binop(L, "__add", 1, 3, <, 2, 4, &rt); - if (ret >= 0) { - return ret; - } - assert(lua_gettop(L) == 4); - - ct_usr = rank(<) > rank(&rt) ? 3 : 4; - ct = rank(<) > rank(&rt) ? lt : rt; - - if (IS_COMPLEX(ct.type)) { - complex_double left, right, res; - - left = check_complex(L, 1, lp, <); - right = check_complex(L, 2, rp, &rt); - assert(lua_gettop(L) == 4); - -#ifdef HAVE_COMPLEX - res = left + right; -#else - res.real = left.real + right.real; - res.imag = left.imag + right.imag; -#endif - - push_complex(L, res, ct_usr, &ct); - return 1; - - } else { - int64_t left = check_intptr(L, 1, lp, <); - int64_t right = check_intptr(L, 2, rp, &rt); - assert(lua_gettop(L) == 4); - - /* note due to 2s complement it doesn't matter if we do the addition as int or uint, - * but the result needs to be uint64_t if either of the sources are */ - - if (lt.pointers && rt.pointers) { - luaL_error(L, "can't add two pointers"); - - } else if (lt.pointers) { - int64_t res = left + (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right; - lt.is_array = 0; - push_number(L, res, 3, <); - - } else if (rt.pointers) { - int64_t res = right + (rt.pointers > 1 ? sizeof(void*) : rt.base_size) * left; - rt.is_array = 0; - push_number(L, res, 4, &rt); - - } else { - push_number(L, left + right, ct_usr, &ct); - } - - return 1; - } -} - -static int cdata_sub(lua_State* L) -{ - struct ctype lt, rt, ct; - void *lp, *rp; - int ct_usr; - int ret; - - lua_settop(L, 2); - - lp = to_cdata(L, 1, <); - rp = to_cdata(L, 2, &rt); - - ret = call_user_binop(L, "__sub", 1, 3, <, 2, 4, &rt); - if (ret >= 0) { - return ret; - } - - ct_usr = rank(<) > rank(&rt) ? 3 : 4; - ct = rank(<) > rank(&rt) ? lt : rt; - - if (IS_COMPLEX(ct.type)) { - complex_double left, right, res; - - left = check_complex(L, 1, lp, <); - right = check_complex(L, 2, rp, &rt); - -#ifdef HAVE_COMPLEX - res = left - right; -#else - res.real = left.real - right.real; - res.imag = left.imag - right.imag; -#endif - - push_complex(L, res, ct_usr, &ct); - return 1; - - } else { - int64_t left = check_intptr(L, 1, lp, <); - int64_t right = check_intptr(L, 2, rp, &rt); - - if (rt.pointers) { - luaL_error(L, "NYI: can't subtract a pointer value"); - - } else if (lt.pointers) { - int64_t res = left - (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right; - lt.is_array = 0; - push_number(L, res, 3, <); - - } else { - int64_t res = left - right; - push_number(L, res, ct_usr, &ct); - } - - return 1; - } -} - -/* TODO fix for unsigned */ -#define NUMBER_ONLY_BINOP(OPSTR, DO_NORMAL, DO_COMPLEX) \ - struct ctype lt, rt, ct; \ - void *lp, *rp; \ - int ct_usr; \ - int ret; \ - \ - lua_settop(L, 2); \ - \ - lp = to_cdata(L, 1, <); \ - rp = to_cdata(L, 2, &rt); \ - \ - ret = call_user_binop(L, OPSTR, 1, 3, <, 2, 4, &rt); \ - if (ret >= 0) { \ - return ret; \ - } \ - \ - ct_usr = rank(<) > rank(&rt) ? 3 : 4; \ - ct = rank(<) > rank(&rt) ? lt : rt; \ - \ - if (IS_COMPLEX(ct.type)) { \ - complex_double res; \ - complex_double left = check_complex(L, 1, lp, <); \ - complex_double right = check_complex(L, 2, rp, &rt); \ - \ - DO_COMPLEX(left, right, res); \ - push_complex(L, res, ct_usr, &ct); \ - \ - } else if (lt.pointers || rt.pointers) { \ - luaL_error(L, "can't operate on a pointer value"); \ - \ - } else { \ - int64_t res; \ - int64_t left = check_intptr(L, 1, lp, <); \ - int64_t right = check_intptr(L, 2, rp, &rt); \ - \ - DO_NORMAL(left, right, res); \ - push_number(L, res, ct_usr, &ct); \ - } \ - \ - return 1 - -#define MUL(l,r,s) s = l * r -#define DIV(l,r,s) s = l / r -#define MOD(l,r,s) s = l % r -#define POW(l,r,s) s = pow(l, r) - -#ifdef HAVE_COMPLEX -#define MULC(l,r,s) s = l * r -#define DIVC(l,r,s) s = l / r -#define MODC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex mod") -#define POWC(l,r,s) s = cpow(l, r) -#else -#define MULC(l,r,s) s.real = l.real * r.real - l.imag * r.imag, s.imag = l.real * r.imag + l.imag * r.real -#define DIVC(l,r,s) s.real = (l.real * r.real + l.imag * r.imag) / (r.real * r.real + r.imag * r.imag), \ - s.imag = (l.imag * r.real - l.real * r.imag) / (r.real * r.real + r.imag * r.imag) -#define MODC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex mod") -#define POWC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex pow") -#endif - -static int cdata_mul(lua_State* L) -{ NUMBER_ONLY_BINOP("__mul", MUL, MULC); } - -static int cdata_div(lua_State* L) -{ NUMBER_ONLY_BINOP("__div", DIV, DIVC); } - -static int cdata_mod(lua_State* L) -{ NUMBER_ONLY_BINOP("__mod", MOD, MODC); } - -static int cdata_pow(lua_State* L) -{ NUMBER_ONLY_BINOP("__pow", POW, POWC); } - -#define COMPARE_BINOP(OPSTR, OP, OPC) \ - struct ctype lt, rt; \ - void *lp, *rp; \ - int ret, res; \ - \ - lua_settop(L, 2); \ - \ - lp = to_cdata(L, 1, <); \ - rp = to_cdata(L, 2, &rt); \ - \ - ret = call_user_binop(L, OPSTR, 1, 3, <, 2, 4, &rt); \ - if (ret >= 0) { \ - return ret; \ - } \ - \ - if (IS_COMPLEX(lt.type) || IS_COMPLEX(rt.type)) { \ - complex_double left = check_complex(L, 1, lp, <); \ - complex_double right = check_complex(L, 2, rp, &rt); \ - \ - res = OPC(left, right); \ - \ - lua_pushboolean(L, res); \ - \ - } else { \ - int64_t left = check_intptr(L, 1, lp, <); \ - int64_t right = check_intptr(L, 2, rp, &rt); \ - \ - if (lt.pointers && rt.pointers) { \ - if (is_void_ptr(<) || is_void_ptr(&rt) || is_same_type(L, 3, 4, <, &rt)) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - } else { \ - goto err; \ - } \ - \ - } else if (lt.is_null && rt.type == FUNCTION_PTR_TYPE) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (rt.is_null && lt.type == FUNCTION_PTR_TYPE) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (lt.pointers && rt.type == INTPTR_TYPE && rt.is_unsigned) {\ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (rt.pointers && lt.type == INTPTR_TYPE && lt.is_unsigned) {\ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (rt.pointers || lt.pointers) { \ - goto err; \ - \ - } else if (lt.is_unsigned && rt.is_unsigned) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (lt.is_unsigned) { \ - res = OP((int64_t) (uint64_t) left, right); \ - \ - } else if (rt.is_unsigned) { \ - res = OP(left, (int64_t) (uint64_t) right); \ - \ - } else { \ - res = OP(left, right); \ - } \ - \ - lua_pushboolean(L, res); \ - } \ - return 1 - -#define EQ(l, r) (l) == (r) -#define LT(l, r) (l) < (r) -#define LE(l, r) (l) <= (r) - -#ifdef HAVE_COMPLEX -#define EQC(l, r) (l) == (r) -#else -#define EQC(l, r) (l).real == (r).real && (l).imag == (r).imag -#endif - -#define LEC(l, r) EQC(l, r), luaL_error(L, "complex numbers are non-orderable") -#define LTC(l, r) EQC(l, r), luaL_error(L, "complex numbers are non-orderable") - -static int cdata_eq(lua_State* L) -{ - COMPARE_BINOP("__eq", EQ, EQC); -err: - lua_pushboolean(L, 0); - return 1; -} - -static int cdata_lt(lua_State* L) -{ - COMPARE_BINOP("__lt", LT, LTC); -err: - lua_getuservalue(L, 1); - lua_getuservalue(L, 2); - push_type_name(L, -2, <); - push_type_name(L, -2, <); - return luaL_error(L, "trying to compare incompatible types %s and %s", lua_tostring(L, -2), lua_tostring(L, -1)); -} - -static int cdata_le(lua_State* L) -{ - COMPARE_BINOP("__le", LE, LEC); -err: - lua_getuservalue(L, 1); - lua_getuservalue(L, 2); - push_type_name(L, -2, <); - push_type_name(L, -2, <); - return luaL_error(L, "trying to compare incompatible types %s and %s", lua_tostring(L, -2), lua_tostring(L, -1)); -} - -static const char* etype_tostring(int type) -{ - switch (type) { - case VOID_TYPE: return "void"; - case DOUBLE_TYPE: return "double"; - case FLOAT_TYPE: return "float"; - case COMPLEX_DOUBLE_TYPE: return "complex double"; - case COMPLEX_FLOAT_TYPE: return "complex float"; - case BOOL_TYPE: return "bool"; - case INT8_TYPE: return "int8"; - case INT16_TYPE: return "int16"; - case INT32_TYPE: return "int32"; - case INT64_TYPE: return "int64"; - case INTPTR_TYPE: return "intptr"; - case ENUM_TYPE: return "enum"; - case UNION_TYPE: return "union"; - case STRUCT_TYPE: return "struct"; - case FUNCTION_PTR_TYPE: return "function ptr"; - case FUNCTION_TYPE: return "function"; - default: return "invalid"; - } -} - -static void print_type(lua_State* L, const struct ctype* ct) -{ - lua_pushfstring(L, " sz %d %d %d align %d ptr %d %d %d type %s%s %d %d %d name %d call %d %d var %d %d %d bit %d %d %d %d jit %d", - /* sz */ - ct->base_size, - ct->array_size, - ct->offset, - /* align */ - ct->align_mask, - /* ptr */ - ct->is_array, - ct->pointers, - ct->const_mask, - /* type */ - ct->is_unsigned ? "u" : "", - etype_tostring(ct->type), - ct->is_reference, - ct->is_defined, - ct->is_null, - /* name */ - ct->has_member_name, - /* call */ - ct->calling_convention, - ct->has_var_arg, - /* var */ - ct->is_variable_array, - ct->is_variable_struct, - ct->variable_size_known, - /* bit */ - ct->is_bitfield, - ct->has_bitfield, - ct->bit_offset, - ct->bit_size, - /* jit */ - ct->is_jitted); -} - -static int ctype_tostring(lua_State* L) -{ - struct ctype ct; - assert(lua_type(L, 1) == LUA_TUSERDATA); - lua_settop(L, 1); - check_ctype(L, 1, &ct); - assert(lua_gettop(L) == 2); - push_type_name(L, -1, &ct); - lua_pushfstring(L, "ctype<%s>", lua_tostring(L, -1)); - - if (DEBUG_TOSTRING) { - print_type(L, &ct); - lua_concat(L, 2); - } - - return 1; -} - -static int cdata_tostring(lua_State* L) -{ - struct ctype ct; - char buf[64]; - void* p; - int ret; - - lua_settop(L, 1); - p = to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__tostring", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - if (ct.pointers > 0 || ct.is_reference || ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) { - push_type_name(L, -1, &ct); - lua_pushfstring(L, "cdata<%s>: %p", lua_tostring(L, -1), p); - - if (DEBUG_TOSTRING) { - print_type(L, &ct); - lua_concat(L, 2); - } - - return 1; - } - - switch (ct.type) { - case COMPLEX_DOUBLE_TYPE: - { - complex_double c = *(complex_double*) p; - lua_pushfstring(L, "%f+%fi", creal(c), cimag(c)); - } - return 1; - - case COMPLEX_FLOAT_TYPE: - { - complex_float c = *(complex_float*) p; - lua_pushfstring(L, "%f+%fi", crealf(c), cimagf(c)); - } - return 1; - - case FUNCTION_PTR_TYPE: - p = *(void**) p; - push_type_name(L, -1, &ct); - lua_pushfstring(L, "cdata<%s>: %p", lua_tostring(L, -1), *(void**) p); - return 1; - - case INTPTR_TYPE: - lua_pushfstring(L, "%p", *(uintptr_t*) p); - return 1; - - case INT64_TYPE: - sprintf(buf, ct.is_unsigned ? "%"PRIu64 : "%"PRId64, *(uint64_t*) p); - lua_pushstring(L, buf); - return 1; - - default: - sprintf(buf, ct.is_unsigned ? "%"PRId64 : "%"PRId64, (int64_t) check_intptr(L, 1, p, &ct)); - lua_pushstring(L, buf); - return 1; - } -} - -static int ffi_errno(lua_State* L) -{ - struct jit* jit = get_jit(L); - - if (!lua_isnoneornil(L, 1)) { - lua_pushinteger(L, jit->last_errno); - jit->last_errno = luaL_checknumber(L, 1); - } else { - lua_pushinteger(L, jit->last_errno); - } - - return 1; -} - -static int ffi_type(lua_State* L) -{ - if (lua_isuserdata(L, 1) && lua_getmetatable(L, 1)) { - if (equals_upval(L, -1, &cdata_mt_key) || equals_upval(L, -1, &ctype_mt_key)) { - lua_pushstring(L, "cdata"); - return 1; - } - lua_pop(L, 1); /* mt */ - } - - /* call the old _G.type, we use an upvalue as _G.type is set - * to this function */ - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, 1); - lua_call(L, lua_gettop(L)-1, LUA_MULTRET); - return lua_gettop(L); -} - -static int ffi_number(lua_State* L) -{ - struct ctype ct; - void* data = to_cdata(L, 1, &ct); - - if (ct.type != INVALID_TYPE) { - lua_pushinteger(L, check_intptr(L, 1, data, &ct)); - return 1; - } else { - /* call the old _G.tonumber, we use an upvalue as _G.tonumber is set - * to this function */ - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, 1); - lua_call(L, lua_gettop(L)-1, LUA_MULTRET); - return lua_gettop(L); - } -} - -static int ffi_string(lua_State* L) -{ - struct ctype ct; - char* data; - lua_settop(L, 2); - - data = (char*) check_cdata(L, 1, &ct); - - if (is_void_ptr(&ct)) { - lua_pushlstring(L, data, (size_t) luaL_checknumber(L, 2)); - return 1; - - } else if (ct.type == INT8_TYPE && ct.pointers == 1) { - size_t sz; - - if (lua_isuserdata(L, 2)) { - ptrdiff_t val; - if (!cdata_tointeger(L, 2, &val)) { - type_error(L, 2, "int", 0, NULL); - } - sz = (size_t) val; - } else if (!lua_isnil(L, 2)) { - sz = (size_t) luaL_checknumber(L, 2); - - } else if (ct.is_array && !ct.is_variable_array) { - char* nul = memchr(data, '\0', ct.array_size); - sz = nul ? nul - data : ct.array_size; - - } else { - sz = strlen(data); - } - - lua_pushlstring(L, data, sz); - return 1; - } - - return luaL_error(L, "unable to convert cdata to string"); -} - -static int ffi_copy(lua_State* L) -{ - struct ctype ft, tt; - char *to, *from; - - setmintop(L, 3); - to = (char*) check_pointer(L, 1, &tt); - from = (char*) check_pointer(L, 2, &ft); - - if (!lua_isnoneornil(L, 3)) { - memcpy(to, from, (size_t) luaL_checknumber(L, 3)); - - } else if (ft.type == INT8_TYPE && ft.pointers == 1) { - size_t sz = ft.is_array ? ft.array_size : strlen(from); - memcpy(to, from, sz); - to[sz] = '\0'; - } - - return 0; -} - -static int ffi_fill(lua_State* L) -{ - struct ctype ct; - void* to; - size_t sz; - int val = 0; - - setmintop(L, 3); - to = check_pointer(L, 1, &ct); - sz = (size_t) luaL_checknumber(L, 2); - - if (!lua_isnoneornil(L, 3)) { - val = (int) luaL_checkinteger(L, 3); - } - - memset(to, val, sz); - return 0; -} - -static int ffi_abi(lua_State* L) -{ - luaL_checkstring(L, 1); - push_upval(L, &abi_key); - lua_pushvalue(L, 1); - lua_rawget(L, -2); - lua_pushboolean(L, lua_toboolean(L, -1)); - return 1; -} - -static int ffi_load(lua_State* L) -{ - const char* libname = luaL_checkstring(L, 1); - void** lib = (void**) lua_newuserdata(L, sizeof(void*)); - - *lib = LoadLibraryA(libname); - -#ifdef LIB_FORMAT_1 - if (!*lib) { - libname = lua_pushfstring(L, LIB_FORMAT_1, lua_tostring(L, 1)); - *lib = LoadLibraryA(libname); - lua_pop(L, 1); - } -#endif - -#ifdef LIB_FORMAT_2 - if (!*lib) { - libname = lua_pushfstring(L, LIB_FORMAT_2, lua_tostring(L, 1)); - *lib = LoadLibraryA(libname); - lua_pop(L, 1); - } -#endif - - if (!*lib) { - return luaL_error(L, "could not load library %s", lua_tostring(L, 1)); - } - - lua_newtable(L); - lua_setuservalue(L, -2); - - push_upval(L, &cmodule_mt_key); - lua_setmetatable(L, -2); - return 1; -} - -static void* find_symbol(lua_State* L, int modidx, const char* asmname) -{ - size_t i; - void** libs; - size_t num; - void* sym = NULL; - - libs = (void**) lua_touserdata(L, modidx); - num = lua_rawlen(L, modidx) / sizeof(void*); - - for (i = 0; i < num && sym == NULL; i++) { - if (libs[i]) { - sym = GetProcAddressA(libs[i], asmname); - } - } - - return sym; -} - -/* pushes the user table */ -static void* lookup_global(lua_State* L, int modidx, int nameidx, const char** pname, struct ctype* ct) -{ - int top = lua_gettop(L); - void* sym; - - modidx = lua_absindex(L, modidx); - nameidx = lua_absindex(L, nameidx); - - *pname = luaL_checkstring(L, nameidx); - - /* get the ctype */ - push_upval(L, &functions_key); - lua_pushvalue(L, nameidx); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - luaL_error(L, "missing declaration for function/global %s", *pname); - return NULL; - } - - /* leave just the ct_usr on the stack */ - *ct = *(const struct ctype*) lua_touserdata(L, -1); - lua_getuservalue(L, -1); - lua_replace(L, top + 1); - lua_pop(L, 1); - - assert(lua_gettop(L) == top + 1); - - /* get the assembly name */ - push_upval(L, &asmname_key); - lua_pushvalue(L, nameidx); - lua_rawget(L, -2); - if (lua_isstring(L, -1)) { - *pname = lua_tostring(L, -1); - } - lua_pop(L, 2); - - sym = find_symbol(L, modidx, *pname); - - assert(lua_gettop(L) == top + 1); - return sym; -} - -static int cmodule_index(lua_State* L) -{ - const char* asmname; - struct ctype ct; - void *sym; - - lua_settop(L, 2); - - /* see if we have already loaded the function */ - lua_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - return 1; - } - lua_pop(L, 2); - - /* check the constants table */ - push_upval(L, &constants_key); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - return 1; - } - lua_pop(L, 2); - - /* lookup_global pushes the ct_usr */ - sym = lookup_global(L, 1, 2, &asmname, &ct); - -#if defined _WIN32 && !defined _WIN64 && (defined __i386__ || defined _M_IX86) - if (!sym && ct.type == FUNCTION_TYPE) { - ct.calling_convention = STD_CALL; - lua_pushfstring(L, "_%s@%d", asmname, x86_return_size(L, -1, &ct)); - sym = find_symbol(L, 1, lua_tostring(L, -1)); - lua_pop(L, 1); - } - - if (!sym && ct.type == FUNCTION_TYPE) { - ct.calling_convention = FAST_CALL; - lua_pushfstring(L, "@%s@%d", asmname, x86_return_size(L, -1, &ct)); - sym = find_symbol(L, 1, lua_tostring(L, -1)); - lua_pop(L, 1); - } -#endif - - if (!sym) { - return luaL_error(L, "failed to find function/global %s", asmname); - } - - assert(lua_gettop(L) == 3); /* module, name, ct_usr */ - - if (ct.type == FUNCTION_TYPE) { - compile_function(L, (cfunction) sym, -1, &ct); - assert(lua_gettop(L) == 4); /* module, name, ct_usr, function */ - - /* set module usr value[luaname] = function to cache for next time */ - lua_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_pushvalue(L, -3); - lua_rawset(L, -3); - lua_pop(L, 1); /* module uv */ - return 1; - } - - /* extern const char* foo; and extern const char foo[]; */ - if (ct.pointers == 1 && ct.type == INT8_TYPE) { - char* str = (char*) sym; - if (!ct.is_array) { - str = *(char**) sym; - } - lua_pushstring(L, str); - return 1; - } - - /* extern struct foo foo[], extern void* foo[]; and extern struct foo foo; */ - if (ct.is_array || (!ct.pointers && (ct.type == UNION_TYPE || ct.type == STRUCT_TYPE))) { - void* p; - ct.is_reference = 1; - p = push_cdata(L, -1, &ct); - *(void**) p = sym; - return 1; - } - - /* extern void* foo; and extern void (*foo)(); */ - if (ct.pointers || ct.type == FUNCTION_PTR_TYPE) { - void* p = push_cdata(L, -1, &ct); - *(void**) p = *(void**) sym; - return 1; - } - - switch (ct.type) { - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case INTPTR_TYPE: - case INT64_TYPE: - { - /* TODO: complex float/double need to be references if .re and - * .imag are setable */ - void* p = push_cdata(L, -1, &ct); - memcpy(p, sym, ct.base_size); - return 1; - } - - case DOUBLE_TYPE: - lua_pushnumber(L, *(double*) sym); - return 1; - - case FLOAT_TYPE: - lua_pushnumber(L, *(float*) sym); - return 1; - - case BOOL_TYPE: - lua_pushboolean(L, *(bool*) sym); - return 1; - - case INT8_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint8_t*) sym : (lua_Integer) *(int8_t*) sym); - return 1; - - case INT16_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint16_t*) sym : (lua_Integer) *(int16_t*) sym); - return 1; - - case INT32_TYPE: - case ENUM_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint32_t*) sym : (lua_Integer) *(int32_t*) sym); - return 1; - } - - return luaL_error(L, "NYI - global value type"); -} - -static int cmodule_newindex(lua_State* L) -{ - const char* name; - void* sym; - struct ctype ct; - - lua_settop(L, 3); - - /* pushes the ct_usr */ - sym = lookup_global(L, 1, 2, &name, &ct); - assert(lua_gettop(L) == 4); /* module, name, value, ct_usr */ - - if (sym == NULL) { - return luaL_error(L, "failed to find global %s", name); - } - - if (ct.type == FUNCTION_TYPE || ct.is_array || (ct.const_mask & 1)) { - return luaL_error(L, "can not set global %s", name); - } - - set_value(L, 3, sym, -1, &ct, 1); - return 0; -} - -static int jit_gc(lua_State* L) -{ - size_t i; - struct jit* jit = get_jit(L); - dasm_free(jit); - for (i = 0; i < jit->pagenum; i++) { - FreePage(jit->pages[i], jit->pages[i]->size); - } - free(jit->pages); - free(jit->globals); - return 0; -} - -static int ffi_debug(lua_State* L) -{ - lua_newtable(L); - push_upval(L, &ctype_mt_key); - lua_setfield(L, -2, "ctype_mt"); - push_upval(L, &cdata_mt_key); - lua_setfield(L, -2, "cdata_mt"); - push_upval(L, &cmodule_mt_key); - lua_setfield(L, -2, "cmodule_mt"); - push_upval(L, &constants_key); - lua_setfield(L, -2, "constants"); - push_upval(L, &types_key); - lua_setfield(L, -2, "types"); - push_upval(L, &jit_key); - lua_setfield(L, -2, "jit"); - push_upval(L, &gc_key); - lua_setfield(L, -2, "gc"); - push_upval(L, &callbacks_key); - lua_setfield(L, -2, "callbacks"); - push_upval(L, &functions_key); - lua_setfield(L, -2, "functions"); - push_upval(L, &abi_key); - lua_setfield(L, -2, "abi"); - push_upval(L, &next_unnamed_key); - lua_setfield(L, -2, "next_unnamed"); - return 1; -} - -static int do64(lua_State* L, int is_unsigned) -{ - lua_Number low, high; - struct ctype ct; - int64_t val; - - lua_settop(L, 2); - - if (!lua_isnil(L, 2)) { - high = luaL_checknumber(L, 1); - low = luaL_checknumber(L, 2); - } else { - high = 0; - low = luaL_checknumber(L, 1); - } - - val = ((int64_t) (uint32_t) high << 32) | (int64_t) (uint32_t) low; - - if (!is_unsigned && (high < 0 || low < 0)) { - val = -val; - } - - memset(&ct, 0, sizeof(ct)); - ct.type = INT64_TYPE; - ct.is_unsigned = is_unsigned; - ct.is_defined = 1; - ct.base_size = sizeof(int64_t); - push_number(L, (int64_t) val, 0, &ct); - - return 1; -} - -static int ffi_i64(lua_State* L) -{ return do64(L, 0); } - -static int ffi_u64(lua_State* L) -{ return do64(L, 1); } - -static const luaL_Reg cdata_mt[] = { - {"__gc", &cdata_gc}, - {"__call", &cdata_call}, - {"free", &cdata_free}, - {"set", &cdata_set}, - {"__index", &cdata_index}, - {"__newindex", &cdata_newindex}, - {"__add", &cdata_add}, - {"__sub", &cdata_sub}, - {"__mul", &cdata_mul}, - {"__div", &cdata_div}, - {"__mod", &cdata_mod}, - {"__pow", &cdata_pow}, - {"__unm", &cdata_unm}, - {"__eq", &cdata_eq}, - {"__lt", &cdata_lt}, - {"__le", &cdata_le}, - {"__tostring", &cdata_tostring}, - {"__concat", &cdata_concat}, - {"__len", &cdata_len}, - {"__pairs", &cdata_pairs}, - {"__ipairs", &cdata_ipairs}, - {NULL, NULL} -}; - -static const luaL_Reg callback_mt[] = { - {"__gc", &callback_free}, - {NULL, NULL} -}; - -static const luaL_Reg ctype_mt[] = { - {"__call", &ctype_call}, - {"__new", &ctype_new}, - {"__tostring", &ctype_tostring}, - {NULL, NULL} -}; - -static const luaL_Reg cmodule_mt[] = { - {"__index", &cmodule_index}, - {"__newindex", &cmodule_newindex}, - {NULL, NULL} -}; - -static const luaL_Reg jit_mt[] = { - {"__gc", &jit_gc}, - {NULL, NULL} -}; - -static const luaL_Reg ffi_reg[] = { - {"cdef", &ffi_cdef}, - {"load", &ffi_load}, - {"new", &ffi_new}, - {"typeof", &ffi_typeof}, - {"cast", &ffi_cast}, - {"metatype", &ffi_metatype}, - {"gc", &ffi_gc}, - {"sizeof", &ffi_sizeof}, - {"alignof", &ffi_alignof}, - {"offsetof", &ffi_offsetof}, - {"istype", &ffi_istype}, - {"errno", &ffi_errno}, - {"string", &ffi_string}, - {"copy", &ffi_copy}, - {"fill", &ffi_fill}, - {"abi", &ffi_abi}, - {"debug", &ffi_debug}, - {"i64", &ffi_i64}, - {"u64", &ffi_u64}, - {NULL, NULL} -}; - -/* leaves the usr table on the stack */ -static void push_builtin(lua_State* L, struct ctype* ct, const char* name, int type, int size, int align, int is_unsigned) -{ - memset(ct, 0, sizeof(*ct)); - ct->type = type; - ct->base_size = size; - ct->align_mask = align; - ct->is_defined = 1; - ct->is_unsigned = is_unsigned; - - if (IS_COMPLEX(type)) { - lua_newtable(L); - } else { - lua_pushnil(L); - } - - push_upval(L, &types_key); - push_ctype(L, -2, ct); - lua_setfield(L, -2, name); - lua_pop(L, 2); /* types, usr table */ -} - -static void push_builtin_undef(lua_State* L, struct ctype* ct, const char* name, int type) -{ - memset(ct, 0, sizeof(*ct)); - ct->type = type; - - push_upval(L, &types_key); - push_ctype(L, 0, ct); - lua_setfield(L, -2, name); - lua_pop(L, 1); /* types */ -} - -static void add_typedef(lua_State* L, const char* from, const char* to) -{ - struct ctype ct; - struct parser P; - P.line = 1; - P.align_mask = DEFAULT_ALIGN_MASK; - P.next = P.prev = from; - - push_upval(L, &types_key); - parse_type(L, &P, &ct); - parse_argument(L, &P, -1, &ct, NULL, NULL); - push_ctype(L, -1, &ct); - - /* stack is at +4: types, type usr, arg usr, ctype */ - - lua_setfield(L, -4, to); - lua_pop(L, 3); /* types, type usr, arg usr */ -} - -static int setup_upvals(lua_State* L) -{ - struct jit* jit = get_jit(L); - - /* jit setup */ - { - dasm_init(jit, 64); -#ifdef _WIN32 - { - SYSTEM_INFO si; - GetSystemInfo(&si); - jit->align_page_size = si.dwAllocationGranularity - 1; - } -#else - jit->align_page_size = sysconf(_SC_PAGE_SIZE) - 1; -#endif - jit->globals = (void**) malloc(64 * sizeof(void*)); - dasm_setupglobal(jit, jit->globals, 64); - compile_globals(jit, L); - } - - /* ffi.C */ - { -#ifdef _WIN32 - size_t sz = sizeof(HMODULE) * 6; - HMODULE* libs = lua_newuserdata(L, sz); - memset(libs, 0, sz); - - /* exe */ - GetModuleHandle(NULL); - /* lua dll */ -#ifdef LUA_DLL_NAME -#define STR2(tok) #tok -#define STR(tok) STR2(tok) - libs[1] = LoadLibraryA(STR(LUA_DLL_NAME)); -#undef STR -#undef STR2 -#endif - - /* crt */ -#ifdef UNDER_CE - libs[2] = LoadLibraryA("coredll.dll"); -#else - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (char*) &_fmode, &libs[2]); - libs[3] = LoadLibraryA("kernel32.dll"); - libs[4] = LoadLibraryA("user32.dll"); - libs[5] = LoadLibraryA("gdi32.dll"); -#endif - - jit->lua_dll = libs[1]; - jit->kernel32_dll = libs[3]; - -#else /* !_WIN32 */ - size_t sz = sizeof(void*) * 5; - void** libs = lua_newuserdata(L, sz); - memset(libs, 0, sz); - - libs[0] = LoadLibraryA(NULL); /* exe */ - libs[1] = LoadLibraryA("libc.so"); -#ifdef __GNUC__ - libs[2] = LoadLibraryA("libgcc.so"); -#endif - libs[3] = LoadLibraryA("libm.so"); - libs[4] = LoadLibraryA("libdl.so"); -#endif - - lua_newtable(L); - lua_setuservalue(L, -2); - - push_upval(L, &cmodule_mt_key); - lua_setmetatable(L, -2); - - lua_setfield(L, 1, "C"); - } - - /* setup builtin types */ - { - complex_double* pc; - struct {char ch; uint16_t v;} a16; - struct {char ch; uint32_t v;} a32; - struct {char ch; uint64_t v;} a64; - struct {char ch; float v;} af; - struct {char ch; double v;} ad; -#ifdef HAVE_LONG_DOUBLE - struct {char ch; long double v;} ald; -#endif - struct {char ch; uintptr_t v;} aptr; - struct ctype ct; - struct {char ch; complex_float v;} cf; - struct {char ch; complex_double v;} cd; -#if defined HAVE_LONG_DOUBLE && defined HAVE_COMPLEX - struct {char ch; complex long double v;} cld; -#endif - - push_builtin(L, &ct, "void", VOID_TYPE, 0, 0, 0); - push_builtin(L, &ct, "bool", BOOL_TYPE, sizeof(_Bool), sizeof(_Bool) -1, 1); - push_builtin(L, &ct, "uint8_t", INT8_TYPE, sizeof(uint8_t), 0, 1); - push_builtin(L, &ct, "int8_t", INT8_TYPE, sizeof(int8_t), 0, 0); - push_builtin(L, &ct, "uint16_t", INT16_TYPE, sizeof(uint16_t), ALIGNOF(a16), 1); - push_builtin(L, &ct, "int16_t", INT16_TYPE, sizeof(int16_t), ALIGNOF(a16), 0); - push_builtin(L, &ct, "uint32_t", INT32_TYPE, sizeof(uint32_t), ALIGNOF(a32), 1); - push_builtin(L, &ct, "int32_t", INT32_TYPE, sizeof(int32_t), ALIGNOF(a32), 0); - push_builtin(L, &ct, "uint64_t", INT64_TYPE, sizeof(uint64_t), ALIGNOF(a64), 1); - push_builtin(L, &ct, "int64_t", INT64_TYPE, sizeof(int64_t), ALIGNOF(a64), 0); - push_builtin(L, &ct, "float", FLOAT_TYPE, sizeof(float), ALIGNOF(af), 0); - push_builtin(L, &ct, "double", DOUBLE_TYPE, sizeof(double), ALIGNOF(ad), 0); -#ifdef HAVE_LONG_DOUBLE - push_builtin(L, &ct, "long double", LONG_DOUBLE_TYPE, sizeof(long double), ALIGNOF(ald), 0); -#else - push_builtin_undef(L, &ct, "long double", LONG_DOUBLE_TYPE); -#endif - push_builtin(L, &ct, "uintptr_t", INTPTR_TYPE, sizeof(uintptr_t), ALIGNOF(aptr), 1); - push_builtin(L, &ct, "intptr_t", INTPTR_TYPE, sizeof(uintptr_t), ALIGNOF(aptr), 0); - push_builtin(L, &ct, "complex float", COMPLEX_FLOAT_TYPE, sizeof(complex_float), ALIGNOF(cf), 0); - push_builtin(L, &ct, "complex double", COMPLEX_DOUBLE_TYPE, sizeof(complex_double), ALIGNOF(cd), 0); -#if defined HAVE_LONG_DOUBLE && defined HAVE_COMPLEX - push_builtin(L, &ct, "complex long double", COMPLEX_LONG_DOUBLE_TYPE, sizeof(complex long double), ALIGNOF(cld), 0); -#else - push_builtin_undef(L, &ct, "complex long double", COMPLEX_LONG_DOUBLE_TYPE); -#endif - - /* add NULL and i constants */ - push_upval(L, &constants_key); - - memset(&ct, 0, sizeof(ct)); - ct.type = VOID_TYPE; - ct.is_defined = 1; - ct.pointers = 1; - ct.is_null = 1; - - /* add ffi.C.NULL */ - push_cdata(L, 0, &ct); - lua_setfield(L, -2, "NULL"); - - /* add ffi.NULL */ - push_cdata(L, 0, &ct); - lua_setfield(L, 1, "NULL"); - - memset(&ct, 0, sizeof(ct)); - ct.type = COMPLEX_DOUBLE_TYPE; - ct.is_defined = 1; - ct.base_size = sizeof(complex_double); - pc = (complex_double*) push_cdata(L, 0, &ct); -#ifdef HAVE_COMPLEX - *pc = 1i; -#else - pc->real = 0; - pc->imag = 1; -#endif - lua_setfield(L, -2, "i"); - - lua_pop(L, 1); /* constants */ - } - - assert(lua_gettop(L) == 1); - - /* setup builtin typedefs */ - { - add_typedef(L, "bool", "_Bool"); - - if (sizeof(uint32_t) == sizeof(size_t)) { - add_typedef(L, "uint32_t", "size_t"); - add_typedef(L, "int32_t", "ssize_t"); - } else if (sizeof(uint64_t) == sizeof(size_t)) { - add_typedef(L, "uint64_t", "size_t"); - add_typedef(L, "int64_t", "ssize_t"); - } - - if (sizeof(int32_t) == sizeof(intptr_t)) { - add_typedef(L, "int32_t", "intptr_t"); - add_typedef(L, "int32_t", "ptrdiff_t"); - } else if (sizeof(int64_t) == sizeof(intptr_t)) { - add_typedef(L, "int64_t", "intptr_t"); - add_typedef(L, "int64_t", "ptrdiff_t"); - } - - if (sizeof(uint8_t) == sizeof(wchar_t)) { - add_typedef(L, "uint8_t", "wchar_t"); - } else if (sizeof(uint16_t) == sizeof(wchar_t)) { - add_typedef(L, "uint16_t", "wchar_t"); - } else if (sizeof(uint32_t) == sizeof(wchar_t)) { - add_typedef(L, "uint32_t", "wchar_t"); - } - - if (sizeof(va_list) == sizeof(char*)) { - add_typedef(L, "char*", "va_list"); - } else { - struct {char ch; va_list v;} av; - lua_pushfstring(L, "struct {char data[%d] __attribute__((align(%d)));}", (int) sizeof(va_list), (int) ALIGNOF(av) + 1); - add_typedef(L, lua_tostring(L, -1), "va_list"); - lua_pop(L, 1); - } - - add_typedef(L, "va_list", "__builtin_va_list"); - add_typedef(L, "va_list", "__gnuc_va_list"); - } - - assert(lua_gettop(L) == 1); - - /* setup ABI params table */ - push_upval(L, &abi_key); - -#if defined ARCH_X86 || defined ARCH_ARM - lua_pushboolean(L, 1); - lua_setfield(L, -2, "32bit"); -#elif defined ARCH_X64 || defined ARCH_PPC64 - lua_pushboolean(L, 1); - lua_setfield(L, -2, "64bit"); -#else -# define UNSUPPORTED_ARCH /* error */ -#endif - -#if defined ARCH_X86 || defined ARCH_X64 || defined ARCH_ARM || defined ARCH_PPC64 - lua_pushboolean(L, 1); - lua_setfield(L, -2, "le"); -#else -# define UNSUPPORTED_ARCH /*error*/ -#endif - -#if defined ARCH_X86 || defined ARCH_X64 || defined ARCH_PPC64 - lua_pushboolean(L, 1); - lua_setfield(L, -2, "fpu"); -#elif defined ARCH_ARM - lua_pushboolean(L, 1); - lua_setfield(L, -2, "softfp"); -#else -# define UNSUPPORTED_ARCH /*error*/ -#endif - lua_pop(L, 1); /* abi tbl */ - - - /* GC table - shouldn't pin cdata values */ - push_upval(L, &gc_key); - lua_newtable(L); - lua_pushliteral(L, "k"); - lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_pop(L, 1); /* gc table */ - - - /* ffi.os */ -#if defined OS_CE - lua_pushliteral(L, "WindowsCE"); -#elif defined OS_WIN - lua_pushliteral(L, "Windows"); -#elif defined OS_OSX - lua_pushliteral(L, "OSX"); -#elif defined OS_LINUX - lua_pushliteral(L, "Linux"); -#elif defined OS_BSD - lua_pushliteral(L, "BSD"); -#elif defined OS_POSIX - lua_pushliteral(L, "POSIX"); -#else - lua_pushliteral(L, "Other"); -#endif - lua_setfield(L, 1, "os"); - - - /* ffi.arch */ -#if defined ARCH_X86 - lua_pushliteral(L, "x86"); -#elif defined ARCH_X64 - lua_pushliteral(L, "x64"); -#elif defined ARCH_ARM - lua_pushliteral(L, "arm"); -#elif defined ARCH_PPC64 - lua_pushliteral(L, "ppc64"); -#else -# define UNSUPPORTED_ARCH /* error */ -#endif - lua_setfield(L, 1, "arch"); - - assert(lua_gettop(L) == 1); - - return 0; -} - -static void setup_mt(lua_State* L, const luaL_Reg* mt, int upvals) -{ - lua_pushboolean(L, 1); - lua_setfield(L, -upvals-2, "__metatable"); - luaL_setfuncs(L, mt, upvals); -} - - -#if defined FFI_ENABLE_LUATEX_INTERFACE -int luaopen_ffi(lua_State* L) -{ - lua_settop(L, 0); - - lua_newtable(L); - set_upval(L, &niluv_key); - - lua_newtable(L); - setup_mt(L, ctype_mt, 0); - set_upval(L, &ctype_mt_key); - - lua_newtable(L); - set_upval(L, &callbacks_key); - - lua_newtable(L); - set_upval(L, &gc_key); - - lua_newtable(L); - push_upval(L, &callbacks_key); - push_upval(L, &gc_key); - setup_mt(L, cdata_mt, 2); - set_upval(L, &cdata_mt_key); - - lua_newtable(L); - setup_mt(L, callback_mt, 0); - set_upval(L, &callback_mt_key); - - lua_newtable(L); - setup_mt(L, cmodule_mt, 0); - set_upval(L, &cmodule_mt_key); - - memset(lua_newuserdata(L, sizeof(struct jit)), 0, sizeof(struct jit)); - lua_newtable(L); - setup_mt(L, jit_mt, 0); - lua_setmetatable(L, -2); - set_upval(L, &jit_key); - - lua_newtable(L); - set_upval(L, &constants_key); - - lua_newtable(L); - set_upval(L, &types_key); - - lua_newtable(L); - set_upval(L, &functions_key); - - lua_newtable(L); - set_upval(L, &asmname_key); - - lua_newtable(L); - set_upval(L, &abi_key); - - lua_pushinteger(L, 1); - set_upval(L, &next_unnamed_key); - - assert(lua_gettop(L) == 0); - - /* ffi table */ - lua_newtable(L); - luaL_setfuncs(L, ffi_reg, 0); - - /* setup_upvals(ffi tbl) */ - lua_pushcfunction(L, &setup_upvals); - lua_pushvalue(L, 1); - lua_call(L, 1, 0); - - assert(lua_gettop(L) == 1); - - lua_getglobal(L, "tonumber"); - lua_pushcclosure(L, &ffi_number, 1); - lua_pushvalue(L, -1); - lua_setglobal(L, "tonumber"); - lua_setfield(L, -2, "number"); /* ffi.number */ - - lua_getglobal(L, "type"); - lua_pushcclosure(L, &ffi_type, 1); - lua_pushvalue(L, -1); - lua_setglobal(L, "type"); - lua_setfield(L, -2, "type"); /* ffi.type */ - return 1; -} -#else -/* This is a stub for OS/ARCH that at this moment don't support ffi */ -int luaopen_ffi(lua_State *L) -{ - int k ; - - k = luaL_dostring(L, "local info = [[\n" -"The ffi module is available for:\n" -"\n" -" archictures : ARCH_X86 and ARCH_X64,\n" -" operating systems : OS_CE, OS_WIN, OS_LINUX, OS_BSD and OS_POSIX\n" -"\n" -"The ARM processor is currently not supported. There are subtle\n" -"differences between this module and the one in luajitTeX \n" -"and we hope to be in sync around TeXLive 2022.\n" -"Different OS can have different interfaces,\n" -"for instance OS_WIN has not 'complex.h'. If you want portable\n" -"code, stick to the most common concepts.\n" -"]]\n" -"\n" -"local function stub()\n" -" texio.write_nl(info)\n" -"end\n" -"\n" -"return {\n" -" fill = stub,\n" -" cast = stub,\n" -" offsetof = stub,\n" -" copy = stub,\n" -" string = stub,\n" -" abi = stub,\n" -" cdef = stub,\n" -" typeof = stub,\n" -" sizeof = stub,\n" -" type = stub,\n" -" number = stub,\n" -" gc = stub,\n" -" metatype = stub,\n" -" errno = stub,\n" -" debug = stub,\n" -" os = '' ,\n" -" arch = '' ,\n" -" NULL = nil ,\n" -" alignof = stub,\n" -" new = stub,\n" -" u64 = stub,\n" -" i64 = stub,\n" -" istype = stub,\n" -" load = stub,\n" -" C = nil ,\n" -"}"); - - return k==0 ? 1 : k; -} -#endif diff --git a/Build/source/texk/web2c/luatexdir/luaffi/ffi.c.orig b/Build/source/texk/web2c/luatexdir/luaffi/ffi.c.orig deleted file mode 100644 index 988e764b2d7..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/ffi.c.orig +++ /dev/null @@ -1,3552 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#include "ffi.h" -#include <math.h> -#include <inttypes.h> - -/* Set to 1 to get extra debugging on print */ -#define DEBUG_TOSTRING 0 - -int jit_key; -int ctype_mt_key; -int cdata_mt_key; -int callback_mt_key; -int cmodule_mt_key; -int constants_key; -int types_key; -int gc_key; -int callbacks_key; -int functions_key; -int abi_key; -int next_unnamed_key; -int niluv_key; -int asmname_key; - -void push_upval(lua_State* L, int* key) -{ - lua_pushlightuserdata(L, key); - lua_rawget(L, LUA_REGISTRYINDEX); -} - -void set_upval(lua_State* L, int* key) -{ - lua_pushlightuserdata(L, key); - lua_insert(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); -} - -int equals_upval(lua_State* L, int idx, int* key) -{ - int ret; - lua_pushvalue(L, idx); - push_upval(L, key); - ret = lua_rawequal(L, -2, -1); - lua_pop(L, 2); - return ret; -} - -struct jit* get_jit(lua_State* L) -{ - struct jit* jit; - push_upval(L, &jit_key); - jit = (struct jit*) lua_touserdata(L, -1); - jit->L = L; - lua_pop(L, 1); /* still in registry */ - return jit; -} - -static int type_error(lua_State* L, int idx, const char* to_type, int to_usr, const struct ctype* to_ct) -{ - luaL_Buffer B; - struct ctype ft; - - assert(to_type || (to_usr && to_ct)); - if (to_usr) { - to_usr = lua_absindex(L, to_usr); - } - - idx = lua_absindex(L, idx); - - luaL_buffinit(L, &B); - to_cdata(L, idx, &ft); - - if (ft.type != INVALID_TYPE) { - push_type_name(L, -1, &ft); - lua_pushfstring(L, "unable to convert argument %d from cdata<%s> to cdata<", idx, lua_tostring(L, -1)); - lua_remove(L, -2); - luaL_addvalue(&B); - } else { - lua_pushfstring(L, "unable to convert argument %d from lua<%s> to cdata<", idx, luaL_typename(L, idx)); - luaL_addvalue(&B); - } - - if (to_ct) { - push_type_name(L, to_usr, to_ct); - luaL_addvalue(&B); - } else { - luaL_addstring(&B, to_type); - } - - luaL_addchar(&B, '>'); - - luaL_pushresult(&B); - return lua_error(L); -} - -static void* userdata_toptr(lua_State* L, int idx) -{ - void* ptr = lua_touserdata(L, idx); - - // check for FILE* - lua_getmetatable(L, idx); - luaL_getmetatable(L, LUA_FILEHANDLE); - int isfile = lua_rawequal(L, -1, -2); - lua_pop(L, 2); - - if (isfile) { -#if LUA_VERSION_NUM == 501 - FILE** stream = (FILE**) ptr; - return *stream; -#else - luaL_Stream* stream = (luaL_Stream*) ptr; - return stream->f; -#endif - } - - return ptr; -} - -static int cdata_tointeger(lua_State* L, int idx, ptrdiff_t* val) -{ - struct ctype ct; - void* addr = to_cdata(L, idx, &ct); - lua_pop(L, 1); - - if (ct.pointers) { - return 0; - } - - switch (ct.type) { - case INT8_TYPE: - *val = *(int8_t*)addr; - return 1; - case INT16_TYPE: - *val = *(int16_t*)addr; - return 1; - case INT32_TYPE: - *val = *(int32_t*)addr; - return 1; - case INT64_TYPE: - *val = *(int64_t*)addr; - return 1; - default: - return 0; - } -} - -static int64_t check_intptr(lua_State* L, int idx, void* p, struct ctype* ct) -{ - if (ct->type == INVALID_TYPE) { - int64_t ret; - memset(ct, 0, sizeof(*ct)); - ct->base_size = 8; - ct->type = INT64_TYPE; - ct->is_defined = 1; - ret = luaL_checknumber(L, idx); - return ret; - - } else if (ct->pointers) { - return (intptr_t) p; - } - - switch (ct->type) { - case INTPTR_TYPE: - case FUNCTION_PTR_TYPE: - return *(intptr_t*) p; - - case INT64_TYPE: - return *(int64_t*) p; - - case INT32_TYPE: - return ct->is_unsigned ? (int64_t) *(uint32_t*) p : (int64_t) *(int32_t*) p; - - case INT16_TYPE: - return ct->is_unsigned ? (int64_t) *(uint16_t*) p : (int64_t) *(int16_t*) p; - - case INT8_TYPE: - return ct->is_unsigned ? (int64_t) *(uint8_t*) p : (int64_t) *(int8_t*) p; - - default: - type_error(L, idx, "intptr_t", 0, NULL); - return 0; - } -} - -static int get_cfunction_address(lua_State* L, int idx, cfunction* addr); - -#define TO_NUMBER(TYPE, ALLOW_POINTERS, LUA_TONUMBER) \ - TYPE ret = 0; \ - void* p; \ - struct ctype ct; \ - cfunction f; \ - \ - switch (lua_type(L, idx)) { \ - case LUA_TBOOLEAN: \ - ret = (TYPE) lua_toboolean(L, idx); \ - break; \ - \ - case LUA_TNUMBER: \ - ret = (TYPE) LUA_TONUMBER(L, idx); \ - break; \ - \ - case LUA_TSTRING: \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) lua_tostring(L, idx); \ - break; \ - \ - case LUA_TLIGHTUSERDATA: \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) lua_topointer(L, idx); \ - break; \ - \ - case LUA_TFUNCTION: \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - if (!get_cfunction_address(L, idx, &f)) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) f; \ - break; \ - \ - case LUA_TUSERDATA: \ - p = to_cdata(L, idx, &ct); \ - \ - if (ct.type == INVALID_TYPE) { \ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) userdata_toptr(L, idx); \ - } else if (ct.pointers || ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) {\ - if (!ALLOW_POINTERS) { \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - ret = (TYPE) (intptr_t) p; \ - } else if (ct.type == COMPLEX_DOUBLE_TYPE) { \ - ret = (TYPE) creal(*(complex_double*) p); \ - } else if (ct.type == COMPLEX_FLOAT_TYPE) { \ - ret = (TYPE) crealf(*(complex_float*) p); \ - } else if (ct.type == DOUBLE_TYPE) { \ - ret = (TYPE) *(double*) p; \ - } else if (ct.type == FLOAT_TYPE) { \ - ret = (TYPE) *(float*) p; \ - } else { \ - ret = check_intptr(L, idx, p, &ct); \ - } \ - lua_pop(L, 1); \ - break; \ - \ - case LUA_TNIL: \ - ret = (TYPE) 0; \ - break; \ - \ - default: \ - type_error(L, idx, #TYPE, 0, NULL); \ - } \ - -static int64_t cast_int64(lua_State* L, int idx, int is_cast) -{ TO_NUMBER(int64_t, is_cast, lua_tointeger); return ret; } - -static uint64_t cast_uint64(lua_State* L, int idx, int is_cast) -{ TO_NUMBER(uint64_t, is_cast, lua_tointeger); return ret; } - -int32_t check_int32(lua_State* L, int idx) -{ return (int32_t) cast_int64(L, idx, 0); } - -uint32_t check_uint32(lua_State* L, int idx) -{ return (uint32_t) cast_uint64(L, idx, 0); } - -int64_t check_int64(lua_State* L, int idx) -{ return cast_int64(L, idx, 0); } - -uint64_t check_uint64(lua_State* L, int idx) -{ return cast_uint64(L, idx, 0); } - -double check_double(lua_State* L, int idx) -{ TO_NUMBER(double, 0, lua_tonumber); return ret; } - -float check_float(lua_State* L, int idx) -{ TO_NUMBER(double, 0, lua_tonumber); return ret; } - -uintptr_t check_uintptr(lua_State* L, int idx) -{ TO_NUMBER(uintptr_t, 1, lua_tointeger); return ret; } - -complex_double check_complex_double(lua_State* L, int idx) -{ - double real = 0, imag = 0; - void* p; - struct ctype ct; - - switch (lua_type(L, idx)) { - case LUA_TNUMBER: - real = (double) lua_tonumber(L, idx); - break; - case LUA_TTABLE: - lua_rawgeti(L, idx, 1); - real = check_double(L, -1); - lua_pop(L, 1); - - lua_rawgeti(L, idx, 2); - if (lua_isnil(L, -1)) { - imag = real; - } else { - imag = check_double(L, -1); - } - lua_pop(L, 1); - break; - case LUA_TUSERDATA: - p = to_cdata(L, idx, &ct); - if (ct.type == COMPLEX_DOUBLE_TYPE) { - real = creal(*(complex_double*) p); - imag = cimag(*(complex_double*) p); - } else if (ct.type == COMPLEX_FLOAT_TYPE) { - real = crealf(*(complex_float*) p); - imag = cimagf(*(complex_float*) p); - } else if (ct.type == DOUBLE_TYPE) { - real = *(double*) p; - } else if (ct.type == FLOAT_TYPE) { - real = *(float*) p; - } else { - real = check_intptr(L, idx, p, &ct); - } - lua_pop(L, 1); - break; - - default: - type_error(L, idx, "complex", 0, NULL); - } - - return mk_complex_double(real, imag); -} - -complex_float check_complex_float(lua_State* L, int idx) -{ - complex_double d = check_complex_double(L, idx); - return mk_complex_float(creal(d), cimag(d)); -} - -static size_t unpack_vararg(lua_State* L, int i, char* to) -{ - void* p; - struct ctype ct; - - switch (lua_type(L, i)) { - case LUA_TBOOLEAN: - *(int*) to = lua_toboolean(L, i); - return sizeof(int); - - case LUA_TNUMBER: - *(double*) to = lua_tonumber(L, i); // TODO in Lua 5.3: lua_tointeger sometimes should be here - return sizeof(double); - - case LUA_TSTRING: - *(const char**) to = lua_tostring(L, i); - return sizeof(const char*); - - case LUA_TLIGHTUSERDATA: - *(void**) to = lua_touserdata(L, i); - return sizeof(void*); - - case LUA_TUSERDATA: - p = to_cdata(L, i, &ct); - lua_pop(L, 1); - - if (ct.type == INVALID_TYPE) { - *(void**) to = userdata_toptr(L, i); - return sizeof(void*); - - } else if (ct.pointers || ct.type == INTPTR_TYPE) { - *(void**) to = p; - return sizeof(void*); - - } else if (ct.type == INT32_TYPE) { - *(int32_t*) to = *(int32_t*) p; - return sizeof(int32_t); - - } else if (ct.type == INT64_TYPE) { - *(int64_t*) to = *(int64_t*) p; - return sizeof(int64_t); - } - goto err; - - case LUA_TNIL: - *(void**) to = NULL; - return sizeof(void*); - - default: - goto err; - } - -err: - return type_error(L, i, "vararg", 0, NULL); -} - -void unpack_varargs_stack(lua_State* L, int first, int last, char* to) -{ - int i; - - for (i = first; i <= last; i++) { - to += unpack_vararg(L, i, to); - } -} - -void unpack_varargs_stack_skip(lua_State* L, int first, int last, int ints_to_skip, int floats_to_skip, char* to) -{ - int i; - - for (i = first; i <= last; i++) { - int type = lua_type(L, i); - - if (type == LUA_TNUMBER && --floats_to_skip >= 0) { - continue; - } else if (type != LUA_TNUMBER && --ints_to_skip >= 0) { - continue; - } - - to += unpack_vararg(L, i, to); - } -} - -void unpack_varargs_float(lua_State* L, int first, int last, int max, char* to) -{ - int i; - - for (i = first; i <= last && max > 0; i++) { - if (lua_type(L, i) == LUA_TNUMBER) { - unpack_vararg(L, i, to); - to += sizeof(double); - max--; - } - } -} - -void unpack_varargs_int(lua_State* L, int first, int last, int max, char* to) -{ - int i; - - for (i = first; i <= last && max > 0; i++) { - if (lua_type(L, i) != LUA_TNUMBER) { - unpack_vararg(L, i, to); - to += sizeof(void*); - max--; - } - } -} - -void unpack_varargs_reg(lua_State* L, int first, int last, char* to) -{ - int i; - - for (i = first; i <= last; i++) { - unpack_vararg(L, i, to); - to += sizeof(double); - } -} - -/* to_enum tries to convert a value at idx to the enum type indicated by to_ct - * and uv to_usr. For strings this means it will do a string lookup for the - * enum type. It leaves the stack unchanged. Will throw an error if the type - * at idx can't be conerted. - */ -int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* to_ct) -{ - int32_t ret; - - switch (lua_type(L, idx)) { - case LUA_TSTRING: - /* lookup string in to_usr to find value */ - to_usr = lua_absindex(L, to_usr); - lua_pushvalue(L, idx); - lua_rawget(L, to_usr); - - if (lua_isnil(L, -1)) { - goto err; - } - - ret = (int32_t) lua_tointeger(L, -1); - lua_pop(L, 1); - return ret; - - case LUA_TUSERDATA: - return check_int32(L, idx); - - case LUA_TNIL: - return (int32_t) 0; - - case LUA_TNUMBER: - return (int32_t) lua_tointeger(L, idx); - - default: - goto err; - } - -err: - return type_error(L, idx, NULL, to_usr, to_ct); -} - -/* to_pointer tries converts a value at idx to a pointer. It fills out ct and - * pushes the uv of the found type. It will throw a lua error if it can not - * convert the value to a pointer. */ -static void* check_pointer(lua_State* L, int idx, struct ctype* ct) -{ - void* p; - memset(ct, 0, sizeof(*ct)); - idx = lua_absindex(L, idx); - - switch (lua_type(L, idx)) { - case LUA_TNIL: - ct->type = VOID_TYPE; - ct->pointers = 1; - ct->is_null = 1; - lua_pushnil(L); - return NULL; - - case LUA_TNUMBER: - ct->type = INTPTR_TYPE; - ct->is_unsigned = 1; - ct->pointers = 0; - lua_pushnil(L); - return (void*) (uintptr_t) lua_tonumber(L, idx); // TODO in Lua 5.3: maybe change to lua_tointeger - - case LUA_TLIGHTUSERDATA: - ct->type = VOID_TYPE; - ct->pointers = 1; - lua_pushnil(L); - return lua_touserdata(L, idx); - - case LUA_TSTRING: - ct->type = INT8_TYPE; - ct->pointers = 1; - ct->is_unsigned = IS_CHAR_UNSIGNED; - ct->is_array = 1; - ct->base_size = 1; - ct->const_mask = 2; - lua_pushnil(L); - return (void*) lua_tolstring(L, idx, &ct->array_size); - - case LUA_TUSERDATA: - p = to_cdata(L, idx, ct); - - if (ct->type == INVALID_TYPE) { - /* some other type of user data */ - ct->type = VOID_TYPE; - ct->pointers = 1; - return userdata_toptr(L, idx); - } else if (ct->type == STRUCT_TYPE || ct->type == UNION_TYPE) { - return p; - } else { - return (void*) (intptr_t) check_intptr(L, idx, p, ct); - } - break; - } - - type_error(L, idx, "pointer", 0, NULL); - return NULL; -} - -static int is_void_ptr(const struct ctype* ct) -{ - return ct->type == VOID_TYPE - && ct->pointers == 1; -} - -static int is_same_type(lua_State* L, int usr1, int usr2, const struct ctype* t1, const struct ctype* t2) -{ - if (t1->type != t2->type) { - return 0; - } - -#if LUA_VERSION_NUM == 501 - if (lua_isnil(L, usr1) != lua_isnil(L, usr2)) { - int ret; - usr1 = lua_absindex(L, usr1); - usr2 = lua_absindex(L, usr2); - push_upval(L, &niluv_key); - - ret = lua_rawequal(L, usr1, -1) - || lua_rawequal(L, usr2, -1); - - lua_pop(L, 1); - - if (ret) { - return 1; - } - } -#endif - - return lua_rawequal(L, usr1, usr2); -} - -static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers); - -/* to_typed_pointer converts a value at idx to a type tt with target uv to_usr - * checking all types. May push a temporary value so that it can create - * structs on the fly. */ -void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt) -{ - struct ctype ft; - void* p; - - to_usr = lua_absindex(L, to_usr); - idx = lua_absindex(L, idx); - - if (tt->pointers == 1 && (tt->type == STRUCT_TYPE || tt->type == UNION_TYPE) && lua_type(L, idx) == LUA_TTABLE) { - /* need to construct a struct of the target type */ - struct ctype ct = *tt; - ct.pointers = ct.is_array = 0; - p = push_cdata(L, to_usr, &ct); - set_struct(L, idx, p, to_usr, &ct, 1); - return p; - } - - p = check_pointer(L, idx, &ft); - - if (tt->pointers == 1 && ft.pointers == 0 && (ft.type == STRUCT_TYPE || ft.type == UNION_TYPE)) { - /* auto dereference structs */ - ft.pointers = 1; - ft.const_mask <<= 1; - } - - if (is_void_ptr(tt)) { - /* any pointer can convert to void* */ - goto suc; - - } else if (is_void_ptr(&ft) && (ft.pointers || ft.is_reference)) { - /* void* can convert to any pointer */ - goto suc; - - } else if (ft.is_null) { - /* NULL can convert to any pointer */ - goto suc; - - } else if (!is_same_type(L, to_usr, -1, tt, &ft)) { - /* the base type is different */ - goto err; - - } else if (tt->pointers != ft.pointers) { - goto err; - - } else if (ft.const_mask & ~tt->const_mask) { - /* for every const in from it must be in to, there are further rules - * for const casting (see the c++ spec), but they are hard to test - * quickly */ - goto err; - } - -suc: - return p; - -err: - type_error(L, idx, NULL, to_usr, tt); - return NULL; -} - -/** - * gets the address of the wrapped C function for the lua function value at idx - * and returns 1 if it exists; otherwise returns 0 and nothing is pushed */ -static int get_cfunction_address(lua_State* L, int idx, cfunction* addr) -{ - if (!lua_isfunction(L, idx)) return 0; - - int top = lua_gettop(L); - - // Get the last upvalue - int n = 2; - while (lua_getupvalue(L, idx, n)) { - lua_pop(L, 1); - n++; - } - - if (!lua_getupvalue(L, idx, n - 1)) - return 0; - - if (!lua_isuserdata(L, -1) || !lua_getmetatable(L, -1)) { - lua_pop(L, 1); - return 0; - } - - push_upval(L, &callback_mt_key); - if (!lua_rawequal(L, -1, -2)) { - lua_pop(L, 3); - return 0; - } - - /* stack is: - * userdata upval - * metatable - * callback_mt - */ - - cfunction* f = lua_touserdata(L, -3); - *addr = f[1]; - lua_pop(L, 3); - return 1; -} - -/* to_cfunction converts a value at idx with usr table at to_usr and type tt - * into a function. Leaves the stack unchanged. */ -static cfunction check_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt, int check_pointers) -{ - void* p; - struct ctype ft; - cfunction f; - int top = lua_gettop(L); - - idx = lua_absindex(L, idx); - to_usr = lua_absindex(L, to_usr); - - switch (lua_type(L, idx)) { - case LUA_TFUNCTION: - if (get_cfunction_address(L, idx, &f)) { - return f; - } - - /* Function cdatas are pinned and must be manually cleaned up by - * calling func:free(). */ - push_upval(L, &callbacks_key); - f = compile_callback(L, idx, to_usr, tt); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - lua_pop(L, 1); /* callbacks tbl */ - return f; - - case LUA_TNIL: - return NULL; - - case LUA_TLIGHTUSERDATA: - if (check_pointers) { - goto err; - } else { - return (cfunction) lua_touserdata(L, idx); - } - - case LUA_TUSERDATA: - p = to_cdata(L, idx, &ft); - assert(lua_gettop(L) == top + 1); - - if (ft.type == INVALID_TYPE) { - if (check_pointers) { - goto err; - } else { - lua_pop(L, 1); - return (cfunction) lua_touserdata(L, idx); - } - - } else if (ft.is_null) { - lua_pop(L, 1); - return NULL; - - } else if (!check_pointers && (ft.pointers || ft.type == INTPTR_TYPE)) { - lua_pop(L, 1); - return (cfunction) *(void**) p; - - } else if (ft.type != FUNCTION_PTR_TYPE) { - goto err; - - } else if (!check_pointers) { - lua_pop(L, 1); - return *(cfunction*) p; - - } else if (ft.calling_convention != tt->calling_convention) { - goto err; - - } else if (!is_same_type(L, -1, to_usr, &ft, tt)) { - goto err; - - } else { - lua_pop(L, 1); - return *(cfunction*) p; - } - - default: - goto err; - } - -err: - type_error(L, idx, NULL, to_usr, tt); - return NULL; -} - -/* to_type_cfunction converts a value at idx with uv at to_usr and type tt to - * a cfunction. Leaves the stack unchanged. */ -cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt) -{ return check_cfunction(L, idx, to_usr, tt, 1); } - -static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers); - -static void set_array(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers) -{ - size_t i, sz, esz; - struct ctype et; - - idx = lua_absindex(L, idx); - to_usr = lua_absindex(L, to_usr); - - switch (lua_type(L, idx)) { - case LUA_TSTRING: - if (tt->pointers == 1 && tt->type == INT8_TYPE) { - const char* str = lua_tolstring(L, idx, &sz); - - if (!tt->is_variable_array && sz >= tt->array_size) { - memcpy(to, str, tt->array_size); - } else { - /* include nul terminator */ - memcpy(to, str, sz+1); - } - } else { - goto err; - } - break; - - case LUA_TTABLE: - et = *tt; - et.pointers--; - et.const_mask >>= 1; - et.is_array = 0; - esz = et.pointers ? sizeof(void*) : et.base_size; - - lua_rawgeti(L, idx, 2); - - if (tt->is_variable_array) { - /* we have no idea how big the array is, so set values based off - * how many items were given to us */ - lua_pop(L, 1); - for (i = 0; i < lua_rawlen(L, idx); i++) { - lua_rawgeti(L, idx, (int) i + 1); - set_value(L, -1, (char*) to + esz * i, to_usr, &et, check_pointers); - lua_pop(L, 1); - } - - } else if (lua_isnil(L, -1)) { - /* there is no second element, so we set the whole array to the - * first element (or nil - ie 0) if there is no first element) */ - lua_pop(L, 1); - lua_rawgeti(L, idx, 1); - - if (lua_isnil(L, -1)) { - memset(to, 0, ctype_size(L, tt)); - } else { - /* if its still variable we have no idea how many values to set */ - for (i = 0; i < tt->array_size; i++) { - set_value(L, -1, (char*) to + esz * i, to_usr, &et, check_pointers); - } - } - - lua_pop(L, 1); - - } else { - /* there is a second element, so we set each element using the - * equiv index in the table initializer */ - lua_pop(L, 1); - for (i = 0; i < tt->array_size; i++) { - lua_rawgeti(L, idx, (int) (i+1)); - - if (lua_isnil(L, -1)) { - /* we've hit the end of the values provided in the - * initializer, so memset the rest to zero */ - lua_pop(L, 1); - memset((char*) to + esz * i, 0, (tt->array_size - i) * esz); - break; - - } else { - set_value(L, -1, (char*) to + esz * i, to_usr, &et, check_pointers); - lua_pop(L, 1); - } - } - } - break; - - default: - goto err; - } - - return; - -err: - type_error(L, idx, NULL, to_usr, tt); -} - -/* pops the member key from the stack, leaves the member user value on the - * stack. Returns the member offset. Returns -ve if the member can not be - * found. */ -static ptrdiff_t get_member(lua_State* L, int usr, const struct ctype* ct, struct ctype* mt) -{ - ptrdiff_t off; - lua_rawget(L, usr); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - return -1; - } - - *mt = *(const struct ctype*) lua_touserdata(L, -1); - lua_getuservalue(L, -1); - lua_replace(L, -2); - - if (mt->is_variable_array && ct->variable_size_known) { - /* eg char mbr[?] */ - size_t sz = (mt->pointers > 1) ? sizeof(void*) : mt->base_size; - assert(ct->is_variable_struct && mt->is_array); - mt->array_size = ct->variable_increment / sz; - mt->is_variable_array = 0; - - } else if (mt->is_variable_struct && ct->variable_size_known) { - /* eg struct {char a; char b[?]} mbr; */ - assert(ct->is_variable_struct); - mt->variable_size_known = 1; - mt->variable_increment = ct->variable_increment; - } - - off = mt->offset; - mt->offset = 0; - return off; -} - -static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers) -{ - int have_first = 0; - int have_other = 0; - struct ctype mt; - void* p; - - to_usr = lua_absindex(L, to_usr); - idx = lua_absindex(L, idx); - - switch (lua_type(L, idx)) { - case LUA_TTABLE: - /* match up to the members based off the table initializers key - this - * will match both numbered and named members in the user table - * we need a special case for when no entries in the initializer - - * zero initialize the c struct, and only one entry in the initializer - * - set all members to this value */ - memset(to, 0, ctype_size(L, tt)); - lua_pushnil(L); - while (lua_next(L, idx)) { - ptrdiff_t off; - - if (!have_first && lua_tonumber(L, -2) == 1 && lua_tonumber(L, -1) != 0) { - have_first = 1; - } else if (!have_other && (lua_type(L, -2) != LUA_TNUMBER || lua_tonumber(L, -2) != 1)) { - have_other = 1; - } - - lua_pushvalue(L, -2); - off = get_member(L, to_usr, tt, &mt); - assert(off >= 0); - set_value(L, -2, (char*) to + off, -1, &mt, check_pointers); - - /* initializer value, mt usr */ - lua_pop(L, 2); - } - - /* if we only had a single non zero value then initialize all members to that value */ - if (!have_other && have_first && tt->type != UNION_TYPE) { - size_t i, sz; - ptrdiff_t off; - lua_rawgeti(L, idx, 1); - sz = lua_rawlen(L, to_usr); - - for (i = 2; i < sz; i++) { - lua_pushinteger(L, i); - off = get_member(L, to_usr, tt, &mt); - assert(off >= 0); - set_value(L, -2, (char*) to + off, -1, &mt, check_pointers); - lua_pop(L, 1); /* mt usr */ - } - - lua_pop(L, 1); /* initializer table */ - } - break; - - case LUA_TUSERDATA: - if (check_pointers) { - p = check_typed_pointer(L, idx, to_usr, tt); - } else { - struct ctype ct; - p = check_pointer(L, idx, &ct); - } - memcpy(to, p, tt->base_size); - lua_pop(L, 1); - break; - - default: - goto err; - } - - return; - -err: - type_error(L, idx, NULL, to_usr, tt); -} - -static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers) -{ - int top = lua_gettop(L); - - if (tt->is_array) { - set_array(L, idx, to, to_usr, tt, check_pointers); - - } else if (tt->pointers || tt->is_reference) { - union { - uint8_t c[sizeof(void*)]; - void* p; - } u; - - if (lua_istable(L, idx)) { - luaL_error(L, "Can't set a pointer member to a struct that's about to be freed"); - } - - if (check_pointers) { - u.p = check_typed_pointer(L, idx, to_usr, tt); - } else { - struct ctype ct; - u.p = check_pointer(L, idx, &ct); - } - -#ifndef ALLOW_MISALIGNED_ACCESS - if ((uintptr_t) to & PTR_ALIGN_MASK) { - memcpy(to, u.c, sizeof(void*)); - } else -#endif - { - *(void**) to = u.p; - } - - lua_pop(L, 1); - - } else if (tt->is_bitfield) { - - uint64_t hi_mask = UINT64_C(0) - (UINT64_C(1) << (tt->bit_offset + tt->bit_size)); - uint64_t low_mask = (UINT64_C(1) << tt->bit_offset) - UINT64_C(1); - uint64_t val = check_uint64(L, idx); - val &= (UINT64_C(1) << tt->bit_size) - 1; - val <<= tt->bit_offset; - *(uint64_t*) to = val | (*(uint64_t*) to & (hi_mask | low_mask)); - - } else if (tt->type == STRUCT_TYPE || tt->type == UNION_TYPE) { - set_struct(L, idx, to, to_usr, tt, check_pointers); - - } else { - -#ifndef ALLOW_MISALIGNED_ACCESS - union { - uint8_t c[8]; - _Bool b; - uint64_t u64; - float f; - double d; - cfunction func; - } misalign; - - void* origto = to; - - if ((uintptr_t) origto & (tt->base_size - 1)) { - to = misalign.c; - } -#endif - - switch (tt->type) { - case BOOL_TYPE: - *(_Bool*) to = (cast_int64(L, idx, !check_pointers) != 0); - break; - case INT8_TYPE: - if (tt->is_unsigned) { - *(uint8_t*) to = (uint8_t) cast_uint64(L, idx, !check_pointers); - } else { - *(int8_t*) to = (int8_t) cast_int64(L, idx, !check_pointers); - } - break; - case INT16_TYPE: - if (tt->is_unsigned) { - *(uint16_t*) to = (uint16_t) cast_uint64(L, idx, !check_pointers); - } else { - *(int16_t*) to = (int16_t) cast_int64(L, idx, !check_pointers); - } - break; - case INT32_TYPE: - if (tt->is_unsigned) { - *(uint32_t*) to = (uint32_t) cast_uint64(L, idx, !check_pointers); - } else { - *(int32_t*) to = (int32_t) cast_int64(L, idx, !check_pointers); - } - break; - case INT64_TYPE: - if (tt->is_unsigned) { - *(uint64_t*) to = cast_uint64(L, idx, !check_pointers); - } else { - *(int64_t*) to = cast_int64(L, idx, !check_pointers); - } - break; - case FLOAT_TYPE: - *(float*) to = (float) check_double(L, idx); - break; - case DOUBLE_TYPE: - *(double*) to = check_double(L, idx); - break; - case COMPLEX_FLOAT_TYPE: - *(complex_float*) to = check_complex_float(L, idx); - break; - case COMPLEX_DOUBLE_TYPE: - *(complex_double*) to = check_complex_double(L, idx); - break; - case INTPTR_TYPE: - *(uintptr_t*) to = check_uintptr(L, idx); - break; - case ENUM_TYPE: - *(int32_t*) to = check_enum(L, idx, to_usr, tt); - break; - case FUNCTION_PTR_TYPE: - *(cfunction*) to = check_cfunction(L, idx, to_usr, tt, check_pointers); - break; - default: - goto err; - } - -#ifndef ALLOW_MISALIGNED_ACCESS - if ((uintptr_t) origto & (tt->base_size - 1)) { - memcpy(origto, misalign.c, tt->base_size); - } -#endif - } - - assert(lua_gettop(L) == top); - return; -err: - type_error(L, idx, NULL, to_usr, tt); -} - -static int ffi_typeof(lua_State* L) -{ - struct ctype ct; - check_ctype(L, 1, &ct); - push_ctype(L, -1, &ct); - return 1; -} - -static void setmintop(lua_State* L, int idx) -{ - if (lua_gettop(L) < idx) { - lua_settop(L, idx); - } -} - -/* warning: in the case that it finds an array size, it removes that index */ -static void get_variable_array_size(lua_State* L, int idx, struct ctype* ct) -{ - /* we only care about the variable buisness for the variable array - * directly ie ffi.new('char[?]') or the struct that contains the variable - * array ffi.new('struct {char v[?]}'). A pointer to the struct doesn't - * care about the variable size (it treats it as a zero sized array). */ - - if (ct->is_variable_array) { - assert(ct->is_array); - ct->array_size = (size_t) luaL_checknumber(L, idx); - ct->is_variable_array = 0; - lua_remove(L, idx); - - } else if (ct->is_variable_struct && !ct->variable_size_known) { - assert(ct->type == STRUCT_TYPE && !ct->is_array); - ct->variable_increment *= (size_t) luaL_checknumber(L, idx); - ct->variable_size_known = 1; - lua_remove(L, idx); - } -} - -static int is_scalar(struct ctype* ct) -{ - int type = ct->type; - if (ct->pointers || ct->is_reference) { - return !ct->is_array; - } - return type != STRUCT_TYPE && type != UNION_TYPE && !IS_COMPLEX(type); -} - -static int should_pack(lua_State *L, int ct_usr, struct ctype* ct, int idx) -{ - struct ctype argt; - ct_usr = lua_absindex(L, ct_usr); - - if (IS_COMPLEX(ct->type)) { - return 0; - } - - switch (lua_type(L, idx)) { - case LUA_TTABLE: - return 0; - case LUA_TSTRING: - return ct->type == STRUCT_TYPE; - case LUA_TUSERDATA: - // don't pack if the argument is a cdata with the same type - to_cdata(L, idx, &argt); - int same = is_same_type(L, ct_usr, -1, ct, &argt); - lua_pop(L, 1); - return !same; - default: - return 1; - } -} - -static int do_new(lua_State* L, int is_cast) -{ - int cargs, i; - void* p; - struct ctype ct; - int check_ptrs = !is_cast; - - check_ctype(L, 1, &ct); - - /* don't push a callback when we have a c function, as cb:set needs a - * compiled callback from a lua function to work */ - if (!ct.pointers && ct.type == FUNCTION_PTR_TYPE && (lua_isnil(L, 2) || lua_isfunction(L, 2))) { - // Get the bound C function if this is a ffi lua function - cfunction func; - if (get_cfunction_address(L, 2, &func)) { - p = push_cdata(L, -1, &ct); - *(cfunction*) p = func; - return 1; - } - - /* Function cdatas are pinned and must be manually cleaned up by - * calling func:free(). */ - compile_callback(L, 2, -1, &ct); - push_upval(L, &callbacks_key); - lua_pushvalue(L, -2); - lua_pushboolean(L, 1); - lua_rawset(L, -3); - lua_pop(L, 1); /* callbacks tbl */ - return 1; - } - - /* this removes the vararg argument if its needed, and errors if its invalid */ - if (!is_cast) { - get_variable_array_size(L, 2, &ct); - } - - p = push_cdata(L, -1, &ct); - - /* if the user mt has a __gc function then call ffi.gc on this value */ - if (push_user_mt(L, -2, &ct)) { - push_upval(L, &gc_key); - lua_pushvalue(L, -3); - - /* user_mt.__gc */ - lua_pushliteral(L, "__gc"); - lua_rawget(L, -4); - - lua_rawset(L, -3); /* gc_upval[cdata] = user_mt.__gc */ - lua_pop(L, 2); /* user_mt and gc_upval */ - } - - /* stack is: - * ctype arg - * ctor args ... 0+ - * ctype usr - * cdata - */ - - cargs = lua_gettop(L) - 3; - - if (cargs == 0) { - return 1; - } - - int scalar = is_scalar(&ct); - if (scalar && cargs > 1) { - return luaL_error(L, "too many initializers"); - } - - if (cargs > 1 || (!scalar && should_pack(L, -2, &ct, 2))) { - lua_createtable(L, cargs, 0); - lua_replace(L, 1); - for (i = 1; i <= cargs; i++) { - lua_pushvalue(L, i + 1); - lua_rawseti(L, 1, i); - } - assert(lua_gettop(L) == cargs + 3); - set_value(L, 1, p, -2, &ct, check_ptrs); - return 1; - } - - set_value(L, 2, p, -2, &ct, check_ptrs); - return 1; -} - -static int ffi_new(lua_State* L) -{ return do_new(L, 0); } - -static int ffi_cast(lua_State* L) -{ return do_new(L, 1); } - -static int ctype_new(lua_State* L) -{ return do_new(L, 0); } - -static int ctype_call(lua_State* L) -{ - struct ctype ct; - int top = lua_gettop(L); - - check_ctype(L, 1, &ct); - - if (push_user_mt(L, -1, &ct)) { - lua_pushstring(L, "__new"); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - lua_insert(L, 1); // function at bottom of stack under args - lua_pop(L, 2); - lua_call(L, top, 1); - return 1; - } - lua_pop(L, 2); - } - lua_pop(L, 1); - - assert(lua_gettop(L) == top); - return do_new(L, 0); -} - -static int ffi_sizeof(lua_State* L) -{ - struct ctype ct; - check_ctype(L, 1, &ct); - get_variable_array_size(L, 2, &ct); - lua_pushinteger(L, ctype_size(L, &ct)); - return 1; -} - -static int ffi_alignof(lua_State* L) -{ - struct ctype ct, mt; - lua_settop(L, 2); - check_ctype(L, 1, &ct); - - /* if no member is specified then we return the alignment of the type */ - if (lua_isnil(L, 2)) { - lua_pushinteger(L, ct.align_mask + 1); - return 1; - } - - /* get the alignment of the member */ - lua_pushvalue(L, 2); - if (get_member(L, -2, &ct, &mt) < 0) { - push_type_name(L, 3, &ct); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); - } - - lua_pushinteger(L, mt.align_mask + 1); - return 1; -} - -static int ffi_offsetof(lua_State* L) -{ - ptrdiff_t off; - struct ctype ct, mt; - lua_settop(L, 2); - check_ctype(L, 1, &ct); - - lua_pushvalue(L, 2); - off = get_member(L, -2, &ct, &mt); /* this replaces the member key at -1 with the mbr usr value */ - if (off < 0) { - push_type_name(L, 3, &ct); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); - } - - lua_pushinteger(L, off); - - if (!mt.is_bitfield) { - return 1; - } - - lua_pushinteger(L, mt.bit_offset); - lua_pushinteger(L, mt.bit_size); - return 3; -} - -static int ffi_istype(lua_State* L) -{ - struct ctype tt, ft; - check_ctype(L, 1, &tt); - to_cdata(L, 2, &ft); - - if (ft.type == INVALID_TYPE) { - goto fail; - } - - if (!is_same_type(L, 3, 4, &tt, &ft)) { - goto fail; - } - - if (tt.pointers != ft.pointers) { - goto fail; - } - - if (tt.is_array != ft.is_array) { - goto fail; - } - - if (tt.is_array && tt.array_size != ft.array_size) { - goto fail; - } - - if (tt.calling_convention != ft.calling_convention) { - goto fail; - } - - lua_pushboolean(L, 1); - return 1; - -fail: - lua_pushboolean(L, 0); - return 1; -} - -static int cdata_gc(lua_State* L) -{ - struct ctype ct; - check_cdata(L, 1, &ct); - lua_settop(L, 1); - - /* call the gc func if there is any registered */ - lua_pushvalue(L, 1); - lua_rawget(L, lua_upvalueindex(2)); - if (!lua_isnil(L, -1)) { - lua_pushvalue(L, 1); - lua_pcall(L, 1, 0, 0); - } - - /* unset the closure */ - lua_pushvalue(L, 1); - lua_pushnil(L); - lua_rawset(L, lua_upvalueindex(1)); - - return 0; -} - -static int callback_free(lua_State* L) -{ - cfunction* p = (cfunction*) lua_touserdata(L, 1); - // FIXME: temporarily disabled to prevent SIGTRAP on exit - // free_code(get_jit(L), L, *p); - return 0; -} - -static int cdata_free(lua_State* L) -{ - struct ctype ct; - cfunction* p = (cfunction*) check_cdata(L, 1, &ct); - lua_settop(L, 1); - - /* unset the closure */ - lua_pushvalue(L, 1); - lua_pushnil(L); - lua_rawset(L, lua_upvalueindex(1)); - - if (ct.is_jitted) { - free_code(get_jit(L), L, *p); - *p = NULL; - } - - return 0; -} - -static int cdata_set(lua_State* L) -{ - struct ctype ct; - cfunction* p = (cfunction*) check_cdata(L, 1, &ct); - luaL_checktype(L, 2, LUA_TFUNCTION); - - if (!ct.is_jitted) { - luaL_error(L, "can't set the function for a non-lua callback"); - } - - if (*p == NULL) { - luaL_error(L, "can't set the function for a free'd callback"); - } - - push_func_ref(L, *p); - lua_pushvalue(L, 2); - lua_rawseti(L, -2, CALLBACK_FUNC_USR_IDX); - - /* remove the closure for this callback as it embeds the function pointer - * value */ - lua_pushvalue(L, 1); - lua_pushboolean(L, 1); - lua_rawset(L, lua_upvalueindex(1)); - - return 0; -} - -static int cdata_call(lua_State* L) -{ - struct ctype ct; - int top = lua_gettop(L); - cfunction* p = (cfunction*) check_cdata(L, 1, &ct); - - if (push_user_mt(L, -1, &ct)) { - lua_pushliteral(L, "__call"); - lua_rawget(L, -2); - - if (!lua_isnil(L, -1)) { - lua_insert(L, 1); - lua_pop(L, 2); /* ct_usr, user_mt */ - lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); - return lua_gettop(L); - } - } - if (ct.pointers || ct.type != FUNCTION_PTR_TYPE) { - return luaL_error(L, "only function callbacks are callable"); - } - - lua_pushvalue(L, 1); - lua_rawget(L, lua_upvalueindex(1)); - - if (!lua_isfunction(L, -1)) { - lua_pop(L, 1); - compile_function(L, *p, -1, &ct); - - assert(lua_gettop(L) == top + 2); /* uv, closure */ - - /* closures[func] = closure */ - lua_pushvalue(L, 1); - lua_pushvalue(L, -2); - lua_rawset(L, lua_upvalueindex(1)); - - lua_replace(L, 1); - } else { - lua_replace(L, 1); - } - - lua_pop(L, 1); /* uv */ - assert(lua_gettop(L) == top); - - lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); - return lua_gettop(L); -} - -static int user_mt_key; - -static int ffi_metatype(lua_State* L) -{ - struct ctype ct; - lua_settop(L, 2); - - check_ctype(L, 1, &ct); - if (lua_type(L, 2) != LUA_TTABLE && lua_type(L, 2) != LUA_TNIL) { - return luaL_argerror(L, 2, "metatable must be a table or nil"); - } - - lua_pushlightuserdata(L, &user_mt_key); - lua_pushvalue(L, 2); - lua_rawset(L, 3); /* user[user_mt_key] = mt */ - - /* return the passed in ctype */ - push_ctype(L, 3, &ct); - return 1; -} - -/* push_user_mt returns 1 if the type has a user metatable and pushes it onto - * the stack, otherwise it returns 0 and pushes nothing */ -int push_user_mt(lua_State* L, int ct_usr, const struct ctype* ct) -{ - if (ct->type != STRUCT_TYPE && ct->type != UNION_TYPE && !IS_COMPLEX(ct->type)) { - return 0; - } - if (!lua_istable(L, ct_usr)) { - return 0; - } - - ct_usr = lua_absindex(L, ct_usr); - lua_pushlightuserdata(L, &user_mt_key); - lua_rawget(L, ct_usr); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - return 0; - } - return 1; -} - -static int ffi_gc(lua_State* L) -{ - struct ctype ct; - lua_settop(L, 2); - check_cdata(L, 1, &ct); - - push_upval(L, &gc_key); - lua_pushvalue(L, 1); - lua_pushvalue(L, 2); - lua_rawset(L, -3); - - /* return the cdata back */ - lua_settop(L, 1); - return 1; -} - -/* lookup_cdata_index returns the offset of the found type and user value on - * the stack if valid. Otherwise returns -ve and doesn't touch the stack. - */ -static ptrdiff_t lookup_cdata_index(lua_State* L, int idx, int ct_usr, struct ctype* ct) -{ - struct ctype mt; - ptrdiff_t off; - - ct_usr = lua_absindex(L, ct_usr); - int type = lua_type(L, idx); - - switch (type) { - case LUA_TNUMBER: - case LUA_TUSERDATA: - /* possibilities are array, pointer */ - - if (!ct->pointers || is_void_ptr(ct)) { - return -1; - } - - // unbox cdata - if (type == LUA_TUSERDATA) { - if (!cdata_tointeger(L, idx, &off)) { - return -1; - } - } else { - off = lua_tointeger(L, idx); - } - - ct->is_array = 0; - ct->pointers--; - ct->const_mask >>= 1; - ct->is_reference = 0; - - lua_pushvalue(L, ct_usr); - - return (ct->pointers ? sizeof(void*) : ct->base_size) * off; - - case LUA_TSTRING: - /* possibilities are struct/union, pointer to struct/union */ - - if ((ct->type != STRUCT_TYPE && ct->type != UNION_TYPE) || ct->is_array || ct->pointers > 1) { - return -1; - } - - lua_pushvalue(L, idx); - off = get_member(L, ct_usr, ct, &mt); - if (off < 0) { - return -1; - } - - *ct = mt; - return off; - - default: - return -1; - } -} - -static int cdata_newindex(lua_State* L) -{ - struct ctype tt; - char* to; - ptrdiff_t off; - - lua_settop(L, 3); - - to = (char*) check_cdata(L, 1, &tt); - off = lookup_cdata_index(L, 2, -1, &tt); - - if (off < 0) { - if (!push_user_mt(L, -1, &tt)) { - goto err; - } - - lua_pushliteral(L, "__newindex"); - lua_rawget(L, -2); - - if (lua_isnil(L, -1)) { - goto err; - } - - lua_insert(L, 1); - lua_settop(L, 4); - lua_call(L, 3, LUA_MULTRET); - return lua_gettop(L); - } - - if (tt.const_mask & 1) { - return luaL_error(L, "can't set const data"); - } - - set_value(L, 3, to + off, -1, &tt, 1); - return 0; - -err: - push_type_name(L, 4, &tt); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); -} - -static int cdata_index(lua_State* L) -{ - void* to; - struct ctype ct; - char* data; - ptrdiff_t off; - - lua_settop(L, 2); - data = (char*) check_cdata(L, 1, &ct); - assert(lua_gettop(L) == 3); - - if (!ct.pointers) { - switch (ct.type) { - case FUNCTION_PTR_TYPE: - /* Callbacks use the same metatable as standard cdata values, but have set - * and free members. So instead of mt.__index = mt, we do the equiv here. */ - lua_getmetatable(L, 1); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - return 1; - - /* This provides the .re and .im virtual members */ - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - if (!lua_isstring(L, 2)) { - luaL_error(L, "invalid member for complex number"); - - } else if (strcmp(lua_tostring(L, 2), "re") == 0) { - lua_pushnumber(L, ct.type == COMPLEX_DOUBLE_TYPE ? creal(*(complex_double*) data) : crealf(*(complex_float*) data)); - - } else if (strcmp(lua_tostring(L, 2), "im") == 0) { - lua_pushnumber(L, ct.type == COMPLEX_DOUBLE_TYPE ? cimag(*(complex_double*) data) : cimagf(*(complex_float*) data)); - - } else { - luaL_error(L, "invalid member for complex number"); - } - return 1; - } - } - - off = lookup_cdata_index(L, 2, -1, &ct); - - if (off < 0) { - assert(lua_gettop(L) == 3); - if (!push_user_mt(L, -1, &ct)) { - goto err; - } - - lua_pushliteral(L, "__index"); - lua_rawget(L, -2); - - if (lua_isnil(L, -1)) { - goto err; - } - - if (lua_istable(L, -1)) { - lua_pushvalue(L, 2); - lua_gettable(L, -2); - return 1; - } - - lua_insert(L, 1); - lua_settop(L, 3); - lua_call(L, 2, LUA_MULTRET); - return lua_gettop(L); - -err: - push_type_name(L, 3, &ct); - return luaL_error(L, "type %s has no member %s", lua_tostring(L, -1), lua_tostring(L, 2)); - } - - assert(lua_gettop(L) == 4); /* ct, key, ct_usr, mbr_usr */ - data += off; - - if (ct.is_array) { - /* push a reference to the array */ - ct.is_reference = 1; - to = push_cdata(L, -1, &ct); - *(void**) to = data; - return 1; - - } else if (ct.is_bitfield) { - - if (ct.type == INT64_TYPE) { - struct ctype rt; - uint64_t val = *(uint64_t*) data; - val >>= ct.bit_offset; - val &= (UINT64_C(1) << ct.bit_size) - 1; - - memset(&rt, 0, sizeof(rt)); - rt.base_size = 8; - rt.type = INT64_TYPE; - rt.is_unsigned = 1; - rt.is_defined = 1; - - to = push_cdata(L, 0, &rt); - *(uint64_t*) to = val; - - return 1; - - } else if (ct.type == BOOL_TYPE) { - uint64_t val = *(uint64_t*) data; - lua_pushboolean(L, (int) (val & (UINT64_C(1) << ct.bit_offset))); - return 1; - - } else { - uint64_t val = *(uint64_t*) data; - val >>= ct.bit_offset; - val &= (UINT64_C(1) << ct.bit_size) - 1; - lua_pushinteger(L, val); - return 1; - } - - } else if (ct.pointers) { -#ifndef ALLOW_MISALIGNED_ACCESS - union { - uint8_t c[8]; - void* p; - } misalignbuf; - - if ((uintptr_t) data & PTR_ALIGN_MASK) { - memcpy(misalignbuf.c, data, sizeof(void*)); - data = misalignbuf.c; - } -#endif - to = push_cdata(L, -1, &ct); - *(void**) to = *(void**) data; - return 1; - - } else if (ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) { - /* push a reference to the member */ - ct.is_reference = 1; - to = push_cdata(L, -1, &ct); - *(void**) to = data; - return 1; - - } else if (ct.type == FUNCTION_PTR_TYPE) { - cfunction* pf = (cfunction*) push_cdata(L, -1, &ct); - *pf = *(cfunction*) data; - return 1; - - } else { -#ifndef ALLOW_MISALIGNED_ACCESS - union { - uint8_t c[8]; - double d; - float f; - uint64_t u64; - } misalignbuf; - - assert(ct.base_size <= 8); - - if ((uintptr_t) data & (ct.base_size - 1)) { - memcpy(misalignbuf.c, data, ct.base_size); - data = misalignbuf.c; - } -#endif - - switch (ct.type) { - case BOOL_TYPE: - lua_pushboolean(L, *(_Bool*) data); - break; - case INT8_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint8_t*) data : (lua_Integer) *(int8_t*) data); - break; - case INT16_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint16_t*) data : (lua_Integer) *(int16_t*) data); - break; - case ENUM_TYPE: - case INT32_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint32_t*) data : (lua_Integer) *(int32_t*) data); - break; - case INT64_TYPE: - to = push_cdata(L, -1, &ct); - *(int64_t*) to = *(int64_t*) data; - break; - case INTPTR_TYPE: - to = push_cdata(L, -1, &ct); - *(intptr_t*) to = *(intptr_t*) data; - break; - case FLOAT_TYPE: - lua_pushnumber(L, *(float*) data); - break; - case DOUBLE_TYPE: - lua_pushnumber(L, *(double*) data); - break; - case COMPLEX_DOUBLE_TYPE: - to = push_cdata(L, -1, &ct); - *(complex_double*) to = *(complex_double*) data; - break; - case COMPLEX_FLOAT_TYPE: - to = push_cdata(L, -1, &ct); - *(complex_float*) to = *(complex_float*) data; - break; - default: - luaL_error(L, "internal error: invalid member type"); - } - - return 1; - } -} - -static complex_double check_complex(lua_State* L, int idx, void* p, struct ctype* ct) -{ - if (ct->type == INVALID_TYPE) { - double d = luaL_checknumber(L, idx); -#ifdef HAVE_COMPLEX - return d; -#else - complex_double c; - c.real = d; - c.imag = 0; - return c; -#endif - } else if (ct->type == COMPLEX_DOUBLE_TYPE) { - return *(complex_double*) p; - } else if (ct->type == COMPLEX_FLOAT_TYPE) { - complex_float* f = (complex_float*) p; -#ifdef HAVE_COMPLEX - return *f; -#else - complex_double d; - d.real = f->real; - d.imag = f->imag; - return d; -#endif - } else { - complex_double dummy; - type_error(L, idx, "complex", 0, NULL); - memset(&dummy, 0, sizeof(dummy)); - return dummy; - } -} - -static int rank(const struct ctype* ct) -{ - if (ct->pointers) { - return 5; - } - - switch (ct->type) { - case COMPLEX_DOUBLE_TYPE: - return 7; - case COMPLEX_FLOAT_TYPE: - return 6; - case INTPTR_TYPE: - return sizeof(intptr_t) >= sizeof(int64_t) ? 4 : 1; - case INT64_TYPE: - return ct->is_unsigned ? 3 : 2; - case INT32_TYPE: - case INT16_TYPE: - case INT8_TYPE: - return 2; - default: - return 0; - } -} - -static void push_complex(lua_State* L, complex_double res, int ct_usr, const struct ctype* ct) -{ - if (ct->type == COMPLEX_DOUBLE_TYPE) { - complex_double* p = (complex_double*) push_cdata(L, ct_usr, ct); - *p = res; - } else { - complex_float* p = (complex_float*) push_cdata(L, ct_usr, ct); -#ifdef HAVE_COMPLEX - *p = (complex float) res; -#else - p->real = (float) res.real; - p->imag = (float) res.imag; -#endif - } -} - -static void push_number(lua_State* L, int64_t val, int ct_usr, const struct ctype* ct) -{ - if ((ct->pointers || ct->type == INTPTR_TYPE) && sizeof(intptr_t) != sizeof(int64_t)) { - intptr_t* p = (intptr_t*) push_cdata(L, ct_usr, ct); - *p = val; - } else { - int64_t* p = (int64_t*) push_cdata(L, ct_usr, ct); - *p = val; - } -} - -static int call_user_op(lua_State* L, const char* opfield, int idx, int ct_usr, const struct ctype* ct) -{ - idx = lua_absindex(L, idx); - - if (push_user_mt(L, ct_usr, ct)) { - lua_pushstring(L, opfield); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - int top = lua_gettop(L); - lua_pushvalue(L, idx); - lua_call(L, 1, LUA_MULTRET); - return lua_gettop(L) - top + 1; - } - lua_pop(L, 2); - } - return -1; -} - -static int cdata_unm(lua_State* L) -{ - struct ctype ct; - void* p; - int64_t val; - int ret; - - lua_settop(L, 1); - p = to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__unm", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - val = check_intptr(L, 1, p, &ct); - - if (ct.pointers) { - luaL_error(L, "can't negate a pointer value"); - } else { - memset(&ct, 0, sizeof(ct)); - ct.type = INT64_TYPE; - ct.base_size = 8; - ct.is_defined = 1; - push_number(L, -val, 0, &ct); - } - - return 1; -} - -/* returns -ve if no binop was called otherwise returns the number of return - * arguments */ -static int call_user_binop(lua_State* L, const char* opfield, int lidx, int lusr, const struct ctype* lt, int ridx, int rusr, const struct ctype* rt) -{ - lidx = lua_absindex(L, lidx); - ridx = lua_absindex(L, ridx); - - if (push_user_mt(L, lusr, lt)) { - lua_pushstring(L, opfield); - lua_rawget(L, -2); - - if (!lua_isnil(L, -1)) { - int top = lua_gettop(L); - lua_pushvalue(L, lidx); - lua_pushvalue(L, ridx); - lua_call(L, 2, LUA_MULTRET); - return lua_gettop(L) - top + 1; - } - - lua_pop(L, 2); /* user_mt and user_mt.op */ - } - - if (push_user_mt(L, rusr, rt)) { - lua_pushstring(L, opfield); - lua_rawget(L, -2); - - if (!lua_isnil(L, -1)) { - int top = lua_gettop(L); - lua_pushvalue(L, lidx); - lua_pushvalue(L, ridx); - lua_call(L, 2, LUA_MULTRET); - return lua_gettop(L) - top + 1; - } - - lua_pop(L, 2); /* user_mt and user_mt.op */ - } - - return -1; -} - -static int cdata_concat(lua_State* L) -{ - struct ctype lt, rt; - int ret; - - lua_settop(L, 2); - to_cdata(L, 1, <); - to_cdata(L, 2, &rt); - - ret = call_user_binop(L, "__concat", 1, 3, <, 2, 4, &rt); - if (ret >= 0) { - return ret; - } - - return luaL_error(L, "NYI"); -} - -static int cdata_len(lua_State* L) -{ - struct ctype ct; - int ret; - - lua_settop(L, 1); - to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__len", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - push_type_name(L, 2, &ct); - return luaL_error(L, "type %s does not implement the __len metamethod", lua_tostring(L, -1)); -} - -static int cdata_pairs(lua_State* L) -{ - struct ctype ct; - int ret; - - lua_settop(L, 1); - to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__pairs", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - push_type_name(L, 2, &ct); - return luaL_error(L, "type %s does not implement the __pairs metamethod", lua_tostring(L, -1)); -} - -static int cdata_ipairs(lua_State* L) -{ - struct ctype ct; - int ret; - - lua_settop(L, 1); - to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__ipairs", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - push_type_name(L, 2, &ct); - return luaL_error(L, "type %s does not implement the __ipairs metamethod", lua_tostring(L, -1)); -} - -static int cdata_add(lua_State* L) -{ - struct ctype lt, rt, ct; - void *lp, *rp; - int ct_usr; - int ret; - - lua_settop(L, 2); - - lp = to_cdata(L, 1, <); - rp = to_cdata(L, 2, &rt); - assert(lua_gettop(L) == 4); - - ret = call_user_binop(L, "__add", 1, 3, <, 2, 4, &rt); - if (ret >= 0) { - return ret; - } - assert(lua_gettop(L) == 4); - - ct_usr = rank(<) > rank(&rt) ? 3 : 4; - ct = rank(<) > rank(&rt) ? lt : rt; - - if (IS_COMPLEX(ct.type)) { - complex_double left, right, res; - - left = check_complex(L, 1, lp, <); - right = check_complex(L, 2, rp, &rt); - assert(lua_gettop(L) == 4); - -#ifdef HAVE_COMPLEX - res = left + right; -#else - res.real = left.real + right.real; - res.imag = left.imag + right.imag; -#endif - - push_complex(L, res, ct_usr, &ct); - return 1; - - } else { - int64_t left = check_intptr(L, 1, lp, <); - int64_t right = check_intptr(L, 2, rp, &rt); - assert(lua_gettop(L) == 4); - - /* note due to 2s complement it doesn't matter if we do the addition as int or uint, - * but the result needs to be uint64_t if either of the sources are */ - - if (lt.pointers && rt.pointers) { - luaL_error(L, "can't add two pointers"); - - } else if (lt.pointers) { - int64_t res = left + (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right; - lt.is_array = 0; - push_number(L, res, 3, <); - - } else if (rt.pointers) { - int64_t res = right + (rt.pointers > 1 ? sizeof(void*) : rt.base_size) * left; - rt.is_array = 0; - push_number(L, res, 4, &rt); - - } else { - push_number(L, left + right, ct_usr, &ct); - } - - return 1; - } -} - -static int cdata_sub(lua_State* L) -{ - struct ctype lt, rt, ct; - void *lp, *rp; - int ct_usr; - int ret; - - lua_settop(L, 2); - - lp = to_cdata(L, 1, <); - rp = to_cdata(L, 2, &rt); - - ret = call_user_binop(L, "__sub", 1, 3, <, 2, 4, &rt); - if (ret >= 0) { - return ret; - } - - ct_usr = rank(<) > rank(&rt) ? 3 : 4; - ct = rank(<) > rank(&rt) ? lt : rt; - - if (IS_COMPLEX(ct.type)) { - complex_double left, right, res; - - left = check_complex(L, 1, lp, <); - right = check_complex(L, 2, rp, &rt); - -#ifdef HAVE_COMPLEX - res = left - right; -#else - res.real = left.real - right.real; - res.imag = left.imag - right.imag; -#endif - - push_complex(L, res, ct_usr, &ct); - return 1; - - } else { - int64_t left = check_intptr(L, 1, lp, <); - int64_t right = check_intptr(L, 2, rp, &rt); - - if (rt.pointers) { - luaL_error(L, "NYI: can't subtract a pointer value"); - - } else if (lt.pointers) { - int64_t res = left - (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right; - lt.is_array = 0; - push_number(L, res, 3, <); - - } else { - int64_t res = left - right; - push_number(L, res, ct_usr, &ct); - } - - return 1; - } -} - -/* TODO fix for unsigned */ -#define NUMBER_ONLY_BINOP(OPSTR, DO_NORMAL, DO_COMPLEX) \ - struct ctype lt, rt, ct; \ - void *lp, *rp; \ - int ct_usr; \ - int ret; \ - \ - lua_settop(L, 2); \ - \ - lp = to_cdata(L, 1, <); \ - rp = to_cdata(L, 2, &rt); \ - \ - ret = call_user_binop(L, OPSTR, 1, 3, <, 2, 4, &rt); \ - if (ret >= 0) { \ - return ret; \ - } \ - \ - ct_usr = rank(<) > rank(&rt) ? 3 : 4; \ - ct = rank(<) > rank(&rt) ? lt : rt; \ - \ - if (IS_COMPLEX(ct.type)) { \ - complex_double res; \ - complex_double left = check_complex(L, 1, lp, <); \ - complex_double right = check_complex(L, 2, rp, &rt); \ - \ - DO_COMPLEX(left, right, res); \ - push_complex(L, res, ct_usr, &ct); \ - \ - } else if (lt.pointers || rt.pointers) { \ - luaL_error(L, "can't operate on a pointer value"); \ - \ - } else { \ - int64_t res; \ - int64_t left = check_intptr(L, 1, lp, <); \ - int64_t right = check_intptr(L, 2, rp, &rt); \ - \ - DO_NORMAL(left, right, res); \ - push_number(L, res, ct_usr, &ct); \ - } \ - \ - return 1 - -#define MUL(l,r,s) s = l * r -#define DIV(l,r,s) s = l / r -#define MOD(l,r,s) s = l % r -#define POW(l,r,s) s = pow(l, r) - -#ifdef HAVE_COMPLEX -#define MULC(l,r,s) s = l * r -#define DIVC(l,r,s) s = l / r -#define MODC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex mod") -#define POWC(l,r,s) s = cpow(l, r) -#else -#define MULC(l,r,s) s.real = l.real * r.real - l.imag * r.imag, s.imag = l.real * r.imag + l.imag * r.real -#define DIVC(l,r,s) s.real = (l.real * r.real + l.imag * r.imag) / (r.real * r.real + r.imag * r.imag), \ - s.imag = (l.imag * r.real - l.real * r.imag) / (r.real * r.real + r.imag * r.imag) -#define MODC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex mod") -#define POWC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex pow") -#endif - -static int cdata_mul(lua_State* L) -{ NUMBER_ONLY_BINOP("__mul", MUL, MULC); } - -static int cdata_div(lua_State* L) -{ NUMBER_ONLY_BINOP("__div", DIV, DIVC); } - -static int cdata_mod(lua_State* L) -{ NUMBER_ONLY_BINOP("__mod", MOD, MODC); } - -static int cdata_pow(lua_State* L) -{ NUMBER_ONLY_BINOP("__pow", POW, POWC); } - -#define COMPARE_BINOP(OPSTR, OP, OPC) \ - struct ctype lt, rt; \ - void *lp, *rp; \ - int ret, res; \ - \ - lua_settop(L, 2); \ - \ - lp = to_cdata(L, 1, <); \ - rp = to_cdata(L, 2, &rt); \ - \ - ret = call_user_binop(L, OPSTR, 1, 3, <, 2, 4, &rt); \ - if (ret >= 0) { \ - return ret; \ - } \ - \ - if (IS_COMPLEX(lt.type) || IS_COMPLEX(rt.type)) { \ - complex_double left = check_complex(L, 1, lp, <); \ - complex_double right = check_complex(L, 2, rp, &rt); \ - \ - res = OPC(left, right); \ - \ - lua_pushboolean(L, res); \ - \ - } else { \ - int64_t left = check_intptr(L, 1, lp, <); \ - int64_t right = check_intptr(L, 2, rp, &rt); \ - \ - if (lt.pointers && rt.pointers) { \ - if (is_void_ptr(<) || is_void_ptr(&rt) || is_same_type(L, 3, 4, <, &rt)) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - } else { \ - goto err; \ - } \ - \ - } else if (lt.is_null && rt.type == FUNCTION_PTR_TYPE) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (rt.is_null && lt.type == FUNCTION_PTR_TYPE) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (lt.pointers && rt.type == INTPTR_TYPE && rt.is_unsigned) {\ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (rt.pointers && lt.type == INTPTR_TYPE && lt.is_unsigned) {\ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (rt.pointers || lt.pointers) { \ - goto err; \ - \ - } else if (lt.is_unsigned && rt.is_unsigned) { \ - res = OP((uint64_t) left, (uint64_t) right); \ - \ - } else if (lt.is_unsigned) { \ - res = OP((int64_t) (uint64_t) left, right); \ - \ - } else if (rt.is_unsigned) { \ - res = OP(left, (int64_t) (uint64_t) right); \ - \ - } else { \ - res = OP(left, right); \ - } \ - \ - lua_pushboolean(L, res); \ - } \ - return 1 - -#define EQ(l, r) (l) == (r) -#define LT(l, r) (l) < (r) -#define LE(l, r) (l) <= (r) - -#ifdef HAVE_COMPLEX -#define EQC(l, r) (l) == (r) -#else -#define EQC(l, r) (l).real == (r).real && (l).imag == (r).imag -#endif - -#define LEC(l, r) EQC(l, r), luaL_error(L, "complex numbers are non-orderable") -#define LTC(l, r) EQC(l, r), luaL_error(L, "complex numbers are non-orderable") - -static int cdata_eq(lua_State* L) -{ - COMPARE_BINOP("__eq", EQ, EQC); -err: - lua_pushboolean(L, 0); - return 1; -} - -static int cdata_lt(lua_State* L) -{ - COMPARE_BINOP("__lt", LT, LTC); -err: - lua_getuservalue(L, 1); - lua_getuservalue(L, 2); - push_type_name(L, -2, <); - push_type_name(L, -2, <); - return luaL_error(L, "trying to compare incompatible types %s and %s", lua_tostring(L, -2), lua_tostring(L, -1)); -} - -static int cdata_le(lua_State* L) -{ - COMPARE_BINOP("__le", LE, LEC); -err: - lua_getuservalue(L, 1); - lua_getuservalue(L, 2); - push_type_name(L, -2, <); - push_type_name(L, -2, <); - return luaL_error(L, "trying to compare incompatible types %s and %s", lua_tostring(L, -2), lua_tostring(L, -1)); -} - -static const char* etype_tostring(int type) -{ - switch (type) { - case VOID_TYPE: return "void"; - case DOUBLE_TYPE: return "double"; - case FLOAT_TYPE: return "float"; - case COMPLEX_DOUBLE_TYPE: return "complex double"; - case COMPLEX_FLOAT_TYPE: return "complex float"; - case BOOL_TYPE: return "bool"; - case INT8_TYPE: return "int8"; - case INT16_TYPE: return "int16"; - case INT32_TYPE: return "int32"; - case INT64_TYPE: return "int64"; - case INTPTR_TYPE: return "intptr"; - case ENUM_TYPE: return "enum"; - case UNION_TYPE: return "union"; - case STRUCT_TYPE: return "struct"; - case FUNCTION_PTR_TYPE: return "function ptr"; - case FUNCTION_TYPE: return "function"; - default: return "invalid"; - } -} - -static void print_type(lua_State* L, const struct ctype* ct) -{ - lua_pushfstring(L, " sz %d %d %d align %d ptr %d %d %d type %s%s %d %d %d name %d call %d %d var %d %d %d bit %d %d %d %d jit %d", - /* sz */ - ct->base_size, - ct->array_size, - ct->offset, - /* align */ - ct->align_mask, - /* ptr */ - ct->is_array, - ct->pointers, - ct->const_mask, - /* type */ - ct->is_unsigned ? "u" : "", - etype_tostring(ct->type), - ct->is_reference, - ct->is_defined, - ct->is_null, - /* name */ - ct->has_member_name, - /* call */ - ct->calling_convention, - ct->has_var_arg, - /* var */ - ct->is_variable_array, - ct->is_variable_struct, - ct->variable_size_known, - /* bit */ - ct->is_bitfield, - ct->has_bitfield, - ct->bit_offset, - ct->bit_size, - /* jit */ - ct->is_jitted); -} - -static int ctype_tostring(lua_State* L) -{ - struct ctype ct; - assert(lua_type(L, 1) == LUA_TUSERDATA); - lua_settop(L, 1); - check_ctype(L, 1, &ct); - assert(lua_gettop(L) == 2); - push_type_name(L, -1, &ct); - lua_pushfstring(L, "ctype<%s>", lua_tostring(L, -1)); - - if (DEBUG_TOSTRING) { - print_type(L, &ct); - lua_concat(L, 2); - } - - return 1; -} - -static int cdata_tostring(lua_State* L) -{ - struct ctype ct; - char buf[64]; - void* p; - int ret; - - lua_settop(L, 1); - p = to_cdata(L, 1, &ct); - - ret = call_user_op(L, "__tostring", 1, 2, &ct); - if (ret >= 0) { - return ret; - } - - if (ct.pointers > 0 || ct.is_reference || ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) { - push_type_name(L, -1, &ct); - lua_pushfstring(L, "cdata<%s>: %p", lua_tostring(L, -1), p); - - if (DEBUG_TOSTRING) { - print_type(L, &ct); - lua_concat(L, 2); - } - - return 1; - } - - switch (ct.type) { - case COMPLEX_DOUBLE_TYPE: - { - complex_double c = *(complex_double*) p; - lua_pushfstring(L, "%f+%fi", creal(c), cimag(c)); - } - return 1; - - case COMPLEX_FLOAT_TYPE: - { - complex_float c = *(complex_float*) p; - lua_pushfstring(L, "%f+%fi", crealf(c), cimagf(c)); - } - return 1; - - case FUNCTION_PTR_TYPE: - p = *(void**) p; - push_type_name(L, -1, &ct); - lua_pushfstring(L, "cdata<%s>: %p", lua_tostring(L, -1), *(void**) p); - return 1; - - case INTPTR_TYPE: - lua_pushfstring(L, "%p", *(uintptr_t*) p); - return 1; - - case INT64_TYPE: - sprintf(buf, ct.is_unsigned ? "%"PRIu64 : "%"PRId64, *(uint64_t*) p); - lua_pushstring(L, buf); - return 1; - - default: - sprintf(buf, ct.is_unsigned ? "%"PRId64 : "%"PRId64, (int64_t) check_intptr(L, 1, p, &ct)); - lua_pushstring(L, buf); - return 1; - } -} - -static int ffi_errno(lua_State* L) -{ - struct jit* jit = get_jit(L); - - if (!lua_isnoneornil(L, 1)) { - lua_pushinteger(L, jit->last_errno); - jit->last_errno = luaL_checknumber(L, 1); - } else { - lua_pushinteger(L, jit->last_errno); - } - - return 1; -} - -static int ffi_type(lua_State* L) -{ - if (lua_isuserdata(L, 1) && lua_getmetatable(L, 1)) { - if (equals_upval(L, -1, &cdata_mt_key) || equals_upval(L, -1, &ctype_mt_key)) { - lua_pushstring(L, "cdata"); - return 1; - } - lua_pop(L, 1); /* mt */ - } - - /* call the old _G.type, we use an upvalue as _G.type is set - * to this function */ - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, 1); - lua_call(L, lua_gettop(L)-1, LUA_MULTRET); - return lua_gettop(L); -} - -static int ffi_number(lua_State* L) -{ - struct ctype ct; - void* data = to_cdata(L, 1, &ct); - - if (ct.type != INVALID_TYPE) { - lua_pushinteger(L, check_intptr(L, 1, data, &ct)); - return 1; - } else { - /* call the old _G.tonumber, we use an upvalue as _G.tonumber is set - * to this function */ - lua_pushvalue(L, lua_upvalueindex(1)); - lua_insert(L, 1); - lua_call(L, lua_gettop(L)-1, LUA_MULTRET); - return lua_gettop(L); - } -} - -static int ffi_string(lua_State* L) -{ - struct ctype ct; - char* data; - lua_settop(L, 2); - - data = (char*) check_cdata(L, 1, &ct); - - if (is_void_ptr(&ct)) { - lua_pushlstring(L, data, (size_t) luaL_checknumber(L, 2)); - return 1; - - } else if (ct.type == INT8_TYPE && ct.pointers == 1) { - size_t sz; - - if (lua_isuserdata(L, 2)) { - ptrdiff_t val; - if (!cdata_tointeger(L, 2, &val)) { - type_error(L, 2, "int", 0, NULL); - } - sz = (size_t) val; - } else if (!lua_isnil(L, 2)) { - sz = (size_t) luaL_checknumber(L, 2); - - } else if (ct.is_array && !ct.is_variable_array) { - char* nul = memchr(data, '\0', ct.array_size); - sz = nul ? nul - data : ct.array_size; - - } else { - sz = strlen(data); - } - - lua_pushlstring(L, data, sz); - return 1; - } - - return luaL_error(L, "unable to convert cdata to string"); -} - -static int ffi_copy(lua_State* L) -{ - struct ctype ft, tt; - char *to, *from; - - setmintop(L, 3); - to = (char*) check_pointer(L, 1, &tt); - from = (char*) check_pointer(L, 2, &ft); - - if (!lua_isnoneornil(L, 3)) { - memcpy(to, from, (size_t) luaL_checknumber(L, 3)); - - } else if (ft.type == INT8_TYPE && ft.pointers == 1) { - size_t sz = ft.is_array ? ft.array_size : strlen(from); - memcpy(to, from, sz); - to[sz] = '\0'; - } - - return 0; -} - -static int ffi_fill(lua_State* L) -{ - struct ctype ct; - void* to; - size_t sz; - int val = 0; - - setmintop(L, 3); - to = check_pointer(L, 1, &ct); - sz = (size_t) luaL_checknumber(L, 2); - - if (!lua_isnoneornil(L, 3)) { - val = (int) luaL_checkinteger(L, 3); - } - - memset(to, val, sz); - return 0; -} - -static int ffi_abi(lua_State* L) -{ - luaL_checkstring(L, 1); - push_upval(L, &abi_key); - lua_pushvalue(L, 1); - lua_rawget(L, -2); - lua_pushboolean(L, lua_toboolean(L, -1)); - return 1; -} - -static int ffi_load(lua_State* L) -{ - const char* libname = luaL_checkstring(L, 1); - void** lib = (void**) lua_newuserdata(L, sizeof(void*)); - - *lib = LoadLibraryA(libname); - -#ifdef LIB_FORMAT_1 - if (!*lib) { - libname = lua_pushfstring(L, LIB_FORMAT_1, lua_tostring(L, 1)); - *lib = LoadLibraryA(libname); - lua_pop(L, 1); - } -#endif - -#ifdef LIB_FORMAT_2 - if (!*lib) { - libname = lua_pushfstring(L, LIB_FORMAT_2, lua_tostring(L, 1)); - *lib = LoadLibraryA(libname); - lua_pop(L, 1); - } -#endif - - if (!*lib) { - return luaL_error(L, "could not load library %s", lua_tostring(L, 1)); - } - - lua_newtable(L); - lua_setuservalue(L, -2); - - push_upval(L, &cmodule_mt_key); - lua_setmetatable(L, -2); - return 1; -} - -static void* find_symbol(lua_State* L, int modidx, const char* asmname) -{ - size_t i; - void** libs; - size_t num; - void* sym = NULL; - - libs = (void**) lua_touserdata(L, modidx); - num = lua_rawlen(L, modidx) / sizeof(void*); - - for (i = 0; i < num && sym == NULL; i++) { - if (libs[i]) { - sym = GetProcAddressA(libs[i], asmname); - } - } - - return sym; -} - -/* pushes the user table */ -static void* lookup_global(lua_State* L, int modidx, int nameidx, const char** pname, struct ctype* ct) -{ - int top = lua_gettop(L); - void* sym; - - modidx = lua_absindex(L, modidx); - nameidx = lua_absindex(L, nameidx); - - *pname = luaL_checkstring(L, nameidx); - - /* get the ctype */ - push_upval(L, &functions_key); - lua_pushvalue(L, nameidx); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - luaL_error(L, "missing declaration for function/global %s", *pname); - return NULL; - } - - /* leave just the ct_usr on the stack */ - *ct = *(const struct ctype*) lua_touserdata(L, -1); - lua_getuservalue(L, -1); - lua_replace(L, top + 1); - lua_pop(L, 1); - - assert(lua_gettop(L) == top + 1); - - /* get the assembly name */ - push_upval(L, &asmname_key); - lua_pushvalue(L, nameidx); - lua_rawget(L, -2); - if (lua_isstring(L, -1)) { - *pname = lua_tostring(L, -1); - } - lua_pop(L, 2); - - sym = find_symbol(L, modidx, *pname); - - assert(lua_gettop(L) == top + 1); - return sym; -} - -static int cmodule_index(lua_State* L) -{ - const char* asmname; - struct ctype ct; - void *sym; - - lua_settop(L, 2); - - /* see if we have already loaded the function */ - lua_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - return 1; - } - lua_pop(L, 2); - - /* check the constants table */ - push_upval(L, &constants_key); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - if (!lua_isnil(L, -1)) { - return 1; - } - lua_pop(L, 2); - - /* lookup_global pushes the ct_usr */ - sym = lookup_global(L, 1, 2, &asmname, &ct); - -#if defined _WIN32 && !defined _WIN64 && (defined __i386__ || defined _M_IX86) - if (!sym && ct.type == FUNCTION_TYPE) { - ct.calling_convention = STD_CALL; - lua_pushfstring(L, "_%s@%d", asmname, x86_return_size(L, -1, &ct)); - sym = find_symbol(L, 1, lua_tostring(L, -1)); - lua_pop(L, 1); - } - - if (!sym && ct.type == FUNCTION_TYPE) { - ct.calling_convention = FAST_CALL; - lua_pushfstring(L, "@%s@%d", asmname, x86_return_size(L, -1, &ct)); - sym = find_symbol(L, 1, lua_tostring(L, -1)); - lua_pop(L, 1); - } -#endif - - if (!sym) { - return luaL_error(L, "failed to find function/global %s", asmname); - } - - assert(lua_gettop(L) == 3); /* module, name, ct_usr */ - - if (ct.type == FUNCTION_TYPE) { - compile_function(L, (cfunction) sym, -1, &ct); - assert(lua_gettop(L) == 4); /* module, name, ct_usr, function */ - - /* set module usr value[luaname] = function to cache for next time */ - lua_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_pushvalue(L, -3); - lua_rawset(L, -3); - lua_pop(L, 1); /* module uv */ - return 1; - } - - /* extern const char* foo; and extern const char foo[]; */ - if (ct.pointers == 1 && ct.type == INT8_TYPE) { - char* str = (char*) sym; - if (!ct.is_array) { - str = *(char**) sym; - } - lua_pushstring(L, str); - return 1; - } - - /* extern struct foo foo[], extern void* foo[]; and extern struct foo foo; */ - if (ct.is_array || (!ct.pointers && (ct.type == UNION_TYPE || ct.type == STRUCT_TYPE))) { - void* p; - ct.is_reference = 1; - p = push_cdata(L, -1, &ct); - *(void**) p = sym; - return 1; - } - - /* extern void* foo; and extern void (*foo)(); */ - if (ct.pointers || ct.type == FUNCTION_PTR_TYPE) { - void* p = push_cdata(L, -1, &ct); - *(void**) p = *(void**) sym; - return 1; - } - - switch (ct.type) { - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case INTPTR_TYPE: - case INT64_TYPE: - { - /* TODO: complex float/double need to be references if .re and - * .imag are setable */ - void* p = push_cdata(L, -1, &ct); - memcpy(p, sym, ct.base_size); - return 1; - } - - case DOUBLE_TYPE: - lua_pushnumber(L, *(double*) sym); - return 1; - - case FLOAT_TYPE: - lua_pushnumber(L, *(float*) sym); - return 1; - - case BOOL_TYPE: - lua_pushboolean(L, *(bool*) sym); - return 1; - - case INT8_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint8_t*) sym : (lua_Integer) *(int8_t*) sym); - return 1; - - case INT16_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint16_t*) sym : (lua_Integer) *(int16_t*) sym); - return 1; - - case INT32_TYPE: - case ENUM_TYPE: - lua_pushinteger(L, ct.is_unsigned ? (lua_Integer) *(uint32_t*) sym : (lua_Integer) *(int32_t*) sym); - return 1; - } - - return luaL_error(L, "NYI - global value type"); -} - -static int cmodule_newindex(lua_State* L) -{ - const char* name; - void* sym; - struct ctype ct; - - lua_settop(L, 3); - - /* pushes the ct_usr */ - sym = lookup_global(L, 1, 2, &name, &ct); - assert(lua_gettop(L) == 4); /* module, name, value, ct_usr */ - - if (sym == NULL) { - return luaL_error(L, "failed to find global %s", name); - } - - if (ct.type == FUNCTION_TYPE || ct.is_array || (ct.const_mask & 1)) { - return luaL_error(L, "can not set global %s", name); - } - - set_value(L, 3, sym, -1, &ct, 1); - return 0; -} - -static int jit_gc(lua_State* L) -{ - size_t i; - struct jit* jit = get_jit(L); - dasm_free(jit); - for (i = 0; i < jit->pagenum; i++) { - FreePage(jit->pages[i], jit->pages[i]->size); - } - free(jit->pages); - free(jit->globals); - return 0; -} - -static int ffi_debug(lua_State* L) -{ - lua_newtable(L); - push_upval(L, &ctype_mt_key); - lua_setfield(L, -2, "ctype_mt"); - push_upval(L, &cdata_mt_key); - lua_setfield(L, -2, "cdata_mt"); - push_upval(L, &cmodule_mt_key); - lua_setfield(L, -2, "cmodule_mt"); - push_upval(L, &constants_key); - lua_setfield(L, -2, "constants"); - push_upval(L, &types_key); - lua_setfield(L, -2, "types"); - push_upval(L, &jit_key); - lua_setfield(L, -2, "jit"); - push_upval(L, &gc_key); - lua_setfield(L, -2, "gc"); - push_upval(L, &callbacks_key); - lua_setfield(L, -2, "callbacks"); - push_upval(L, &functions_key); - lua_setfield(L, -2, "functions"); - push_upval(L, &abi_key); - lua_setfield(L, -2, "abi"); - push_upval(L, &next_unnamed_key); - lua_setfield(L, -2, "next_unnamed"); - return 1; -} - -static int do64(lua_State* L, int is_unsigned) -{ - lua_Number low, high; - struct ctype ct; - int64_t val; - - lua_settop(L, 2); - - if (!lua_isnil(L, 2)) { - high = luaL_checknumber(L, 1); - low = luaL_checknumber(L, 2); - } else { - high = 0; - low = luaL_checknumber(L, 1); - } - - val = ((int64_t) (uint32_t) high << 32) | (int64_t) (uint32_t) low; - - if (!is_unsigned && (high < 0 || low < 0)) { - val = -val; - } - - memset(&ct, 0, sizeof(ct)); - ct.type = INT64_TYPE; - ct.is_unsigned = is_unsigned; - ct.is_defined = 1; - ct.base_size = sizeof(int64_t); - push_number(L, (int64_t) val, 0, &ct); - - return 1; -} - -static int ffi_i64(lua_State* L) -{ return do64(L, 0); } - -static int ffi_u64(lua_State* L) -{ return do64(L, 1); } - -static const luaL_Reg cdata_mt[] = { - {"__gc", &cdata_gc}, - {"__call", &cdata_call}, - {"free", &cdata_free}, - {"set", &cdata_set}, - {"__index", &cdata_index}, - {"__newindex", &cdata_newindex}, - {"__add", &cdata_add}, - {"__sub", &cdata_sub}, - {"__mul", &cdata_mul}, - {"__div", &cdata_div}, - {"__mod", &cdata_mod}, - {"__pow", &cdata_pow}, - {"__unm", &cdata_unm}, - {"__eq", &cdata_eq}, - {"__lt", &cdata_lt}, - {"__le", &cdata_le}, - {"__tostring", &cdata_tostring}, - {"__concat", &cdata_concat}, - {"__len", &cdata_len}, - {"__pairs", &cdata_pairs}, - {"__ipairs", &cdata_ipairs}, - {NULL, NULL} -}; - -static const luaL_Reg callback_mt[] = { - {"__gc", &callback_free}, - {NULL, NULL} -}; - -static const luaL_Reg ctype_mt[] = { - {"__call", &ctype_call}, - {"__new", &ctype_new}, - {"__tostring", &ctype_tostring}, - {NULL, NULL} -}; - -static const luaL_Reg cmodule_mt[] = { - {"__index", &cmodule_index}, - {"__newindex", &cmodule_newindex}, - {NULL, NULL} -}; - -static const luaL_Reg jit_mt[] = { - {"__gc", &jit_gc}, - {NULL, NULL} -}; - -static const luaL_Reg ffi_reg[] = { - {"cdef", &ffi_cdef}, - {"load", &ffi_load}, - {"new", &ffi_new}, - {"typeof", &ffi_typeof}, - {"cast", &ffi_cast}, - {"metatype", &ffi_metatype}, - {"gc", &ffi_gc}, - {"sizeof", &ffi_sizeof}, - {"alignof", &ffi_alignof}, - {"offsetof", &ffi_offsetof}, - {"istype", &ffi_istype}, - {"errno", &ffi_errno}, - {"string", &ffi_string}, - {"copy", &ffi_copy}, - {"fill", &ffi_fill}, - {"abi", &ffi_abi}, - {"debug", &ffi_debug}, - {"i64", &ffi_i64}, - {"u64", &ffi_u64}, - {NULL, NULL} -}; - -/* leaves the usr table on the stack */ -static void push_builtin(lua_State* L, struct ctype* ct, const char* name, int type, int size, int align, int is_unsigned) -{ - memset(ct, 0, sizeof(*ct)); - ct->type = type; - ct->base_size = size; - ct->align_mask = align; - ct->is_defined = 1; - ct->is_unsigned = is_unsigned; - - if (IS_COMPLEX(type)) { - lua_newtable(L); - } else { - lua_pushnil(L); - } - - push_upval(L, &types_key); - push_ctype(L, -2, ct); - lua_setfield(L, -2, name); - lua_pop(L, 2); /* types, usr table */ -} - -static void push_builtin_undef(lua_State* L, struct ctype* ct, const char* name, int type) -{ - memset(ct, 0, sizeof(*ct)); - ct->type = type; - - push_upval(L, &types_key); - push_ctype(L, 0, ct); - lua_setfield(L, -2, name); - lua_pop(L, 1); /* types */ -} - -static void add_typedef(lua_State* L, const char* from, const char* to) -{ - struct ctype ct; - struct parser P; - P.line = 1; - P.align_mask = DEFAULT_ALIGN_MASK; - P.next = P.prev = from; - - push_upval(L, &types_key); - parse_type(L, &P, &ct); - parse_argument(L, &P, -1, &ct, NULL, NULL); - push_ctype(L, -1, &ct); - - /* stack is at +4: types, type usr, arg usr, ctype */ - - lua_setfield(L, -4, to); - lua_pop(L, 3); /* types, type usr, arg usr */ -} - -static int setup_upvals(lua_State* L) -{ - struct jit* jit = get_jit(L); - - /* jit setup */ - { - dasm_init(jit, 64); -#ifdef _WIN32 - { - SYSTEM_INFO si; - GetSystemInfo(&si); - jit->align_page_size = si.dwAllocationGranularity - 1; - } -#else - jit->align_page_size = sysconf(_SC_PAGE_SIZE) - 1; -#endif - jit->globals = (void**) malloc(64 * sizeof(void*)); - dasm_setupglobal(jit, jit->globals, 64); - compile_globals(jit, L); - } - - /* ffi.C */ - { -#ifdef _WIN32 - size_t sz = sizeof(HMODULE) * 6; - HMODULE* libs = lua_newuserdata(L, sz); - memset(libs, 0, sz); - - /* exe */ - GetModuleHandle(NULL); - /* lua dll */ -#ifdef LUA_DLL_NAME -#define STR2(tok) #tok -#define STR(tok) STR2(tok) - libs[1] = LoadLibraryA(STR(LUA_DLL_NAME)); -#undef STR -#undef STR2 -#endif - - /* crt */ -#ifdef UNDER_CE - libs[2] = LoadLibraryA("coredll.dll"); -#else - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (char*) &_fmode, &libs[2]); - libs[3] = LoadLibraryA("kernel32.dll"); - libs[4] = LoadLibraryA("user32.dll"); - libs[5] = LoadLibraryA("gdi32.dll"); -#endif - - jit->lua_dll = libs[1]; - jit->kernel32_dll = libs[3]; - -#else /* !_WIN32 */ - size_t sz = sizeof(void*) * 5; - void** libs = lua_newuserdata(L, sz); - memset(libs, 0, sz); - - libs[0] = LoadLibraryA(NULL); /* exe */ - libs[1] = LoadLibraryA("libc.so"); -#ifdef __GNUC__ - libs[2] = LoadLibraryA("libgcc.so"); -#endif - libs[3] = LoadLibraryA("libm.so"); - libs[4] = LoadLibraryA("libdl.so"); -#endif - - lua_newtable(L); - lua_setuservalue(L, -2); - - push_upval(L, &cmodule_mt_key); - lua_setmetatable(L, -2); - - lua_setfield(L, 1, "C"); - } - - /* setup builtin types */ - { - complex_double* pc; - struct {char ch; uint16_t v;} a16; - struct {char ch; uint32_t v;} a32; - struct {char ch; uint64_t v;} a64; - struct {char ch; float v;} af; - struct {char ch; double v;} ad; -#ifdef HAVE_LONG_DOUBLE - struct {char ch; long double v;} ald; -#endif - struct {char ch; uintptr_t v;} aptr; - struct ctype ct; - struct {char ch; complex_float v;} cf; - struct {char ch; complex_double v;} cd; -#if defined HAVE_LONG_DOUBLE && defined HAVE_COMPLEX - struct {char ch; complex long double v;} cld; -#endif - - push_builtin(L, &ct, "void", VOID_TYPE, 0, 0, 0); - push_builtin(L, &ct, "bool", BOOL_TYPE, sizeof(_Bool), sizeof(_Bool) -1, 1); - push_builtin(L, &ct, "uint8_t", INT8_TYPE, sizeof(uint8_t), 0, 1); - push_builtin(L, &ct, "int8_t", INT8_TYPE, sizeof(int8_t), 0, 0); - push_builtin(L, &ct, "uint16_t", INT16_TYPE, sizeof(uint16_t), ALIGNOF(a16), 1); - push_builtin(L, &ct, "int16_t", INT16_TYPE, sizeof(int16_t), ALIGNOF(a16), 0); - push_builtin(L, &ct, "uint32_t", INT32_TYPE, sizeof(uint32_t), ALIGNOF(a32), 1); - push_builtin(L, &ct, "int32_t", INT32_TYPE, sizeof(int32_t), ALIGNOF(a32), 0); - push_builtin(L, &ct, "uint64_t", INT64_TYPE, sizeof(uint64_t), ALIGNOF(a64), 1); - push_builtin(L, &ct, "int64_t", INT64_TYPE, sizeof(int64_t), ALIGNOF(a64), 0); - push_builtin(L, &ct, "float", FLOAT_TYPE, sizeof(float), ALIGNOF(af), 0); - push_builtin(L, &ct, "double", DOUBLE_TYPE, sizeof(double), ALIGNOF(ad), 0); -#ifdef HAVE_LONG_DOUBLE - push_builtin(L, &ct, "long double", LONG_DOUBLE_TYPE, sizeof(long double), ALIGNOF(ald), 0); -#else - push_builtin_undef(L, &ct, "long double", LONG_DOUBLE_TYPE); -#endif - push_builtin(L, &ct, "uintptr_t", INTPTR_TYPE, sizeof(uintptr_t), ALIGNOF(aptr), 1); - push_builtin(L, &ct, "intptr_t", INTPTR_TYPE, sizeof(uintptr_t), ALIGNOF(aptr), 0); - push_builtin(L, &ct, "complex float", COMPLEX_FLOAT_TYPE, sizeof(complex_float), ALIGNOF(cf), 0); - push_builtin(L, &ct, "complex double", COMPLEX_DOUBLE_TYPE, sizeof(complex_double), ALIGNOF(cd), 0); -#if defined HAVE_LONG_DOUBLE && defined HAVE_COMPLEX - push_builtin(L, &ct, "complex long double", COMPLEX_LONG_DOUBLE_TYPE, sizeof(complex long double), ALIGNOF(cld), 0); -#else - push_builtin_undef(L, &ct, "complex long double", COMPLEX_LONG_DOUBLE_TYPE); -#endif - - /* add NULL and i constants */ - push_upval(L, &constants_key); - - memset(&ct, 0, sizeof(ct)); - ct.type = VOID_TYPE; - ct.is_defined = 1; - ct.pointers = 1; - ct.is_null = 1; - - /* add ffi.C.NULL */ - push_cdata(L, 0, &ct); - lua_setfield(L, -2, "NULL"); - - /* add ffi.NULL */ - push_cdata(L, 0, &ct); - lua_setfield(L, 1, "NULL"); - - memset(&ct, 0, sizeof(ct)); - ct.type = COMPLEX_DOUBLE_TYPE; - ct.is_defined = 1; - ct.base_size = sizeof(complex_double); - pc = (complex_double*) push_cdata(L, 0, &ct); -#ifdef HAVE_COMPLEX - *pc = 1i; -#else - pc->real = 0; - pc->imag = 1; -#endif - lua_setfield(L, -2, "i"); - - lua_pop(L, 1); /* constants */ - } - - assert(lua_gettop(L) == 1); - - /* setup builtin typedefs */ - { - add_typedef(L, "bool", "_Bool"); - - if (sizeof(uint32_t) == sizeof(size_t)) { - add_typedef(L, "uint32_t", "size_t"); - add_typedef(L, "int32_t", "ssize_t"); - } else if (sizeof(uint64_t) == sizeof(size_t)) { - add_typedef(L, "uint64_t", "size_t"); - add_typedef(L, "int64_t", "ssize_t"); - } - - if (sizeof(int32_t) == sizeof(intptr_t)) { - add_typedef(L, "int32_t", "intptr_t"); - add_typedef(L, "int32_t", "ptrdiff_t"); - } else if (sizeof(int64_t) == sizeof(intptr_t)) { - add_typedef(L, "int64_t", "intptr_t"); - add_typedef(L, "int64_t", "ptrdiff_t"); - } - - if (sizeof(uint8_t) == sizeof(wchar_t)) { - add_typedef(L, "uint8_t", "wchar_t"); - } else if (sizeof(uint16_t) == sizeof(wchar_t)) { - add_typedef(L, "uint16_t", "wchar_t"); - } else if (sizeof(uint32_t) == sizeof(wchar_t)) { - add_typedef(L, "uint32_t", "wchar_t"); - } - - if (sizeof(va_list) == sizeof(char*)) { - add_typedef(L, "char*", "va_list"); - } else { - struct {char ch; va_list v;} av; - lua_pushfstring(L, "struct {char data[%d] __attribute__((align(%d)));}", (int) sizeof(va_list), (int) ALIGNOF(av) + 1); - add_typedef(L, lua_tostring(L, -1), "va_list"); - lua_pop(L, 1); - } - - add_typedef(L, "va_list", "__builtin_va_list"); - add_typedef(L, "va_list", "__gnuc_va_list"); - } - - assert(lua_gettop(L) == 1); - - /* setup ABI params table */ - push_upval(L, &abi_key); - -#if defined ARCH_X86 || defined ARCH_ARM - lua_pushboolean(L, 1); - lua_setfield(L, -2, "32bit"); -#elif defined ARCH_X64 || defined ARCH_PPC64 - lua_pushboolean(L, 1); - lua_setfield(L, -2, "64bit"); -#else -#error -#endif - -#if defined ARCH_X86 || defined ARCH_X64 || defined ARCH_ARM || defined ARCH_PPC64 - lua_pushboolean(L, 1); - lua_setfield(L, -2, "le"); -#else -#error -#endif - -#if defined ARCH_X86 || defined ARCH_X64 || defined ARCH_PPC64 - lua_pushboolean(L, 1); - lua_setfield(L, -2, "fpu"); -#elif defined ARCH_ARM - lua_pushboolean(L, 1); - lua_setfield(L, -2, "softfp"); -#else -#error -#endif - lua_pop(L, 1); /* abi tbl */ - - - /* GC table - shouldn't pin cdata values */ - push_upval(L, &gc_key); - lua_newtable(L); - lua_pushliteral(L, "k"); - lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_pop(L, 1); /* gc table */ - - - /* ffi.os */ -#if defined OS_CE - lua_pushliteral(L, "WindowsCE"); -#elif defined OS_WIN - lua_pushliteral(L, "Windows"); -#elif defined OS_OSX - lua_pushliteral(L, "OSX"); -#elif defined OS_LINUX - lua_pushliteral(L, "Linux"); -#elif defined OS_BSD - lua_pushliteral(L, "BSD"); -#elif defined OS_POSIX - lua_pushliteral(L, "POSIX"); -#else - lua_pushliteral(L, "Other"); -#endif - lua_setfield(L, 1, "os"); - - - /* ffi.arch */ -#if defined ARCH_X86 - lua_pushliteral(L, "x86"); -#elif defined ARCH_X64 - lua_pushliteral(L, "x64"); -#elif defined ARCH_ARM - lua_pushliteral(L, "arm"); -#elif defined ARCH_PPC64 - lua_pushliteral(L, "ppc64"); -#else -# error -#endif - lua_setfield(L, 1, "arch"); - - assert(lua_gettop(L) == 1); - - return 0; -} - -static void setup_mt(lua_State* L, const luaL_Reg* mt, int upvals) -{ - lua_pushboolean(L, 1); - lua_setfield(L, -upvals-2, "__metatable"); - luaL_setfuncs(L, mt, upvals); -} - -int luaopen_ffi(lua_State* L) -{ - lua_settop(L, 0); - - lua_newtable(L); - set_upval(L, &niluv_key); - - lua_newtable(L); - setup_mt(L, ctype_mt, 0); - set_upval(L, &ctype_mt_key); - - lua_newtable(L); - set_upval(L, &callbacks_key); - - lua_newtable(L); - set_upval(L, &gc_key); - - lua_newtable(L); - push_upval(L, &callbacks_key); - push_upval(L, &gc_key); - setup_mt(L, cdata_mt, 2); - set_upval(L, &cdata_mt_key); - - lua_newtable(L); - setup_mt(L, callback_mt, 0); - set_upval(L, &callback_mt_key); - - lua_newtable(L); - setup_mt(L, cmodule_mt, 0); - set_upval(L, &cmodule_mt_key); - - memset(lua_newuserdata(L, sizeof(struct jit)), 0, sizeof(struct jit)); - lua_newtable(L); - setup_mt(L, jit_mt, 0); - lua_setmetatable(L, -2); - set_upval(L, &jit_key); - - lua_newtable(L); - set_upval(L, &constants_key); - - lua_newtable(L); - set_upval(L, &types_key); - - lua_newtable(L); - set_upval(L, &functions_key); - - lua_newtable(L); - set_upval(L, &asmname_key); - - lua_newtable(L); - set_upval(L, &abi_key); - - lua_pushinteger(L, 1); - set_upval(L, &next_unnamed_key); - - assert(lua_gettop(L) == 0); - - /* ffi table */ - lua_newtable(L); - luaL_setfuncs(L, ffi_reg, 0); - - /* setup_upvals(ffi tbl) */ - lua_pushcfunction(L, &setup_upvals); - lua_pushvalue(L, 1); - lua_call(L, 1, 0); - - assert(lua_gettop(L) == 1); - - lua_getglobal(L, "tonumber"); - lua_pushcclosure(L, &ffi_number, 1); - lua_pushvalue(L, -1); - lua_setglobal(L, "tonumber"); - lua_setfield(L, -2, "number"); /* ffi.number */ - - lua_getglobal(L, "type"); - lua_pushcclosure(L, &ffi_type, 1); - lua_pushvalue(L, -1); - lua_setglobal(L, "type"); - lua_setfield(L, -2, "type"); /* ffi.type */ - return 1; -} diff --git a/Build/source/texk/web2c/luatexdir/luaffi/ffi.h b/Build/source/texk/web2c/luatexdir/luaffi/ffi.h deleted file mode 100644 index 8190a973892..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/ffi.h +++ /dev/null @@ -1,476 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#pragma once - -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#ifdef __cplusplus -extern "C" { -# include <lua.h> -# include <lauxlib.h> -# include <lualib.h> -} -# define EXTERN_C extern "C" -#else -# include <lua.h> -# include <lauxlib.h> -# include <lualib.h> -# define EXTERN_C extern -#endif - -#ifdef _WIN32 -#include <windows.h> -#else -#include <errno.h> -#include <unistd.h> -#include <dlfcn.h> -#include <sys/mman.h> -#endif - -#if ( defined( _WIN32) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__DragonFly__)) -/* We should include something equivalent to */ -/* complex.h */ -#else -#include <complex.h> -#define HAVE_COMPLEX -#define HAVE_LONG_DOUBLE -#endif - - -#ifndef NDEBUG -#define DASM_CHECKS -#endif - -struct jit; -#define Dst_DECL struct jit* Dst -#define Dst_REF (Dst->ctx) -#define DASM_EXTERN(a,b,c,d) get_extern(a,b,c,d) - -#include "dynasm/dasm_proto.h" - -#if defined LUA_FFI_BUILD_AS_DLL -# define EXPORT __declspec(dllexport) -#elif defined __GNUC__ -# define EXPORT __attribute__((visibility("default"))) -#else -# define EXPORT -#endif - -EXTERN_C EXPORT int luaopen_ffi(lua_State* L); - -static int lua_absindex2(lua_State* L, int idx) { - return (LUA_REGISTRYINDEX <= idx && idx < 0) - ? lua_gettop(L) + idx + 1 - : idx; -} -/* use our own version of lua_absindex such that lua_absindex(L, 0) == 0 */ -#define lua_absindex(L, idx) lua_absindex2(L, idx) - -#if LUA_VERSION_NUM == 501 -static void lua_callk(lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k) -{ - lua_call(L, nargs, nresults); -} -/* -** set functions from list 'l' into table at top - 'nup'; each -** function gets the 'nup' elements at the top as upvalues. -** Returns with only the table at the stack. -*/ -static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup, "too many upvalues"); - for (; l && l->name; l++) { /* fill the table with given functions */ - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} -#define lua_setuservalue lua_setfenv -#define lua_getuservalue lua_getfenv -#define lua_rawlen lua_objlen -static char* luaL_prepbuffsize(luaL_Buffer* B, size_t sz) { - if (sz > LUAL_BUFFERSIZE) { - luaL_error(B->L, "string too long"); - } - return luaL_prepbuffer(B); -} -#elif LUA_VERSION_NUM == 503 -static void (lua_remove)(lua_State *L, int idx) { - lua_remove(L, idx); -} -#endif - -/* architectures */ -#if defined _WIN32 && defined UNDER_CE -# define OS_CE -#elif defined _WIN32 -# define OS_WIN -#elif defined __APPLE__ && defined __MACH__ -# define OS_OSX -#elif defined __linux__ -# define OS_LINUX -#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ -# define OS_BSD -#elif defined unix || defined __unix__ || defined __unix || defined _POSIX_VERSION || defined _XOPEN_VERSION -# define OS_POSIX -#endif - -/* architecture */ -#if defined __i386__ || defined _M_IX86 -# define ARCH_X86 -#elif defined __amd64__ || defined _M_X64 -# define ARCH_X64 -#elif defined __arm__ || defined __ARM__ || defined ARM || defined __ARM || defined __arm || defined __aarch64__ -# define ARCH_ARM -#elif defined __powerpc64__ -# define ARCH_PPC64 -#else -# define UNSUPPORTED_ARCH -#endif - - -/* See ffi.c: replace luaopen_ffi with a stub */ -/* if FFI_ENABLE_LUATEX_INTERFACE is not defined */ -#if (defined ARCH_X86 || defined ARCH_X64) && (defined OS_CE || defined OS_WIN || defined OS_LINUX || defined OS_BSD || defined OS_POSIX || defined OS_OSX) -#define FFI_ENABLE_LUATEX_INTERFACE -#endif -/* for the moment */ -#if (defined __CYGWIN__) -#undef FFI_ENABLE_LUATEX_INTERFACE -#endif - - - - -#ifdef _WIN32 - -# ifdef UNDER_CE - static void* DoLoadLibraryA(const char* name) { - wchar_t buf[MAX_PATH]; - int sz = MultiByteToWideChar(CP_UTF8, 0, name, -1, buf, 512); - if (sz > 0) { - buf[sz] = 0; - return LoadLibraryW(buf); - } else { - return NULL; - } - } -# define LoadLibraryA DoLoadLibraryA -# else -# define GetProcAddressA GetProcAddress -# endif - -# define LIB_FORMAT_1 "%s.dll" -# define AllocPage(size) VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE) -# define FreePage(data, size) VirtualFree(data, 0, MEM_RELEASE) -# define EnableExecute(data, size) do {DWORD old; VirtualProtect(data, size, PAGE_EXECUTE, &old); FlushInstructionCache(GetCurrentProcess(), data, size);} while (0) -# define EnableWrite(data, size) do {DWORD old; VirtualProtect(data, size, PAGE_READWRITE, &old);} while (0) - -#else -#ifdef OS_OSX -# define LIB_FORMAT_1 "%s.dylib" -# define LIB_FORMAT_2 "lib%s.dylib" -#else -# define LIB_FORMAT_1 "%s.so" -# define LIB_FORMAT_2 "lib%s.so" -#endif -# define LoadLibraryA(name) dlopen(name, RTLD_LAZY | RTLD_GLOBAL) -# define GetProcAddressA(lib, name) dlsym(lib, name) -# define AllocPage(size) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) -# define FreePage(data, size) munmap(data, size) -# define EnableExecute(data, size) mprotect(data, size, PROT_READ|PROT_EXEC) -# define EnableWrite(data, size) mprotect(data, size, PROT_READ|PROT_WRITE) -#endif - -#if defined ARCH_X86 || defined ARCH_X64 -#define ALLOW_MISALIGNED_ACCESS -#endif - -struct token; - -struct parser { - int line; - const char* next; - const char* prev; - unsigned align_mask; -}; - -struct page { - size_t size; - size_t off; - size_t freed; -}; - -struct jit { - lua_State* L; - int32_t last_errno; - dasm_State* ctx; - size_t pagenum; - struct page** pages; - size_t align_page_size; - void** globals; - int function_extern; - void* lua_dll; - void* kernel32_dll; -}; - -#define ALIGN_DOWN(PTR, MASK) \ - (((uintptr_t) (PTR)) & (~ ((uintptr_t) (MASK)) )) -#define ALIGN_UP(PTR, MASK) \ - (( ((uintptr_t) (PTR)) + ((uintptr_t) (MASK)) ) & (~ ((uintptr_t) (MASK)) )) - -/* struct cdata/struct ctype */ - -#define PTR_ALIGN_MASK (sizeof(void*) - 1) -#define FUNCTION_ALIGN_MASK (sizeof(void (*)()) - 1) -#define DEFAULT_ALIGN_MASK 7 - -#ifdef OS_OSX -/* TODO: figure out why the alignof trick doesn't work on OS X */ -#define ALIGNED_DEFAULT 7 -#elif defined __GNUC__ -#define ALIGNED_DEFAULT (__alignof__(void* __attribute__((aligned))) - 1) -#else -#define ALIGNED_DEFAULT PTR_ALIGN_MASK -#endif - -extern int jit_key; -extern int ctype_mt_key; -extern int cdata_mt_key; -extern int cmodule_mt_key; -extern int callback_mt_key; -extern int constants_key; -extern int types_key; -extern int gc_key; -extern int callbacks_key; -extern int functions_key; -extern int abi_key; -extern int next_unnamed_key; -extern int niluv_key; -extern int asmname_key; - -int equals_upval(lua_State* L, int idx, int* key); -void push_upval(lua_State* L, int* key); -void set_upval(lua_State* L, int* key); -struct jit* get_jit(lua_State* L); - -/* both ctype and cdata are stored as userdatas - * - * usr value is a table shared between the related subtypes which has: - * name -> member ctype (for structs and unions) - * +ves -> member ctype - in memory order (for structs) - * +ves -> argument ctype (for function prototypes) - * 0 -> return ctype (for function prototypes) - * light userdata -> misc - */ - -enum { - C_CALL, - STD_CALL, - FAST_CALL, -}; - -enum { - INVALID_TYPE, - VOID_TYPE, - FLOAT_TYPE, - DOUBLE_TYPE, - LONG_DOUBLE_TYPE, - COMPLEX_FLOAT_TYPE, - COMPLEX_DOUBLE_TYPE, - COMPLEX_LONG_DOUBLE_TYPE, - BOOL_TYPE, - INT8_TYPE, - INT16_TYPE, - INT32_TYPE, - INT64_TYPE, - INTPTR_TYPE, - ENUM_TYPE, - UNION_TYPE, - STRUCT_TYPE, - FUNCTION_TYPE, - FUNCTION_PTR_TYPE, -}; - -#define IS_CHAR_UNSIGNED (((char) -1) > 0) -#define IS_COMPLEX(type) ((type) == COMPLEX_FLOAT_TYPE || (type) == COMPLEX_DOUBLE_TYPE) - -#define POINTER_BITS 2 -#define POINTER_MAX ((1 << POINTER_BITS) - 1) - -#define ALIGNOF(S) ((int) ((char*) &S.v - (char*) &S - 1)) - -/* Note: if adding a new member that is associated with a struct/union - * definition then it needs to be copied over in ctype.c:set_defined for when - * we create types based off of the declaration alone. - * - * Since this is used as a header for every ctype and cdata, and we create a - * ton of them on the stack, we try and minimise its size. - */ -struct ctype { - size_t base_size; /* size of the base type in bytes */ - - union { - /* valid if is_bitfield */ - struct { - /* size of bitfield in bits */ - unsigned bit_size : 7; - /* offset within the current byte between 0-63 */ - unsigned bit_offset : 6; - }; - /* Valid if is_array */ - size_t array_size; - /* Valid for is_variable_struct or is_variable_array. If - * variable_size_known (only used for is_variable_struct) then this is - * the total increment otherwise this is the per element increment. - */ - size_t variable_increment; - }; - size_t offset; - unsigned align_mask : 4; /* as (align bytes - 1) eg 7 gives 8 byte alignment */ - unsigned pointers : POINTER_BITS; /* number of dereferences to get to the base type including +1 for arrays */ - unsigned const_mask : POINTER_MAX + 1; /* const pointer mask, LSB is current pointer, +1 for the whether the base type is const */ - unsigned type : 5; /* value given by type enum above */ - unsigned is_reference : 1; - unsigned is_array : 1; - unsigned is_defined : 1; - unsigned is_null : 1; - unsigned has_member_name : 1; - unsigned calling_convention : 2; - unsigned has_var_arg : 1; - unsigned is_variable_array : 1; /* set for variable array types where we don't know the variable size yet */ - unsigned is_variable_struct : 1; - unsigned variable_size_known : 1; /* used for variable structs after we know the variable size */ - unsigned is_bitfield : 1; - unsigned has_bitfield : 1; - unsigned is_jitted : 1; - unsigned is_packed : 1; - unsigned is_unsigned : 1; -}; - -#ifdef _MSC_VER -__declspec(align(16)) -#endif -struct cdata { - const struct ctype type -/*#ifdef __GNUC__*/ -/* __attribute__ ((aligned(16)))*/ -/*#endif*/ - ; -}; - -typedef void (*cfunction)(void); - -#ifdef HAVE_COMPLEX -typedef double complex complex_double; -typedef float complex complex_float; -static complex_double mk_complex_double(double real, double imag) { - return real + imag * 1i; -} -static complex_double mk_complex_float(double real, double imag) { - return real + imag * 1i; -} -#else -typedef struct { - double real, imag; -} complex_double; - -typedef struct { - float real, imag; -} complex_float; - -static complex_double mk_complex_double(double real, double imag) { - complex_double ret = { real, imag }; - return ret; -} -static complex_float mk_complex_float(double real, double imag) { - complex_float ret = { real, imag }; - return ret; -} -//#if !defined(__MINGW64__) -static double creal(complex_double c) { - return c.real; -} -static float crealf(complex_float c) { - return c.real; -} - -static double cimag(complex_double c) { - return c.imag; -} -static float cimagf(complex_float c) { - return c.imag; -} -//#endif -#endif - -#define CALLBACK_FUNC_USR_IDX 1 - -void set_defined(lua_State* L, int ct_usr, struct ctype* ct); -struct ctype* push_ctype(lua_State* L, int ct_usr, const struct ctype* ct); -void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct); /* called from asm */ -void push_callback(lua_State* L, cfunction luafunc, cfunction cfunc); -void check_ctype(lua_State* L, int idx, struct ctype* ct); -void* to_cdata(lua_State* L, int idx, struct ctype* ct); -void* check_cdata(lua_State* L, int idx, struct ctype* ct); -size_t ctype_size(lua_State* L, const struct ctype* ct); - -int parse_type(lua_State* L, struct parser* P, struct ctype* type); -void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* type, struct token* name, struct parser* asmname); -void push_type_name(lua_State* L, int usr, const struct ctype* ct); - -int push_user_mt(lua_State* L, int ct_usr, const struct ctype* ct); - -int ffi_cdef(lua_State* L); - -void push_func_ref(lua_State* L, cfunction func); -void free_code(struct jit* jit, lua_State* L, cfunction func); -int x86_return_size(lua_State* L, int usr, const struct ctype* ct); -void compile_function(lua_State* L, cfunction f, int ct_usr, const struct ctype* ct); -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct); -void compile_globals(struct jit* jit, lua_State* L); -int get_extern(struct jit* jit, uint8_t* addr, int idx, int type); - -/* WARNING: assembly needs to be updated for prototype changes of these functions */ -int check_bool(lua_State* L, int idx); -double check_double(lua_State* L, int idx); -double check_complex_imag(lua_State* L, int idx); -float check_float(lua_State* L, int idx); -uint64_t check_uint64(lua_State* L, int idx); -int64_t check_int64(lua_State* L, int idx); -int32_t check_int32(lua_State* L, int idx); -uint32_t check_uint32(lua_State* L, int idx); -uintptr_t check_uintptr(lua_State* L, int idx); -int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* tt); -/* these two will always push a value so that we can create structs/functions on the fly */ -void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt); -cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt); -complex_double check_complex_double(lua_State* L, int idx); -complex_float check_complex_float(lua_State* L, int idx); - -void unpack_varargs_stack(lua_State* L, int first, int last, char* to); -void unpack_varargs_reg(lua_State* L, int first, int last, char* to); - -void unpack_varargs_stack_skip(lua_State* L, int first, int last, int ints_to_skip, int floats_to_skip, char* to); -void unpack_varargs_float(lua_State* L, int first, int last, int max, char* to); -void unpack_varargs_int(lua_State* L, int first, int last, int max, char* to); - - - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/ffi.h.orig b/Build/source/texk/web2c/luatexdir/luaffi/ffi.h.orig deleted file mode 100644 index dabdc9b38bb..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/ffi.h.orig +++ /dev/null @@ -1,455 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#pragma once - -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#ifdef __cplusplus -extern "C" { -# include <lua.h> -# include <lauxlib.h> -# include <lualib.h> -} -# define EXTERN_C extern "C" -#else -# include <lua.h> -# include <lauxlib.h> -# include <lualib.h> -# define EXTERN_C extern -#endif - -#ifdef _WIN32 -#include <windows.h> -#else -#include <errno.h> -#include <unistd.h> -#include <dlfcn.h> -#include <sys/mman.h> -#endif - -#include <complex.h> -#define HAVE_COMPLEX -#define HAVE_LONG_DOUBLE - -#ifndef NDEBUG -#define DASM_CHECKS -#endif - -struct jit; -#define Dst_DECL struct jit* Dst -#define Dst_REF (Dst->ctx) -#define DASM_EXTERN(a,b,c,d) get_extern(a,b,c,d) - -#include "dynasm/dasm_proto.h" - -#if defined LUA_FFI_BUILD_AS_DLL -# define EXPORT __declspec(dllexport) -#elif defined __GNUC__ -# define EXPORT __attribute__((visibility("default"))) -#else -# define EXPORT -#endif - -EXTERN_C EXPORT int luaopen_ffi(lua_State* L); - -static int lua_absindex2(lua_State* L, int idx) { - return (LUA_REGISTRYINDEX <= idx && idx < 0) - ? lua_gettop(L) + idx + 1 - : idx; -} -/* use our own version of lua_absindex such that lua_absindex(L, 0) == 0 */ -#define lua_absindex(L, idx) lua_absindex2(L, idx) - -#if LUA_VERSION_NUM == 501 -static void lua_callk(lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k) -{ - lua_call(L, nargs, nresults); -} -/* -** set functions from list 'l' into table at top - 'nup'; each -** function gets the 'nup' elements at the top as upvalues. -** Returns with only the table at the stack. -*/ -static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup, "too many upvalues"); - for (; l && l->name; l++) { /* fill the table with given functions */ - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} -#define lua_setuservalue lua_setfenv -#define lua_getuservalue lua_getfenv -#define lua_rawlen lua_objlen -static char* luaL_prepbuffsize(luaL_Buffer* B, size_t sz) { - if (sz > LUAL_BUFFERSIZE) { - luaL_error(B->L, "string too long"); - } - return luaL_prepbuffer(B); -} -#elif LUA_VERSION_NUM == 503 -static void (lua_remove)(lua_State *L, int idx) { - lua_remove(L, idx); -} -#endif - -/* architectures */ -#if defined _WIN32 && defined UNDER_CE -# define OS_CE -#elif defined _WIN32 -# define OS_WIN -#elif defined __APPLE__ && defined __MACH__ -# define OS_OSX -#elif defined __linux__ -# define OS_LINUX -#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ -# define OS_BSD -#elif defined unix || defined __unix__ || defined __unix || defined _POSIX_VERSION || defined _XOPEN_VERSION -# define OS_POSIX -#endif - -/* architecture */ -#if defined __i386__ || defined _M_IX86 -# define ARCH_X86 -#elif defined __amd64__ || defined _M_X64 -# define ARCH_X64 -#elif defined __arm__ || defined __ARM__ || defined ARM || defined __ARM || defined __arm || defined __aarch64__ -# define ARCH_ARM -#elif defined __powerpc64__ -# define ARCH_PPC64 -#else -# error -#endif - - -#ifdef _WIN32 - -# ifdef UNDER_CE - static void* DoLoadLibraryA(const char* name) { - wchar_t buf[MAX_PATH]; - int sz = MultiByteToWideChar(CP_UTF8, 0, name, -1, buf, 512); - if (sz > 0) { - buf[sz] = 0; - return LoadLibraryW(buf); - } else { - return NULL; - } - } -# define LoadLibraryA DoLoadLibraryA -# else -# define GetProcAddressA GetProcAddress -# endif - -# define LIB_FORMAT_1 "%s.dll" -# define AllocPage(size) VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE) -# define FreePage(data, size) VirtualFree(data, 0, MEM_RELEASE) -# define EnableExecute(data, size) do {DWORD old; VirtualProtect(data, size, PAGE_EXECUTE, &old); FlushInstructionCache(GetCurrentProcess(), data, size);} while (0) -# define EnableWrite(data, size) do {DWORD old; VirtualProtect(data, size, PAGE_READWRITE, &old);} while (0) - -#else -#ifdef OS_OSX -# define LIB_FORMAT_1 "%s.dylib" -# define LIB_FORMAT_2 "lib%s.dylib" -#else -# define LIB_FORMAT_1 "%s.so" -# define LIB_FORMAT_2 "lib%s.so" -#endif -# define LoadLibraryA(name) dlopen(name, RTLD_LAZY | RTLD_GLOBAL) -# define GetProcAddressA(lib, name) dlsym(lib, name) -# define AllocPage(size) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) -# define FreePage(data, size) munmap(data, size) -# define EnableExecute(data, size) mprotect(data, size, PROT_READ|PROT_EXEC) -# define EnableWrite(data, size) mprotect(data, size, PROT_READ|PROT_WRITE) -#endif - -#if defined ARCH_X86 || defined ARCH_X64 -#define ALLOW_MISALIGNED_ACCESS -#endif - -struct token; - -struct parser { - int line; - const char* next; - const char* prev; - unsigned align_mask; -}; - -struct page { - size_t size; - size_t off; - size_t freed; -}; - -struct jit { - lua_State* L; - int32_t last_errno; - dasm_State* ctx; - size_t pagenum; - struct page** pages; - size_t align_page_size; - void** globals; - int function_extern; - void* lua_dll; - void* kernel32_dll; -}; - -#define ALIGN_DOWN(PTR, MASK) \ - (((uintptr_t) (PTR)) & (~ ((uintptr_t) (MASK)) )) -#define ALIGN_UP(PTR, MASK) \ - (( ((uintptr_t) (PTR)) + ((uintptr_t) (MASK)) ) & (~ ((uintptr_t) (MASK)) )) - -/* struct cdata/struct ctype */ - -#define PTR_ALIGN_MASK (sizeof(void*) - 1) -#define FUNCTION_ALIGN_MASK (sizeof(void (*)()) - 1) -#define DEFAULT_ALIGN_MASK 7 - -#ifdef OS_OSX -/* TODO: figure out why the alignof trick doesn't work on OS X */ -#define ALIGNED_DEFAULT 7 -#elif defined __GNUC__ -#define ALIGNED_DEFAULT (__alignof__(void* __attribute__((aligned))) - 1) -#else -#define ALIGNED_DEFAULT PTR_ALIGN_MASK -#endif - -extern int jit_key; -extern int ctype_mt_key; -extern int cdata_mt_key; -extern int cmodule_mt_key; -extern int callback_mt_key; -extern int constants_key; -extern int types_key; -extern int gc_key; -extern int callbacks_key; -extern int functions_key; -extern int abi_key; -extern int next_unnamed_key; -extern int niluv_key; -extern int asmname_key; - -int equals_upval(lua_State* L, int idx, int* key); -void push_upval(lua_State* L, int* key); -void set_upval(lua_State* L, int* key); -struct jit* get_jit(lua_State* L); - -/* both ctype and cdata are stored as userdatas - * - * usr value is a table shared between the related subtypes which has: - * name -> member ctype (for structs and unions) - * +ves -> member ctype - in memory order (for structs) - * +ves -> argument ctype (for function prototypes) - * 0 -> return ctype (for function prototypes) - * light userdata -> misc - */ - -enum { - C_CALL, - STD_CALL, - FAST_CALL, -}; - -enum { - INVALID_TYPE, - VOID_TYPE, - FLOAT_TYPE, - DOUBLE_TYPE, - LONG_DOUBLE_TYPE, - COMPLEX_FLOAT_TYPE, - COMPLEX_DOUBLE_TYPE, - COMPLEX_LONG_DOUBLE_TYPE, - BOOL_TYPE, - INT8_TYPE, - INT16_TYPE, - INT32_TYPE, - INT64_TYPE, - INTPTR_TYPE, - ENUM_TYPE, - UNION_TYPE, - STRUCT_TYPE, - FUNCTION_TYPE, - FUNCTION_PTR_TYPE, -}; - -#define IS_CHAR_UNSIGNED (((char) -1) > 0) -#define IS_COMPLEX(type) ((type) == COMPLEX_FLOAT_TYPE || (type) == COMPLEX_DOUBLE_TYPE) - -#define POINTER_BITS 2 -#define POINTER_MAX ((1 << POINTER_BITS) - 1) - -#define ALIGNOF(S) ((int) ((char*) &S.v - (char*) &S - 1)) - -/* Note: if adding a new member that is associated with a struct/union - * definition then it needs to be copied over in ctype.c:set_defined for when - * we create types based off of the declaration alone. - * - * Since this is used as a header for every ctype and cdata, and we create a - * ton of them on the stack, we try and minimise its size. - */ -struct ctype { - size_t base_size; /* size of the base type in bytes */ - - union { - /* valid if is_bitfield */ - struct { - /* size of bitfield in bits */ - unsigned bit_size : 7; - /* offset within the current byte between 0-63 */ - unsigned bit_offset : 6; - }; - /* Valid if is_array */ - size_t array_size; - /* Valid for is_variable_struct or is_variable_array. If - * variable_size_known (only used for is_variable_struct) then this is - * the total increment otherwise this is the per element increment. - */ - size_t variable_increment; - }; - size_t offset; - unsigned align_mask : 4; /* as (align bytes - 1) eg 7 gives 8 byte alignment */ - unsigned pointers : POINTER_BITS; /* number of dereferences to get to the base type including +1 for arrays */ - unsigned const_mask : POINTER_MAX + 1; /* const pointer mask, LSB is current pointer, +1 for the whether the base type is const */ - unsigned type : 5; /* value given by type enum above */ - unsigned is_reference : 1; - unsigned is_array : 1; - unsigned is_defined : 1; - unsigned is_null : 1; - unsigned has_member_name : 1; - unsigned calling_convention : 2; - unsigned has_var_arg : 1; - unsigned is_variable_array : 1; /* set for variable array types where we don't know the variable size yet */ - unsigned is_variable_struct : 1; - unsigned variable_size_known : 1; /* used for variable structs after we know the variable size */ - unsigned is_bitfield : 1; - unsigned has_bitfield : 1; - unsigned is_jitted : 1; - unsigned is_packed : 1; - unsigned is_unsigned : 1; -}; - -#ifdef _MSC_VER -__declspec(align(16)) -#endif -struct cdata { - const struct ctype type -#ifdef __GNUC__ - __attribute__ ((aligned(16))) -#endif - ; -}; - -typedef void (*cfunction)(void); - -#ifdef HAVE_COMPLEX -typedef double complex complex_double; -typedef float complex complex_float; -static complex_double mk_complex_double(double real, double imag) { - return real + imag * 1i; -} -static complex_double mk_complex_float(double real, double imag) { - return real + imag * 1i; -} -#else -typedef struct { - double real, imag; -} complex_double; - -typedef struct { - float real, imag; -} complex_float; - -static complex_double mk_complex_double(double real, double imag) { - complex_double ret = { real, imag }; - return ret; -} -static complex_float mk_complex_float(double real, double imag) { - complex_float ret = { real, imag }; - return ret; -} -static double creal(complex_double c) { - return c.real; -} -static float crealf(complex_float c) { - return c.real; -} - -static double cimag(complex_double c) { - return c.imag; -} -static float cimagf(complex_float c) { - return c.imag; -} -#endif - -#define CALLBACK_FUNC_USR_IDX 1 - -void set_defined(lua_State* L, int ct_usr, struct ctype* ct); -struct ctype* push_ctype(lua_State* L, int ct_usr, const struct ctype* ct); -void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct); /* called from asm */ -void push_callback(lua_State* L, cfunction luafunc, cfunction cfunc); -void check_ctype(lua_State* L, int idx, struct ctype* ct); -void* to_cdata(lua_State* L, int idx, struct ctype* ct); -void* check_cdata(lua_State* L, int idx, struct ctype* ct); -size_t ctype_size(lua_State* L, const struct ctype* ct); - -int parse_type(lua_State* L, struct parser* P, struct ctype* type); -void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* type, struct token* name, struct parser* asmname); -void push_type_name(lua_State* L, int usr, const struct ctype* ct); - -int push_user_mt(lua_State* L, int ct_usr, const struct ctype* ct); - -int ffi_cdef(lua_State* L); - -void push_func_ref(lua_State* L, cfunction func); -void free_code(struct jit* jit, lua_State* L, cfunction func); -int x86_return_size(lua_State* L, int usr, const struct ctype* ct); -void compile_function(lua_State* L, cfunction f, int ct_usr, const struct ctype* ct); -cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct); -void compile_globals(struct jit* jit, lua_State* L); -int get_extern(struct jit* jit, uint8_t* addr, int idx, int type); - -/* WARNING: assembly needs to be updated for prototype changes of these functions */ -int check_bool(lua_State* L, int idx); -double check_double(lua_State* L, int idx); -double check_complex_imag(lua_State* L, int idx); -float check_float(lua_State* L, int idx); -uint64_t check_uint64(lua_State* L, int idx); -int64_t check_int64(lua_State* L, int idx); -int32_t check_int32(lua_State* L, int idx); -uint32_t check_uint32(lua_State* L, int idx); -uintptr_t check_uintptr(lua_State* L, int idx); -int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* tt); -/* these two will always push a value so that we can create structs/functions on the fly */ -void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt); -cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt); -complex_double check_complex_double(lua_State* L, int idx); -complex_float check_complex_float(lua_State* L, int idx); - -void unpack_varargs_stack(lua_State* L, int first, int last, char* to); -void unpack_varargs_reg(lua_State* L, int first, int last, char* to); - -void unpack_varargs_stack_skip(lua_State* L, int first, int last, int ints_to_skip, int floats_to_skip, char* to); -void unpack_varargs_float(lua_State* L, int first, int last, int max, char* to); -void unpack_varargs_int(lua_State* L, int first, int last, int max, char* to); - - - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/generate_call_h.bat b/Build/source/texk/web2c/luatexdir/luaffi/generate_call_h.bat deleted file mode 100644 index bb8ce26188c..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/generate_call_h.bat +++ /dev/null @@ -1,4 +0,0 @@ -lua.exe dynasm\dynasm.lua -LNE -D X32WIN -o call_x86.h call_x86.dasc -lua.exe dynasm\dynasm.lua -LNE -D X64 -o call_x64.h call_x86.dasc -lua.exe dynasm\dynasm.lua -LNE -D X64 -D X64WIN -o call_x64win.h call_x86.dasc -lua.exe dynasm\dynasm.lua -LNE -o call_arm.h call_arm.dasc diff --git a/Build/source/texk/web2c/luatexdir/luaffi/luaffi-scm-1.rockspec b/Build/source/texk/web2c/luatexdir/luaffi/luaffi-scm-1.rockspec deleted file mode 100644 index 42cea90e6cb..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/luaffi-scm-1.rockspec +++ /dev/null @@ -1,34 +0,0 @@ -package = "luaffi" -version = "scm-1" - -source = { - url = "git://github.com/facebook/luaffifb.git", -} - -description = { - summary = "FFI library for calling C functions from lua", - detailed = [[ - ]], - homepage = "https://github.com/facebook/luaffifb", - license = "BSD" -} - -dependencies = { - "lua >= 5.1", -} - -build = { - type = "builtin", - modules = { - ['ffi'] = { - incdirs = { - "dynasm" - }, - sources = { - "call.c", "ctype.c", "ffi.c", "parser.c", - } - }, - ['ffi.libtest'] = 'test.c', - ['ffi.test'] = 'test.lua', - } -} diff --git a/Build/source/texk/web2c/luatexdir/luaffi/msvc/inttypes.h b/Build/source/texk/web2c/luatexdir/luaffi/msvc/inttypes.h deleted file mode 100644 index d137c703f41..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/msvc/inttypes.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -/* Signed integers */ -#define PRId8 "d" -#define PRId16 "d" -#define PRId32 "d" -#define PRId64 "I64d" -#define PRIi8 "i" -#define PRIi16 "i" -#define PRIi32 "i" -#define PRIi64 "I64i" - -/* Unsigned integers */ -#define PRIo8 "o" -#define PRIo16 "o" -#define PRIo32 "o" -#define PRIo64 "I64o" -#define PRIu8 "u" -#define PRIu16 "u" -#define PRIu32 "u" -#define PRIu64 "I64u" -#define PRIx8 "x" -#define PRIx16 "x" -#define PRIx32 "x" -#define PRIx64 "I64x" -#define PRIX8 "X" -#define PRIX16 "X" -#define PRIX32 "X" -#define PRIX64 "I64X" -#define PRIxPTR PRIx32 -#define PRIXPTR PRIX32 diff --git a/Build/source/texk/web2c/luatexdir/luaffi/msvc/stdbool.h b/Build/source/texk/web2c/luatexdir/luaffi/msvc/stdbool.h deleted file mode 100644 index 0bf760b0599..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/msvc/stdbool.h +++ /dev/null @@ -1,42 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et - * - * Copyright (c) 2009 James R. McKaskill - * - * This software is licensed under the stock MIT license: - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * ---------------------------------------------------------------------------- - */ - -#pragma once - - -#if defined __cplusplus -typedef bool _Bool; - -#else -#pragma warning(disable:4244) /* conversion from int to _Bool */ -typedef unsigned char _Bool; -#define bool _Bool -#define true 1 -#define false 0 -#define __bool_true_false_are_defined 1 - -#endif diff --git a/Build/source/texk/web2c/luatexdir/luaffi/msvc/stdint.h b/Build/source/texk/web2c/luatexdir/luaffi/msvc/stdint.h deleted file mode 100644 index 627d30eb68b..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/msvc/stdint.h +++ /dev/null @@ -1,174 +0,0 @@ -// boost cstdint.hpp header file ------------------------------------------// - -// (C) Copyright Beman Dawes 1999. -// (C) Copyright Jens Mauer 2001 -// (C) Copyright John Maddock 2001 -// Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/integer for documentation. - -// Revision History -// 31 Oct 01 use BOOST_HAS_LONG_LONG to check for "long long" (Jens M.) -// 16 Apr 01 check LONGLONG_MAX when looking for "long long" (Jens Maurer) -// 23 Jan 01 prefer "long" over "int" for int32_t and intmax_t (Jens Maurer) -// 12 Nov 00 Merged <boost/stdint.h> (Jens Maurer) -// 23 Sep 00 Added INTXX_C macro support (John Maddock). -// 22 Sep 00 Better 64-bit support (John Maddock) -// 29 Jun 00 Reimplement to avoid including stdint.h within namespace boost -// 8 Aug 99 Initial version (Beman Dawes) - - -#ifndef STDINT_H -#define STDINT_H - -#ifndef UNDER_CE -#include <crtdefs.h> -#endif - -#include <limits.h> - -// These are fairly safe guesses for some 16-bit, and most 32-bit and 64-bit -// platforms. For other systems, they will have to be hand tailored. -// -// Because the fast types are assumed to be the same as the undecorated types, -// it may be possible to hand tailor a more efficient implementation. Such -// an optimization may be illusionary; on the Intel x86-family 386 on, for -// example, byte arithmetic and load/stores are as fast as "int" sized ones. - -// 8-bit types ------------------------------------------------------------// - -# if UCHAR_MAX == 0xff - typedef signed char int8_t; - typedef signed char int_least8_t; - typedef signed char int_fast8_t; - typedef unsigned char uint8_t; - typedef unsigned char uint_least8_t; - typedef unsigned char uint_fast8_t; -# else -# error defaults not correct; you must hand modify boost/cstdint.hpp -# endif - -// 16-bit types -----------------------------------------------------------// - -# if USHRT_MAX == 0xffff -# if defined(__crayx1) - // The Cray X1 has a 16-bit short, however it is not recommend - // for use in performance critical code. - typedef short int16_t; - typedef short int_least16_t; - typedef int int_fast16_t; - typedef unsigned short uint16_t; - typedef unsigned short uint_least16_t; - typedef unsigned int uint_fast16_t; -# else - typedef short int16_t; - typedef short int_least16_t; - typedef short int_fast16_t; - typedef unsigned short uint16_t; - typedef unsigned short uint_least16_t; - typedef unsigned short uint_fast16_t; -# endif -# elif (USHRT_MAX == 0xffffffff) && defined(CRAY) - // no 16-bit types on Cray: - typedef short int_least16_t; - typedef short int_fast16_t; - typedef unsigned short uint_least16_t; - typedef unsigned short uint_fast16_t; -# else -# error defaults not correct; you must hand modify boost/cstdint.hpp -# endif - -// 32-bit types -----------------------------------------------------------// - -# if ULONG_MAX == 0xffffffff - typedef long int32_t; - typedef long int_least32_t; - typedef long int_fast32_t; - typedef unsigned long uint32_t; - typedef unsigned long uint_least32_t; - typedef unsigned long uint_fast32_t; -# elif UINT_MAX == 0xffffffff - typedef int int32_t; - typedef int int_least32_t; - typedef int int_fast32_t; - typedef unsigned int uint32_t; - typedef unsigned int uint_least32_t; - typedef unsigned int uint_fast32_t; -# else -# error defaults not correct; you must hand modify boost/cstdint.hpp -# endif - -// 64-bit types + intmax_t and uintmax_t ----------------------------------// - - // - // we have Borland/Intel/Microsoft __int64: - // - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; - typedef __int64 int64_t; - typedef __int64 int_least64_t; - typedef __int64 int_fast64_t; - typedef unsigned __int64 uint64_t; - typedef unsigned __int64 uint_least64_t; - typedef unsigned __int64 uint_fast64_t; - - - -/**************************************************** - -Macro definition section: - -Define various INTXX_C macros only if -__STDC_CONSTANT_MACROS is defined. - -Undefine the macros if __STDC_CONSTANT_MACROS is -not defined and the macros are (cf <cassert>). - -Added 23rd September 2000 (John Maddock). -Modified 11th September 2001 to be excluded when -BOOST_HAS_STDINT_H is defined (John Maddock). - -******************************************************/ - -#if defined(__STDC_CONSTANT_MACROS) || !defined(__cplusplus) -// -// Borland/Intel/Microsoft compilers have width specific suffixes: -// -# define INT8_C(value) value##i8 -# define INT16_C(value) value##i16 -# define INT32_C(value) value##i32 -# define INT64_C(value) value##i64 -# define UINT8_C(value) value##ui8 -# define UINT16_C(value) value##ui16 -# define UINT32_C(value) value##ui32 -# define UINT64_C(value) value##ui64 -# define INTMAX_C(value) value##i64 -# define UINTMAX_C(value) value##ui64 - -#endif // __STDC_CONSTANT_MACROS_DEFINED etc. - -#if defined(__STDC_LIMIT_MACROS) || !defined(__cplusplus) -# define INT8_MIN INT8_C(-127)-1 -# define INT8_MAX INT8_C(127) -# define INT16_MIN INT16_C(-32767)-1 -# define INT16_MAX INT16_C(32767) -# define INT32_MIN INT32_C(-2147483647)-1 -# define INT32_MAX INT32_C(2147483647) -# define INT64_MAX INT64_C(9223372036854775807) -# define UINT8_MAX UINT8_C(255) -# define UINT16_MAX UINT16_C(65535) -# define UINT32_MAX UINT32_C(4294967295) -# define UINT64_MAX UINT64_C(18446744073709551615) -#endif - -#ifdef UNDER_CE -typedef unsigned long uintptr_t; -typedef long intptr_t; -#endif - - - -#endif // BOOST_CSTDINT_HPP - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/msvcbuild.bat b/Build/source/texk/web2c/luatexdir/luaffi/msvcbuild.bat deleted file mode 100644 index 79c11eb19f2..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/msvcbuild.bat +++ /dev/null @@ -1,76 +0,0 @@ -@if not defined INCLUDE goto :FAIL - -@setlocal - -@if "%1"=="debug-5.1" goto :DEBUG_5_1 - -rem These should not have quotes -@set LUA_INCLUDE=Z:\c\lua-5.2.0\src -@set LUA_LIB=Z:\c\lua-5.2.0\lua5.2.lib -@set LUA_EXE=Z:\c\lua-5.2.0\lua.exe -rem This the name of the dll that can be handed to LoadLibrary. This should not have a path. -@set LUA_DLL=lua5.2.dll -@goto :DEBUG - -:DEBUG_5_1 -@set LUA_INCLUDE=Z:\c\lua-5.1.4\src -@set LUA_LIB=Z:\c\lua-5.1.4\lua5.1.lib -@set LUA_EXE=Z:\c\lua-5.1.4\lua.exe -@set LUA_DLL=lua5.1.dll - -:DEBUG -@set DO_CL=cl.exe /nologo /c /MDd /FC /Zi /Od /W3 /WX /D_CRT_SECURE_NO_DEPRECATE /DLUA_FFI_BUILD_AS_DLL /I"msvc" -@set DO_LINK=link /nologo /debug -@set DO_MT=mt /nologo - -@if "%1"=="debug" goto :COMPILE -@if "%1"=="debug-5.1" goto :COMPILE -@if "%1"=="test" goto :COMPILE -@if "%1"=="clean" goto :CLEAN -@if "%1"=="release" goto :RELEASE -@if "%1"=="test-release" goto :RELEASE - -:RELEASE -@set DO_CL=cl.exe /nologo /c /MD /Ox /W3 /Zi /WX /D_CRT_SECURE_NO_DEPRECATE /DLUA_FFI_BUILD_AS_DLL /I"msvc" -@set DO_LINK=link.exe /nologo /debug -@set DO_MT=mt.exe /nologo -@goto :COMPILE - -:COMPILE -"%LUA_EXE%" dynasm\dynasm.lua -LNE -D X32WIN -o call_x86.h call_x86.dasc -"%LUA_EXE%" dynasm\dynasm.lua -LNE -D X64 -o call_x64.h call_x86.dasc -"%LUA_EXE%" dynasm\dynasm.lua -LNE -D X64 -D X64WIN -o call_x64win.h call_x86.dasc -"%LUA_EXE%" dynasm\dynasm.lua -LNE -o call_arm.h call_arm.dasc -%DO_CL% /I"." /I"%LUA_INCLUDE%" /DLUA_DLL_NAME="%LUA_DLL%" call.c ctype.c ffi.c parser.c -%DO_LINK% /DLL /OUT:ffi.dll "%LUA_LIB%" *.obj -if exist ffi.dll.manifest^ - %DO_MT% -manifest ffi.dll.manifest -outputresource:"ffi.dll;2" - -%DO_CL% /Gd test.c /Fo"test_cdecl.obj" -%DO_CL% /Gz test.c /Fo"test_stdcall.obj" -%DO_CL% /Gr test.c /Fo"test_fastcall.obj" -%DO_LINK% /DLL /OUT:test_cdecl.dll test_cdecl.obj -%DO_LINK% /DLL /OUT:test_stdcall.dll test_stdcall.obj -%DO_LINK% /DLL /OUT:test_fastcall.dll test_fastcall.obj -if exist test_cdecl.dll.manifest^ - %DO_MT% -manifest test_cdecl.dll.manifest -outputresource:"test_cdecl.dll;2" -if exist test_stdcall.dll.manifest^ - %DO_MT% -manifest test_stdcall.dll.manifest -outputresource:"test_stdcall.dll;2" -if exist test_fastcall.dll.manifest^ - %DO_MT% -manifest test_fastcall.dll.manifest -outputresource:"test_fastcall.dll;2" - -@if "%1"=="test" "%LUA_EXE%" test.lua -@if "%1"=="test-5.2" "%LUA_EXE%" test.lua -@if "%1"=="test-release" "%LUA_EXE%" test.lua -@goto :CLEAN_OBJ - -:CLEAN -del *.dll -:CLEAN_OBJ -del *.obj *.manifest -@goto :END - -:FAIL -@echo You must open a "Visual Studio .NET Command Prompt" to run this script -:END - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/parser.c b/Build/source/texk/web2c/luatexdir/luaffi/parser.c deleted file mode 100644 index dceb84550b6..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/parser.c +++ /dev/null @@ -1,2618 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#include "ffi.h" - -#define IS_CONST(tok) (IS_LITERAL(tok, "const") || IS_LITERAL(tok, "__const") || IS_LITERAL(tok, "__const__")) -#define IS_VOLATILE(tok) (IS_LITERAL(tok, "volatile") || IS_LITERAL(tok, "__volatile") || IS_LITERAL(tok, "__volatile__")) -#define IS_RESTRICT(tok) (IS_LITERAL(tok, "restrict") || IS_LITERAL(tok, "__restrict") || IS_LITERAL(tok, "__restrict__")) -#define IS_INLINE(tok) (IS_LITERAL(tok, "inline") || IS_LITERAL(tok, "__inline") || IS_LITERAL(tok, "__inline__")) - -enum etoken { - TOK_NIL, - TOK_NUMBER, - TOK_STRING, - TOK_TOKEN, - - /* the order of these values must match the token strings in lex.c */ - - TOK_3_BEGIN, - TOK_VA_ARG, - - TOK_2_BEGIN, - TOK_LEFT_SHIFT, TOK_RIGHT_SHIFT, TOK_LOGICAL_AND, TOK_LOGICAL_OR, TOK_LESS_EQUAL, - TOK_GREATER_EQUAL, TOK_EQUAL, TOK_NOT_EQUAL, - - TOK_1_BEGIN, - TOK_OPEN_CURLY, TOK_CLOSE_CURLY, TOK_SEMICOLON, TOK_COMMA, TOK_COLON, - TOK_ASSIGN, TOK_OPEN_PAREN, TOK_CLOSE_PAREN, TOK_OPEN_SQUARE, TOK_CLOSE_SQUARE, - TOK_DOT, TOK_AMPERSAND, TOK_LOGICAL_NOT, TOK_BITWISE_NOT, TOK_MINUS, - TOK_PLUS, TOK_STAR, TOK_DIVIDE, TOK_MODULUS, TOK_LESS, - TOK_GREATER, TOK_BITWISE_XOR, TOK_BITWISE_OR, TOK_QUESTION, TOK_POUND, - - TOK_REFERENCE = TOK_AMPERSAND, - TOK_MULTIPLY = TOK_STAR, - TOK_BITWISE_AND = TOK_AMPERSAND, -}; - -struct token { - enum etoken type; - int64_t integer; - const char* str; - size_t size; -}; - -#define IS_LITERAL(TOK, STR) \ - (((TOK).size == sizeof(STR) - 1) && 0 == memcmp((TOK).str, STR, sizeof(STR) - 1)) - -/* the order of tokens _must_ match the order of the enum etoken enum */ - -static char tok3[][4] = { - "...", /* unused ">>=", "<<=", */ -}; - -static char tok2[][3] = { - "<<", ">>", "&&", "||", "<=", - ">=", "==", "!=", - /* unused "+=", "-=", "*=", "/=", "%=", "&=", "^=", "|=", "++", "--", "->", "::", */ -}; - -static char tok1[] = { - '{', '}', ';', ',', ':', - '=', '(', ')', '[', ']', - '.', '&', '!', '~', '-', - '+', '*', '/', '%', '<', - '>', '^', '|', '?', '#' -}; - -static int next_token(lua_State* L, struct parser* P, struct token* tok) -{ - size_t i; - const char* s = P->next; - - /* UTF8 BOM */ - if (s[0] == '\xEF' && s[1] == '\xBB' && s[2] == '\xBF') { - s += 3; - } - - /* consume whitespace and comments */ - for (;;) { - /* consume whitespace */ - while(*s == '\t' || *s == '\n' || *s == ' ' || *s == '\v' || *s == '\r') { - if (*s == '\n') { - P->line++; - } - s++; - } - - /* consume comments */ - if (*s == '/' && *(s+1) == '/') { - - s = strchr(s, '\n'); - if (!s) { - luaL_error(L, "non-terminated comment"); - } - - } else if (*s == '/' && *(s+1) == '*') { - s += 2; - - for (;;) { - if (s[0] == '\0') { - luaL_error(L, "non-terminated comment"); - } else if (s[0] == '*' && s[1] == '/') { - s += 2; - break; - } else if (s[0] == '\n') { - P->line++; - } - s++; - } - - } else if (*s == '\0') { - tok->type = TOK_NIL; - return 0; - - } else { - break; - } - } - - P->prev = s; - - for (i = 0; i < sizeof(tok3) / sizeof(tok3[0]); i++) { - if (s[0] == tok3[i][0] && s[1] == tok3[i][1] && s[2] == tok3[i][2]) { - tok->type = (enum etoken) (TOK_3_BEGIN + 1 + i); - P->next = s + 3; - goto end; - } - } - - for (i = 0; i < sizeof(tok2) / sizeof(tok2[0]); i++) { - if (s[0] == tok2[i][0] && s[1] == tok2[i][1]) { - tok->type = (enum etoken) (TOK_2_BEGIN + 1 + i); - P->next = s + 2; - goto end; - } - } - - for (i = 0; i < sizeof(tok1) / sizeof(tok1[0]); i++) { - if (s[0] == tok1[i]) { - tok->type = (enum etoken) (TOK_1_BEGIN + 1 + i); - P->next = s + 1; - goto end; - } - } - - if (*s == '.' || *s == '-' || ('0' <= *s && *s <= '9')) { - /* number */ - tok->type = TOK_NUMBER; - - /* split out the negative case so we get the full range of bits for - * unsigned (eg to support 0xFFFFFFFF where sizeof(long) == 4) - */ - if (*s == '-') { - tok->integer = strtol(s, (char**) &s, 0); - } else { - tok->integer = strtoul(s, (char**) &s, 0); - } - - while (*s == 'u' || *s == 'U' || *s == 'l' || *s == 'L') { - s++; - } - - P->next = s; - goto end; - - } else if (*s == '\'' || *s == '\"') { - /* "..." or '...' */ - char quote = *s; - s++; /* jump over " */ - - tok->type = TOK_STRING; - tok->str = s; - - while (*s != quote) { - - if (*s == '\0' || (*s == '\\' && *(s+1) == '\0')) { - return luaL_error(L, "string not finished"); - } - - if (*s == '\\') { - s++; - } - - s++; - } - - tok->size = s - tok->str; - s++; /* jump over " */ - P->next = s; - goto end; - - } else if (('a' <= *s && *s <= 'z') || ('A' <= *s && *s <= 'Z') || *s == '_') { - /* tokens */ - tok->type = TOK_TOKEN; - tok->str = s; - - while (('a' <= *s && *s <= 'z') || ('A' <= *s && *s <= 'Z') || *s == '_' || ('0' <= *s && *s <= '9')) { - s++; - } - - tok->size = s - tok->str; - P->next = s; - goto end; - - } else { - return luaL_error(L, "invalid character %d", P->line); - } - -end: - /*fprintf(stderr, "token %d %d %.*s %.10s\n", tok->type, (int) tok->size, (tok->type == TOK_TOKEN || tok->type == TOK_STRING) ? (int) tok->size : 0, tok->str, P->next);*/ - return 1; -} - -#define require_token(L, P, tok) require_token_line(L, P, tok, __FILE__, __LINE__) - -static void require_token_line(lua_State* L, struct parser* P, struct token* tok, const char* file, int line) -{ - if (!next_token(L, P, tok)) { - luaL_error(L, "unexpected end on line %s:%d", file, line); - } -} - -static void check_token(lua_State* L, struct parser* P, int type, const char* str, const char* err, ...) -{ - struct token tok; - if (!next_token(L, P, &tok) || tok.type != type || (tok.type == TOK_TOKEN && (tok.size != strlen(str) || memcmp(tok.str, str, tok.size) != 0))) { - va_list ap; - va_start(ap, err); - lua_pushvfstring(L, err, ap); - lua_error(L); - } -} - -static void put_back(struct parser* P) -{ P->next = P->prev; } - - -int64_t calculate_constant(lua_State* L, struct parser* P); - -static int g_name_key; -static int g_front_name_key; -static int g_back_name_key; - -#ifndef max -#define max(a,b) ((a) < (b) ? (b) : (a)) -#endif - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -enum test {TEST}; - -/* Parses an enum definition from after the open curly through to the close - * curly. Expects the user table to be on the top of the stack - */ -static int parse_enum(lua_State* L, struct parser* P, struct ctype* type) -{ - struct token tok; - int value = -1; - int ct_usr = lua_gettop(L); - - for (;;) { - require_token(L, P, &tok); - - assert(lua_gettop(L) == ct_usr); - - if (tok.type == TOK_CLOSE_CURLY) { - break; - } else if (tok.type != TOK_TOKEN) { - return luaL_error(L, "unexpected token in enum at line %d", P->line); - } - - lua_pushlstring(L, tok.str, tok.size); - - require_token(L, P, &tok); - - if (tok.type == TOK_COMMA || tok.type == TOK_CLOSE_CURLY) { - /* we have an auto calculated enum value */ - value++; - } else if (tok.type == TOK_ASSIGN) { - /* we have an explicit enum value */ - value = (int) calculate_constant(L, P); - require_token(L, P, &tok); - } else { - return luaL_error(L, "unexpected token in enum at line %d", P->line); - } - - assert(lua_gettop(L) == ct_usr + 1); - - /* add the enum value to the constants table */ - push_upval(L, &constants_key); - lua_pushvalue(L, -2); - lua_pushinteger(L, value); - lua_rawset(L, -3); - lua_pop(L, 1); - - assert(lua_gettop(L) == ct_usr + 1); - - /* add the enum value to the enum usr value table */ - lua_pushinteger(L, value); - lua_rawset(L, ct_usr); - - if (tok.type == TOK_CLOSE_CURLY) { - break; - } else if (tok.type != TOK_COMMA) { - return luaL_error(L, "unexpected token in enum at line %d", P->line); - } - } - - type->base_size = sizeof(enum test); - type->align_mask = sizeof(enum test) - 1; - - assert(lua_gettop(L) == ct_usr); - return 0; -} - -static void calculate_member_position(lua_State* L, struct parser* P, struct ctype* ct, struct ctype* mt, int* pbit_offset, int* pbitfield_type) -{ - int bit_offset = *pbit_offset; - - if (ct->type == UNION_TYPE) { - size_t msize; - - if (mt->is_variable_struct || mt->is_variable_array) { - luaL_error(L, "NYI: variable sized members in unions"); - return; - - } else if (mt->is_bitfield) { - msize = (mt->align_mask + 1); -#ifdef _WIN32 - /* MSVC has a bug where it doesn't update the alignment of - * a union for bitfield members. */ - mt->align_mask = 0; -#endif - - } else if (mt->is_array) { - msize = mt->array_size * (mt->pointers > 1 ? sizeof(void*) : mt->base_size); - - } else { - msize = mt->pointers ? sizeof(void*) : mt->base_size; - } - - ct->base_size = max(ct->base_size, msize); - - } else if (mt->is_bitfield) { - if (mt->has_member_name && mt->bit_size == 0) { - luaL_error(L, "zero length bitfields must be unnamed on line %d", P->line); - } - -#if defined _WIN32 - /* MSVC uses a seperate storage unit for each size. This is aligned - * before the first bitfield. :0 finishes up the storage unit using - * the greater alignment of the storage unit or the type used with the - * :0. This is equivalent to the :0 always creating a new storage - * unit, but not necesserily using it yet. - */ - - if (*pbitfield_type == -1 && mt->bit_size == 0) { - /* :0 not after a bitfield are ignored */ - return; - } - - { - int different_storage = mt->align_mask != *pbitfield_type; - int no_room_left = bit_offset + mt->bit_size > (mt->align_mask + 1) * CHAR_BIT; - - if (different_storage || no_room_left || !mt->bit_size) { - ct->base_size += (bit_offset + CHAR_BIT - 1) / CHAR_BIT; - bit_offset = 0; - if (*pbitfield_type >= 0) { - ct->base_size = ALIGN_UP(ct->base_size, *pbitfield_type); - } - ct->base_size = ALIGN_UP(ct->base_size, mt->align_mask); - } - } - - mt->bit_offset = bit_offset; - mt->offset = ct->base_size; - - *pbitfield_type = mt->align_mask; - bit_offset += mt->bit_size; - -// #elif defined OS_OSX -// /* OSX doesn't use containers and bitfields are not aligned. So -// * bitfields never add any padding, except for :0 which still forces -// * an alignment based off the type used with the :0 */ -// if (mt->bit_size) { -// mt->offset = ct->base_size; -// mt->bit_offset = bit_offset; -// bit_offset += mt->bit_size; -// ct->base_size += bit_offset / CHAR_BIT; -// bit_offset = bit_offset % CHAR_BIT; -// } else { -// ct->base_size += (bit_offset + CHAR_BIT - 1) / CHAR_BIT; -// ct->base_size = ALIGN_UP(ct->base_size, mt->align_mask); -// bit_offset = 0; -// } - -// if (!mt->has_member_name) { -// /* unnamed bitfields don't update the struct alignment */ -// mt->align_mask = 0; -// } - -#elif defined __GNUC__ - /* GCC tries to pack bitfields in as close as much as possible, but - * still making sure that they don't cross alignment boundaries. - * :0 forces an alignment based off the type used with the :0 - */ - - int bits_used = (ct->base_size - ALIGN_DOWN(ct->base_size, mt->align_mask)) * CHAR_BIT + bit_offset; - int need_to_realign = bits_used + mt->bit_size > mt->base_size * CHAR_BIT; - - if (!mt->is_packed && (!mt->bit_size || need_to_realign)) { - ct->base_size += (bit_offset + CHAR_BIT - 1) / CHAR_BIT; - ct->base_size = ALIGN_UP(ct->base_size, mt->align_mask); - bit_offset = 0; - } - - mt->bit_offset = bit_offset; - mt->offset = ct->base_size; - - bit_offset += mt->bit_size; - ct->base_size += bit_offset / CHAR_BIT; - bit_offset = bit_offset % CHAR_BIT; - - /* unnamed bitfields don't update the struct alignment */ - if (!mt->has_member_name) { - mt->align_mask = 0; - } -#else -#error -#endif - - } else { - /* finish up the current bitfield storage unit */ - ct->base_size += (bit_offset + CHAR_BIT - 1) / CHAR_BIT; - bit_offset = 0; - - if (*pbitfield_type >= 0) { - ct->base_size = ALIGN_UP(ct->base_size, *pbitfield_type); - } - - *pbitfield_type = -1; - - ct->base_size = ALIGN_UP(ct->base_size, mt->align_mask); - mt->offset = ct->base_size; - - if (mt->is_variable_array) { - ct->is_variable_struct = 1; - ct->variable_increment = mt->pointers > 1 ? sizeof(void*) : mt->base_size; - - } else if (mt->is_variable_struct) { - assert(!mt->variable_size_known && !mt->is_array && !mt->pointers); - ct->base_size += mt->base_size; - ct->is_variable_struct = 1; - ct->variable_increment = mt->variable_increment; - - } else if (mt->is_array) { - ct->base_size += mt->array_size * (mt->pointers > 1 ? sizeof(void*) : mt->base_size); - - } else { - ct->base_size += mt->pointers ? sizeof(void*) : mt->base_size; - } - } - - /* increase the outer struct/union alignment if needed */ - if (mt->align_mask > (int) ct->align_mask) { - ct->align_mask = mt->align_mask; - } - - if (mt->has_bitfield || mt->is_bitfield) { - ct->has_bitfield = 1; - } - - *pbit_offset = bit_offset; -} - -static int copy_submembers(lua_State* L, int to_usr, int from_usr, const struct ctype* ft, int* midx) -{ - struct ctype ct; - int i, sublen; - - from_usr = lua_absindex(L, from_usr); - to_usr = lua_absindex(L, to_usr); - - /* integer keys */ - sublen = (int) lua_rawlen(L, from_usr); - for (i = 1; i <= sublen; i++) { - lua_rawgeti(L, from_usr, i); - - ct = *(const struct ctype*) lua_touserdata(L, -1); - ct.offset += ft->offset; - lua_getuservalue(L, -1); - - push_ctype(L, -1, &ct); - lua_rawseti(L, to_usr, (*midx)++); - - lua_pop(L, 2); /* ctype, user value */ - } - - /* string keys */ - lua_pushnil(L); - while (lua_next(L, from_usr)) { - if (lua_type(L, -2) == LUA_TSTRING) { - struct ctype ct = *(const struct ctype*) lua_touserdata(L, -1); - ct.offset += ft->offset; - lua_getuservalue(L, -1); - - /* uservalue[sub_mname] = new_sub_mtype */ - lua_pushvalue(L, -3); - push_ctype(L, -2, &ct); - lua_rawset(L, to_usr); - - lua_pop(L, 1); /* remove submember user value */ - } - lua_pop(L, 1); - } - - return 0; -} - -static int add_member(lua_State* L, int ct_usr, int mname, int mbr_usr, const struct ctype* mt, int* midx) -{ - ct_usr = lua_absindex(L, ct_usr); - mname = lua_absindex(L, mname); - - push_ctype(L, mbr_usr, mt); - - /* usrvalue[mbr index] = pushed mtype */ - lua_pushvalue(L, -1); - lua_rawseti(L, ct_usr, (*midx)++); - - /* set usrvalue[mname] = pushed mtype */ - lua_pushvalue(L, mname); - lua_pushvalue(L, -2); - lua_rawset(L, ct_usr); - - /* set usrvalue[mtype] = mname */ - lua_pushvalue(L, -1); - lua_pushvalue(L, mname); - lua_rawset(L, ct_usr); - - lua_pop(L, 1); - - return 0; -} - -/* Parses a struct from after the open curly through to the close curly. - */ -static int parse_struct(lua_State* L, struct parser* P, int tmp_usr, const struct ctype* ct) -{ - struct token tok; - int midx = 1; - int top = lua_gettop(L); - - tmp_usr = lua_absindex(L, tmp_usr); - - /* parse members */ - for (;;) { - struct ctype mbase; - - assert(lua_gettop(L) == top); - - /* see if we're at the end of the struct */ - require_token(L, P, &tok); - if (tok.type == TOK_CLOSE_CURLY) { - break; - } else if (ct->is_variable_struct) { - return luaL_error(L, "can't have members after a variable sized member on line %d", P->line); - } else { - put_back(P); - } - - /* members are of the form - * <base type> <arg>, <arg>, <arg>; - * eg struct foo bar, *bar2[2]; - * mbase is 'struct foo' - * mtype is '' then '*[2]' - * mname is 'bar' then 'bar2' - */ - - parse_type(L, P, &mbase); - - for (;;) { - struct token mname; - struct ctype mt = mbase; - - memset(&mname, 0, sizeof(mname)); - - if (ct->is_variable_struct) { - return luaL_error(L, "can't have members after a variable sized member on line %d", P->line); - } - - assert(lua_gettop(L) == top + 1); - parse_argument(L, P, -1, &mt, &mname, NULL); - assert(lua_gettop(L) == top + 2); - - if (!mt.is_defined && (mt.pointers - mt.is_array) == 0) { - return luaL_error(L, "member type is undefined on line %d", P->line); - } - - if (mt.type == VOID_TYPE && (mt.pointers - mt.is_array) == 0) { - return luaL_error(L, "member type can not be void on line %d", P->line); - } - - mt.has_member_name = (mname.size > 0); - lua_pushlstring(L, mname.str, mname.size); - - add_member(L, tmp_usr, -1, -2, &mt, &midx); - - /* pop the usr value from push_argument and the member name */ - lua_pop(L, 2); - assert(lua_gettop(L) == top + 1); - - require_token(L, P, &tok); - if (tok.type == TOK_SEMICOLON) { - break; - } else if (tok.type != TOK_COMMA) { - luaL_error(L, "unexpected token in struct definition on line %d", P->line); - } - } - - /* pop the usr value from push_type */ - lua_pop(L, 1); - } - - assert(lua_gettop(L) == top); - return 0; -} - -static int calculate_struct_offsets(lua_State* L, struct parser* P, int ct_usr, struct ctype* ct, int tmp_usr) -{ - int i; - int midx = 1; - int sz = (int) lua_rawlen(L, tmp_usr); - int bit_offset = 0; - int bitfield_type = -1; - - ct_usr = lua_absindex(L, ct_usr); - tmp_usr = lua_absindex(L, tmp_usr); - - for (i = 1; i <= sz; i++) { - struct ctype mt; - - /* get the member type */ - lua_rawgeti(L, tmp_usr, i); - mt = *(const struct ctype*) lua_touserdata(L, -1); - - /* get the member user table */ - lua_getuservalue(L, -1); - - /* get the member name */ - lua_pushvalue(L, -2); - lua_rawget(L, tmp_usr); - - calculate_member_position(L, P, ct, &mt, &bit_offset, &bitfield_type); - - if (mt.has_member_name) { - assert(!lua_isnil(L, -1)); - add_member(L, ct_usr, -1, -2, &mt, &midx); - - } else if (mt.type == STRUCT_TYPE || mt.type == UNION_TYPE) { - /* With an unnamed member we copy all of the submembers into our - * usr value adjusting the offset as necessary. Note ctypes are - * immutable so need to push a new ctype to update the offset. - */ - copy_submembers(L, ct_usr, -2, &mt, &midx); - - } else { - /* We ignore unnamed members that aren't structs or unions. These - * are there just to change the padding */ - } - - lua_pop(L, 3); - } - - /* finish up the current bitfield storage unit */ - ct->base_size += (bit_offset + CHAR_BIT - 1) / CHAR_BIT; - - /* only void is allowed 0 size */ - if (ct->base_size == 0) { - ct->base_size = 1; - } - - ct->base_size = ALIGN_UP(ct->base_size, ct->align_mask); - return 0; -} - -/* copy over attributes that could be specified before the typedef eg - * __attribute__(packed) const type_t */ -static void instantiate_typedef(struct parser* P, struct ctype* tt, const struct ctype* ft) -{ - struct ctype pt = *tt; - *tt = *ft; - - tt->const_mask |= pt.const_mask; - tt->is_packed = pt.is_packed; - - if (tt->is_packed) { - tt->align_mask = 0; - } else { - /* Instantiate the typedef in the current packing. This may be - * further updated if a pointer is added or another alignment - * attribute is applied. If pt.align_mask is already non-zero than an - * increased alignment via __declspec(aligned(#)) has been set. */ - tt->align_mask = max(min(P->align_mask, tt->align_mask), pt.align_mask); - } -} - -/* this parses a struct or union starting with the optional - * name before the opening brace - * leaves the type usr value on the stack - */ -static int parse_record(lua_State* L, struct parser* P, struct ctype* ct) -{ - struct token tok; - int top = lua_gettop(L); - - require_token(L, P, &tok); - - /* name is optional */ - if (tok.type == TOK_TOKEN) { - /* declaration */ - lua_pushlstring(L, tok.str, tok.size); - - assert(lua_gettop(L) == top+1); - - /* lookup the name to see if we've seen this type before */ - push_upval(L, &types_key); - lua_pushvalue(L, -2); - lua_rawget(L, top+2); - - assert(lua_gettop(L) == top+3); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop the nil usr value */ - lua_newtable(L); /* the new usr table */ - - /* stack layout is: - * top+1: record name - * top+2: types table - * top+3: new usr table - */ - - lua_pushlightuserdata(L, &g_name_key); - lua_pushvalue(L, top+1); - lua_rawset(L, top+3); /* usr[name_key] = name */ - - lua_pushvalue(L, top+1); - push_ctype(L, top+3, ct); - lua_rawset(L, top+2); /* types[name] = new_ctype */ - - } else { - /* get the exsting declared type */ - const struct ctype* prevt = (const struct ctype*) lua_touserdata(L, top+3); - - if (prevt->type != ct->type) { - lua_getuservalue(L, top+3); - push_type_name(L, -1, ct); - push_type_name(L, top+3, prevt); - luaL_error(L, "type '%s' previously declared as '%s'", lua_tostring(L, -2), lua_tostring(L, -1)); - } - - instantiate_typedef(P, ct, prevt); - - /* replace the ctype with its usr value */ - lua_getuservalue(L, -1); - lua_replace(L, -2); - } - - /* remove the extra name and types table */ - lua_replace(L, -3); - lua_pop(L, 1); - - assert(lua_gettop(L) == top + 1 && lua_istable(L, -1)); - - /* if a name is given then we may be at the end of the string - * eg for ffi.new('struct foo') - */ - if (!next_token(L, P, &tok)) { - return 0; - } - - } else { - /* create a new unnamed record */ - int num; - - /* get the next unnamed number */ - push_upval(L, &next_unnamed_key); - num = lua_tointeger(L, -1); - lua_pop(L, 1); - - /* increment the unnamed upval */ - lua_pushinteger(L, num + 1); - set_upval(L, &next_unnamed_key); - - lua_newtable(L); /* the new usr table - leave on stack */ - - /* usr[name_key] = num */ - lua_pushlightuserdata(L, &g_name_key); - lua_pushfstring(L, "%d", num); - lua_rawset(L, -3); - } - - if (tok.type != TOK_OPEN_CURLY) { - /* this may just be a declaration or use of the type as an argument or - * member */ - put_back(P); - return 0; - } - - if (ct->is_defined) { - return luaL_error(L, "redefinition in line %d", P->line); - } - - assert(lua_gettop(L) == top + 1 && lua_istable(L, -1)); - - if (ct->type == ENUM_TYPE) { - parse_enum(L, P, ct); - } else { - /* we do a two stage parse, where we parse the content first and build up - * the temp user table. We then iterate over that to calculate the offsets - * and fill out ct_usr. This is so we can handle out of order members - * (eg vtable) and attributes specified at the end of the struct. - */ - lua_newtable(L); - parse_struct(L, P, -1, ct); - calculate_struct_offsets(L, P, -2, ct, -1); - assert(lua_gettop(L) == top + 2 && lua_istable(L, -1)); - lua_pop(L, 1); - } - - assert(lua_gettop(L) == top + 1 && lua_istable(L, -1)); - set_defined(L, -1, ct); - assert(lua_gettop(L) == top + 1); - return 0; -} - -/* parses single or multi work built in types, and pushes it onto the stack */ -static int parse_type_name(lua_State* L, struct parser* P) -{ - struct token tok; - int flags = 0; - - enum { - UNSIGNED = 0x01, - SIGNED = 0x02, - LONG = 0x04, - SHORT = 0x08, - INT = 0x10, - CHAR = 0x20, - LONG_LONG = 0x40, - INT8 = 0x80, - INT16 = 0x100, - INT32 = 0x200, - INT64 = 0x400, - DOUBLE = 0x800, - FLOAT = 0x1000, - COMPLEX = 0x2000, - }; - - require_token(L, P, &tok); - - /* we have to manually decode the builtin types since they can take up - * more then one token - */ - for (;;) { - if (tok.type != TOK_TOKEN) { - break; - } else if (IS_LITERAL(tok, "unsigned")) { - flags |= UNSIGNED; - } else if (IS_LITERAL(tok, "signed")) { - flags |= SIGNED; - } else if (IS_LITERAL(tok, "short")) { - flags |= SHORT; - } else if (IS_LITERAL(tok, "char")) { - flags |= CHAR; - } else if (IS_LITERAL(tok, "long")) { - flags |= (flags & LONG) ? LONG_LONG : LONG; - } else if (IS_LITERAL(tok, "int")) { - flags |= INT; - } else if (IS_LITERAL(tok, "__int8")) { - flags |= INT8; - } else if (IS_LITERAL(tok, "__int16")) { - flags |= INT16; - } else if (IS_LITERAL(tok, "__int32")) { - flags |= INT32; - } else if (IS_LITERAL(tok, "__int64")) { - flags |= INT64; - } else if (IS_LITERAL(tok, "double")) { - flags |= DOUBLE; - } else if (IS_LITERAL(tok, "float")) { - flags |= FLOAT; - } else if (IS_LITERAL(tok, "complex") || IS_LITERAL(tok, "_Complex")) { - flags |= COMPLEX; - } else if (IS_LITERAL(tok, "register")) { - /* ignore */ - } else { - break; - } - - if (!next_token(L, P, &tok)) { - break; - } - } - - if (flags) { - put_back(P); - } - - if (flags & CHAR) { - if (flags & SIGNED) { - lua_pushliteral(L, "int8_t"); - } else if (flags & UNSIGNED) { - lua_pushliteral(L, "uint8_t"); - } else { - lua_pushstring(L, (((char) -1) > 0) ? "uint8_t" : "int8_t"); - } - - } else if (flags & INT8) { - lua_pushstring(L, (flags & UNSIGNED) ? "uint8_t" : "int8_t"); - } else if (flags & INT16) { - lua_pushstring(L, (flags & UNSIGNED) ? "uint16_t" : "int16_t"); - } else if (flags & INT32) { - lua_pushstring(L, (flags & UNSIGNED) ? "uint32_t" : "int32_t"); - } else if (flags & (INT64 | LONG_LONG)) { - lua_pushstring(L, (flags & UNSIGNED) ? "uint64_t" : "int64_t"); - - } else if (flags & COMPLEX) { - if (flags & LONG) { - lua_pushliteral(L, "complex long double"); - } else if (flags & FLOAT) { - lua_pushliteral(L, "complex float"); - } else { - lua_pushliteral(L, "complex double"); - } - - } else if (flags & DOUBLE) { - if (flags & LONG) { - lua_pushliteral(L, "long double"); - } else { - lua_pushliteral(L, "double"); - } - - } else if (flags & FLOAT) { - lua_pushliteral(L, "float"); - - } else if (flags & SHORT) { -#define SHORT_TYPE(u) (sizeof(short) == sizeof(int64_t) ? u "int64_t" : sizeof(short) == sizeof(int32_t) ? u "int32_t" : u "int16_t") - if (flags & UNSIGNED) { - lua_pushstring(L, SHORT_TYPE("u")); - } else { - lua_pushstring(L, SHORT_TYPE("")); - } -#undef SHORT_TYPE - - } else if (flags & LONG) { -#define LONG_TYPE(u) (sizeof(long) == sizeof(int64_t) ? u "int64_t" : u "int32_t") - if (flags & UNSIGNED) { - lua_pushstring(L, LONG_TYPE("u")); - } else { - lua_pushstring(L, LONG_TYPE("")); - } -#undef LONG_TYPE - - } else if (flags) { -#define INT_TYPE(u) (sizeof(int) == sizeof(int64_t) ? u "int64_t" : sizeof(int) == sizeof(int32_t) ? u "int32_t" : u "int16_t") - if (flags & UNSIGNED) { - lua_pushstring(L, INT_TYPE("u")); - } else { - lua_pushstring(L, INT_TYPE("")); - } -#undef INT_TYPE - - } else { - lua_pushlstring(L, tok.str, tok.size); - } - - return 0; -} - -/* parse_attribute parses a token to see if it is an attribute. It may then - * parse some following tokens to decode the attribute setting the appropriate - * fields in ct. It will return 1 if the token was used (and possibly some - * more following it) or 0 if not. If the token was used, the next token must - * be retrieved using next_token/require_token. - */ -static int parse_attribute(lua_State* L, struct parser* P, struct token* tok, struct ctype* ct, struct parser* asmname) -{ - if (tok->type != TOK_TOKEN) { - return 0; - - } else if (asmname && (IS_LITERAL(*tok, "__asm__") || IS_LITERAL(*tok, "__asm"))) { - check_token(L, P, TOK_OPEN_PAREN, NULL, "unexpected token after __asm__ on line %d", P->line); - *asmname = *P; - - require_token(L, P, tok); - while (tok->type == TOK_STRING) { - require_token(L, P, tok); - } - - if (tok->type != TOK_CLOSE_PAREN) { - luaL_error(L, "unexpected token after __asm__ on line %d", P->line); - } - return 1; - - } else if (IS_LITERAL(*tok, "__attribute__") || IS_LITERAL(*tok, "__declspec")) { - int parens = 1; - check_token(L, P, TOK_OPEN_PAREN, NULL, "expected parenthesis after __attribute__ or __declspec on line %d", P->line); - - for (;;) { - require_token(L, P, tok); - if (tok->type == TOK_OPEN_PAREN) { - parens++; - } else if (tok->type == TOK_CLOSE_PAREN) { - if (--parens == 0) { - break; - } - - } else if (tok->type != TOK_TOKEN) { - /* ignore unknown symbols within parentheses */ - - } else if (IS_LITERAL(*tok, "align") || IS_LITERAL(*tok, "aligned") || IS_LITERAL(*tok, "__aligned__")) { - unsigned align = 0; - require_token(L, P, tok); - - switch (tok->type) { - case TOK_CLOSE_PAREN: - align = ALIGNED_DEFAULT; - put_back(P); - break; - - case TOK_OPEN_PAREN: - require_token(L, P, tok); - - if (tok->type != TOK_NUMBER) { - luaL_error(L, "expected align(#) on line %d", P->line); - } - - switch (tok->integer) { - case 1: align = 0; break; - case 2: align = 1; break; - case 4: align = 3; break; - case 8: align = 7; break; - case 16: align = 15; break; - default: - luaL_error(L, "unsupported align size on line %d", P->line); - } - - check_token(L, P, TOK_CLOSE_PAREN, NULL, "expected align(#) on line %d", P->line); - break; - - default: - luaL_error(L, "expected align(#) on line %d", P->line); - } - - /* __attribute__(aligned(#)) is only supposed to increase alignment */ - ct->align_mask = max(align, ct->align_mask); - - } else if (IS_LITERAL(*tok, "packed") || IS_LITERAL(*tok, "__packed__")) { - ct->align_mask = 0; - ct->is_packed = 1; - - } else if (IS_LITERAL(*tok, "mode") || IS_LITERAL(*tok, "__mode__")) { - - check_token(L, P, TOK_OPEN_PAREN, NULL, "expected mode(MODE) on line %d", P->line); - - require_token(L, P, tok); - if (tok->type != TOK_TOKEN) { - luaL_error(L, "expected mode(MODE) on line %d", P->line); - } - - if (ct->type == FLOAT_TYPE || ct->type == DOUBLE_TYPE) { - struct {char ch; float v;} af; - struct {char ch; double v;} ad; - - if (IS_LITERAL(*tok, "SF") || IS_LITERAL(*tok, "__SF__")) { - ct->type = FLOAT_TYPE; - ct->base_size = sizeof(float); - ct->align_mask = ALIGNOF(af); - - } else if (IS_LITERAL(*tok, "DF") || IS_LITERAL(*tok, "__DF__")) { - ct->type = DOUBLE_TYPE; - ct->base_size = sizeof(double); - ct->align_mask = ALIGNOF(ad); - - } else { - luaL_error(L, "unexpected mode on line %d", P->line); - } - - } else { - struct {char ch; uint16_t v;} a16; - struct {char ch; uint32_t v;} a32; - struct {char ch; uint64_t v;} a64; - - if (IS_LITERAL(*tok, "QI") || IS_LITERAL(*tok, "__QI__") - || IS_LITERAL(*tok, "byte") || IS_LITERAL(*tok, "__byte__") - ) { - ct->type = INT8_TYPE; - ct->base_size = sizeof(uint8_t); - ct->align_mask = 0; - - } else if (IS_LITERAL(*tok, "HI") || IS_LITERAL(*tok, "__HI__")) { - ct->type = INT16_TYPE; - ct->base_size = sizeof(uint16_t); - ct->align_mask = ALIGNOF(a16); - - } else if (IS_LITERAL(*tok, "SI") || IS_LITERAL(*tok, "__SI__") -#if defined ARCH_X86 || defined ARCH_ARM - || IS_LITERAL(*tok, "word") || IS_LITERAL(*tok, "__word__") - || IS_LITERAL(*tok, "pointer") || IS_LITERAL(*tok, "__pointer__") -#endif - ) { - ct->type = INT32_TYPE; - ct->base_size = sizeof(uint32_t); - ct->align_mask = ALIGNOF(a32); - - } else if (IS_LITERAL(*tok, "DI") || IS_LITERAL(*tok, "__DI__") -#if defined ARCH_X64 || defined ARCH_PPC64 - || IS_LITERAL(*tok, "word") || IS_LITERAL(*tok, "__word__") - || IS_LITERAL(*tok, "pointer") || IS_LITERAL(*tok, "__pointer__") -#endif - ) { - ct->type = INT64_TYPE; - ct->base_size = sizeof(uint64_t); - ct->align_mask = ALIGNOF(a64); - - } else { - luaL_error(L, "unexpected mode on line %d", P->line); - } - } - - check_token(L, P, TOK_CLOSE_PAREN, NULL, "expected mode(MODE) on line %d", P->line); - - } else if (IS_LITERAL(*tok, "cdecl") || IS_LITERAL(*tok, "__cdecl__")) { - ct->calling_convention = C_CALL; - - } else if (IS_LITERAL(*tok, "fastcall") || IS_LITERAL(*tok, "__fastcall__")) { - ct->calling_convention = FAST_CALL; - - } else if (IS_LITERAL(*tok, "stdcall") || IS_LITERAL(*tok, "__stdcall__")) { - ct->calling_convention = STD_CALL; - } - /* ignore unknown tokens within parentheses */ - } - return 1; - - } else if (IS_LITERAL(*tok, "__cdecl")) { - ct->calling_convention = C_CALL; - return 1; - - } else if (IS_LITERAL(*tok, "__fastcall")) { - ct->calling_convention = FAST_CALL; - return 1; - - } else if (IS_LITERAL(*tok, "__stdcall")) { - ct->calling_convention = STD_CALL; - return 1; - - } else if (IS_LITERAL(*tok, "__extension__") || IS_LITERAL(*tok, "extern")) { - /* ignore */ - return 1; - - } else { - return 0; - } -} - -/* parses out the base type of a type expression in a function declaration, - * struct definition, typedef etc - * - * leaves the usr value of the type on the stack - */ -int parse_type(lua_State* L, struct parser* P, struct ctype* ct) -{ - struct token tok; - int top = lua_gettop(L); - - memset(ct, 0, sizeof(*ct)); - - require_token(L, P, &tok); - - /* get const/volatile before the base type */ - for (;;) { - if (tok.type != TOK_TOKEN) { - return luaL_error(L, "unexpected value before type name on line %d", P->line); - - } else if (IS_CONST(tok)) { - ct->const_mask = 1; - require_token(L, P, &tok); - - } else if (IS_VOLATILE(tok) || - IS_RESTRICT(tok) || - IS_LITERAL(tok, "static") || - IS_INLINE(tok)) { - /* ignored for now */ - require_token(L, P, &tok); - } else if (parse_attribute(L, P, &tok, ct, NULL)) { - /* get function attributes before the return type */ - require_token(L, P, &tok); - - } else { - break; - } - } - - /* get base type */ - if (tok.type != TOK_TOKEN) { - return luaL_error(L, "unexpected value before type name on line %d", P->line); - - } else if (IS_LITERAL(tok, "struct")) { - ct->type = STRUCT_TYPE; - parse_record(L, P, ct); - - } else if (IS_LITERAL(tok, "union")) { - ct->type = UNION_TYPE; - parse_record(L, P, ct); - - } else if (IS_LITERAL(tok, "enum")) { - ct->type = ENUM_TYPE; - parse_record(L, P, ct); - - } else { - put_back(P); - - /* lookup type */ - push_upval(L, &types_key); - parse_type_name(L, P); - lua_rawget(L, -2); - lua_remove(L, -2); - - if (lua_isnil(L, -1)) { - lua_pushlstring(L, tok.str, tok.size); - return luaL_error(L, "unknown type %s on line %d", lua_tostring(L, -1), P->line); - } - - instantiate_typedef(P, ct, (const struct ctype*) lua_touserdata(L, -1)); - - /* we only want the usr tbl from the ctype in the types tbl */ - lua_getuservalue(L, -1); - lua_replace(L, -2); - } - - while (next_token(L, P, &tok)) { - if (tok.type != TOK_TOKEN) { - put_back(P); - break; - - } else if (IS_CONST(tok) || IS_VOLATILE(tok)) { - /* ignore for now */ - - } else { - put_back(P); - break; - } - } - - assert(lua_gettop(L) == top + 1 && (lua_istable(L, -1) || lua_isnil(L, -1))); - return 0; -} - -enum name_type { - BOTH, - FRONT, - BACK, -}; - -static void append_type_name(luaL_Buffer* B, int usr, const struct ctype* ct, enum name_type type) -{ - size_t i; - lua_State* L = B->L; - - usr = lua_absindex(L, usr); - - if (type == FRONT || type == BOTH) { - if (ct->type != FUNCTION_PTR_TYPE && (ct->const_mask & (1 << ct->pointers))) { - luaL_addstring(B, "const "); - } - - if (ct->is_unsigned) { - luaL_addstring(B, "unsigned "); - } - - switch (ct->type) { - case ENUM_TYPE: - luaL_addstring(B, "enum "); - goto get_name; - - case STRUCT_TYPE: - luaL_addstring(B, "struct "); - goto get_name; - - case UNION_TYPE: - luaL_addstring(B, "union "); - goto get_name; - - get_name: - lua_pushlightuserdata(L, &g_name_key); - lua_rawget(L, usr); - luaL_addvalue(B); - break; - - case FUNCTION_TYPE: - case FUNCTION_PTR_TYPE: - lua_pushlightuserdata(L, &g_front_name_key); - lua_rawget(L, usr); - luaL_addvalue(B); - break; - - case VOID_TYPE: - luaL_addstring(B, "void"); - break; - case BOOL_TYPE: - luaL_addstring(B, "bool"); - break; - case DOUBLE_TYPE: - luaL_addstring(B, "double"); - break; - case LONG_DOUBLE_TYPE: - luaL_addstring(B, "long double"); - break; - case FLOAT_TYPE: - luaL_addstring(B, "float"); - break; - case COMPLEX_LONG_DOUBLE_TYPE: - luaL_addstring(B, "long complex double"); - break; - case COMPLEX_DOUBLE_TYPE: - luaL_addstring(B, "complex double"); - break; - case COMPLEX_FLOAT_TYPE: - luaL_addstring(B, "complex float"); - break; - case INT8_TYPE: - luaL_addstring(B, "char"); - break; - case INT16_TYPE: - luaL_addstring(B, "short"); - break; - case INT32_TYPE: - luaL_addstring(B, "int"); - break; - case INT64_TYPE: - luaL_addstring(B, "long long"); - break; - - case INTPTR_TYPE: - if (sizeof(intptr_t) == sizeof(int32_t)) { - luaL_addstring(B, "long"); - } else if (sizeof(intptr_t) == sizeof(int64_t)) { - luaL_addstring(B, "long long"); - } else { - luaL_error(L, "internal error - bad type"); - } - break; - - default: - luaL_error(L, "internal error - bad type %d", ct->type); - } - - for (i = 0; i < ct->pointers - ct->is_array; i++) { - luaL_addchar(B, '*'); - if (ct->const_mask & (1 << (ct->pointers - i - 1))) { - luaL_addstring(B, " const"); - } - } - } - - if (type == BOTH || type == BACK) { - if (ct->is_reference) { - luaL_addstring(B, " &"); - } - - if (ct->is_variable_array && !ct->variable_size_known) { - luaL_addstring(B, "[?]"); - } else if (ct->is_array) { - lua_pushfstring(L, "[%d]", (int) ct->array_size); - luaL_addvalue(B); - } - - if (ct->type == FUNCTION_PTR_TYPE || ct->type == FUNCTION_TYPE) { - lua_pushlightuserdata(L, &g_back_name_key); - lua_rawget(L, usr); - luaL_addvalue(B); - } - - if (ct->is_bitfield) { - lua_pushfstring(L, " : %d", (int) ct->bit_size); - luaL_addvalue(B); - } - } -} - -void push_type_name(lua_State* L, int usr, const struct ctype* ct) -{ - luaL_Buffer B; - usr = lua_absindex(L, usr); - luaL_buffinit(L, &B); - append_type_name(&B, usr, ct, BOTH); - luaL_pushresult(&B); -} - -static void push_function_type_strings(lua_State* L, int usr, const struct ctype* ct) -{ - size_t i, args; - luaL_Buffer B; - int top = lua_gettop(L); - const struct ctype* ret_ct; - - int arg_ct = top+3; - int arg_usr = top+4; - int ret_usr = top+6; - - usr = lua_absindex(L, usr); - - /* return type */ - lua_settop(L, top+4); /* room for two returns and two temp positions */ - lua_rawgeti(L, usr, 0); - lua_getuservalue(L, -1); - ret_ct = (const struct ctype*) lua_touserdata(L, -2); - - luaL_buffinit(L, &B); - append_type_name(&B, ret_usr, ret_ct, FRONT); - - if (ret_ct->type != FUNCTION_TYPE && ret_ct->type != FUNCTION_PTR_TYPE) { - luaL_addchar(&B, ' '); - } - - switch (ct->calling_convention) { - case STD_CALL: - luaL_addstring(&B, "(__stdcall *"); - break; - case FAST_CALL: - luaL_addstring(&B, "(__fastcall *"); - break; - case C_CALL: - luaL_addstring(&B, "(*"); - break; - default: - luaL_error(L, "internal error - unknown calling convention"); - } - - luaL_pushresult(&B); - lua_replace(L, top+1); - - luaL_buffinit(L, &B); - luaL_addstring(&B, ")("); - - /* arguments */ - args = lua_rawlen(L, usr); - for (i = 1; i <= args; i++) { - if (i > 1) { - luaL_addstring(&B, ", "); - } - - /* note push the arg and user value below the indexes used by the buffer - * and use indexes relative to top to avoid problems due to the buffer - * system pushing a variable number of arguments onto the stack */ - lua_rawgeti(L, usr, (int) i); - lua_replace(L, arg_ct); - lua_getuservalue(L, arg_ct); - lua_replace(L, arg_usr); - append_type_name(&B, arg_usr, (const struct ctype*) lua_touserdata(L, arg_ct), BOTH); - } - - luaL_addstring(&B, ")"); - append_type_name(&B, ret_usr, ret_ct, BACK); - luaL_pushresult(&B); - lua_replace(L, top+2); - - lua_settop(L, top+2); - assert(lua_isstring(L, top+1) && lua_isstring(L, top+2)); -} - -/* parses from after the opening paranthesis to after the closing parenthesis */ -static void parse_function_arguments(lua_State* L, struct parser* P, int ct_usr, struct ctype* ct) -{ - struct token tok; - int args = 0; - int top = lua_gettop(L); - - ct_usr = lua_absindex(L, ct_usr); - - for (;;) { - require_token(L, P, &tok); - - if (tok.type == TOK_CLOSE_PAREN) { - break; - } - - if (args) { - if (tok.type != TOK_COMMA) { - luaL_error(L, "unexpected token in function argument %d on line %d", args, P->line); - } - - require_token(L, P, &tok); - } - - if (tok.type == TOK_VA_ARG) { - ct->has_var_arg = true; - check_token(L, P, TOK_CLOSE_PAREN, "", "unexpected token after ... in function on line %d", P->line); - break; - - } else if (tok.type == TOK_TOKEN) { - struct ctype at; - - put_back(P); - parse_type(L, P, &at); - parse_argument(L, P, -1, &at, NULL, NULL); - - assert(lua_gettop(L) == top + 2); - - /* array arguments are just treated as their base pointer type */ - at.is_array = 0; - - /* check for the c style int func(void) and error on other uses of arguments of type void */ - if (at.type == VOID_TYPE && at.pointers == 0) { - if (args) { - luaL_error(L, "can't have argument of type void on line %d", P->line); - } - - check_token(L, P, TOK_CLOSE_PAREN, "", "unexpected void in function on line %d", P->line); - lua_pop(L, 2); - break; - } - - push_ctype(L, -1, &at); - lua_rawseti(L, ct_usr, ++args); - - lua_pop(L, 2); /* parse_type and parse_argument at_usr */ - - } else { - luaL_error(L, "unexpected token in function argument %d on line %d", args+1, P->line); - } - } - - assert(lua_gettop(L) == top); -} - -static int max_bitfield_size(int type) -{ - switch (type) { - case BOOL_TYPE: - return 1; - case INT8_TYPE: - return 8; - case INT16_TYPE: - return 16; - case INT32_TYPE: - case ENUM_TYPE: - return 32; - case INT64_TYPE: - return 64; - default: - return -1; - } -} - -static struct ctype* parse_argument2(lua_State* L, struct parser* P, int ct_usr, struct ctype* ct, struct token* name, struct parser* asmname); - -/* parses from after the first ( in a function declaration or function pointer - * can be one of: - * void foo(...) before ... - * void (foo)(...) before foo - * void (* <>)(...) before <> which is the inner type - */ -static struct ctype* parse_function(lua_State* L, struct parser* P, int ct_usr, struct ctype* ct, struct token* name, struct parser* asmname) -{ - /* We have a function pointer or a function. The usr table will - * get replaced by the canonical one (if there is one) in - * find_canonical_usr after all the arguments and returns have - * been parsed. */ - struct token tok; - int top = lua_gettop(L); - struct ctype* ret; - - lua_newtable(L); - ret = push_ctype(L, ct_usr, ct); - lua_rawseti(L, -2, 0); - ct_usr = lua_gettop(L); - - memset(ct, 0, sizeof(*ct)); - ct->base_size = sizeof(void (*)()); - ct->align_mask = min(FUNCTION_ALIGN_MASK, P->align_mask); - ct->type = FUNCTION_TYPE; - ct->is_defined = 1; - - if (name->type == TOK_NIL) { - for (;;) { - require_token(L, P, &tok); - - if (tok.type == TOK_STAR) { - - if (ct->type == FUNCTION_TYPE) { - ct->type = FUNCTION_PTR_TYPE; - } else if (ct->pointers == POINTER_MAX) { - luaL_error(L, "maximum number of pointer derefs reached - use a struct to break up the pointers on line %d", P->line); - } else { - ct->pointers++; - ct->const_mask <<= 1; - } - - } else if (parse_attribute(L, P, &tok, ct, asmname)) { - /* parse_attribute sets the appropriate fields */ - - } else { - /* call parse_argument to handle the inner contents - * e.g. the <> in "void (* <>) (...)". Note that the - * inner contents can itself be a function, a function - * ptr, array, etc (e.g. "void (*signal(int sig, void - * (*func)(int)))(int)" ). - */ - put_back(P); - ct = parse_argument2(L, P, ct_usr, ct, name, asmname); - break; - } - } - - check_token(L, P, TOK_CLOSE_PAREN, NULL, "unexpected token in function on line %d", P->line); - check_token(L, P, TOK_OPEN_PAREN, NULL, "unexpected token in function on line %d", P->line); - } - - parse_function_arguments(L, P, ct_usr, ct); - - /* if we have an inner function then set the outer function ptr as its - * return type and return the inner function - * e.g. for void (* <signal(int, void (*)(int))> )(int) inner is - * surrounded by <>, return type is void (*)(int) - */ - if (lua_gettop(L) == ct_usr+1) { - lua_replace(L, ct_usr); - } - - assert(lua_gettop(L) == top + 1 && lua_istable(L, -1)); - return ret; -} - -static struct ctype* parse_argument2(lua_State* L, struct parser* P, int ct_usr, struct ctype* ct, struct token* name, struct parser* asmname) -{ - struct token tok; - int top = lua_gettop(L); - int ft_usr = 0; - - luaL_checkstack(L, 10, "function too complex"); - ct_usr = lua_absindex(L, ct_usr); - - for (;;) { - if (!next_token(L, P, &tok)) { - /* we've reached the end of the string */ - break; - - } else if (tok.type == TOK_STAR) { - if (ct->pointers == POINTER_MAX) { - luaL_error(L, "maximum number of pointer derefs reached - use a struct to break up the pointers on line %d", P->line); - } - - ct->pointers++; - ct->const_mask <<= 1; - - /* __declspec(align(#)) may come before the type in a member */ - if (!ct->is_packed) { - ct->align_mask = max(min(PTR_ALIGN_MASK, P->align_mask), ct->align_mask); - } - - } else if (tok.type == TOK_REFERENCE) { - ct->is_reference = 1; - - } else if (parse_attribute(L, P, &tok, ct, asmname)) { - /* parse attribute has filled out appropriate fields in type */ - - } else if (tok.type == TOK_OPEN_PAREN) { - ct = parse_function(L, P, ct_usr, ct, name, asmname); - ft_usr = lua_gettop(L); - - } else if (tok.type == TOK_OPEN_SQUARE) { - /* array */ - if (ct->pointers == POINTER_MAX) { - luaL_error(L, "maximum number of pointer derefs reached - use a struct to break up the pointers"); - } - ct->is_array = 1; - ct->pointers++; - ct->const_mask <<= 1; - require_token(L, P, &tok); - - if (ct->pointers == 1 && !ct->is_defined) { - luaL_error(L, "array of undefined type on line %d", P->line); - } - - if (ct->is_variable_struct || ct->is_variable_array) { - luaL_error(L, "can't have an array of a variably sized type on line %d", P->line); - } - - if (tok.type == TOK_QUESTION) { - ct->is_variable_array = 1; - ct->variable_increment = (ct->pointers > 1) ? sizeof(void*) : ct->base_size; - check_token(L, P, TOK_CLOSE_SQUARE, "", "invalid character in array on line %d", P->line); - - } else if (tok.type == TOK_CLOSE_SQUARE) { - ct->array_size = 0; - - } else if (tok.type == TOK_TOKEN && IS_RESTRICT(tok)) { - /* odd gcc extension foo[__restrict] for arguments */ - ct->array_size = 0; - check_token(L, P, TOK_CLOSE_SQUARE, "", "invalid character in array on line %d", P->line); - - } else { - int64_t asize; - put_back(P); - asize = calculate_constant(L, P); - if (asize < 0) { - luaL_error(L, "array size can not be negative on line %d", P->line); - } - ct->array_size = (size_t) asize; - check_token(L, P, TOK_CLOSE_SQUARE, "", "invalid character in array on line %d", P->line); - } - - } else if (tok.type == TOK_COLON) { - int64_t bsize = calculate_constant(L, P); - - if (ct->pointers || bsize < 0 || bsize > max_bitfield_size(ct->type)) { - luaL_error(L, "invalid bitfield on line %d", P->line); - } - - ct->is_bitfield = 1; - ct->bit_size = (unsigned) bsize; - - } else if (tok.type != TOK_TOKEN) { - /* we've reached the end of the declaration */ - put_back(P); - break; - - } else if (IS_CONST(tok)) { - ct->const_mask |= 1; - - } else if (IS_VOLATILE(tok) || IS_RESTRICT(tok)) { - /* ignored for now */ - - } else { - *name = tok; - } - } - - assert((ft_usr == 0 && lua_gettop(L) == top) || (lua_gettop(L) == top + 1 && ft_usr == top + 1 && (lua_istable(L, -1) || lua_isnil(L, -1)))); - return ct; -} - -static void find_canonical_usr(lua_State* L, int ct_usr, const struct ctype *ct) -{ - struct ctype rt; - int top = lua_gettop(L); - int types; - - if (ct->type != FUNCTION_PTR_TYPE && ct->type != FUNCTION_TYPE) { - return; - } - - luaL_checkstack(L, 10, "function too complex"); - ct_usr = lua_absindex(L, ct_usr); - - /* check to see if we already have the canonical usr table */ - lua_pushlightuserdata(L, &g_name_key); - lua_rawget(L, ct_usr); - if (!lua_isnil(L, -1)) { - lua_pop(L, 1); - assert(top == lua_gettop(L)); - return; - } - lua_pop(L, 1); - - assert(top == lua_gettop(L)); - - /* first canonize the return type */ - lua_rawgeti(L, ct_usr, 0); - rt = *(struct ctype*) lua_touserdata(L, -1); - lua_getuservalue(L, -1); - find_canonical_usr(L, -1, &rt); - push_ctype(L, -1, &rt); - lua_rawseti(L, ct_usr, 0); - lua_pop(L, 2); /* return ctype and usr */ - - assert(top == lua_gettop(L)); - - /* look up the type string in the types table */ - push_upval(L, &types_key); - types = lua_gettop(L); - - push_function_type_strings(L, ct_usr, ct); - lua_pushvalue(L, -2); - lua_pushvalue(L, -2); - lua_concat(L, 2); - - lua_pushvalue(L, -1); - lua_rawget(L, types); - - assert(lua_gettop(L) == types + 4 && types == top + 1); - /* stack: types, front, back, both, looked up value */ - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - - lua_pushlightuserdata(L, &g_front_name_key); - lua_pushvalue(L, -4); - lua_rawset(L, ct_usr); - - lua_pushlightuserdata(L, &g_back_name_key); - lua_pushvalue(L, -3); - lua_rawset(L, ct_usr); - - lua_pushlightuserdata(L, &g_name_key); - lua_pushvalue(L, -2); - lua_rawset(L, ct_usr); - - lua_pushvalue(L, -1); - push_ctype(L, ct_usr, ct); - lua_rawset(L, types); - } else { - lua_getuservalue(L, -1); - lua_replace(L, ct_usr); - lua_pop(L, 1); - } - - lua_pop(L, 4); - assert(top == lua_gettop(L) && types == top + 1); -} - - -/* parses after the main base type of a typedef, function argument or - * struct/union member - * eg for const void* bar[3] the base type is void with the subtype so far of - * const, this parses the "* bar[3]" and updates the type argument - * - * ct_usr and type must be as filled out by parse_type - * - * pushes the updated user value on the top of the stack - */ -void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ct, struct token* pname, struct parser* asmname) -{ - struct token tok, name; - int top = lua_gettop(L); - - memset(&name, 0, sizeof(name)); - parse_argument2(L, P, ct_usr, ct, &name, asmname); - - for (;;) { - if (!next_token(L, P, &tok)) { - break; - } else if (parse_attribute(L, P, &tok, ct, asmname)) { - /* parse_attribute sets the appropriate fields */ - } else { - put_back(P); - break; - } - } - - if (lua_gettop(L) == top) { - lua_pushvalue(L, ct_usr); - } - - find_canonical_usr(L, -1, ct); - - if (pname) { - *pname = name; - } -} - -static void parse_typedef(lua_State* L, struct parser* P) -{ - struct token tok; - struct ctype base_type; - int top = lua_gettop(L); - - parse_type(L, P, &base_type); - - for (;;) { - struct ctype arg_type = base_type; - struct token name; - - memset(&name, 0, sizeof(name)); - - assert(lua_gettop(L) == top + 1); - parse_argument(L, P, -1, &arg_type, &name, NULL); - assert(lua_gettop(L) == top + 2); - - if (!name.size) { - luaL_error(L, "Can't have a typedef without a name on line %d", P->line); - } else if (arg_type.is_variable_array) { - luaL_error(L, "Can't typedef a variable length array on line %d", P->line); - } - - push_upval(L, &types_key); - lua_pushlstring(L, name.str, name.size); - push_ctype(L, -3, &arg_type); - lua_rawset(L, -3); - lua_pop(L, 2); /* types and parse_argument usr tbl */ - - require_token(L, P, &tok); - - if (tok.type == TOK_SEMICOLON) { - break; - } else if (tok.type != TOK_COMMA) { - luaL_error(L, "Unexpected character in typedef on line %d", P->line); - } - } - - lua_pop(L, 1); /* parse_type usr tbl */ - assert(lua_gettop(L) == top); -} - -static bool is_hex(char ch) -{ return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F'); } - -static bool is_digit(char ch) -{ return '0' <= ch && ch <= '9'; } - -static int from_hex(char ch) -{ - if (ch >= 'a') { - return ch - 'a' + 10; - } else if (ch >= 'A') { - return ch - 'A' + 10; - } else { - return ch - '0'; - } -} - -static void push_strings(lua_State* L, struct parser* P) -{ - luaL_Buffer B; - luaL_buffinit(L, &B); - - for (;;) { - const char *p, *e; - char *t, *s; - struct token tok; - - require_token(L, P, &tok); - if (tok.type != TOK_STRING) { - break; - } - - p = tok.str; - e = p + tok.size; - - t = luaL_prepbuffsize(&B, tok.size); - s = t; - - while (p < e) { - if (*p == '\\') { - if (++p == e) { - luaL_error(L, "parse error in string"); - } - switch (*p) { - case '\\': *(t++) = '\\'; p++; break; - case '\"': *(t++) = '\"'; p++; break; - case '\'': *(t++) = '\''; p++; break; - case 'n': *(t++) = '\n'; p++; break; - case 'r': *(t++) = '\r'; p++; break; - case 'b': *(t++) = '\b'; p++; break; - case 't': *(t++) = '\t'; p++; break; - case 'f': *(t++) = '\f'; p++; break; - case 'a': *(t++) = '\a'; p++; break; - case 'v': *(t++) = '\v'; p++; break; - case 'e': *(t++) = 0x1B; p++; break; - case 'x': - { - uint8_t u; - p++; - if (p + 2 > e || !is_hex(p[0]) || !is_hex(p[1])) { - luaL_error(L, "parse error in string"); - } - u = (from_hex(p[0]) << 4) | from_hex(p[1]); - *(t++) = *(char*) &u; - p += 2; - break; - } - default: - { - uint8_t u; - const char* e2 = min(p + 3, e); - if (!is_digit(*p)) { - luaL_error(L, "parse error in string"); - } - u = *p - '0'; - p++; - while (is_digit(*p) && p < e2) { - u = 10*u + *p-'0'; - p++; - } - *(t++) = *(char*) &u; - break; - } - } - } else { - *(t++) = *(p++); - } - } - - luaL_addsize(&B, t-s); - } - - luaL_pushresult(&B); -} - -static void parse_constant_assignemnt(lua_State* L, - struct parser* P, - const struct ctype* type, - const struct token* name) -{ - int64_t val = calculate_constant(L, P); - - check_token(L, P, TOK_SEMICOLON, "", "expected ; after constant definition on line %d", P->line); - - push_upval(L, &constants_key); - lua_pushlstring(L, name->str, name->size); - - switch (type->type) { - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - if (type->is_unsigned) - lua_pushinteger(L, (unsigned int) val); - else - lua_pushinteger(L, (int) val); - break; - - default: - luaL_error(L, "expected a valid 8-, 16-, or 32-bit signed or unsigned integer type after 'static const' on line %d", P->line); - } - - lua_rawset(L, -3); - lua_pop(L, 2); /*constants and type*/ -} - -#define END 0 -#define PRAGMA_POP 1 - -static int parse_root(lua_State* L, struct parser* P) -{ - int top = lua_gettop(L); - struct token tok; - - while (next_token(L, P, &tok)) { - /* we can have: - * struct definition - * enum definition - * union definition - * struct/enum/union declaration - * typedef - * function declaration - * pragma pack - */ - - assert(lua_gettop(L) == top); - - if (tok.type == TOK_SEMICOLON) { - /* empty semicolon in root continue on */ - - } else if (tok.type == TOK_POUND) { - - check_token(L, P, TOK_TOKEN, "pragma", "unexpected pre processor directive on line %d", P->line); - check_token(L, P, TOK_TOKEN, "pack", "unexpected pre processor directive on line %d", P->line); - check_token(L, P, TOK_OPEN_PAREN, "", "invalid pack directive on line %d", P->line); - - require_token(L, P, &tok); - - if (tok.type == TOK_NUMBER) { - if (tok.integer != 1 && tok.integer != 2 && tok.integer != 4 && tok.integer != 8 && tok.integer != 16) { - luaL_error(L, "pack directive with invalid pack size on line %d", P->line); - } - - P->align_mask = (unsigned) (tok.integer - 1); - check_token(L, P, TOK_CLOSE_PAREN, "", "invalid pack directive on line %d", P->line); - - } else if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "push")) { - int line = P->line; - unsigned previous_alignment = P->align_mask; - - check_token(L, P, TOK_CLOSE_PAREN, "", "invalid pack directive on line %d", P->line); - - if (parse_root(L, P) != PRAGMA_POP) { - luaL_error(L, "reached end of string without a pragma pop to match the push on line %d", line); - } - - P->align_mask = previous_alignment; - - } else if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "pop")) { - check_token(L, P, TOK_CLOSE_PAREN, "", "invalid pack directive on line %d", P->line); - return PRAGMA_POP; - - } else { - luaL_error(L, "invalid pack directive on line %d", P->line); - } - - - } else if (tok.type != TOK_TOKEN) { - return luaL_error(L, "unexpected character on line %d", P->line); - - } else if (IS_LITERAL(tok, "__extension__")) { - /* ignore */ - continue; - - } else if (IS_LITERAL(tok, "extern")) { - /* ignore extern as data and functions can only be extern */ - continue; - - } else if (IS_LITERAL(tok, "typedef")) { - parse_typedef(L, P); - - } else { - /* type declaration, type definition, or function declaration */ - struct ctype type; - struct token name; - struct parser asmname; - - memset(&name, 0, sizeof(name)); - memset(&asmname, 0, sizeof(asmname)); - - put_back(P); - parse_type(L, P, &type); - - for (;;) { - parse_argument(L, P, -1, &type, &name, &asmname); - - if (name.size) { - /* global/function declaration */ - - /* set asmname_tbl[name] = asmname */ - if (asmname.next) { - push_upval(L, &asmname_key); - lua_pushlstring(L, name.str, name.size); - push_strings(L, &asmname); - lua_rawset(L, -3); - lua_pop(L, 1); /* asmname upval */ - } - - push_upval(L, &functions_key); - lua_pushlstring(L, name.str, name.size); - push_ctype(L, -3, &type); - lua_rawset(L, -3); - lua_pop(L, 1); /* functions upval */ - } else { - /* type declaration/definition - already been processed */ - } - - lua_pop(L, 1); - - if (!next_token(L, P, &tok)) { - break; - } - - if (tok.type == TOK_COMMA) { - continue; - } - - if (tok.type == TOK_OPEN_CURLY) { - int line = P->line; - int remaining = 1; - while (remaining > 0 && next_token(L, P, &tok)) { - if (tok.type == TOK_CLOSE_CURLY) { - remaining--; - } else if (tok.type == TOK_OPEN_CURLY) { - remaining++; - } - } - if (remaining > 0) { - luaL_error(L, "missing closing bracket for line %d", line); - } - } else if (tok.type == TOK_ASSIGN) { - parse_constant_assignemnt(L, P, &type, &name); - } else if (tok.type != TOK_SEMICOLON) { - luaL_error(L, "missing semicolon on line %d", P->line); - } - break; - } - - lua_pop(L, 1); - } - } - - return END; -} - -int ffi_cdef(lua_State* L) -{ - struct parser P; - - P.line = 1; - P.prev = P.next = luaL_checkstring(L, 1); - P.align_mask = DEFAULT_ALIGN_MASK; - - if (parse_root(L, &P) == PRAGMA_POP) { - luaL_error(L, "pragma pop without an associated push on line %d", P.line); - } - - return 0; -} - -/* calculate_constant handles operator precedence by having a number of - * recursive commands each of which computes the result at that level of - * precedence and above. calculate_constant1 is the highest precedence - */ - -static int64_t string_to_int(const char* str, size_t size) -{ - const char* end = str + size; - char c = *str++; - if (str < end) - { - if (c == '\\') { - c = *str++; - switch (c) { - case '\'': c = '\''; break; - case '\"': c = '\"'; break; - case '\?': c = '\?'; break; - case '\\': c = '\\'; break; - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case 'e': c = 27; break; - case 'x': - c = 0; - while (str < end) { - char d = *str++; - c *= 16; - if (d >= '0' && d <= '9') c += (d - '0'); - else c += (d - 'a' + 10); - } - break; - default: - c = c - '0'; - while (str < end) { - char d = *str++; - c = c*8 + (d - '0'); - } - break; - } - } - } - return c; -} - -static int try_cast(lua_State* L) -{ - struct parser* P = (struct parser*) lua_touserdata(L, 1); - struct ctype ct; - struct token name, tok; - memset(&name, 0, sizeof(name)); - - parse_type(L, P, &ct); - parse_argument(L, P, -1, &ct, &name, NULL); - - require_token(L, P, &tok); - if (tok.type != TOK_CLOSE_PAREN || name.size) { - return luaL_error(L, "invalid cast"); - } - - if (ct.pointers/* || ct.type != INT32_TYPE*/) { - return luaL_error(L, "unsupported cast on line %d", P->line); - } - - return 0; -} - -static int64_t calculate_constant2(lua_State* L, struct parser* P, struct token* tok); - -/* () */ -static int64_t calculate_constant1(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t ret; - - if (tok->type == TOK_NUMBER) { - ret = tok->integer; - next_token(L, P, tok); - return ret; - - } else if (tok->type == TOK_TOKEN) { - /* look up name in constants table */ - push_upval(L, &constants_key); - lua_pushlstring(L, tok->str, tok->size); - lua_rawget(L, -2); - lua_remove(L, -2); /* constants table */ - - if (!lua_isnumber(L, -1)) { - lua_pushlstring(L, tok->str, tok->size); - luaL_error(L, "use of undefined constant %s on line %d", lua_tostring(L, -1), P->line); - } - - ret = (int64_t) lua_tonumber(L, -1); - lua_pop(L, 1); - next_token(L, P, tok); - return ret; - - } else if (tok->type == TOK_OPEN_PAREN) { - struct parser before_cast = *P; - int top = lua_gettop(L); - - /* see if this is a numeric cast, which we ignore */ - lua_pushcfunction(L, &try_cast); - lua_pushlightuserdata(L, P); - if (!lua_pcall(L, 1, 0, 0)) { - next_token(L, P, tok); - return calculate_constant2(L, P, tok); - } - lua_settop(L, top); - - *P = before_cast; - ret = calculate_constant(L, P); - - require_token(L, P, tok); - if (tok->type != TOK_CLOSE_PAREN) { - luaL_error(L, "error whilst parsing constant at line %d", P->line); - } - - next_token(L, P, tok); - return ret; - - } else if (tok->type == TOK_STRING) { - ret = string_to_int(tok->str, tok->size); - - next_token(L, P, tok); - return ret; - - } else { - return luaL_error(L, "unexpected token whilst parsing constant at line %d", P->line); - } -} - -/* ! and ~, unary + and -, and sizeof */ -static int64_t calculate_constant2(lua_State* L, struct parser* P, struct token* tok) -{ - if (tok->type == TOK_LOGICAL_NOT) { - require_token(L, P, tok); - return !calculate_constant2(L, P, tok); - - } else if (tok->type == TOK_BITWISE_NOT) { - require_token(L, P, tok); - return ~calculate_constant2(L, P, tok); - - } else if (tok->type == TOK_PLUS) { - require_token(L, P, tok); - return calculate_constant2(L, P, tok); - - } else if (tok->type == TOK_MINUS) { - require_token(L, P, tok); - return -calculate_constant2(L, P, tok); - - } else if (tok->type == TOK_TOKEN && - (IS_LITERAL(*tok, "sizeof") - || IS_LITERAL(*tok, "alignof") - || IS_LITERAL(*tok, "__alignof__") - || IS_LITERAL(*tok, "__alignof"))) { - - bool issize = IS_LITERAL(*tok, "sizeof"); - struct ctype type; - - require_token(L, P, tok); - if (tok->type != TOK_OPEN_PAREN) { - luaL_error(L, "invalid sizeof at line %d", P->line); - } - - parse_type(L, P, &type); - parse_argument(L, P, -1, &type, NULL, NULL); - lua_pop(L, 2); - - require_token(L, P, tok); - if (tok->type != TOK_CLOSE_PAREN) { - luaL_error(L, "invalid sizeof at line %d", P->line); - } - - next_token(L, P, tok); - - return issize ? ctype_size(L, &type) : type.align_mask + 1; - - } else { - return calculate_constant1(L, P, tok); - } -} - -/* binary * / and % (left associative) */ -static int64_t calculate_constant3(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant2(L, P, tok); - - for (;;) { - if (tok->type == TOK_MULTIPLY) { - require_token(L, P, tok); - left *= calculate_constant2(L, P, tok); - - } else if (tok->type == TOK_DIVIDE) { - require_token(L, P, tok); - left /= calculate_constant2(L, P, tok); - - } else if (tok->type == TOK_MODULUS) { - require_token(L, P, tok); - left %= calculate_constant2(L, P, tok); - - } else { - return left; - } - } -} - -/* binary + and - (left associative) */ -static int64_t calculate_constant4(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant3(L, P, tok); - - for (;;) { - if (tok->type == TOK_PLUS) { - require_token(L, P, tok); - left += calculate_constant3(L, P, tok); - - } else if (tok->type == TOK_MINUS) { - require_token(L, P, tok); - left -= calculate_constant3(L, P, tok); - - } else { - return left; - } - } -} - -/* binary << and >> (left associative) */ -static int64_t calculate_constant5(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant4(L, P, tok); - - for (;;) { - if (tok->type == TOK_LEFT_SHIFT) { - require_token(L, P, tok); - left <<= calculate_constant4(L, P, tok); - - } else if (tok->type == TOK_RIGHT_SHIFT) { - require_token(L, P, tok); - left >>= calculate_constant4(L, P, tok); - - } else { - return left; - } - } -} - -/* binary <, <=, >, and >= (left associative) */ -static int64_t calculate_constant6(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant5(L, P, tok); - - for (;;) { - if (tok->type == TOK_LESS) { - require_token(L, P, tok); - left = (left < calculate_constant5(L, P, tok)); - - } else if (tok->type == TOK_LESS_EQUAL) { - require_token(L, P, tok); - left = (left <= calculate_constant5(L, P, tok)); - - } else if (tok->type == TOK_GREATER) { - require_token(L, P, tok); - left = (left > calculate_constant5(L, P, tok)); - - } else if (tok->type == TOK_GREATER_EQUAL) { - require_token(L, P, tok); - left = (left >= calculate_constant5(L, P, tok)); - - } else { - return left; - } - } -} - -/* binary ==, != (left associative) */ -static int64_t calculate_constant7(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant6(L, P, tok); - - for (;;) { - if (tok->type == TOK_EQUAL) { - require_token(L, P, tok); - left = (left == calculate_constant6(L, P, tok)); - - } else if (tok->type == TOK_NOT_EQUAL) { - require_token(L, P, tok); - left = (left != calculate_constant6(L, P, tok)); - - } else { - return left; - } - } -} - -/* binary & (left associative) */ -static int64_t calculate_constant8(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant7(L, P, tok); - - for (;;) { - if (tok->type == TOK_BITWISE_AND) { - require_token(L, P, tok); - left = (left & calculate_constant7(L, P, tok)); - - } else { - return left; - } - } -} - -/* binary ^ (left associative) */ -static int64_t calculate_constant9(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant8(L, P, tok); - - for (;;) { - if (tok->type == TOK_BITWISE_XOR) { - require_token(L, P, tok); - left = (left ^ calculate_constant8(L, P, tok)); - - } else { - return left; - } - } -} - -/* binary | (left associative) */ -static int64_t calculate_constant10(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant9(L, P, tok); - - for (;;) { - if (tok->type == TOK_BITWISE_OR) { - require_token(L, P, tok); - left = (left | calculate_constant9(L, P, tok)); - - } else { - return left; - } - } -} - -/* binary && (left associative) */ -static int64_t calculate_constant11(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant10(L, P, tok); - - for (;;) { - if (tok->type == TOK_LOGICAL_AND) { - require_token(L, P, tok); - left = (left && calculate_constant10(L, P, tok)); - - } else { - return left; - } - } -} - -/* binary || (left associative) */ -static int64_t calculate_constant12(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant11(L, P, tok); - - for (;;) { - if (tok->type == TOK_LOGICAL_OR) { - require_token(L, P, tok); - left = (left || calculate_constant11(L, P, tok)); - - } else { - return left; - } - } -} - -/* ternary ?: (right associative) */ -static int64_t calculate_constant13(lua_State* L, struct parser* P, struct token* tok) -{ - int64_t left = calculate_constant12(L, P, tok); - - if (tok->type == TOK_QUESTION) { - int64_t middle, right; - require_token(L, P, tok); - middle = calculate_constant13(L, P, tok); - if (tok->type != TOK_COLON) { - luaL_error(L, "invalid ternery (? :) in constant on line %d", P->line); - } - require_token(L, P, tok); - right = calculate_constant13(L, P, tok); - return left ? middle : right; - - } else { - return left; - } -} - -int64_t calculate_constant(lua_State* L, struct parser* P) -{ - struct token tok; - int64_t ret; - require_token(L, P, &tok); - ret = calculate_constant13(L, P, &tok); - - if (tok.type != TOK_NIL) { - put_back(P); - } - - return ret; -} - - - - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/test.c b/Build/source/texk/web2c/luatexdir/luaffi/test.c deleted file mode 100644 index 20f5d136f20..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/test.c +++ /dev/null @@ -1,720 +0,0 @@ -/* vim: ts=4 sw=4 sts=4 et tw=78 - * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. - * Portions copyright (c) 2011 James R. McKaskill. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <stddef.h> -#include <stdbool.h> -#include <stdarg.h> - -#ifdef _WIN32 -#include <windows.h> -#else -#include <errno.h> -#endif - -#include <complex.h> -#define HAVE_COMPLEX - -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C extern -#endif - -#ifdef _WIN32 -#define EXPORT EXTERN_C __declspec(dllexport) -#elif defined __GNUC__ -#define EXPORT EXTERN_C __attribute__((visibility("default"))) -#else -#define EXPORT EXTERN_C -#endif - -enum e8 { - FOO8, - BAR8, -}; -enum e16 { - FOO16 = 1 << 8, - BAR16, - BIG16 = 1 << 14, -}; -enum e32 { - FOO32 = 1 << 16, - BAR32, - BIG32 = 1 << 30, -}; - -EXPORT bool have_complex(); - -bool have_complex() -{ -#ifdef HAVE_COMPLEX - return 1; -#else - return 0; -#endif -} - -EXPORT bool is_msvc; - -bool is_msvc = -#ifdef _MSC_VER - 1; -#else - 0; -#endif - -EXPORT int test_pow(int v); -int test_pow(int v) -{ return v * v; } - -#define ADD(TYPE, NAME) \ - EXPORT TYPE NAME(TYPE a, TYPE b); \ - TYPE NAME(TYPE a, TYPE b) { return a + b; } - -ADD(int8_t, add_i8) -ADD(uint8_t, add_u8) -ADD(int16_t, add_i16) -ADD(uint16_t, add_u16) -ADD(int32_t, add_i32) -ADD(uint32_t, add_u32) -ADD(int64_t, add_i64) -ADD(uint64_t, add_u64) -ADD(double, add_d) -ADD(float, add_f) -#ifdef HAVE_COMPLEX -ADD(double complex, add_dc) -ADD(float complex, add_fc) -#endif - -EXPORT enum e8 inc_e8(enum e8 v); -EXPORT enum e16 inc_e16(enum e16 v); -EXPORT enum e32 inc_e32(enum e32 v); -enum e8 inc_e8(enum e8 v) {return v+1;} -enum e16 inc_e16(enum e16 v) {return v+1;} -enum e32 inc_e32(enum e32 v) {return v+1;} - -EXPORT _Bool not_b(_Bool v); -EXPORT _Bool not_b2(_Bool v); - -_Bool not_b(_Bool v) {return !v;} -_Bool not_b2(_Bool v) {return !v;} - -#define PRINT(TYPE, NAME, FORMAT) \ - EXPORT int NAME(char* buf, TYPE val); \ - int NAME(char* buf, TYPE val) {return sprintf(buf, "%" FORMAT, val);} - -PRINT(int8_t, print_i8, PRId8) -PRINT(uint8_t, print_u8, PRIu8) -PRINT(int16_t, print_i16, PRId16) -PRINT(uint16_t, print_u16, PRIu16) -PRINT(int32_t, print_i32, PRId32) -PRINT(uint32_t, print_u32, PRIu32) -PRINT(int64_t, print_i64, PRId64) -PRINT(uint64_t, print_u64, PRIu64) -PRINT(double, print_d, "g") -PRINT(float, print_f, "g") -PRINT(const char*, print_s, "s") -PRINT(void*, print_p, "p") -PRINT(enum e8, print_e8, "d") -PRINT(enum e16, print_e16, "d") -PRINT(enum e32, print_e32, "d") - -#ifdef HAVE_COMPLEX -EXPORT int print_dc(char* buf, double complex val); -EXPORT int print_fc(char* buf, float complex val); -int print_dc(char* buf, double complex val) {return sprintf(buf, "%g+%gi", creal(val), cimag(val));} -int print_fc(char* buf, float complex val) {return sprintf(buf, "%g+%gi", creal(val), cimag(val));} -#endif - -EXPORT int print_b(char* buf, _Bool val); -EXPORT int print_b2(char* buf, _Bool val); -int print_b(char* buf, _Bool val) {return sprintf(buf, "%s", val ? "true" : "false");} -int print_b2(char* buf, _Bool val) {return sprintf(buf, "%s", val ? "true" : "false");} - -EXPORT bool (*ret_fp(bool (*val)(bool)))(bool); -bool (*ret_fp(bool (*val)(bool)))(bool) -{return val;} - -#define OFFSETOF(STRUCT, MEMBER) ((int) ((char*) &STRUCT.MEMBER - (char*) &S - 1)) - -#define ALIGN_UP(VALUE, ALIGNMENT, SUFFIX) \ - struct align_##ALIGNMENT##_##SUFFIX { \ - char pad; \ - VALUE; \ - }; \ - EXPORT int print_align_##ALIGNMENT##_##SUFFIX(char* buf, struct align_##ALIGNMENT##_##SUFFIX* p); \ - int print_align_##ALIGNMENT##_##SUFFIX(char* buf, struct align_##ALIGNMENT##_##SUFFIX* p) { \ - struct {char ch; struct align_##ALIGNMENT##_##SUFFIX v;} s; \ - int off = sprintf(buf, "size %d offset %d align %d value ", \ - (int) sizeof(s.v), \ - (int) (((char*) &p->v) - (char*) p), \ - (int) (((char*) &s.v) - (char*) &s)); \ - return print_##SUFFIX(buf+off, p->v); \ - } - -#ifdef HAVE_COMPLEX -#define COMPLEX_ALIGN(ALIGNMENT, ATTR) \ - ALIGN_UP(ATTR(double complex), ALIGNMENT, dc) \ - ALIGN_UP(ATTR(float complex), ALIGNMENT, fc) -#else -#define COMPLEX_ALIGN(ALIGNMENT, ATTR) -#endif - -/* MSVC doesn't support __declspec(aligned(#)) on enums see C4329 */ -#define ENUM_ALIGN2(ALIGNMENT, ATTR) \ - ALIGN_UP(ATTR(enum e8), ALIGNMENT, e8) \ - ALIGN_UP(ATTR(enum e16), ALIGNMENT, e16) \ - ALIGN_UP(ATTR(enum e32), ALIGNMENT, e32) \ - -#ifdef _MSC_VER -#define ENUM_ALIGN(ALIGNMENT, ATTR) -#else -#define ENUM_ALIGN(ALIGNMENT, ATTR) ENUM_ALIGN2(ALIGNMENT, ATTR) -#endif - -#define ALIGN2(ALIGNMENT, ATTR) \ - ALIGN_UP(ATTR(uint16_t), ALIGNMENT, u16) \ - ALIGN_UP(ATTR(uint32_t), ALIGNMENT, u32) \ - ALIGN_UP(ATTR(uint64_t), ALIGNMENT, u64) \ - ALIGN_UP(ATTR(float), ALIGNMENT, f) \ - ALIGN_UP(ATTR(double), ALIGNMENT, d) \ - ALIGN_UP(ATTR(const char*), ALIGNMENT, s) \ - ALIGN_UP(ATTR(void*), ALIGNMENT, p) \ - ALIGN_UP(ATTR(_Bool), ALIGNMENT, b) \ - ALIGN_UP(ATTR(_Bool), ALIGNMENT, b2) \ - ENUM_ALIGN(ALIGNMENT, ATTR) \ - COMPLEX_ALIGN(ALIGNMENT, ATTR) - -#define NO_ATTR(TYPE) TYPE v - -#ifdef _MSC_VER -#define ALIGN_NO_ATTR(ALIGNMENT) \ - ALIGN2(ALIGNMENT, NO_ATTR) \ - ENUM_ALIGN2(ALIGNMENT, NO_ATTR) -#else -#define ALIGN_NO_ATTR(ALIGNMENT) \ - ALIGN2(ALIGNMENT, NO_ATTR) -#endif - -ALIGN_NO_ATTR(0) - -#pragma pack(push) -#pragma pack(1) -ALIGN_NO_ATTR(1) -#pragma pack(2) -ALIGN_NO_ATTR(2) -#pragma pack(4) -ALIGN_NO_ATTR(4) -#pragma pack(8) -ALIGN_NO_ATTR(8) -#pragma pack(16) -ALIGN_NO_ATTR(16) -#pragma pack(pop) - -#ifdef _MSC_VER -#define ATTR_(TYPE, ALIGN) __declspec(align(ALIGN)) TYPE v -#else -#define ATTR_(TYPE, ALIGN) TYPE v __attribute__((aligned(ALIGN))) -#endif - -#define ATTR1(TYPE) ATTR_(TYPE, 1) -#define ATTR2(TYPE) ATTR_(TYPE, 2) -#define ATTR4(TYPE) ATTR_(TYPE, 4) -#define ATTR8(TYPE) ATTR_(TYPE, 8) -#define ATTR16(TYPE) ATTR_(TYPE, 16) - -#define ATTR_DEF(TYPE) TYPE v __attribute__((aligned)) - -ALIGN2(attr_1, ATTR1) -ALIGN2(attr_2, ATTR2) -ALIGN2(attr_4, ATTR4) -ALIGN2(attr_8, ATTR8) -ALIGN2(attr_16, ATTR16) - -#ifndef _MSC_VER -ALIGN2(attr_def, ATTR_DEF) -#endif - -#ifdef _MSC_VER -#define alignof(type) __alignof(type) -#else -#define alignof(type) __alignof__(type) -#endif - -EXPORT int max_alignment(); - -int max_alignment() -{ return alignof(struct align_attr_16_p); } - -/* bit_fields1.cpp */ -/* compile with: /LD */ -struct Date { - unsigned short nWeekDay : 3; /* 0..7 (3 bits) */ - unsigned short nMonthDay : 6; /* 0..31 (6 bits) */ - unsigned short nMonth : 5; /* 0..12 (5 bits) */ - unsigned short nYear : 8; /* 0..100 (8 bits) */ -}; - -EXPORT int print_date(size_t* sz, size_t* align, char* buf, struct Date* d); - -int print_date(size_t* sz, size_t* align, char* buf, struct Date* d) { - *sz = sizeof(struct Date); - *align = alignof(struct Date); - return sprintf(buf, "%d %d %d %d", d->nWeekDay, d->nMonthDay, d->nMonth, d->nYear); -} - -/* bit_fields2.cpp */ -/* compile with: /LD */ -struct Date2 { - unsigned nWeekDay : 3; /* 0..7 (3 bits) */ - unsigned nMonthDay : 6; /* 0..31 (6 bits) */ - unsigned : 0; /* Force alignment to next boundary. */ - unsigned nMonth : 5; /* 0..12 (5 bits) */ - unsigned nYear : 8; /* 0..100 (8 bits) */ -}; - -EXPORT int print_date2(size_t* sz, size_t* align, char* buf, struct Date2* d); - -int print_date2(size_t* sz, size_t* align, char* buf, struct Date2* d) { - *sz = sizeof(struct Date2); - *align = alignof(struct Date2); - return sprintf(buf, "%d %d %d %d", d->nWeekDay, d->nMonthDay, d->nMonth, d->nYear); -} - -// Examples from SysV X86 ABI -struct sysv1 { - int j:5; - int k:6; - int m:7; -}; - -EXPORT int print_sysv1(size_t* sz, size_t* align, char* buf, struct sysv1* s); - -int print_sysv1(size_t* sz, size_t* align, char* buf, struct sysv1* s) { - *sz = sizeof(struct sysv1); - *align = alignof(struct sysv1); - return sprintf(buf, "%d %d %d", s->j, s->k, s->m); -} - -struct sysv2 { - short s:9; - int j:9; - char c; - short t:9; - short u:9; - char d; -}; - -EXPORT int print_sysv2(size_t* sz, size_t* align, char* buf, struct sysv2* s); - -int print_sysv2(size_t* sz, size_t* align, char* buf, struct sysv2* s) { - *sz = sizeof(struct sysv2); - *align = alignof(struct sysv2); - return sprintf(buf, "%d %d %d %d %d %d", s->s, s->j, s->c, s->t, s->u, s->d); -} - -struct sysv3 { - char c; - short s:8; -}; - -EXPORT int print_sysv3(size_t* sz, size_t* align, char* buf, struct sysv3* s); - -int print_sysv3(size_t* sz, size_t* align, char* buf, struct sysv3* s) { - *sz = sizeof(struct sysv3); - *align = alignof(struct sysv3); - return sprintf(buf, "%d %d", s->c, s->s); -} - -union sysv4 { - char c; - short s:8; -}; - -EXPORT int print_sysv4(size_t* sz, size_t* align, char* buf, union sysv4* s); - -int print_sysv4(size_t* sz, size_t* align, char* buf, union sysv4* s) { - *sz = sizeof(union sysv4); - *align = alignof(union sysv4); - return sprintf(buf, "%d", s->s); -} - -struct sysv5 { - char c; - int :0; - char d; - short :9; - char e; - char :0; -}; - -EXPORT int print_sysv5(size_t* sz, size_t* align, char* buf, struct sysv5* s); - -int print_sysv5(size_t* sz, size_t* align, char* buf, struct sysv5* s) { - *sz = sizeof(struct sysv5); - *align = alignof(struct sysv5); - return sprintf(buf, "%d %d %d", s->c, s->d, s->e); -} - -struct sysv6 { - char c; - int :0; - char d; - int :9; - char e; -}; - -EXPORT int print_sysv6(size_t* sz, size_t* align, char* buf, struct sysv6* s); - -int print_sysv6(size_t* sz, size_t* align, char* buf, struct sysv6* s) { - *sz = sizeof(struct sysv6); - *align = alignof(struct sysv6); - return sprintf(buf, "%d %d %d", s->c, s->d, s->e); -} - -struct sysv7 { - int j:9; - short s:9; - char c; - short t:9; - short u:9; -}; - -EXPORT int print_sysv7(size_t* sz, size_t* align, char* buf, struct sysv7* s); - -int print_sysv7(size_t* sz, size_t* align, char* buf, struct sysv7* s) { - *sz = sizeof(struct sysv7); - *align = alignof(struct sysv7); - return sprintf(buf, "%d %d %d %d %d", s->j, s->s, s->c, s->t, s->u); -} - -/* Now some targeting bitfield tests */ - -/* Bitfield alignment */ -#define BITALIGN(TNUM,BNUM) \ - struct ba_##TNUM##_##BNUM { \ - char a; \ - uint##TNUM##_t b : BNUM; \ - }; \ - EXPORT int print_ba_##TNUM##_##BNUM(size_t* sz, size_t* align, char* buf, struct ba_##TNUM##_##BNUM* s); \ - int print_ba_##TNUM##_##BNUM(size_t* sz, size_t* align, char* buf, struct ba_##TNUM##_##BNUM* s) { \ - *sz = sizeof(struct ba_##TNUM##_##BNUM); \ - *align = alignof(struct ba_##TNUM##_##BNUM); \ - return sprintf(buf, "%d %d", (int) s->a, (int) s->b); \ - } - -BITALIGN(8,7) -BITALIGN(16,7) -BITALIGN(16,15) -BITALIGN(32,7) -BITALIGN(32,15) -BITALIGN(32,31) -BITALIGN(64,7) -BITALIGN(64,15) -BITALIGN(64,31) -BITALIGN(64,63) - -/* Do unsigned and signed coallesce */ -#define BITCOALESCE(NUM) \ - struct bc##NUM { \ - uint##NUM##_t a : 3; \ - int##NUM##_t b : 3; \ - }; \ - EXPORT int print_bc##NUM(size_t* sz, size_t* align, char* buf, struct bc##NUM* s); \ - int print_bc##NUM(size_t* sz, size_t* align, char* buf, struct bc##NUM* s) { \ - *sz = sizeof(struct bc##NUM); \ - *align = alignof(struct bc##NUM); \ - return sprintf(buf, "%d %d", (int) s->a, (int) s->b); \ - } - -BITCOALESCE(8) -BITCOALESCE(16) -BITCOALESCE(32) -BITCOALESCE(64) - -// Do different sizes coallesce -struct bdsz { - uint8_t a : 3; - uint16_t b : 3; - uint32_t c : 3; - uint64_t d : 3; -}; - -EXPORT int print_bdsz(size_t* sz, size_t* align, char* buf, struct bdsz* s); -int print_bdsz(size_t* sz, size_t* align, char* buf, struct bdsz* s) { - *sz = sizeof(struct bdsz); - *align = alignof(struct bdsz); - return sprintf(buf, "%d %d %d %d", (int) s->a, (int) s->b, (int) s->c, (int) s->d); -} - -// Does coallesence upgrade the storage unit -struct bcup { - uint8_t a : 7; - uint16_t b : 9; - uint32_t c : 17; - uint64_t d : 33; -}; - -EXPORT int print_bcup(size_t* sz, size_t* align, char* buf, struct bcup* s); -int print_bcup(size_t* sz, size_t* align, char* buf, struct bcup* s) { - *sz = sizeof(struct bcup); - *align = alignof(struct bcup); - return sprintf(buf, "%d %d %d %"PRIu64, (int) s->a, (int) s->b, (int) s->c, (uint64_t) s->d); -} - -// Is unaligned access allowed -struct buna { - uint32_t a : 31; - uint32_t b : 31; -}; - -EXPORT int print_buna(size_t* sz, size_t* align, char* buf, struct buna* s); -int print_buna(size_t* sz, size_t* align, char* buf, struct buna* s) { - *sz = sizeof(struct buna); - *align = alignof(struct buna); - return sprintf(buf, "%d %d", (int) s->a, (int) s->b); -} - -/* What does a lone :0 do */ -#define BITLONEZERO(NUM) \ - struct blz##NUM { \ - uint##NUM##_t a; \ - uint##NUM##_t :0; \ - uint##NUM##_t b; \ - }; \ - EXPORT int print_##blz##NUM(size_t* sz, size_t* align, char* buf, struct blz##NUM* s); \ - int print_blz##NUM(size_t* sz, size_t* align, char* buf, struct blz##NUM* s) { \ - *sz = sizeof(struct blz##NUM); \ - *align = alignof(struct blz##NUM); \ - return sprintf(buf, "%d %d", (int) s->a, (int) s->b); \ - } - -BITLONEZERO(8) -BITLONEZERO(16) -BITLONEZERO(32) -BITLONEZERO(64) - -/* What does a :0 or unnamed :# of the same or different type do */ -#define BITZERO(NUM, ZNUM, BNUM) \ - struct bz_##NUM##_##ZNUM##_##BNUM { \ - uint8_t a; \ - uint##NUM##_t b : 3; \ - uint##ZNUM##_t :BNUM; \ - uint##NUM##_t c : 3; \ - }; \ - EXPORT int print_bz_##NUM##_##ZNUM##_##BNUM(size_t* sz, size_t* align, char* buf, struct bz_##NUM##_##ZNUM##_##BNUM* s); \ - int print_bz_##NUM##_##ZNUM##_##BNUM(size_t* sz, size_t* align, char* buf, struct bz_##NUM##_##ZNUM##_##BNUM* s) { \ - *sz = sizeof(struct bz_##NUM##_##ZNUM##_##BNUM); \ - *align = alignof(struct bz_##NUM##_##ZNUM##_##BNUM); \ - return sprintf(buf, "%d %d %d", (int) s->a, (int) s->b, (int) s->c); \ - } - -BITZERO(8,8,0) -BITZERO(8,8,7) -BITZERO(8,16,0) -BITZERO(8,16,7) -BITZERO(8,16,15) -BITZERO(8,32,0) -BITZERO(8,32,7) -BITZERO(8,32,15) -BITZERO(8,32,31) -BITZERO(8,64,0) -BITZERO(8,64,7) -BITZERO(8,64,15) -BITZERO(8,64,31) -BITZERO(8,64,63) -BITZERO(16,8,0) -BITZERO(16,8,7) -BITZERO(16,16,0) -BITZERO(16,16,7) -BITZERO(16,16,15) -BITZERO(16,32,0) -BITZERO(16,32,7) -BITZERO(16,32,15) -BITZERO(16,32,31) -BITZERO(16,64,0) -BITZERO(16,64,7) -BITZERO(16,64,15) -BITZERO(16,64,31) -BITZERO(16,64,63) -BITZERO(32,8,0) -BITZERO(32,8,7) -BITZERO(32,16,0) -BITZERO(32,16,7) -BITZERO(32,16,15) -BITZERO(32,32,0) -BITZERO(32,32,7) -BITZERO(32,32,15) -BITZERO(32,32,31) -BITZERO(32,64,0) -BITZERO(32,64,7) -BITZERO(32,64,15) -BITZERO(32,64,31) -BITZERO(32,64,63) -BITZERO(64,8,0) -BITZERO(64,8,7) -BITZERO(64,16,0) -BITZERO(64,16,7) -BITZERO(64,16,15) -BITZERO(64,32,0) -BITZERO(64,32,7) -BITZERO(64,32,15) -BITZERO(64,32,31) -BITZERO(64,64,0) -BITZERO(64,64,7) -BITZERO(64,64,15) -BITZERO(64,64,31) -BITZERO(64,64,63) - -#define CALL(TYPE, SUFFIX) \ - EXPORT TYPE call_##SUFFIX(TYPE (*func)(TYPE), TYPE arg); \ - TYPE call_##SUFFIX(TYPE (*func)(TYPE), TYPE arg) { \ - return func(arg); \ - } - -CALL(int, i) -CALL(float, f) -CALL(double, d) -CALL(const char*, s) -CALL(_Bool, b) -CALL(enum e8, e8) -CALL(enum e16, e16) -CALL(enum e32, e32) -#ifdef HAVE_COMPLEX -CALL(double complex, dc) -CALL(float complex, fc) -#endif - -struct fptr { -#ifdef _MSC_VER - int (__cdecl *p)(int); -#else - int (*p)(int); -#endif -}; - -EXPORT int call_fptr(struct fptr* s, int val); - -int call_fptr(struct fptr* s, int val) { - return (s->p)(val); -} - -EXPORT bool g_b; -EXPORT int8_t g_i8; -EXPORT int16_t g_i16; -EXPORT int32_t g_i32; -EXPORT int64_t g_i64; -EXPORT uint8_t g_u8; -EXPORT uint16_t g_u16; -EXPORT uint32_t g_u32; -EXPORT uint64_t g_u64; -EXPORT float g_f; -EXPORT double g_d; -#ifdef HAVE_COMPLEX -EXPORT double complex g_dc; -EXPORT float complex g_fc; -#endif -EXPORT bool (*g_fp)(bool); -EXPORT const char g_s[]; -EXPORT const char* g_sp; -EXPORT void* g_p; -EXPORT enum e8 g_e8; -EXPORT enum e16 g_e16; -EXPORT enum e32 g_e32; -EXPORT struct Date g_date; - -bool g_b = true; -int8_t g_i8 = -8; -int16_t g_i16 = -16; -int32_t g_i32 = -32; -int64_t g_i64 = -64; -uint8_t g_u8 = 8; -uint16_t g_u16 = 16; -uint32_t g_u32 = 32; -uint64_t g_u64 = 64; -float g_f = 3; -double g_d = 5; -#ifdef HAVE_COMPLEX -double complex g_dc = 7+8i; -float complex g_fc = 6+9i; -#endif -bool (*g_fp)(bool) = ¬_b; -void* g_p = (void*) ¬_b; -const char g_s[] = "g_s"; -const char* g_sp = "g_sp"; -enum e8 g_e8 = FOO8; -enum e16 g_e16 = FOO16; -enum e32 g_e32 = FOO32; -struct Date g_date = {1,2,3,4}; - -EXPORT void set_errno(int val); -EXPORT int get_errno(void); - -void set_errno(int val) { -#ifdef _WIN32 - SetLastError(val); -#else - errno = val; -#endif -} - -int get_errno(void) { -#ifdef _WIN32 - return GetLastError(); -#else - return errno; -#endif -} - -EXPORT int va_list_size, va_list_align; -int va_list_size = sizeof(va_list); -int va_list_align = alignof(va_list); - - -EXPORT char buf[512]; -char buf[512]; - -EXPORT void test_call_echo(char* c); -void test_call_echo(char* c) -{ - sprintf(buf, "%s", c); -} - -EXPORT void test_call_pppppii(void* a, void* b, void* c, void* d, void* e, int f, int g); -void test_call_pppppii(void* a, void* b, void* c, void* d, void* e, int f, int g) -{ - sprintf(buf, "%p %p %p %p %p %d %d", a, b, c, d, e, f, g); -} - -EXPORT void test_call_pppppiiiiii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, int i3, int i4, int i5, int i6); -void test_call_pppppiiiiii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, int i3, int i4, int i5, int i6) -{ - sprintf(buf, "%p %p %p %p %p %d %d %d %d %d %d", p1, p2, p3, p4, p5, i1, i2, i3, i4, i5, i6); -} - -EXPORT void test_call_pppppffffff(void* p1, void* p2, void* p3, void* p4, void* p5, float f1, float f2, float f3, float f4, float f5, float f6); -void test_call_pppppffffff(void* p1, void* p2, void* p3, void* p4, void* p5, float f1, float f2, float f3, float f4, float f5, float f6) -{ - sprintf(buf, "%p %p %p %p %p %0.1f %0.1f %0.1f %0.1f %0.1f %0.1f", p1, p2, p3, p4, p5, f1, f2, f3, f4, f5, f6); -} - -EXPORT void test_call_pppppiifiii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, float f3, int i4, int i5, int i6); -void test_call_pppppiifiii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, float f3, int i4, int i5, int i6) -{ - sprintf(buf, "%p %p %p %p %p %d %d %0.1f %d %d %d", p1, p2, p3, p4, p5, i1, i2, f3, i4, i5, i6); -} - -EXPORT void test_call_pppppiiifii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, int i3, float f4, int i5, int i6); -void test_call_pppppiiifii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, int i3, float f4, int i5, int i6) -{ - sprintf(buf, "%p %p %p %p %p %d %d %d %0.1f %d %d", p1, p2, p3, p4, p5, i1, i2, i3, f4, i5, i6); -} - diff --git a/Build/source/texk/web2c/luatexdir/luaffi/test.lua b/Build/source/texk/web2c/luatexdir/luaffi/test.lua deleted file mode 100644 index 8a9b7189f04..00000000000 --- a/Build/source/texk/web2c/luatexdir/luaffi/test.lua +++ /dev/null @@ -1,1003 +0,0 @@ --- vim: ts=4 sw=4 sts=4 et tw=78 --- Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. --- Portions copyright (c) 2011 James R. McKaskill. --- --- This source code is licensed under the BSD-style license found in the --- LICENSE file in the root directory of this source tree. An additional grant --- of patent rights can be found in the PATENTS file in the same directory. --- -io.stdout:setvbuf('no') -local ffi = require 'ffi' -local dlls = {} - -local function loadlib(lib) - for pattern in package.cpath:gmatch('[^;]+') do - local path = pattern:gsub('?', lib) - local ok, lib = pcall(ffi.load, path) - if ok then - return lib - end - end - error("Unable to load", lib) -end - -if _VERSION == 'Lua 5.1' then - dlls.__cdecl = loadlib('ffi/libtest') -else - dlls.__cdecl = ffi.load(package.searchpath('ffi.libtest', package.cpath)) -end - -if ffi.arch == 'x86' and ffi.os == 'Windows' then - dlls.__stdcall = ffi.load('test_stdcall') - dlls.__fastcall = ffi.load('test_fastcall') -end - -local function check(a, b, msg) - if a ~= b then - print('check', a, b) - end - return _G.assert(a == b, msg) -end - -print('Running test') - -ffi.cdef [[ -enum e8 { - FOO8, - BAR8, -}; -enum e16 { - FOO16 = 1 << 8, - BAR16, - BIG16 = 1 << 14, -}; -enum e32 { - FOO32 = 1 << 16, - BAR32, - BIG32 = 1 << 30, -}; -int max_alignment(); -bool is_msvc, is_msvc2 __asm__("is_msvc"); -bool have_complex(void); -bool have_complex2() __asm__("have" /*foo*/ "\x5F" "complex"); // 5F is _ - -int8_t add_i8(int8_t a, int8_t b); -uint8_t add_u8(uint8_t a, uint8_t b); -int16_t add_i16(int16_t a, int16_t b); -uint16_t add_i16(uint16_t a, uint16_t b); -int32_t add_i32(int32_t a, int32_t b); -uint32_t add_u32(uint32_t a, uint32_t b); -int64_t add_i64(int64_t a, int64_t b); -uint64_t add_u64(uint64_t a, uint64_t b); -double add_d(double a, double b); -float add_f(float a, float b); -double complex add_dc(double complex a, double complex b); -float complex add_fc(float complex a, float complex b); -enum e8 inc_e8(enum e8); -enum e16 inc_e16(enum e16); -enum e32 inc_e32(enum e32); -bool not_b(bool v); -_Bool not_b2(_Bool v); -typedef bool (*fp)(bool); -fp ret_fp(fp v); -bool (*ret_fp2(bool (*)(bool)))(bool) __asm("ret_fp"); - -int print_i8(char* buf, int8_t val); -int print_u8(char* buf, uint8_t val); -int print_i16(char* buf, int16_t val); -int print_u16(char* buf, uint16_t val); -int print_i32(char* buf, int32_t val); -int print_u32(char* buf, uint32_t val); -int print_i64(char* buf, int64_t val); -int print_u64(char* buf, uint64_t val); -int print_s(char* buf, const char* val); -int print_b(char* buf, bool val); -int print_b2(char* buf, _Bool val); -int print_d(char* buf, double val); -int print_f(char* buf, float val); -int print_p(char* buf, void* val); -int print_dc(char* buf, double complex val); -int print_fc(char* buf, float complex val); -int print_e8(char* buf, enum e8 val); -int print_e16(char* buf, enum e16 val); -int print_e32(char* buf, enum e32 val); -int sprintf(char* buf, const char* format, ...); - -// Examples from MSDN - -// bit_fields1.cpp -// compile with: /LD -struct Date { - unsigned short nWeekDay : 3; // 0..7 (3 bits) - unsigned short nMonthDay : 6; // 0..31 (6 bits) - unsigned short nMonth : 5; // 0..12 (5 bits) - unsigned short nYear : 8; // 0..100 (8 bits) -}; - -// bit_fields2.cpp -// compile with: /LD -struct Date2 { - unsigned nWeekDay : 3; // 0..7 (3 bits) - unsigned nMonthDay : 6; // 0..31 (6 bits) - unsigned : 0; // Force alignment to next boundary. - unsigned nMonth : 5; // 0..12 (5 bits) - unsigned nYear : 8; // 0..100 (8 bits) -}; - -// For checking the alignment of short bitfields -struct Date3 { - char pad; - unsigned short nWeekDay : 3; // 0..7 (3 bits) - unsigned short nMonthDay : 6; // 0..31 (6 bits) - unsigned short nMonth : 5; // 0..12 (5 bits) - unsigned short nYear : 8; // 0..100 (8 bits) -}; - -// For checking the alignment and container of int64 bitfields -struct bit64 { - char pad; - uint64_t a : 15; - uint64_t b : 14; - uint64_t c : 13; - uint64_t d : 12; -}; - -// Examples from SysV X86 ABI -struct sysv1 { - int j:5; - int k:6; - int m:7; -}; - -struct sysv2 { - short s:9; - int j:9; - char c; - short t:9; - short u:9; - char d; -}; - -struct sysv3 { - char c; - short s:8; -}; - -union sysv4 { - char c; - short s:8; -}; - -struct sysv5 { - char c; - int :0; - char d; - short :9; - char e; - char :0; -}; - -struct sysv6 { - char c; - int :0; - char d; - int :9; - char e; -}; - -struct sysv7 { - int j:9; - short s:9; - char c; - short t:9; - short u:9; -}; - -int print_date(size_t* sz, size_t* align, char* buf, struct Date* s); -int print_date2(size_t* sz, size_t* align, char* buf, struct Date2* s); -int print_date3(size_t* sz, size_t* align, char* buf, struct Date3* d); -int print_bit64(size_t* sz, size_t* align, char* buf, struct bit64* d); -int print_sysv1(size_t* sz, size_t* align, char* buf, struct sysv1* s); -int print_sysv2(size_t* sz, size_t* align, char* buf, struct sysv2* s); -int print_sysv3(size_t* sz, size_t* align, char* buf, struct sysv3* s); -int print_sysv4(size_t* sz, size_t* align, char* buf, union sysv4* s); -int print_sysv5(size_t* sz, size_t* align, char* buf, struct sysv5* s); -int print_sysv6(size_t* sz, size_t* align, char* buf, struct sysv6* s); -int print_sysv7(size_t* sz, size_t* align, char* buf, struct sysv7* s); - -struct fptr { - int (__cdecl *p)(int); -}; -int call_fptr(struct fptr* s, int val); - -bool g_b; -int8_t g_i8; -int16_t g_i16; -int32_t g_i32; -int64_t g_i64; -uint8_t g_u8; -uint16_t g_u16; -uint32_t g_u32; -uint64_t g_u64; -float g_f; -double g_d; -double complex g_dc; -float complex g_fc; -bool (*g_fp)(bool); -const char g_s[]; -const char* g_sp; -void* g_p; -enum e8 g_e8; -enum e16 g_e16; -enum e32 g_e32; -struct Date g_date; - -void set_errno(int val); -int get_errno(void); -]] - -local align = [[ -struct align_ALIGN_SUFFIX { - char pad; - TYPE v; -}; - -int print_align_ALIGN_SUFFIX(char* buf, struct align_ALIGN_SUFFIX* p); -]] - -local palign = [[ -#pragma pack(push) -#pragma pack(ALIGN) -]] .. align .. [[ -#pragma pack(pop) -]] - -local bitfields = [[ -struct bcTNUM { - uintTNUM_t a : 3; - intTNUM_t b : 3; -}; -struct blzTNUM { - uintTNUM_t a; - uintTNUM_t :0; - uintTNUM_t b; -}; -int print_bcTNUM(size_t* sz, size_t* align, char* buf, struct bcTNUM* s); -int print_blzTNUM(size_t* sz, size_t* align, char* buf, struct blzTNUM* s); -]] - -local bitalign = [[ -struct ba_TNUM_BNUM { - char a; - uintTNUM_t b : BNUM; -}; -struct bu_TNUM_BNUM { - char a; - uintTNUM_t :BNUM; - char b; -}; -int print_ba_TNUM_BNUM(size_t* sz, size_t* align, char* buf, struct ba_TNUM_BNUM* s); -]] - -local bitzero = [[ -struct bz_TNUM_ZNUM_BNUM { - uint8_t a; - uintTNUM_t b : 3; - uintZNUM_t :BNUM; - uintTNUM_t c : 3; -}; -int print_bz_TNUM_ZNUM_BNUM(size_t* sz, size_t* align, char* buf, struct bz_TNUM_ZNUM_BNUM* s); -]] - -local i = ffi.C.i -local test_values = { - ['void*'] = ffi.new('char[3]'), - ['const char*'] = 'foo', - float = 3.4, - double = 5.6, - uint16_t = 65000, - uint32_t = ffi.new('uint32_t', 700000056), - uint64_t = 12345678901234, - bool = true, - _Bool = false, - ['float complex'] = 3.1+4.2*i, - ['double complex'] = 5.1+6.2*i, - ['enum e8'] = ffi.C.FOO8, - ['enum e16'] = ffi.C.FOO16, - ['enum e32'] = ffi.C.FOO32, -} - -local types = { - b = 'bool', - b2 = '_Bool', - d = 'double', - f = 'float', - u64 = 'uint64_t', - u32 = 'uint32_t', - u16 = 'uint16_t', - s = 'const char*', - p = 'void*', - e8 = 'enum e8', - e16 = 'enum e16', - e32 = 'enum e32', -} - -local buf = ffi.new('char[256]') - -local function checkbuf(type, ret, msg) - local str = tostring(test_values[type]):gsub('^cdata%b<>: ', '') - check(ffi.string(buf), str, msg) - check(ret, #str, msg) -end - -local function checkalign(type, v, ret) - --print(v) - local str = tostring(test_values[type]):gsub('^cdata%b<>: ', '') - check(ffi.string(buf), ('size %d offset %d align %d value %s'):format(ffi.sizeof(v), ffi.offsetof(v, 'v'), ffi.alignof(v, 'v'), str)) - check(ret, #str) -end - -local u64 = ffi.typeof('uint64_t') -local i64 = ffi.typeof('int64_t') - -local first = true - -for convention,c in pairs(dlls) do - check(c.add_i8(1,1), 2) - check(c.add_i8(256,1), 1) - check(c.add_i8(127,1), -128) - check(c.add_i8(-120,120), 0) - check(c.add_u8(255,1), 0) - check(c.add_u8(120,120), 240) - check(c.add_i16(2000,4000), 6000) - check(c.add_d(20, 12), 32) - check(c.add_f(40, 32), 72) - check(c.not_b(true), false) - check(c.not_b2(false), true) - check(c.inc_e8(c.FOO8), c.BAR8) - check(c.inc_e8('FOO8'), c.BAR8) - check(c.inc_e16(c.FOO16), c.BAR16) - check(c.inc_e32(c.FOO32), c.BAR32) - check(c.ret_fp(c.g_fp), c.g_fp) - check(c.ret_fp2(c.g_fp), c.g_fp) - - if c.have_complex() then - check(c.add_dc(3+4*i, 4+5*i), 7+9*i) - check(c.add_fc(2+4*i, 6+8*i), 8+12*i) - types.dc = 'double complex' - types.fc = 'float complex' - else - types.dc = nil - types.fc = nil - end - check((3+4*i).re, 3) - check((3+4*i).im, 4) - check(ffi.new('complex float', 2+8*i).re, 2) - check(ffi.new('complex float', 5+6*i).im, 6) - - check(c.have_complex(), c.have_complex2()) - check(c.is_msvc, c.is_msvc2) - - check(c.g_b, true) - check(c.g_i8, -8) - check(c.g_i16, -16) - check(c.g_i32, -32) - check(c.g_i64, i64(-64)) - check(c.g_u8, 8) - check(c.g_u16, 16) - check(c.g_u32, 32) - check(c.g_u64, u64(64)) - check(c.g_f, 3) - check(c.g_d, 5) - if c.have_complex() then - check(c.g_dc, 7 + 8*i) - check(c.g_fc, 6 + 9*i) - end - check(ffi.cast('void*', c.g_fp), c.g_p) - check(c.g_s, 'g_s') - check(c.g_sp, 'g_sp') - check(c.g_e8, c.FOO8) - check(c.g_e16, c.FOO16) - check(c.g_e32, c.FOO32) - check(c.g_date.nWeekDay, 1) - check(c.g_date.nMonthDay, 2) - check(c.g_date.nMonth, 3) - check(c.g_date.nYear, 4) - - c.g_b = false; check(c.g_b, false) - c.g_i8 = -108; check(c.g_i8, -108) - c.g_i16 = -1016; check(c.g_i16, -1016) - c.g_i32 = -1032; check(c.g_i32, -1032) - c.g_i64 = -1064; check(c.g_i64, i64(-1064)) - c.g_u8 = 208; check(c.g_u8, 208) - c.g_u16 = 2016; check(c.g_u16, 2016) - c.g_u32 = 2032; check(c.g_u32, 2032) - c.g_u64 = 2064; check(c.g_u64, u64(2064)) - c.g_f = 13; check(c.g_f, 13) - c.g_d = 15; check(c.g_d, 15) - if c.have_complex() then - c.g_dc = 17+18*i; check(c.g_dc, 17+18*i) - c.g_fc = 16+19*i; check(c.g_fc, 16+19*i) - end - c.g_sp = 'foo'; check(c.g_sp, 'foo') - c.g_e8 = c.BAR8; check(c.g_e8, c.BAR8) - c.g_e16 = c.BAR16; check(c.g_e16, c.BAR16) - c.g_e32 = c.BAR32; check(c.g_e32, c.BAR32) - c.g_date.nWeekDay = 3; check(c.g_date.nWeekDay, 3) - - local align_attr = c.is_msvc and [[ - struct align_attr_ALIGN_SUFFIX { - char pad; - __declspec(align(ALIGN)) TYPE v; - }; - - int print_align_attr_ALIGN_SUFFIX(char* buf, struct align_attr_ALIGN_SUFFIX* p); - ]] or [[ - struct align_attr_ALIGN_SUFFIX { - char pad; - TYPE v __attribute__(aligned(ALIGN)); - }; - - int print_align_attr_ALIGN_SUFFIX(char* buf, struct align_attr_ALIGN_SUFFIX* p); - ]] - - for suffix, type in pairs(types) do - local test = test_values[type] - --print('checkbuf', suffix, type, buf, test) - checkbuf(type, c['print_' .. suffix](buf, test), suffix) - - if first then - ffi.cdef(align:gsub('SUFFIX', suffix):gsub('TYPE', type):gsub('ALIGN', 0)) - end - - local v = ffi.new('struct align_0_' .. suffix, {0, test}) - checkalign(type, v, c['print_align_0_' .. suffix](buf, v)) - - for _,align in ipairs{1,2,4,8,16} do - if align > c.max_alignment() then - break - end - - if first then - ffi.cdef(palign:gsub('SUFFIX', suffix):gsub('TYPE', type):gsub('ALIGN', align)) - ffi.cdef(align_attr:gsub('SUFFIX', suffix):gsub('TYPE', type):gsub('ALIGN', align)) - end - - local v = ffi.new('struct align_' .. align .. '_' .. suffix, {0, test}) - checkalign(type, v, c['print_align_' .. align .. '_' .. suffix](buf, v)) - - -- MSVC doesn't support aligned attributes on enums - if not type:match('^enum e[0-9]*$') or not c.is_msvc then - local v2 = ffi.new('struct align_attr_' .. align .. '_' .. suffix, {0, test}) - checkalign(type, v2, c['print_align_attr_' .. align .. '_' .. suffix](buf, v2)) - end - end - - if not c.is_msvc then - if first then - local h = [[ - struct align_attr_def_SUFFIX { - char pad; - TYPE v __attribute__(aligned); - }; - int print_align_attr_def_SUFFIX(char* buf, struct align_attr_def_SUFFIX* p); - ]] - ffi.cdef(h:gsub('SUFFIX', suffix):gsub('TYPE', type)) - end - - local v = ffi.new('struct align_attr_def_' .. suffix, {0, test}) - -- print(type) - -- print("Align " .. c['print_align_attr_def_' .. suffix](buf, v)) - -- print(ffi.string(buf)) - -- checkalign(type, v, c['print_align_attr_def_' .. suffix](buf, v)) - end - end - - local psz = ffi.new('size_t[1]') - local palign = ffi.new('size_t[1]') - local function check_align(type, test, ret) - --print('check_align', type, test, ret, ffi.string(buf), psz[0], palign[0]) - check(tonumber(palign[0]), ffi.alignof(type)) - check(tonumber(psz[0]), ffi.sizeof(type)) - check(ret, #test) - check(test, ffi.string(buf)) - end - - for _, tnum in ipairs{8, 16, 32, 64} do - if first then - ffi.cdef(bitfields:gsub('TNUM',tnum)) - end - - check_align('struct bc'..tnum, '1 2', c['print_bc'..tnum](psz, palign, buf, {1,2})) - check_align('struct blz'..tnum, '1 2', c['print_blz'..tnum](psz, palign, buf, {1,2})) - - for _, znum in ipairs{8, 16, 32, 64} do - for _, bnum in ipairs{7, 15, 31, 63} do - if bnum > znum then - break - end - if first then - ffi.cdef(bitzero:gsub('TNUM',tnum):gsub('ZNUM',znum):gsub('BNUM', bnum)) - end - check_align('struct bz_'..tnum..'_'..znum..'_'..bnum, '1 2 3', c['print_bz_'..tnum..'_'..znum..'_'..bnum](psz, palign, buf, {1,2,3})) - end - end - - for _, bnum in ipairs{7, 15, 31, 63} do - if bnum > tnum then - break - end - if first then - ffi.cdef(bitalign:gsub('TNUM',tnum):gsub('BNUM',bnum)) - end - check_align('struct ba_'..tnum..'_'..bnum, '1 2', c['print_ba_'..tnum..'_'..bnum](psz, palign, buf, {1,2})) - end - end - - check_align('struct Date', '1 2 3 4', c.print_date(psz, palign, buf, {1,2,3,4})) - check_align('struct Date2', '1 2 3 4', c.print_date2(psz, palign, buf, {1,2,3,4})) - check_align('struct sysv1', '1 2 3', c.print_sysv1(psz, palign, buf, {1,2,3})) - check_align('struct sysv2', '1 2 3 4 5 6', c.print_sysv2(psz, palign, buf, {1,2,3,4,5,6})) - check_align('struct sysv3', '1 2', c.print_sysv3(psz, palign, buf, {1,2})) - check_align('union sysv4', '1', c.print_sysv4(psz, palign, buf, {1})) - check_align('struct sysv5', '1 2 3', c.print_sysv5(psz, palign, buf, {1,2,3})) - check_align('struct sysv6', '1 2 3', c.print_sysv6(psz, palign, buf, {1,2,3})) - check_align('struct sysv7', '1 2 3 4 5', c.print_sysv7(psz, palign, buf, {1,2,3,4,5})) - - local cbs = [[ - typedef const char* (*__cdecl sfunc)(const char*); - int call_i(int (*__cdecl func)(int), int arg); - float call_f(float (*__cdecl func)(float), float arg); - double call_d(double (*__cdecl func)(double), double arg); - const char* call_s(sfunc func, const char* arg); - _Bool call_b(_Bool (*__cdecl func)(_Bool), _Bool arg); - double complex call_dc(double complex (*__cdecl func)(double complex), double complex arg); - float complex call_fc(float complex (*__cdecl func)(float complex), float complex arg); - enum e8 call_e8(enum e8 (*__cdecl func)(enum e8), enum e8 arg); - enum e16 call_e16(enum e16 (*__cdecl func)(enum e16), enum e16 arg); - enum e32 call_e32(enum e32 (*__cdecl func)(enum e32), enum e32 arg); - ]] - - ffi.cdef(cbs:gsub('__cdecl', convention)) - - local u3 = ffi.new('uint64_t', 3) - check(c.call_i(function(a) return 2*a end, 3), 6) - assert(math.abs(c.call_d(function(a) return 2*a end, 3.2) - 6.4) < 0.0000000001) - assert(math.abs(c.call_f(function(a) return 2*a end, 3.2) - 6.4) < 0.000001) - check(ffi.string(c.call_s(function(s) return s + u3 end, 'foobar')), 'bar') - check(c.call_b(function(v) return not v end, true), false) - check(c.call_e8(function(v) return v + 1 end, c.FOO8), c.BAR8) - check(c.call_e16(function(v) return v + 1 end, c.FOO16), c.BAR16) - check(c.call_e32(function(v) return v + 1 end, c.FOO32), c.BAR32) - - if c.have_complex() then - check(c.call_dc(function(v) return v + 2+3*i end, 4+6*i), 6+9*i) - check(c.call_fc(function(v) return v + 1+2*i end, 7+4*i), 8+6*i) - end - - local u2 = ffi.new('uint64_t', 2) - local cb = ffi.new('sfunc', function(s) return s + u3 end) - check(ffi.string(cb('foobar')), 'bar') - check(ffi.string(c.call_s(cb, 'foobar')), 'bar') - cb:set(function(s) return s + u2 end) - check(ffi.string(c.call_s(cb, 'foobar')), 'obar') - - local fp = ffi.new('struct fptr') - assert(fp.p == ffi.C.NULL) - fp.p = function(a) return 2*a end - assert(fp.p ~= ffi.C.NULL) - check(c.call_fptr(fp, 4), 8) - local suc, err = pcall(function() fp.p:set(function() end) end) - assert(not suc) - check(err:gsub('^.*: ',''), "can't set the function for a non-lua callback") - - check(c.call_fptr({function(a) return 3*a end}, 5), 15) - - local suc, err = pcall(c.call_s, function(s) error(ffi.string(s), 0) end, 'my error') - check(suc, false) - check(err, 'my error') - - check(ffi.errno(), c.get_errno()) - c.set_errno(3) - check(ffi.errno(), 3) - check(c.get_errno(), 3) - check(ffi.errno(4), 3) - check(ffi.errno(), 4) - check(c.get_errno(), 4) - - local gccattr = { - __cdecl = 'int test_pow(int v) __attribute__((cdecl));', - __stdcall = 'int test_pow(int v) __attribute__(stdcall);', - __fastcall = '__attribute__(fastcall) int test_pow(int v);', - } - - ffi.cdef(gccattr[convention]) - check(c.test_pow(5), 25) - - ffi.cdef [[ - int va_list_size, va_list_align; - int vsnprintf(char* buf, size_t sz, const char* fmt, va_list ap); - ]] - ffi.new('va_list') - assert(ffi.debug().functions.vsnprintf ~= nil) - assert(ffi.istype('va_list', ffi.new('__builtin_va_list'))) - assert(ffi.istype('va_list', ffi.new('__gnuc_va_list'))) - check(ffi.sizeof('va_list'), c.va_list_size) - check(ffi.alignof('va_list'), c.va_list_align) - - first = false -end - -local c = ffi.C - -assert(c.sprintf(buf, "%g", 5.3) == 3 and ffi.string(buf) == '5.3') -assert(c.sprintf(buf, "%d", false) == 1 and ffi.string(buf) == '0') -assert(c.sprintf(buf, "%d%g", false, 6.7) == 4 and ffi.string(buf) == '06.7') - -assert(ffi.sizeof('uint32_t[?]', 32) == 32 * 4) -assert(ffi.sizeof(ffi.new('uint32_t[?]', 32)) == 32 * 4) - -ffi.cdef [[ -struct vls { - struct { - char a; - struct { - char b; - char v[?]; - } c; - } d; -}; -struct vls2 { - char pad; - union { - uint8_t a; - uint16_t b; - }; -}; -]] - -assert(ffi.sizeof('struct vls', 3) == 5) -assert(ffi.sizeof(ffi.new('struct vls', 4).d.c) == 5) -assert(ffi.offsetof('struct vls2', 'a') == 2) -assert(ffi.sizeof('struct vls2') == 4) - -ffi.cdef [[ static const int DUMMY = 8 << 2; ]] -assert(ffi.C.DUMMY == 32) - -ffi.new('struct {const char* foo;}', {'foo'}) - -assert(not pcall(function() - ffi.new('struct {char* foo;}', {'ff'}) -end)) - -local mt = {} -local vls = ffi.new(ffi.metatype('struct vls', mt), 1) - -assert(not pcall(function() return vls.key end)) - -mt.__index = function(vls, key) - return function(vls, a, b) - return 'in index ' .. key .. ' ' .. vls.d.a .. ' ' .. a .. ' ' .. b - end -end - -vls.d.a = 3 -check(vls:key('a', 'b'), 'in index key 3 a b') - -assert(not pcall(function() vls.k = 3 end)) - -mt.__newindex = function(vls, key, val) - error('in newindex ' .. key .. ' ' .. vls.d.a .. ' ' .. val, 0) -end - -vls.d.a = 4 -local suc, err = pcall(function() vls.key = 'val' end) -assert(not suc) -check(err, 'in newindex key 4 val') - -mt.__add = function(vls, a) return vls.d.a + a end -mt.__sub = function(vls, a) return vls.d.a - a end -mt.__mul = function(vls, a) return vls.d.a * a end -mt.__div = function(vls, a) return vls.d.a / a end -mt.__mod = function(vls, a) return vls.d.a % a end -mt.__pow = function(vls, a) return vls.d.a ^ a end -mt.__eq = function(vls, a) return u64(vls.d.a) == a end -mt.__lt = function(vls, a) return u64(vls.d.a) < a end -mt.__le = function(vls, a) return u64(vls.d.a) <= a end -mt.__call = function(vls, a, b) return '__call', vls.d.a .. a .. (b or 'nil') end -mt.__unm = function(vls) return -vls.d.a end -mt.__concat = function(vls, a) return vls.d.a .. a end -mt.__len = function(vls) return vls.d.a end -mt.__tostring = function(vls) return 'string ' .. vls.d.a end - -vls.d.a = 5 -check(vls + 5, 10) -check(vls - 5, 0) -check(vls * 5, 25) -check(vls / 5, 1) -check(vls % 3, 2) -check(vls ^ 3, 125) -check(vls == u64(4), false) -check(vls == u64(5), true) -check(vls == u64(6), false) -check(vls < u64(4), false) -check(vls < u64(5), false) -check(vls < u64(6), true) -check(vls <= u64(4), false) -check(vls <= u64(5), true) -check(vls <= u64(6), true) -check(-vls, -5) -local a,b = vls('6') -check(a, '__call') -check(b, '56nil') -check(tostring(vls), 'string 5') - -if _VERSION ~= 'Lua 5.1' then - check(vls .. 'str', '5str') - check(#vls, 5) -end - -check(tostring(1.1+3.2*i), '1.1+3.2i') -check((1+3*i)*(2+4*i), -10+10*i) -check((3+2*i)*(3-2*i), 13+0*i) - --- Should ignore unknown attributes -ffi.cdef [[ -typedef int ALenum; -__attribute__((dllimport)) void __attribute__((__cdecl__)) alEnable( ALenum capability ); -]] - -check(ffi.sizeof('struct {char foo[alignof(uint64_t)];}'), ffi.alignof('uint64_t')) - --- Check native number type for int64_t/uint64_t function args/returns in Lua 5.3 -if _VERSION == "Lua 5.3" then - local native_7F = 0x7FFFFFFFFFFFFFFF - local cdata_long_7F = ffi.new("int64_t", 0x7FFFFFFFFFFFFFFF) - local cdata_ulong_7F = ffi.new("uint64_t", 0x7FFFFFFFFFFFFFFF) - - local native_80 = 0x8000000000000000 - - for _, func in ipairs{ffi.C.add_i64, ffi.C.add_u64} do - -- 0x7FFFFFFFFFFFFFFF (native) + 1 == 0x8000000000000000 (native) - local res = func(native_7F, 1) - assert(type(res) == "number", "native_7F: returned value not a number") - assert(res == native_80, "native_7F: math error") - - -- 0x7FFFFFFFFFFFFFFF (cdata int64_t) + 1 == 0x8000000000000000 (native) - local res = func(cdata_long_7F, 1) - assert(type(res) == "number", "cdata_long_7F: returned value not a number") - assert(res == native_80, "cdata_long_7F: math error") - - -- 0x7FFFFFFFFFFFFFFF (cdata uint64_t) + 1 == 0x8000000000000000 (native) - local res = func(cdata_ulong_7F, 1) - assert(type(res) == "number", "cdata_ulong_7F: returned value not a number") - assert(res == native_80, "cdata_ulong_7F: math error") - end -end - --- Long double is not supported yet but it should be parsed -ffi.cdef('long double foo(long double val);') -check(tostring(ffi.debug().functions.foo):match('ctype(%b<>)'), '<long double (*)(long double)>') - -ffi.cdef [[ -typedef int byte1 __attribute__(mode(QI)); -typedef int byte2 __attribute__(mode(HI)); -typedef int byte4 __attribute__(mode(SI)); -typedef int byte8 __attribute__(mode(DI)); -typedef unsigned ubyte8 __attribute__(mode(DI)); -typedef int word __attribute__(mode(word)); -typedef int pointer __attribute__(mode(pointer)); -typedef int byte __attribute__(mode(byte)); -typedef float float4 __attribute__(mode(SF)); -typedef float float8 __attribute__(mode(DF)); -]] -assert(ffi.istype('int8_t', ffi.new('byte1'))) -assert(ffi.istype('int16_t', ffi.new('byte2'))) -assert(ffi.istype('int32_t', ffi.new('byte4'))) -assert(ffi.istype('int64_t', ffi.new('byte8'))) -assert(ffi.istype('uint64_t', ffi.new('ubyte8'))) -check(ffi.sizeof('void*'), ffi.sizeof('pointer')) -check(ffi.alignof('void*'), ffi.alignof('pointer')) -check(ffi.sizeof('void*'), ffi.sizeof('word')) -check(ffi.alignof('void*'), ffi.alignof('word')) -assert(ffi.istype('int8_t', ffi.new('byte'))) -assert(ffi.istype('float', ffi.new('float4'))) -assert(ffi.istype('double', ffi.new('float8'))) - -ffi.cdef('void register_foo(register int val);') -check(tostring(ffi.debug().functions.register_foo):match('%b<>'), '<void (*)(int)>') - -ffi.cdef [[ - typedef struct __sFILE FILE; -]] - -assert(not ffi.istype('int', ffi.new('int*'))) -assert(not ffi.istype('int[]', ffi.new('int*'))) -assert(not ffi.istype('int[3]', ffi.new('int*'))) -assert(not ffi.istype('int[3]', ffi.new('int[2]'))) -assert(ffi.istype('const int[3]', ffi.new('const int[3]'))) -assert(ffi.istype('int[3]', ffi.new('const int[3]'))) - --- Crazy function pointer that takes an int and a function pointer and returns --- a function pointer. Type of &signal. -check(tostring(ffi.typeof('void (*foo(int, void(*)(int)))(int)')):match('%b<>'), '<void (*(*)(int, void (*)(int)))(int)>') - --- Make sure we pass all arguments to tonumber -check(tonumber('FE', 16), 0xFE) - --- Allow casts from pointer to numeric types -ffi.cast('long', ffi.C.NULL) -ffi.cast('int8_t', ffi.C.NULL) -assert(not pcall(function() ffi.new('long', ffi.C.NULL) end)) - --- ffi.new and ffi.cast allow unpacked struct/arrays -assert(ffi.new('int[3]', 1)[0] == 1) -assert(ffi.new('int[3]', {1})[0] == 1) -assert(ffi.new('int[3]', 1, 2)[1] == 2) -assert(ffi.new('int[3]', {1, 2})[1] == 2) - -ffi.cdef[[ -struct var { - char ch[?]; -}; -]] -local d = ffi.new('char[4]') -local v = ffi.cast('struct var*', d) -v.ch = {1,2,3,4} -assert(v.ch[3] == 4) -v.ch = "bar" -assert(v.ch[3] == 0) -assert(v.ch[2] == string.byte('r')) -assert(d[1] == string.byte('a')) - -ffi.cast('char*', 1) - --- 2 arg form of ffi.copy -ffi.copy(d, 'bar') - --- unsigned should be ignored for pointer rules -ffi.cdef[[ -int strncmp(const signed char *s1, const unsigned char *s2, size_t n); -]] -assert(ffi.C.strncmp("two", "three", 3) ~= 0) - -ffi.fill(d, 3, 1) -assert(d[2] == 1) -ffi.fill(d, 3) -assert(d[2] == 0) - --- tests for __new -ffi.cdef[[ -struct newtest { - int a; - int b; - int c; -}; -]] - -local tp = ffi.metatype("struct newtest", {__new = - function(tp, x, y, z) - tp = ffi.new(tp) - tp.a, tp.b, tp.c = x, y, z - return tp - end}) -local v = tp(1, 2, 3) -assert(v.a == 1 and v.b == 2 and v.c == 3) - -local tp = ffi.metatype("struct newtest", {__new = - function(tp, x, y, z) - tp = ffi.new(tp, {a = x, b = y, c = z}) - return tp - end}) -local v = tp(1, 2, 3) -assert(v.a == 1 and v.b == 2 and v.c == 3) - --- tests for __pairs and __ipairs; not iterating just testing what is returned -local tp = ffi.metatype("struct newtest", - {__pairs = function(tp) return tp.a, tp.b end, __ipairs = function(tp) return tp.b, tp.c end} -) -if _VERSION ~= 'Lua 5.1' then - local v = tp(1, 2, 3) - x, y = pairs(v) - assert(x == 1 and y == 2) - x, y = ipairs(v) - assert(x == 2 and y == 3) -end - --- test for pointer to struct having same metamethods -local st = ffi.cdef "struct ptest {int a, b;};" -local tp = ffi.metatype("struct ptest", {__index = function(s, k) return k end, __len = function(s) return 3 end}) - -local a = tp(1, 2) -assert(a.banana == "banana") -assert(#a == 3) -local b = ffi.new("int[2]") -local c = ffi.cast("struct ptest *", b) -assert(c.banana == "banana") -- should have same methods -assert(#c == 3) - - -ffi.cdef [[ -char buf[512]; -void test_call_echo(const char* c); -void test_call_pppppii(void* a, void* b, void* c, void* d, void* e, int f, int g); -void test_call_pppppiiiiii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, int i3, int i4, int i5, int i6); -void test_call_pppppffffff(void* p1, void* p2, void* p3, void* p4, void* p5, float f1, float f2, float f3, float f4, float f5, float f6); -void test_call_pppppiifiii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, float f3, int i4, int i5, int i6); -void test_call_pppppiiifii(void* p1, void* p2, void* p3, void* p4, void* p5, int i1, int i2, int i3, float i4, int i5, int i6); -]] - -ffi.C.test_call_echo("input") -assert(ffi.C.buf == "input") - -local function ptr(x) return ffi.new('void*', x) end - -ffi.C.test_call_pppppii(ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), 6, 7) -assert(ffi.C.buf == "0x1 0x2 0x3 0x4 0x5 6 7") - -ffi.C.test_call_pppppiiiiii(ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), 6, 7, 8, 9, 10, 11) -assert(ffi.C.buf == "0x1 0x2 0x3 0x4 0x5 6 7 8 9 10 11") - -ffi.C.test_call_pppppffffff(ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), 6.5, 7.5, 8.5, 9.5, 10.5, 11.5) -assert(ffi.C.buf == "0x1 0x2 0x3 0x4 0x5 6.5 7.5 8.5 9.5 10.5 11.5") - -ffi.C.test_call_pppppiifiii(ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), 6, 7, 8.5, 9, 10, 11) -assert(ffi.C.buf == "0x1 0x2 0x3 0x4 0x5 6 7 8.5 9 10 11") - -ffi.C.test_call_pppppiiifii(ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), 6, 7, 8, 9.5, 10, 11) -assert(ffi.C.buf == "0x1 0x2 0x3 0x4 0x5 6 7 8 9.5 10 11") - -local sum = ffi.C.add_dc(ffi.new('complex', 1, 2), ffi.new('complex', 3, 5)) -assert(ffi.istype('complex', sum)) - -sum = ffi.C.add_fc(ffi.new('complex float', 1, 2), ffi.new('complex float', 3, 5)) -assert(ffi.istype('complex float', sum)) - -ffi.cdef [[ -struct Arrays { - int ints[3]; - unsigned int uints[3]; -}; -struct ArrayOfArrays { - struct Arrays arrays[3]; -}; -]] - -local struct = ffi.new('struct Arrays') -local structOfStructs = ffi.new('struct ArrayOfArrays') -for i=0,2 do - struct.ints[i] = i - struct.uints[i] = i - structOfStructs.arrays[0].ints[i] = i -end -for i=0,2 do - assert(struct.ints[i] == i) - assert(struct.uints[i] == i) - assert(structOfStructs.arrays[0].ints[i] == i) -end - --- Test ffi.string -local buf = ffi.new('char[5]') -ffi.fill(buf, 4, 97) -buf[4] = 0 - -assert(ffi.string(buf) == 'aaaa') -assert(ffi.string(buf, 4) == 'aaaa') -assert(ffi.string(buf, 2) == 'aa') -assert(ffi.string(buf, 0) == '') -assert(ffi.string(buf, ffi.new('long long', 2)) == 'aa') -assert(ffi.string(buf, ffi.new('int', 2)) == 'aa') - --- Test io.tmpfile() -ffi.cdef [[ - int fprintf ( FILE * stream, const char * format, ... ); -]] -local f = io.tmpfile() -ffi.C.fprintf(f, "test: %s\n", "foo") - -f:seek("set", 0) -local str = f:read('*l') -assert(str == 'test: foo', str) -f:close() - -print('Test PASSED') |