From 147871ce1d93dc5d55baaf17ee3a60de9ea35cc7 Mon Sep 17 00:00:00 2001 From: Luigi Scarso <luigi.scarso@gmail.com> Date: Sun, 5 Jan 2025 12:51:17 +0100 Subject: [PATCH] dos2unix of some files under luaffi/ --- source/texk/web2c/luatexdir/luaffi/call.c | 630 +- source/texk/web2c/luatexdir/luaffi/call_arm.h | 4498 +++++++-------- .../web2c/luatexdir/luaffi/call_arm64.dasc | 2992 +++++----- .../texk/web2c/luatexdir/luaffi/call_arm64.h | 4876 ++++++++-------- .../texk/web2c/luatexdir/luaffi/call_arm_hf.h | 5060 ++++++++--------- source/texk/web2c/luatexdir/luaffi/ctype.c | 630 +- .../texk/web2c/luatexdir/luaffi/fake_dlfcn.c | 328 +- .../texk/web2c/luatexdir/luaffi/fake_dlfcn.h | 40 +- .../texk/web2c/luatexdir/luatex_svnversion.h | 2 +- 9 files changed, 9528 insertions(+), 9528 deletions(-) diff --git a/source/texk/web2c/luatexdir/luaffi/call.c b/source/texk/web2c/luatexdir/luaffi/call.c index 90b464e31..09f38ed38 100644 --- a/source/texk/web2c/luatexdir/luaffi/call.c +++ b/source/texk/web2c/luatexdir/luaffi/call.c @@ -1,315 +1,315 @@ -/* 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, 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); } - -#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(ARCH_ARM) -#include "dynasm/dasm_arm.h" -//See http://code.google.com/p/v8/issues/detail?id=2140 for more information -#if defined(__ARM_PCS_VFP) || (GCC_VERSION==40500||defined(__clang__))&&!defined(__ARM_PCS) && !defined(__SOFTFP__) && !defined(__SOFTFP) && \ - defined(__VFP_FP__) -#include "call_arm_hf.h" -#else -#include "call_arm.h" -#endif -#elif defined ARCH_ARM64 -#include "dynasm/dasm_arm64.h" -#include "call_arm64.h" -#else -#include "dynasm/dasm_x86.h" -#include "call_x86.h" -#endif - -struct jit_head { - size_t size; - int ref; -#ifndef NO_FUNCTION_EXTERN - uint8_t jump[JUMP_SIZE]; -#endif -}; - -#define LINKTABLE_MAX_SIZE ((sizeof(extnames) / sizeof(extnames[0])-1) * (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; -#ifndef NO_FUNCTION_EXTERN - compile_extern_jump(jit, L, func, code->jump); -#endif - - if ((err = dasm_encode(jit, code+1)) != 0) { - char buf[32]; - sprintf(buf, "%x", err); - commit_code(jit, 0); - luaL_error(L, "dasm_encode error %s", buf); - } - - commit_code(jit, codesz); - cfunction ret = (cfunction) (code + 1); - return ret; -} - -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; -#ifndef NO_FUNCTION_EXTERN - if (idx == jit->function_extern) { - jmp = h->jump; - } else -#endif - { - 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 - // thumb address must be called by extern jump rather than direct jump -#ifdef ARCH_ARM - &&((*(uintptr_t*) jmp)&1)==0 -#endif - ) { - return (int32_t) off; - } else { - return (int32_t)(jmp + sizeof(uint8_t*) - addr); - } -} -static void rawgeti(lua_State* L,int idx,ptrdiff_t key){ - lua_rawgeti(L,idx,key); -} - -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); - if(jit->default_functions!=NULL){ - memcpy((uint8_t*)(page+1),jit->default_functions,LINKTABLE_MAX_SIZE); - page->off+=LINKTABLE_MAX_SIZE; - page->freed=page->off; - goto End; - } - - lua_newtable(L); - -#define ADD_FUNC_WITH_NAME(DLL, NAME,FUNC) \ - lua_pushliteral(L, #NAME); \ - func = DLL ? (cfunction) GetProcAddressA(DLL, #FUNC) : NULL; \ - func = func ? func : (cfunction) &FUNC; \ - lua_pushcfunction(L, (lua_CFunction) func); \ - lua_rawset(L, -3) - -#define ADDFUNC(DLL, NAME) ADD_FUNC_WITH_NAME(DLL,NAME,NAME) - - 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_struct); - 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, memcpy);//for x86,x64 only -#if ARM_HF - ADDFUNC(NULL, unpack_varargs_bound); -#endif - ADDFUNC(NULL, push_cdata); - ADDFUNC(NULL, push_int); - ADDFUNC(NULL, push_uint); - ADDFUNC(NULL, lua_pushinteger); - ADDFUNC(NULL, push_float); - ADDFUNC(jit->lua_dll, luaL_error); - ADDFUNC(jit->lua_dll, lua_pushnumber); - ADDFUNC(jit->lua_dll, lua_pushboolean); - ADDFUNC(jit->lua_dll, lua_gettop); -#if LUA_VERSION_NUM<503 || defined(__LP64__) || defined(__amd64__) ||defined (_WIN64) - ADD_FUNC_WITH_NAME(jit->lua_dll,rawgeti, lua_rawgeti); -#else - ADDFUNC(NULL,rawgeti); - -#endif -#if LUA_VERSION_NUM<502 - ADD_FUNC_WITH_NAME(jit->lua_dll, lua_setuservalue,lua_setfenv); -#else - ADDFUNC(jit->lua_dll, lua_setuservalue); -#endif - ADDFUNC(jit->lua_dll, lua_pushnil); - ADDFUNC(jit->lua_dll, lua_call); - ADDFUNC(jit->lua_dll, lua_settop); - ADDFUNC(jit->lua_dll, lua_remove); - ADDFUNC(jit->lua_dll, lua_pushvalue); -#undef ADDFUNC - - for (i = 0; extnames[i] != NULL; i++) { -#ifndef NO_FUNCTION_EXTERN - if (strcmp(extnames[i], "FUNCTION") == 0) { - shred(pdata + page->off, 0, JUMP_SIZE); - jit->function_extern = i; - } else -#endif - { - 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; - } -#ifndef NO_FUNCTION_EXTERN - if(jit->function_extern==0){ - luaL_error(L, "internal error: should define extern FUNCTION"); - } -#endif - jit->default_functions=(uint8_t*)(page+1); - page->freed = page->off; - lua_pop(L, 1); - - } else { - page = jit->pages[jit->pagenum-1]; - EnableWrite(page, page->size); - } - End: - return (uint8_t*) page + page->off; -} - -static void commit_code(struct jit *jit, size_t sz) -{ - struct page* page = jit->pages[jit->pagenum-1]; - page->off += sz; - EnableExecute(page, page->size); -} - -/* 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; - } - if((uint8_t*)(p+1)==jit->default_functions){ - jit->default_functions=NULL; - } - 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"); -} - - +/* 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, 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); } + +#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(ARCH_ARM) +#include "dynasm/dasm_arm.h" +//See http://code.google.com/p/v8/issues/detail?id=2140 for more information +#if defined(__ARM_PCS_VFP) || (GCC_VERSION==40500||defined(__clang__))&&!defined(__ARM_PCS) && !defined(__SOFTFP__) && !defined(__SOFTFP) && \ + defined(__VFP_FP__) +#include "call_arm_hf.h" +#else +#include "call_arm.h" +#endif +#elif defined ARCH_ARM64 +#include "dynasm/dasm_arm64.h" +#include "call_arm64.h" +#else +#include "dynasm/dasm_x86.h" +#include "call_x86.h" +#endif + +struct jit_head { + size_t size; + int ref; +#ifndef NO_FUNCTION_EXTERN + uint8_t jump[JUMP_SIZE]; +#endif +}; + +#define LINKTABLE_MAX_SIZE ((sizeof(extnames) / sizeof(extnames[0])-1) * (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; +#ifndef NO_FUNCTION_EXTERN + compile_extern_jump(jit, L, func, code->jump); +#endif + + if ((err = dasm_encode(jit, code+1)) != 0) { + char buf[32]; + sprintf(buf, "%x", err); + commit_code(jit, 0); + luaL_error(L, "dasm_encode error %s", buf); + } + + commit_code(jit, codesz); + cfunction ret = (cfunction) (code + 1); + return ret; +} + +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; +#ifndef NO_FUNCTION_EXTERN + if (idx == jit->function_extern) { + jmp = h->jump; + } else +#endif + { + 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 + // thumb address must be called by extern jump rather than direct jump +#ifdef ARCH_ARM + &&((*(uintptr_t*) jmp)&1)==0 +#endif + ) { + return (int32_t) off; + } else { + return (int32_t)(jmp + sizeof(uint8_t*) - addr); + } +} +static void rawgeti(lua_State* L,int idx,ptrdiff_t key){ + lua_rawgeti(L,idx,key); +} + +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); + if(jit->default_functions!=NULL){ + memcpy((uint8_t*)(page+1),jit->default_functions,LINKTABLE_MAX_SIZE); + page->off+=LINKTABLE_MAX_SIZE; + page->freed=page->off; + goto End; + } + + lua_newtable(L); + +#define ADD_FUNC_WITH_NAME(DLL, NAME,FUNC) \ + lua_pushliteral(L, #NAME); \ + func = DLL ? (cfunction) GetProcAddressA(DLL, #FUNC) : NULL; \ + func = func ? func : (cfunction) &FUNC; \ + lua_pushcfunction(L, (lua_CFunction) func); \ + lua_rawset(L, -3) + +#define ADDFUNC(DLL, NAME) ADD_FUNC_WITH_NAME(DLL,NAME,NAME) + + 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_struct); + 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, memcpy);//for x86,x64 only +#if ARM_HF + ADDFUNC(NULL, unpack_varargs_bound); +#endif + ADDFUNC(NULL, push_cdata); + ADDFUNC(NULL, push_int); + ADDFUNC(NULL, push_uint); + ADDFUNC(NULL, lua_pushinteger); + ADDFUNC(NULL, push_float); + ADDFUNC(jit->lua_dll, luaL_error); + ADDFUNC(jit->lua_dll, lua_pushnumber); + ADDFUNC(jit->lua_dll, lua_pushboolean); + ADDFUNC(jit->lua_dll, lua_gettop); +#if LUA_VERSION_NUM<503 || defined(__LP64__) || defined(__amd64__) ||defined (_WIN64) + ADD_FUNC_WITH_NAME(jit->lua_dll,rawgeti, lua_rawgeti); +#else + ADDFUNC(NULL,rawgeti); + +#endif +#if LUA_VERSION_NUM<502 + ADD_FUNC_WITH_NAME(jit->lua_dll, lua_setuservalue,lua_setfenv); +#else + ADDFUNC(jit->lua_dll, lua_setuservalue); +#endif + ADDFUNC(jit->lua_dll, lua_pushnil); + ADDFUNC(jit->lua_dll, lua_call); + ADDFUNC(jit->lua_dll, lua_settop); + ADDFUNC(jit->lua_dll, lua_remove); + ADDFUNC(jit->lua_dll, lua_pushvalue); +#undef ADDFUNC + + for (i = 0; extnames[i] != NULL; i++) { +#ifndef NO_FUNCTION_EXTERN + if (strcmp(extnames[i], "FUNCTION") == 0) { + shred(pdata + page->off, 0, JUMP_SIZE); + jit->function_extern = i; + } else +#endif + { + 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; + } +#ifndef NO_FUNCTION_EXTERN + if(jit->function_extern==0){ + luaL_error(L, "internal error: should define extern FUNCTION"); + } +#endif + jit->default_functions=(uint8_t*)(page+1); + page->freed = page->off; + lua_pop(L, 1); + + } else { + page = jit->pages[jit->pagenum-1]; + EnableWrite(page, page->size); + } + End: + return (uint8_t*) page + page->off; +} + +static void commit_code(struct jit *jit, size_t sz) +{ + struct page* page = jit->pages[jit->pagenum-1]; + page->off += sz; + EnableExecute(page, page->size); +} + +/* 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; + } + if((uint8_t*)(p+1)==jit->default_functions){ + jit->default_functions=NULL; + } + 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/source/texk/web2c/luatexdir/luaffi/call_arm.h b/source/texk/web2c/luatexdir/luaffi/call_arm.h index 1db7b2ff4..3d1ce33e6 100644 --- a/source/texk/web2c/luatexdir/luaffi/call_arm.h +++ b/source/texk/web2c/luatexdir/luaffi/call_arm.h @@ -1,2249 +1,2249 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.4.0, DynASM arm version 1.4.0 -** DO NOT EDIT! The original file is in "call_arm.dasc". -*/ - -/* 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. - */ - -//The generate code is for arm not for thumb -#if DASM_VERSION != 10400 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -static const unsigned int build_actionlist[743] = { -0xe28dc000, -0x000b0000, -0xe89c100e, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c100e, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c0006, -0x00000000, -0xe51d1000, -0x000e8180, -0x00000000, -0xe2866000, -0x000b0000, -0x00000000, -0xe8b6100e, -0x00000000, -0xe8b60006, -0x00000000, -0xe4961004, -0x00000000, -0xe1a0c00d, -0xe92d000f, -0x00000000, -0xe92d5050, -0xe1a0600c, -0xe3004000, -0x000c0200, -0xe3404000, -0x000c0200, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030000, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030000, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe5801000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe5801000, -0x00000000, -0xe28d1000, -0x000b0000, -0x00000000, -0xe1a01006, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe12fff3c, -0x00000000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe880100e, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe8800006, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c000c, -0x00000000, -0xe2866004, -0x00000000, -0xe8b6000c, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030003, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe8800006, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe5801000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030004, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030005, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030006, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c000c, -0x00000000, -0xe2866004, -0x00000000, -0xe8b6000c, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030007, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3a01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030008, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3e02000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030009, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3e02000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003000a, -0xe1a06000, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0x00000000, -0xe5960000, -0x00000000, -0xe51d0000, -0x000e8180, -0xe1a01006, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe12fff3c, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3e02000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003000c, -0x00000000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003000b, -0x00000000, -0xe3e01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000d, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe3500000, -0x13a00001, -0x00000000, -0xe6ef0070, -0x00000000, -0xe6af0070, -0x00000000, -0xe6ff0070, -0x00000000, -0xe6bf0070, -0x00000000, -0xe3e01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000f, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030010, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030011, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030012, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030013, -0x00000000, -0xe3e02000, -0xe1a01004, -0xe51d0000, -0x000e8180, -0xeb000000, -0x00030014, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0x00000000, -0xe3e02000, -0xe1a01004, -0xe51d0000, -0x000e8180, -0xeb000000, -0x00030015, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0x00000000, -0xe1a06000, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0xe1a00006, -0x00000000, -0xe1a06000, -0xe1a00004, -0xe1a04001, -0xe3e01002, -0xeb000000, -0x0003000b, -0xe1a00006, -0xe1a01004, -0x00000000, -0xe89da050, -0x00000000, -0xe2866004, -0x00000000, -0xe8a60003, -0x00000000, -0xe28dc000, -0x000b0000, -0xe88c0003, -0x00000000, -0xe4860004, -0x00000000, -0xe50d0000, -0x000e8180, -0x00000000, -0xe2866004, -0x00000000, -0xeca60a01, -0x00000000, -0xeca60b02, -0x00000000, -0xeca60a04, -0x00000000, -0xeca60b04, -0x00000000, -0xeca60b06, -0x00000000, -0xeca60b08, -0x00000000, -0xe92d40f0, -0xe28d700c, -0x00000000, -0xe92d4870, -0xe28db00c, -0x00000000, -0xe24dd004, -0x00000000, -0xe1a04000, -0x00000000, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe04dd00c, -0x00000000, -0xe24dd000, -0x000b0000, -0x00000000, -0xeb000000, -0x00030016, -0xe3500000, -0x000b0000, -0xaa000000, -0x00050001, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030017, -0x0006000b, -0xe1a05000, -0xe04dd185, -0x00000000, -0xe28d6000, -0x000b0000, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0xe50d0000, -0x000e8180, -0x00000000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0x000b0000, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030009, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030018, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000c, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000a, -0x00000000, -0xe2866004, -0x00000000, -0xe1a01000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0x00000000, -0xe28d0000, -0x000b0000, -0x00000000, -0xe1a00006, -0x00000000, -0xe12fff3c, -0x00000000, -0xe2866000, -0x000b0000, -0x00000000, -0xe3a01000, -0x000b0000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0xe3500000, -0x13a00001, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe6ef0070, -0x00000000, -0xe6af0070, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe6ff0070, -0x00000000, -0xe6bf0070, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000d, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030011, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000f, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030010, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030013, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030012, -0x00000000, -0xe1a02001, -0xe1a01004, -0x00000000, -0xe28d0000, -0x000b0000, -0x00000000, -0xe2866004, -0x00000000, -0xe1a00006, -0x00000000, -0xeb000000, -0x00030014, -0x00000000, -0xe1a02001, -0xe1a01004, -0x00000000, -0xe28d0000, -0x000b0000, -0x00000000, -0xe1a00006, -0x00000000, -0xeb000000, -0x00030015, -0x00000000, -0xe2866000, -0x000b0000, -0x00000000, -0xe3a01000, -0x000b0000, -0x00000000, -0xe1a03006, -0x00000000, -0xe28d3000, -0x000b0000, -0x00000000, -0xe1a02005, -0xe1a00004, -0xeb000000, -0x00030019, -0x00000000, -0xe8bd000f, -0x00000000, -0xe8bd0003, -0x00000000, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe12fff3c, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0xe3a00001, -0x00000000, -0xe1a03001, -0xe1a02000, -0x00000000, -0xe1a02001, -0xe1a01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030003, -0xe3a00001, -0x00000000, -0xe1a06000, -0xe1a05001, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0xe5805004, -0xe3a00001, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0xe3a00001, -0x00000000, -0xe3a00000, -0x00000000, -0xe1a01000, -0xe1a00004, -0xeb000000, -0x00030004, -0xe3a00001, -0x00000000, -0xe1a01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003001a, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030005, -0x00000000, -0xe3a00001, -0x00000000, -0xe1a01000, -0xe1a00004, -0xeb000000, -0x00030006, -0xe3a00001, -0x00000000, -0xe1a03001, -0xe1a02000, -0x00000000, -0xe1a02001, -0xe1a01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030007, -0xe3a00001, -0x00000000, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x0003001b, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003001c, -0x00000000, -0xe3a00000, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0x00000000, -0xe3a00001, -0x00000000, -0xe247d00c, -0xe8bd80f0, -0x00000000, -0xe24bd00c, -0xe8bd8870, -0x00000000 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "rawgeti", - "push_cdata", - "lua_remove", - "lua_pushinteger", - "lua_pushboolean", - "push_int", - "push_float", - "lua_pushnumber", - "lua_call", - "check_typed_pointer", - "check_struct", - "lua_settop", - "check_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_uintptr", - "check_float", - "check_double", - "check_complex_double", - "check_complex_float", - "lua_gettop", - "luaL_error", - "check_typed_cfunction", - "unpack_varargs_stack", - "push_uint", - "lua_pushvalue", - "lua_setuservalue", - (const char *)0 -}; - -#define JUMP_SIZE 8 - -#define MIN_BRANCH ((INT32_MIN) >> 8) -#define MAX_BRANCH ((INT32_MAX) >> 8) -//arm pc offset 8 so comparing with next instruction is 4, -//unlike x86 which pass in the current instruction address+1 rather than the next instruction -#define BRANCH_OFF 4 - - -#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) -#ifdef TARGET_OS_IPHONE -#define CK_ALGIN 0 -#else -#define CK_ALGIN 1 -#endif -#define ALIGNED(x, align) (!CK_ALGIN||((int)(x) & (align - 1)) == 0) -#if defined(__ARM_PCS_VFP) || (GCC_VERSION==40500||defined(__clang__))&&!defined(__ARM_PCS) && !defined(__SOFTFP__) && !defined(__SOFTFP) && \ - defined(__VFP_FP__) -#define ARM_HF 1 -#else -#define ARM_HF 0 -#endif -#if ARM_HF&&!CK_ALGIN -#error "Unsupported unaligned stack for hard floating point" -#endif - -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; -} - -typedef struct stack_info{ - int extra; - int int_off; - int stack_off; - int float_size; -#if ARM_HF - int float_off; -#endif -} stack_info; -//vfp use back-filling rule for registers until a float value on stack -typedef struct reg_info{ - uint16_t exs; - union{ - uint8_t ints; - uint8_t regs; - }; -#if ARM_HF - uint8_t float_sealed; - short floats;//each bit is a float: s0-s15 or v0-v7 or q0-q3 - uint8_t left_single; - uint8_t highest_bit; -#endif -} reg_info; - -#define MAX_REGS 4 -#define MAX_FLOAT_REGS 16 -#ifndef bool -#define bool uint8_t -#endif - -#define has_bit(x,b) (((x)&(1<<(b)))!=0) -#define set_bit(x,b) (x=((x)|(1<<(b)))) -#define FIX_ALIGN(x,al) \ - if(!ALIGNED((x),al)){\ - x=ROUND_UP(x,al);\ - } -static ALWAYS_INLINE bool is_float_sealed(reg_info* regs){ -#if ARM_HF -return regs->float_sealed; -#else -return regs->regs>=MAX_REGS; -#endif -} -//return size need to put on stack -static ALWAYS_INLINE int add_int_reg(reg_info* regs){ - if(regs->regs<MAX_REGS){ - regs->regs++; - return 0; - } - return 1; - -} -//return size need to put on stack -static ALWAYS_INLINE int add_int64_reg(reg_info* regs){ - if(regs->regs<MAX_REGS-1){ - regs->regs=ROUND_UP(regs->regs,2)+2; - return 0; - }else if(regs->regs==MAX_REGS-1){ - regs->regs=MAX_REGS; - } - - return 2; -} -static ALWAYS_INLINE bool is_float_type(int t){ - return t==FLOAT_TYPE||t==DOUBLE_TYPE; -} -static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ - struct ctype* mt; - int type,ele_count,i,ct_usr; - lua_getuservalue(L,idx); - ct_usr=lua_absindex(L,-1); - lua_rawgeti(L,ct_usr,1); - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - if(ct->type==COMPLEX_DOUBLE_TYPE){ - if(isfloat) *isfloat=0; - return 4; - }else if(ct->type==COMPLEX_FLOAT_TYPE){ - if(isfloat) *isfloat=1; - return 2; - } - return 0; - } - type=mt->type; - ele_count=(int)(ct->base_size/mt->base_size); - if(ele_count>4||ct->base_size%mt->base_size){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - for (i = 2; i <=4 ; ++i) { - lua_rawgeti(L,ct_usr,i); - if(lua_isnil(L,-1)){//case have array member; - lua_pop(L,1); - break; - } - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - } - if(isfloat){ - *isfloat=mt->type==FLOAT_TYPE; - } - lua_pop(L,1); - return ele_count*(mt->type==FLOAT_TYPE?1:2); -} -#if ARM_HF -static void save_float_reg(struct jit* Dst,int reg,int size,stack_info* st){ - int sz; - if(reg==-1) return; - for(;size>0;size-=8){ - sz=size>8?8:size; - switch(sz){ - case 4: - switch(reg){ - case 0: - break; - case 1: - break; - case 2: - break; - case 3: - break; - case 4: - break; - case 5: - break; - case 6: - break; - case 7: - break; - case 8: - break; - case 9: - break; - case 10: - break; - case 11: - break; - case 12: - break; - case 13: - break; - case 14: - break; - case 15: - break; - } - break; - case 8: - switch(reg>>1){ - case 0: - break; - case 1: - break; - case 2: - break; - case 3: - break; - case 4: - break; - case 5: - break; - case 6: - break; - case 7: - break; - } - reg+=2; - break; - } - st->float_size+=sz; - } -} - -//128 bit vector type is not supported by this -static int add_float_reg(reg_info* regs,int sz,int isfloat){ - - if(is_float_sealed(regs)) return -1; - int i,ret=-1; - if(sz==1){ - if(regs->left_single){ - int n=regs->highest_bit; - for(i=0;i<n;++i){ - if(!has_bit(regs->floats,i)){ - regs->left_single--; - set_bit(regs->floats,i); - ret=i; - } - } - }else{ - ret=regs->highest_bit; - set_bit(regs->floats,regs->highest_bit); - ++regs->highest_bit; - } - }else{ - if(regs->highest_bit>MAX_FLOAT_REGS-sz){ - regs->highest_bit=MAX_FLOAT_REGS; - }else{ - if(!isfloat&&!ALIGNED(regs->highest_bit, 2)){ - regs->highest_bit++; - regs->left_single++; - } - ret=regs->highest_bit; - for(i=0;i<sz;++i){ - set_bit(regs->floats,regs->highest_bit++); - } - } - } - if(regs->highest_bit==MAX_FLOAT_REGS){ - regs->float_sealed=true; - } - return ret; -} -#endif -static void load_reg(struct jit* Dst,int off,int size){ - if(size==16){ - dasm_put(Dst, 0, off); - }else if(size==12){ - dasm_put(Dst, 4, off); - }else if(size==8){ - dasm_put(Dst, 8, off); - }else{ - dasm_put(Dst, 12, off); - } -} -// arm store/load range for immediate value is only -256-255 -static void load_stack(struct jit* Dst,stack_info* st,int size,int align){ - int off=st->stack_off; - FIX_ALIGN(st->stack_off,align); - if((off=st->stack_off-off)){ - dasm_put(Dst, 15, off); - } - if(size==16){ - dasm_put(Dst, 18); - }else if(size==8){ - dasm_put(Dst, 20); - }else{ - dasm_put(Dst, 22); - } - st->stack_off+=size; -} - -static void load_int(struct jit* Dst,stack_info* st,int size,int align){ - FIX_ALIGN(st->int_off,align); - if(st->int_off<0x40*ARM_HF+MAX_REGS*4&&(!st->stack_off||MAX_REGS*4+size<=0x40*ARM_HF+MAX_REGS*4)){ - load_reg(Dst,st->int_off+st->extra,size); - st->int_off+=size; - }else{ - st->int_off=0x40*ARM_HF+MAX_REGS*4; - load_stack(Dst,st,size,align); - } - -} - -static void load_float(struct jit* Dst,stack_info* st,int size,int vfp,int align){ - #if ARM_HF - if(st->float_off<st->float_size){ - if(vfp){ - if(size==4){//float - }else if(size==8){//double - } - }else load_reg(Dst,st->float_off+st->extra,size); - st->float_off+=size; - }else if(vfp){ - if(size==4){//float - }else if(size==8){//double - int off=st->stack_off; - FIX_ALIGN(st->stack_off,align); - if((off=st->stack_off-off)){ - } - } - }else{ - load_stack(Dst,st,size,align); - } - #else - load_int(Dst,st,size,align); - #endif -} -#if ARM_HF -static void push_regs(lua_State* L,struct jit* Dst,int ct_usr,int nargs,stack_info* st){ - const struct ctype* mt; - reg_info regs;int i; - memset(®s,0,sizeof(reg_info)); - for (i = 1; i <= nargs&&!is_float_sealed(®s); ++i){ - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers &&! mt->is_reference) { - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - save_float_reg(Dst,add_float_reg(®s,4,0),16,st); - break; - case DOUBLE_TYPE: - save_float_reg(Dst,add_float_reg(®s,2,0),8,st); - break; - case COMPLEX_FLOAT_TYPE: - save_float_reg(Dst,add_float_reg(®s,2,1),8,st); - break; - case FLOAT_TYPE: - save_float_reg(Dst,add_float_reg(®s,1,1),4,st); - break; - case STRUCT_TYPE: - { - int isfloat,hfasize=hfa_size(L,-1,mt,&isfloat); - if(hfasize){ - save_float_reg(Dst,add_float_reg(®s,hfasize,isfloat),4*hfasize,st); - break; - } - } - case UNION_TYPE: - break; - case INT64_TYPE: - //add_int64_reg(®s); - break; - default: - //add_int_reg(®s);//no need to check type support here - break; - } - } - lua_pop(L,1); - } - st->float_off+=st->int_off; - st->int_off+=0x40; -} -#endif -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; - stack_info st; - - 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"); - } - memset(&st,0,sizeof(stack_info)); - st.extra=0x10; - /* prolog and get the upval table */ - dasm_put(Dst, 24); -#if ARM_HF - push_regs(L,Dst,ct_usr,nargs,&st); -#endif - - dasm_put(Dst, 27, (unsigned short)(L), (((unsigned int)(L))>>16), (unsigned short)(ref), (((unsigned int)(ref))>>16), (unsigned short)(LUA_REGISTRYINDEX), (((unsigned int)(LUA_REGISTRYINDEX))>>16)); - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - - - dasm_put(Dst, 45, num_upvals); - - // Complex type is return in the address stored in r0 for softfp - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if(!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| - (!ARM_HF&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(ARM_HF&&hfa_size(L,-1,mt,NULL))){ - st.int_off+=4; - } - lua_pop(L,1); - - //whether 64 bit type requires 8 bytes alignment in stack is defined by compiler.android compiler reqiures only 4 byte alignment; - //actually the stack it self may reqiures 8 bytes alignment - 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, 52, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_int(Dst,&st,4,4); - dasm_put(Dst, 68); - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - #if ARM_HF - int isfloat,hfasize=0; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - #endif - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 74, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - #if ARM_HF - if(hfasize){ - if(hfasize<=4)load_float(Dst,&st,4*hfasize,0,4*(2-isfloat)); - switch(hfasize){ - case 8: - load_float(Dst,&st,16,0,8); - load_float(Dst,&st,16,0,8); - break; - case 6: - load_float(Dst,&st,16,0,8); - load_float(Dst,&st,8,0,8); - break; - case 4: - break; - case 3: - break; - case 2: - break; - case 1: - break; - } - }else - #endif - if(!mt->is_empty){ - int size=mt->base_size; - if(size<=4){ - load_int(Dst,&st,4,4); - dasm_put(Dst, 90); - }else{ - size=ROUND_UP(size,4); - if(mt->align_mask>4){//8 byte max alignment - if(st.int_off<0x40*ARM_HF+MAX_REGS*4){FIX_ALIGN(st.int_off,8);} - else {FIX_ALIGN(st.stack_off,8);} - } - - if(st.int_off<0x40*ARM_HF+MAX_REGS*4&&(!st.stack_off||st.int_off+size<=0x40*ARM_HF+MAX_REGS*4)){//to ensure consective memory for the struct - dasm_put(Dst, 92, st.int_off+st.extra); - st.int_off+=size; - }else{ - st.int_off=0x40*ARM_HF+MAX_REGS*4; - dasm_put(Dst, 95); - st.stack_off+=size; - } - dasm_put(Dst, 97, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); - } - } - dasm_put(Dst, 107); - break; - } - - case COMPLEX_DOUBLE_TYPE: - - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 112, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_float(Dst,&st,16,0,8); - dasm_put(Dst, 128); - break; - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 134, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_float(Dst,&st,8,0,4); - dasm_put(Dst, 150); - break; - case INT64_TYPE: - - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - - #if CK_ALGIN - FIX_ALIGN(st.int_off,8); - if(st.int_off<16){ - dasm_put(Dst, 156, st.int_off+st.extra); - st.int_off+=8; - }else{ - if(!ALIGNED(st.stack_off,8)){ - st.stack_off+=4; - dasm_put(Dst, 160); - } - dasm_put(Dst, 162); - st.stack_off+=8; - } - #else - load_int(Dst,st,8,8); - #endif - dasm_put(Dst, 164); - #else - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 168, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_int(Dst,&st,8,8); - dasm_put(Dst, 177); - #endif - break; - - case INTPTR_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 183, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_int(Dst,&st,4,4); - dasm_put(Dst, 192); - - break; - - case BOOL_TYPE: - lua_pop(L, 1); - - load_int(Dst,&st,4,4); - dasm_put(Dst, 198); - break; - - case INT8_TYPE: // no need to narrow cause narrowed by caller - case INT16_TYPE: // no need to narrow cause narrowed by caller - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - - load_int(Dst,&st,4,4); - dasm_put(Dst, 202); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - - load_float(Dst,&st,4,ARM_HF,4); - dasm_put(Dst, 206); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - - #if ARM_HF - load_float(Dst,&st,8,ARM_HF,8); - #elif CK_ALGIN - FIX_ALIGN(st.int_off,8); - if(st.int_off<16){ - dasm_put(Dst, 210, st.int_off+st.extra); - st.int_off+=8; - }else{ - if(!ALIGNED(st.stack_off,8)){ - st.stack_off+=4; - dasm_put(Dst, 214); - } - dasm_put(Dst, 216); - st.stack_off+=8; - } - #else - load_float(Dst,&st,8,ARM_HF,8); - #endif - dasm_put(Dst, 218); - 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, 222, ((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, 230, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - goto single_no_pop; - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - int isfloat,hfasize=0; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 246, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - #if ARM_HF - if(hfasize>0){ - switch(hfasize){ - case 8: - break; - case 6: - break; - case 4: - break; - case 3: - break; - case 2: - break; - case 1: - break; - } - }else - #endif - if(!mt->is_empty){ - if(mt->base_size<=4){ - dasm_put(Dst, 267); - }else{ - dasm_put(Dst, 269, st.extra+0x40*ARM_HF, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); - } - } - break; - } - 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, 282, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - - goto single_no_pop; - - case VOID_TYPE: - dasm_put(Dst, 298); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - case INT8_TYPE:// narrow it - case INT16_TYPE:// narrow it - case INT32_TYPE: - dasm_put(Dst, 303); - if (mt->is_unsigned) { - dasm_put(Dst, 305); - } else { - dasm_put(Dst, 309); - } - switch(mt->type){ - case BOOL_TYPE: - dasm_put(Dst, 313); - break; - case INT8_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 316); - } else { - dasm_put(Dst, 318); - } - break; - case INT16_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 320); - } else { - dasm_put(Dst, 322); - } - break; - } - goto single; - - case INT64_TYPE: - dasm_put(Dst, 324); - if (mt->is_unsigned) { - dasm_put(Dst, 326); - } else { - dasm_put(Dst, 330); - } - goto dual; - - case INTPTR_TYPE: - dasm_put(Dst, 334); - goto single; - - case FLOAT_TYPE: - dasm_put(Dst, 339); - #if ARM_HF - lua_pop(L, 1); - #else - goto single; - #endif - break; - case DOUBLE_TYPE: - dasm_put(Dst, 344); - #if ARM_HF - lua_pop(L, 1); - #else - goto dual; - #endif - break; - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 349, st.extra); - break; - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 360, st.extra); - break; - - single: - lua_pop(L, 1); - single_no_pop: - dasm_put(Dst, 371); - - break; - dual: - dasm_put(Dst, 378); - - lua_pop(L, 1); - break; - - - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 387); - - 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; - } -} - -static ALWAYS_INLINE void save_int64_stack_align(struct jit* Dst,reg_info* regs,int align){ - if(align&&!ALIGNED(regs->exs,2)){ - regs->exs++; - dasm_put(Dst, 389); - } - dasm_put(Dst, 391); - regs->exs+=2; -} - -static ALWAYS_INLINE void save_int64_align(struct jit* Dst,reg_info* regs,int align){ - if((align&&!ALIGNED(regs->ints,2))||(regs->ints==MAX_REGS-1&®s->exs/*to ensure consective memory*/)){ - regs->ints++; - } - if(regs->ints<MAX_REGS){ - dasm_put(Dst, 393, ((regs->ints<<2)+0x40*ARM_HF)); - regs->ints+=2; - }else{ - save_int64_stack_align(Dst,regs,align); - } - -} - -static ALWAYS_INLINE void save_int64(struct jit* Dst,reg_info* regs){ - save_int64_align(Dst,regs,1); -} - -static ALWAYS_INLINE void save_int_stack_align(struct jit* Dst,reg_info* regs){ - dasm_put(Dst, 397); - regs->exs++; -} - -static ALWAYS_INLINE void save_int(struct jit* Dst,reg_info* regs){ - if(regs->ints<MAX_REGS){ - dasm_put(Dst, 399, ((regs->ints++<<2)+0x40*ARM_HF)); - }else{ - save_int_stack_align(Dst,regs); - } -} - -static void save_float(struct jit* Dst,reg_info* regs,int size,int isfloat){ -#if ARM_HF - if(!regs->float_sealed){ - int reg=add_float_reg(regs,size,isfloat); - if(reg<0) goto SAVE_STACK; - switch(size){ - case 8: - case 6: - case 4: - goto sf_2; - case 3: - case 2: - sf_2: - break; - case 1: - break; - } - return; - } - SAVE_STACK: - - if(!isfloat&&!ALIGNED(regs->exs,2)){ - regs->exs++; - dasm_put(Dst, 402); - } - switch(size){ - case 1: - dasm_put(Dst, 404); - break; - case 2: - dasm_put(Dst, 406); - break; - case 3: - dasm_put(Dst, 408); - break; - case 4: - dasm_put(Dst, 410); - break; - case 6: - dasm_put(Dst, 412); - break; - case 8: - dasm_put(Dst, 414); - break; - - } - regs->exs+=size; - -#else - if(size==1){ - save_int(Dst,regs); - }else if(size==2){ - save_int64_align(Dst,regs,!isfloat); - } -#endif -} - -static int calculate_stack(lua_State* L,int ct_usr,int nargs){ - const struct ctype* mt; - reg_info regs;int i,stack=0; - memset(®s,0,sizeof(reg_info)); - 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) { - stack+=add_int_reg(®s); - }else{ - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - #if ARM_HF - stack+=add_float_reg(®s,4,0)<0?4:0; - #else - stack+=add_int64_reg(®s); - stack+=add_int64_reg(®s); - #endif - FIX_ALIGN(stack,2); - break; - case DOUBLE_TYPE: - #if ARM_HF - stack+=add_float_reg(®s,2,0)<0?2:0; - #else - stack+=add_int64_reg(®s); - #endif - FIX_ALIGN(stack,2); - break; - case COMPLEX_FLOAT_TYPE:// Though complex alignment is 4, but vfp requires a sequence of regsiters - #if ARM_HF - stack+=add_float_reg(®s,2,1)<0?2:0; - #else - stack+=add_int_reg(®s); - stack+=add_int_reg(®s); - #endif - break; - case FLOAT_TYPE: - #if ARM_HF - stack+=add_float_reg(®s,1,1)<0?1:0; - #else - stack+=add_int_reg(®s); - #endif - break; - case INT64_TYPE: - stack+=add_int64_reg(®s); - FIX_ALIGN(stack,2); - break; - case STRUCT_TYPE:{ - #if ARM_HF - int isfloat; - int hfasize=hfa_size(L,-1,mt,&isfloat); - if(hfasize>0){ - stack+=add_float_reg(®s,2,0)<0?hfasize:0; - if(!isfloat){ - FIX_ALIGN(stack,2); - } - break; - } - #endif - } - case UNION_TYPE:{ - int intsize=(mt->base_size+3)>>2; - if(mt->align_mask>4){//8-byte max alignment - if(regs.ints<MAX_REGS){ - FIX_ALIGN(regs.ints,2); - }else{ - FIX_ALIGN(stack,2); - } - } - - if(regs.ints+intsize<=MAX_REGS){ - regs.ints+=intsize; - }else{ - stack+=regs.ints+intsize-MAX_REGS; - regs.ints=MAX_REGS; - } - break; - } - default: - stack+=add_int_reg(®s);//no need to check type support here - } - } - lua_pop(L,1); - } - FIX_ALIGN(stack,2); - return (regs.ints - #if ARM_HF - /**/||regs.floats - #endif - )?0x40*ARM_HF+0x10+stack*4:0; -} - -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,ret_by_addr, stack_size; - const struct ctype* mt; - void* p; reg_info regs; - - 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); -#if defined __thumb__ //keep frame pointer - dasm_put(Dst, 416); -#else - dasm_put(Dst, 419); -#endif -#if CK_ALGIN - dasm_put(Dst, 422); -#endif - dasm_put(Dst, 424); - - /* Reserve enough stack space for all of the arguments. For hard floating point, - * leave extra 64 bytes - */ - stack_size=calculate_stack(L,ct_usr,nargs); - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - // Complex types in softfp and structs/unions larger than 4-bytes are return in the address stored in r0 - ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| - (!ARM_HF&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(ARM_HF&&hfa_size(L,-1,mt,NULL)); - lua_pop(L,1); - if(ret_by_addr){ - if(stack_size==0) - stack_size=0x40*ARM_HF+0x10; - stack_size+=8; - } - if(stack_size>0){ - if(stack_size>=1<<12){ - dasm_put(Dst, 426, (unsigned short)(stack_size), (((unsigned int)(stack_size))>>16)); - }else{ - dasm_put(Dst, 432, stack_size); - } - if (ct->has_var_arg){ - dasm_put(Dst, 435, nargs, (unsigned short)("too few arguments"), (((unsigned int)("too few arguments"))>>16)); - } - dasm_put(Dst, 452, 0x40*ARM_HF+0x10); - } - - memset(®s,0,sizeof(reg_info)); - - if (ret_by_addr) { - regs.ints++; - dasm_put(Dst, 455, (unsigned short)(mt), (((unsigned int)(mt))>>16), 0x40*ARM_HF); - } - - - 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|| mt->type==STRUCT_TYPE || mt->type==UNION_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - - dasm_put(Dst, 466, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16), i); - - if (mt->pointers || mt->is_reference) { - dasm_put(Dst, 477); - } else if (mt->type == FUNCTION_PTR_TYPE) { - dasm_put(Dst, 481); - } else if (mt->type == ENUM_TYPE) { - dasm_put(Dst, 485); - }else if(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE){ - if(mt->is_empty) continue; - dasm_put(Dst, 489); - #if ARM_HF - { - int hfasize,isfloat; - hfasize=hfa_size(L,-2,mt,&isfloat); - if(hfasize){ - switch(hfasize){ - case 8: - break; - case 6: - break; - case 4: - break; - case 3: - break; - case 2: - break; - case 1: - break; - - } - save_float(Dst,®s,hfasize,isfloat); - continue; - } - } - #endif - - if(mt->align_mask>4){//8 byte max alignment - if(regs.ints<4){ - FIX_ALIGN(regs.ints,2) - }else if(!ALIGNED(regs.exs,2)){ - int diff=regs.exs; - regs.exs+=4; - dasm_put(Dst, 493); - } - } - int size=ROUND_UP(mt->base_size,4)>>2; - dasm_put(Dst, 495, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); - if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+size<=MAX_REGS)){//to ensure consective memory for the struct - dasm_put(Dst, 505, ((regs.ints<<2)+0x40*ARM_HF)); - }else{ - regs.ints=MAX_REGS; - dasm_put(Dst, 508); - } - dasm_put(Dst, 510); - if(regs.ints+size<=MAX_REGS){ - regs.ints+=size; - }else{ - int ex=regs.ints+size-MAX_REGS; - dasm_put(Dst, 512, (ex)<<2); - regs.exs+=ex; - regs.ints=MAX_REGS; - } - continue; - } - - save_int(Dst,®s); - } else { - lua_pop(L, 1); - dasm_put(Dst, 515, i); - - switch (mt->type) { - case BOOL_TYPE: - dasm_put(Dst, 518); - save_int(Dst,®s); - break; - case INT8_TYPE: - dasm_put(Dst, 524); - if (mt->is_unsigned) { - dasm_put(Dst, 528); - } else { - dasm_put(Dst, 530); - } - save_int(Dst,®s); - break; - - case INT16_TYPE: - dasm_put(Dst, 532); - if (mt->is_unsigned) { - dasm_put(Dst, 536); - } else { - dasm_put(Dst, 538); - } - save_int(Dst,®s); - break; - - case INT32_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 540); - } else { - dasm_put(Dst, 544); - } - save_int(Dst,®s); - break; - case INTPTR_TYPE: - dasm_put(Dst, 548); - save_int(Dst,®s); - break; - - case INT64_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 552); - } else { - dasm_put(Dst, 556); - } - save_int64(Dst,®s); - break; - - case DOUBLE_TYPE: - dasm_put(Dst, 560); - save_float(Dst,®s,2,0); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 564); - save_float(Dst,®s,1,1); - break; - - case COMPLEX_DOUBLE_TYPE: - #if ARM_HF - save_float(Dst,®s,4,0); - #else - FIX_ALIGN(regs.ints,2); - dasm_put(Dst, 568); - if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+4<=MAX_REGS)){ - dasm_put(Dst, 571, (regs.ints<<2)); - }else{ - regs.ints=MAX_REGS; - if(!ALIGNED(regs.exs,2)){ - ++regs.exs; - dasm_put(Dst, 574); - } - dasm_put(Dst, 576); - } - dasm_put(Dst, 578); - regs.ints+=4; - goto FIX_REG; - #endif - break; - case COMPLEX_FLOAT_TYPE: - #if ARM_HF - save_float(Dst,®s,2,1); - #else - dasm_put(Dst, 581); - if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+2<=MAX_REGS)){ - dasm_put(Dst, 584, (regs.ints<<2)); - }else{ - regs.ints=MAX_REGS; - dasm_put(Dst, 587); - } - dasm_put(Dst, 589); - regs.ints+=2; - FIX_REG: - if(regs.ints>MAX_REGS){ - dasm_put(Dst, 592, (regs.ints-4)<<2); - regs.exs+=regs.ints-MAX_REGS; - regs.ints=MAX_REGS; - } - #endif - break; - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { - int offset=nargs+1; - dasm_put(Dst, 595, offset); - #if ARM_HF - if(regs.ints==4||regs.float_sealed){ - if(regs.ints<4&®s.float_sealed){//some arg must be loaded to core registers. - } - } - #else - if(regs.ints==4){ - dasm_put(Dst, 598); - } - #endif - else{//no hard floating point in variadic procedure - dasm_put(Dst, 600, ((regs.ints<<2)+ARM_HF*0x40)); - } - - dasm_put(Dst, 603); - regs.ints=4; - } - - #if ARM_HF - switch(ROUND_UP(regs.highest_bit,4)>>1){ - case 8 : - break; - case 7 : - break; - case 6 : - break; - case 5: - break; - case 4 : - break; - case 3 : - break; - case 2 : - break; - case 1 : - break; - } - if(stack_size>0){ - } - #endif - - //pop registers from stack,align 8 for some compiler - assert(regs.ints<=4); - switch(regs.ints){ - case 4: - case 3: - dasm_put(Dst, 608); - break; - case 2: - case 1: - dasm_put(Dst, 610); - #if ARM_HF - if(regs.float_sealed){ - } - #endif - break; - default: - #if ARM_HF - if(regs.float_sealed){ - } - #endif - break; - } - - dasm_put(Dst, 612, (unsigned short)(func), (((unsigned int)(func))>>16)); - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 618, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - - } else { - switch (mt->type) { - case INT64_TYPE: - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - #if CK_ALGIN - dasm_put(Dst, 633); - #else - dasm_put(Dst, 636); - #endif - dasm_put(Dst, 639); - break; - #else - num_upvals++; - dasm_put(Dst, 644, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - break; - #endif - - case INTPTR_TYPE: - num_upvals++; - dasm_put(Dst, 658, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 670); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 672); - break; - - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE:// value must be narrowed before callee return - lua_pop(L, 1); - - dasm_put(Dst, 678); - if (mt->is_unsigned) { - dasm_put(Dst, 680); - } else { - dasm_put(Dst, 684); - } - - dasm_put(Dst, 688); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 690); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - #if CK_ALGIN - dasm_put(Dst, 696); - #else - dasm_put(Dst, 699); - #endif - dasm_put(Dst, 702); - break; - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case STRUCT_TYPE: - case UNION_TYPE:{ - lua_getuservalue(L,-1); - num_upvals += 2; - #if ARM_HF - { - int isfloat,hfasize=hfa_size(L,-2,mt,&isfloat); - if(hfasize>0){ - switch(hfasize){ - case 8: - break; - case 6: - break; - case 4: - case 3: - break; - case 2: - case 1: - break; - - } - switch(hfasize){ - case 8: - break; - case 6: - break; - case 4: - break; - case 3: - break; - case 2: - break; - case 1: - break; - - } - break; - } - } - - #endif - if(mt->base_size>4){ - // value are stored in return storage in r0 for softfp, set usr value here - if(!lua_isnil(L,-1)){ - dasm_put(Dst, 707, (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - } - }else if(mt->is_empty){ - dasm_put(Dst, 719); - break; - }else{ - dasm_put(Dst, 721, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - } - dasm_put(Dst, 735); - break; - } - default: - luaL_error(L, "NYI: call return type"); - } - } - -#ifdef __thumb__ - dasm_put(Dst, 737); -#else - dasm_put(Dst, 740); -#endif - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, NULL, 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); - } -} - +/* +** This file has been pre-processed with DynASM. +** http://luajit.org/dynasm.html +** DynASM version 1.4.0, DynASM arm version 1.4.0 +** DO NOT EDIT! The original file is in "call_arm.dasc". +*/ + +/* 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. + */ + +//The generate code is for arm not for thumb +#if DASM_VERSION != 10400 +#error "Version mismatch between DynASM and included encoding engine" +#endif + +static const unsigned int build_actionlist[743] = { +0xe28dc000, +0x000b0000, +0xe89c100e, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c100e, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c0006, +0x00000000, +0xe51d1000, +0x000e8180, +0x00000000, +0xe2866000, +0x000b0000, +0x00000000, +0xe8b6100e, +0x00000000, +0xe8b60006, +0x00000000, +0xe4961004, +0x00000000, +0xe1a0c00d, +0xe92d000f, +0x00000000, +0xe92d5050, +0xe1a0600c, +0xe3004000, +0x000c0200, +0xe3404000, +0x000c0200, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030000, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030000, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe5801000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe5801000, +0x00000000, +0xe28d1000, +0x000b0000, +0x00000000, +0xe1a01006, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe12fff3c, +0x00000000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe880100e, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe8800006, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c000c, +0x00000000, +0xe2866004, +0x00000000, +0xe8b6000c, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030003, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe8800006, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe5801000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030004, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030005, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030006, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c000c, +0x00000000, +0xe2866004, +0x00000000, +0xe8b6000c, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030007, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3a01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030008, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3e02000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030009, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3e02000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003000a, +0xe1a06000, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0x00000000, +0xe5960000, +0x00000000, +0xe51d0000, +0x000e8180, +0xe1a01006, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe12fff3c, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3e02000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003000c, +0x00000000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003000b, +0x00000000, +0xe3e01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000d, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe3500000, +0x13a00001, +0x00000000, +0xe6ef0070, +0x00000000, +0xe6af0070, +0x00000000, +0xe6ff0070, +0x00000000, +0xe6bf0070, +0x00000000, +0xe3e01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000f, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030010, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030011, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030012, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030013, +0x00000000, +0xe3e02000, +0xe1a01004, +0xe51d0000, +0x000e8180, +0xeb000000, +0x00030014, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0x00000000, +0xe3e02000, +0xe1a01004, +0xe51d0000, +0x000e8180, +0xeb000000, +0x00030015, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0x00000000, +0xe1a06000, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0xe1a00006, +0x00000000, +0xe1a06000, +0xe1a00004, +0xe1a04001, +0xe3e01002, +0xeb000000, +0x0003000b, +0xe1a00006, +0xe1a01004, +0x00000000, +0xe89da050, +0x00000000, +0xe2866004, +0x00000000, +0xe8a60003, +0x00000000, +0xe28dc000, +0x000b0000, +0xe88c0003, +0x00000000, +0xe4860004, +0x00000000, +0xe50d0000, +0x000e8180, +0x00000000, +0xe2866004, +0x00000000, +0xeca60a01, +0x00000000, +0xeca60b02, +0x00000000, +0xeca60a04, +0x00000000, +0xeca60b04, +0x00000000, +0xeca60b06, +0x00000000, +0xeca60b08, +0x00000000, +0xe92d40f0, +0xe28d700c, +0x00000000, +0xe92d4870, +0xe28db00c, +0x00000000, +0xe24dd004, +0x00000000, +0xe1a04000, +0x00000000, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe04dd00c, +0x00000000, +0xe24dd000, +0x000b0000, +0x00000000, +0xeb000000, +0x00030016, +0xe3500000, +0x000b0000, +0xaa000000, +0x00050001, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030017, +0x0006000b, +0xe1a05000, +0xe04dd185, +0x00000000, +0xe28d6000, +0x000b0000, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0xe50d0000, +0x000e8180, +0x00000000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0x000b0000, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030009, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030018, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000c, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000a, +0x00000000, +0xe2866004, +0x00000000, +0xe1a01000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0x00000000, +0xe28d0000, +0x000b0000, +0x00000000, +0xe1a00006, +0x00000000, +0xe12fff3c, +0x00000000, +0xe2866000, +0x000b0000, +0x00000000, +0xe3a01000, +0x000b0000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0xe3500000, +0x13a00001, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe6ef0070, +0x00000000, +0xe6af0070, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe6ff0070, +0x00000000, +0xe6bf0070, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000d, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030011, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000f, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030010, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030013, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030012, +0x00000000, +0xe1a02001, +0xe1a01004, +0x00000000, +0xe28d0000, +0x000b0000, +0x00000000, +0xe2866004, +0x00000000, +0xe1a00006, +0x00000000, +0xeb000000, +0x00030014, +0x00000000, +0xe1a02001, +0xe1a01004, +0x00000000, +0xe28d0000, +0x000b0000, +0x00000000, +0xe1a00006, +0x00000000, +0xeb000000, +0x00030015, +0x00000000, +0xe2866000, +0x000b0000, +0x00000000, +0xe3a01000, +0x000b0000, +0x00000000, +0xe1a03006, +0x00000000, +0xe28d3000, +0x000b0000, +0x00000000, +0xe1a02005, +0xe1a00004, +0xeb000000, +0x00030019, +0x00000000, +0xe8bd000f, +0x00000000, +0xe8bd0003, +0x00000000, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe12fff3c, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0xe3a00001, +0x00000000, +0xe1a03001, +0xe1a02000, +0x00000000, +0xe1a02001, +0xe1a01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030003, +0xe3a00001, +0x00000000, +0xe1a06000, +0xe1a05001, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0xe5805004, +0xe3a00001, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0xe3a00001, +0x00000000, +0xe3a00000, +0x00000000, +0xe1a01000, +0xe1a00004, +0xeb000000, +0x00030004, +0xe3a00001, +0x00000000, +0xe1a01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003001a, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030005, +0x00000000, +0xe3a00001, +0x00000000, +0xe1a01000, +0xe1a00004, +0xeb000000, +0x00030006, +0xe3a00001, +0x00000000, +0xe1a03001, +0xe1a02000, +0x00000000, +0xe1a02001, +0xe1a01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030007, +0xe3a00001, +0x00000000, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x0003001b, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003001c, +0x00000000, +0xe3a00000, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0x00000000, +0xe3a00001, +0x00000000, +0xe247d00c, +0xe8bd80f0, +0x00000000, +0xe24bd00c, +0xe8bd8870, +0x00000000 +}; + +static const char *const globnames[] = { + (const char *)0 +}; +static const char *const extnames[] = { + "rawgeti", + "push_cdata", + "lua_remove", + "lua_pushinteger", + "lua_pushboolean", + "push_int", + "push_float", + "lua_pushnumber", + "lua_call", + "check_typed_pointer", + "check_struct", + "lua_settop", + "check_enum", + "check_uint32", + "check_int32", + "check_uint64", + "check_int64", + "check_uintptr", + "check_float", + "check_double", + "check_complex_double", + "check_complex_float", + "lua_gettop", + "luaL_error", + "check_typed_cfunction", + "unpack_varargs_stack", + "push_uint", + "lua_pushvalue", + "lua_setuservalue", + (const char *)0 +}; + +#define JUMP_SIZE 8 + +#define MIN_BRANCH ((INT32_MIN) >> 8) +#define MAX_BRANCH ((INT32_MAX) >> 8) +//arm pc offset 8 so comparing with next instruction is 4, +//unlike x86 which pass in the current instruction address+1 rather than the next instruction +#define BRANCH_OFF 4 + + +#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) +#ifdef TARGET_OS_IPHONE +#define CK_ALGIN 0 +#else +#define CK_ALGIN 1 +#endif +#define ALIGNED(x, align) (!CK_ALGIN||((int)(x) & (align - 1)) == 0) +#if defined(__ARM_PCS_VFP) || (GCC_VERSION==40500||defined(__clang__))&&!defined(__ARM_PCS) && !defined(__SOFTFP__) && !defined(__SOFTFP) && \ + defined(__VFP_FP__) +#define ARM_HF 1 +#else +#define ARM_HF 0 +#endif +#if ARM_HF&&!CK_ALGIN +#error "Unsupported unaligned stack for hard floating point" +#endif + +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; +} + +typedef struct stack_info{ + int extra; + int int_off; + int stack_off; + int float_size; +#if ARM_HF + int float_off; +#endif +} stack_info; +//vfp use back-filling rule for registers until a float value on stack +typedef struct reg_info{ + uint16_t exs; + union{ + uint8_t ints; + uint8_t regs; + }; +#if ARM_HF + uint8_t float_sealed; + short floats;//each bit is a float: s0-s15 or v0-v7 or q0-q3 + uint8_t left_single; + uint8_t highest_bit; +#endif +} reg_info; + +#define MAX_REGS 4 +#define MAX_FLOAT_REGS 16 +#ifndef bool +#define bool uint8_t +#endif + +#define has_bit(x,b) (((x)&(1<<(b)))!=0) +#define set_bit(x,b) (x=((x)|(1<<(b)))) +#define FIX_ALIGN(x,al) \ + if(!ALIGNED((x),al)){\ + x=ROUND_UP(x,al);\ + } +static ALWAYS_INLINE bool is_float_sealed(reg_info* regs){ +#if ARM_HF +return regs->float_sealed; +#else +return regs->regs>=MAX_REGS; +#endif +} +//return size need to put on stack +static ALWAYS_INLINE int add_int_reg(reg_info* regs){ + if(regs->regs<MAX_REGS){ + regs->regs++; + return 0; + } + return 1; + +} +//return size need to put on stack +static ALWAYS_INLINE int add_int64_reg(reg_info* regs){ + if(regs->regs<MAX_REGS-1){ + regs->regs=ROUND_UP(regs->regs,2)+2; + return 0; + }else if(regs->regs==MAX_REGS-1){ + regs->regs=MAX_REGS; + } + + return 2; +} +static ALWAYS_INLINE bool is_float_type(int t){ + return t==FLOAT_TYPE||t==DOUBLE_TYPE; +} +static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ + struct ctype* mt; + int type,ele_count,i,ct_usr; + lua_getuservalue(L,idx); + ct_usr=lua_absindex(L,-1); + lua_rawgeti(L,ct_usr,1); + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + if(ct->type==COMPLEX_DOUBLE_TYPE){ + if(isfloat) *isfloat=0; + return 4; + }else if(ct->type==COMPLEX_FLOAT_TYPE){ + if(isfloat) *isfloat=1; + return 2; + } + return 0; + } + type=mt->type; + ele_count=(int)(ct->base_size/mt->base_size); + if(ele_count>4||ct->base_size%mt->base_size){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + for (i = 2; i <=4 ; ++i) { + lua_rawgeti(L,ct_usr,i); + if(lua_isnil(L,-1)){//case have array member; + lua_pop(L,1); + break; + } + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + } + if(isfloat){ + *isfloat=mt->type==FLOAT_TYPE; + } + lua_pop(L,1); + return ele_count*(mt->type==FLOAT_TYPE?1:2); +} +#if ARM_HF +static void save_float_reg(struct jit* Dst,int reg,int size,stack_info* st){ + int sz; + if(reg==-1) return; + for(;size>0;size-=8){ + sz=size>8?8:size; + switch(sz){ + case 4: + switch(reg){ + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + case 12: + break; + case 13: + break; + case 14: + break; + case 15: + break; + } + break; + case 8: + switch(reg>>1){ + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + } + reg+=2; + break; + } + st->float_size+=sz; + } +} + +//128 bit vector type is not supported by this +static int add_float_reg(reg_info* regs,int sz,int isfloat){ + + if(is_float_sealed(regs)) return -1; + int i,ret=-1; + if(sz==1){ + if(regs->left_single){ + int n=regs->highest_bit; + for(i=0;i<n;++i){ + if(!has_bit(regs->floats,i)){ + regs->left_single--; + set_bit(regs->floats,i); + ret=i; + } + } + }else{ + ret=regs->highest_bit; + set_bit(regs->floats,regs->highest_bit); + ++regs->highest_bit; + } + }else{ + if(regs->highest_bit>MAX_FLOAT_REGS-sz){ + regs->highest_bit=MAX_FLOAT_REGS; + }else{ + if(!isfloat&&!ALIGNED(regs->highest_bit, 2)){ + regs->highest_bit++; + regs->left_single++; + } + ret=regs->highest_bit; + for(i=0;i<sz;++i){ + set_bit(regs->floats,regs->highest_bit++); + } + } + } + if(regs->highest_bit==MAX_FLOAT_REGS){ + regs->float_sealed=true; + } + return ret; +} +#endif +static void load_reg(struct jit* Dst,int off,int size){ + if(size==16){ + dasm_put(Dst, 0, off); + }else if(size==12){ + dasm_put(Dst, 4, off); + }else if(size==8){ + dasm_put(Dst, 8, off); + }else{ + dasm_put(Dst, 12, off); + } +} +// arm store/load range for immediate value is only -256-255 +static void load_stack(struct jit* Dst,stack_info* st,int size,int align){ + int off=st->stack_off; + FIX_ALIGN(st->stack_off,align); + if((off=st->stack_off-off)){ + dasm_put(Dst, 15, off); + } + if(size==16){ + dasm_put(Dst, 18); + }else if(size==8){ + dasm_put(Dst, 20); + }else{ + dasm_put(Dst, 22); + } + st->stack_off+=size; +} + +static void load_int(struct jit* Dst,stack_info* st,int size,int align){ + FIX_ALIGN(st->int_off,align); + if(st->int_off<0x40*ARM_HF+MAX_REGS*4&&(!st->stack_off||MAX_REGS*4+size<=0x40*ARM_HF+MAX_REGS*4)){ + load_reg(Dst,st->int_off+st->extra,size); + st->int_off+=size; + }else{ + st->int_off=0x40*ARM_HF+MAX_REGS*4; + load_stack(Dst,st,size,align); + } + +} + +static void load_float(struct jit* Dst,stack_info* st,int size,int vfp,int align){ + #if ARM_HF + if(st->float_off<st->float_size){ + if(vfp){ + if(size==4){//float + }else if(size==8){//double + } + }else load_reg(Dst,st->float_off+st->extra,size); + st->float_off+=size; + }else if(vfp){ + if(size==4){//float + }else if(size==8){//double + int off=st->stack_off; + FIX_ALIGN(st->stack_off,align); + if((off=st->stack_off-off)){ + } + } + }else{ + load_stack(Dst,st,size,align); + } + #else + load_int(Dst,st,size,align); + #endif +} +#if ARM_HF +static void push_regs(lua_State* L,struct jit* Dst,int ct_usr,int nargs,stack_info* st){ + const struct ctype* mt; + reg_info regs;int i; + memset(®s,0,sizeof(reg_info)); + for (i = 1; i <= nargs&&!is_float_sealed(®s); ++i){ + lua_rawgeti(L, ct_usr, i); + mt = (const struct ctype*) lua_touserdata(L, -1); + if (!mt->pointers &&! mt->is_reference) { + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + save_float_reg(Dst,add_float_reg(®s,4,0),16,st); + break; + case DOUBLE_TYPE: + save_float_reg(Dst,add_float_reg(®s,2,0),8,st); + break; + case COMPLEX_FLOAT_TYPE: + save_float_reg(Dst,add_float_reg(®s,2,1),8,st); + break; + case FLOAT_TYPE: + save_float_reg(Dst,add_float_reg(®s,1,1),4,st); + break; + case STRUCT_TYPE: + { + int isfloat,hfasize=hfa_size(L,-1,mt,&isfloat); + if(hfasize){ + save_float_reg(Dst,add_float_reg(®s,hfasize,isfloat),4*hfasize,st); + break; + } + } + case UNION_TYPE: + break; + case INT64_TYPE: + //add_int64_reg(®s); + break; + default: + //add_int_reg(®s);//no need to check type support here + break; + } + } + lua_pop(L,1); + } + st->float_off+=st->int_off; + st->int_off+=0x40; +} +#endif +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; + stack_info st; + + 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"); + } + memset(&st,0,sizeof(stack_info)); + st.extra=0x10; + /* prolog and get the upval table */ + dasm_put(Dst, 24); +#if ARM_HF + push_regs(L,Dst,ct_usr,nargs,&st); +#endif + + dasm_put(Dst, 27, (unsigned short)(L), (((unsigned int)(L))>>16), (unsigned short)(ref), (((unsigned int)(ref))>>16), (unsigned short)(LUA_REGISTRYINDEX), (((unsigned int)(LUA_REGISTRYINDEX))>>16)); + + /* get the lua function */ + lua_pushvalue(L, fidx); + lua_rawseti(L, -2, ++num_upvals); + + + dasm_put(Dst, 45, num_upvals); + + // Complex type is return in the address stored in r0 for softfp + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + if(!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| + (!ARM_HF&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(ARM_HF&&hfa_size(L,-1,mt,NULL))){ + st.int_off+=4; + } + lua_pop(L,1); + + //whether 64 bit type requires 8 bytes alignment in stack is defined by compiler.android compiler reqiures only 4 byte alignment; + //actually the stack it self may reqiures 8 bytes alignment + 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, 52, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_int(Dst,&st,4,4); + dasm_put(Dst, 68); + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + #if ARM_HF + int isfloat,hfasize=0; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + #endif + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 74, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + #if ARM_HF + if(hfasize){ + if(hfasize<=4)load_float(Dst,&st,4*hfasize,0,4*(2-isfloat)); + switch(hfasize){ + case 8: + load_float(Dst,&st,16,0,8); + load_float(Dst,&st,16,0,8); + break; + case 6: + load_float(Dst,&st,16,0,8); + load_float(Dst,&st,8,0,8); + break; + case 4: + break; + case 3: + break; + case 2: + break; + case 1: + break; + } + }else + #endif + if(!mt->is_empty){ + int size=mt->base_size; + if(size<=4){ + load_int(Dst,&st,4,4); + dasm_put(Dst, 90); + }else{ + size=ROUND_UP(size,4); + if(mt->align_mask>4){//8 byte max alignment + if(st.int_off<0x40*ARM_HF+MAX_REGS*4){FIX_ALIGN(st.int_off,8);} + else {FIX_ALIGN(st.stack_off,8);} + } + + if(st.int_off<0x40*ARM_HF+MAX_REGS*4&&(!st.stack_off||st.int_off+size<=0x40*ARM_HF+MAX_REGS*4)){//to ensure consective memory for the struct + dasm_put(Dst, 92, st.int_off+st.extra); + st.int_off+=size; + }else{ + st.int_off=0x40*ARM_HF+MAX_REGS*4; + dasm_put(Dst, 95); + st.stack_off+=size; + } + dasm_put(Dst, 97, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); + } + } + dasm_put(Dst, 107); + break; + } + + case COMPLEX_DOUBLE_TYPE: + + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 112, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_float(Dst,&st,16,0,8); + dasm_put(Dst, 128); + break; + case COMPLEX_FLOAT_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 134, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_float(Dst,&st,8,0,4); + dasm_put(Dst, 150); + break; + case INT64_TYPE: + + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + + #if CK_ALGIN + FIX_ALIGN(st.int_off,8); + if(st.int_off<16){ + dasm_put(Dst, 156, st.int_off+st.extra); + st.int_off+=8; + }else{ + if(!ALIGNED(st.stack_off,8)){ + st.stack_off+=4; + dasm_put(Dst, 160); + } + dasm_put(Dst, 162); + st.stack_off+=8; + } + #else + load_int(Dst,st,8,8); + #endif + dasm_put(Dst, 164); + #else + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 168, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_int(Dst,&st,8,8); + dasm_put(Dst, 177); + #endif + break; + + case INTPTR_TYPE: + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 183, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_int(Dst,&st,4,4); + dasm_put(Dst, 192); + + break; + + case BOOL_TYPE: + lua_pop(L, 1); + + load_int(Dst,&st,4,4); + dasm_put(Dst, 198); + break; + + case INT8_TYPE: // no need to narrow cause narrowed by caller + case INT16_TYPE: // no need to narrow cause narrowed by caller + case ENUM_TYPE: + case INT32_TYPE: + lua_pop(L, 1); + + load_int(Dst,&st,4,4); + dasm_put(Dst, 202); + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + + load_float(Dst,&st,4,ARM_HF,4); + dasm_put(Dst, 206); + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + + #if ARM_HF + load_float(Dst,&st,8,ARM_HF,8); + #elif CK_ALGIN + FIX_ALIGN(st.int_off,8); + if(st.int_off<16){ + dasm_put(Dst, 210, st.int_off+st.extra); + st.int_off+=8; + }else{ + if(!ALIGNED(st.stack_off,8)){ + st.stack_off+=4; + dasm_put(Dst, 214); + } + dasm_put(Dst, 216); + st.stack_off+=8; + } + #else + load_float(Dst,&st,8,ARM_HF,8); + #endif + dasm_put(Dst, 218); + 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, 222, ((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, 230, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + goto single_no_pop; + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + int isfloat,hfasize=0; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 246, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + #if ARM_HF + if(hfasize>0){ + switch(hfasize){ + case 8: + break; + case 6: + break; + case 4: + break; + case 3: + break; + case 2: + break; + case 1: + break; + } + }else + #endif + if(!mt->is_empty){ + if(mt->base_size<=4){ + dasm_put(Dst, 267); + }else{ + dasm_put(Dst, 269, st.extra+0x40*ARM_HF, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); + } + } + break; + } + 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, 282, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + + goto single_no_pop; + + case VOID_TYPE: + dasm_put(Dst, 298); + lua_pop(L, 1); + break; + + case BOOL_TYPE: + case INT8_TYPE:// narrow it + case INT16_TYPE:// narrow it + case INT32_TYPE: + dasm_put(Dst, 303); + if (mt->is_unsigned) { + dasm_put(Dst, 305); + } else { + dasm_put(Dst, 309); + } + switch(mt->type){ + case BOOL_TYPE: + dasm_put(Dst, 313); + break; + case INT8_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 316); + } else { + dasm_put(Dst, 318); + } + break; + case INT16_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 320); + } else { + dasm_put(Dst, 322); + } + break; + } + goto single; + + case INT64_TYPE: + dasm_put(Dst, 324); + if (mt->is_unsigned) { + dasm_put(Dst, 326); + } else { + dasm_put(Dst, 330); + } + goto dual; + + case INTPTR_TYPE: + dasm_put(Dst, 334); + goto single; + + case FLOAT_TYPE: + dasm_put(Dst, 339); + #if ARM_HF + lua_pop(L, 1); + #else + goto single; + #endif + break; + case DOUBLE_TYPE: + dasm_put(Dst, 344); + #if ARM_HF + lua_pop(L, 1); + #else + goto dual; + #endif + break; + case COMPLEX_DOUBLE_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 349, st.extra); + break; + case COMPLEX_FLOAT_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 360, st.extra); + break; + + single: + lua_pop(L, 1); + single_no_pop: + dasm_put(Dst, 371); + + break; + dual: + dasm_put(Dst, 378); + + lua_pop(L, 1); + break; + + + + default: + luaL_error(L, "NYI: callback return type"); + } + } + + dasm_put(Dst, 387); + + 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; + } +} + +static ALWAYS_INLINE void save_int64_stack_align(struct jit* Dst,reg_info* regs,int align){ + if(align&&!ALIGNED(regs->exs,2)){ + regs->exs++; + dasm_put(Dst, 389); + } + dasm_put(Dst, 391); + regs->exs+=2; +} + +static ALWAYS_INLINE void save_int64_align(struct jit* Dst,reg_info* regs,int align){ + if((align&&!ALIGNED(regs->ints,2))||(regs->ints==MAX_REGS-1&®s->exs/*to ensure consective memory*/)){ + regs->ints++; + } + if(regs->ints<MAX_REGS){ + dasm_put(Dst, 393, ((regs->ints<<2)+0x40*ARM_HF)); + regs->ints+=2; + }else{ + save_int64_stack_align(Dst,regs,align); + } + +} + +static ALWAYS_INLINE void save_int64(struct jit* Dst,reg_info* regs){ + save_int64_align(Dst,regs,1); +} + +static ALWAYS_INLINE void save_int_stack_align(struct jit* Dst,reg_info* regs){ + dasm_put(Dst, 397); + regs->exs++; +} + +static ALWAYS_INLINE void save_int(struct jit* Dst,reg_info* regs){ + if(regs->ints<MAX_REGS){ + dasm_put(Dst, 399, ((regs->ints++<<2)+0x40*ARM_HF)); + }else{ + save_int_stack_align(Dst,regs); + } +} + +static void save_float(struct jit* Dst,reg_info* regs,int size,int isfloat){ +#if ARM_HF + if(!regs->float_sealed){ + int reg=add_float_reg(regs,size,isfloat); + if(reg<0) goto SAVE_STACK; + switch(size){ + case 8: + case 6: + case 4: + goto sf_2; + case 3: + case 2: + sf_2: + break; + case 1: + break; + } + return; + } + SAVE_STACK: + + if(!isfloat&&!ALIGNED(regs->exs,2)){ + regs->exs++; + dasm_put(Dst, 402); + } + switch(size){ + case 1: + dasm_put(Dst, 404); + break; + case 2: + dasm_put(Dst, 406); + break; + case 3: + dasm_put(Dst, 408); + break; + case 4: + dasm_put(Dst, 410); + break; + case 6: + dasm_put(Dst, 412); + break; + case 8: + dasm_put(Dst, 414); + break; + + } + regs->exs+=size; + +#else + if(size==1){ + save_int(Dst,regs); + }else if(size==2){ + save_int64_align(Dst,regs,!isfloat); + } +#endif +} + +static int calculate_stack(lua_State* L,int ct_usr,int nargs){ + const struct ctype* mt; + reg_info regs;int i,stack=0; + memset(®s,0,sizeof(reg_info)); + 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) { + stack+=add_int_reg(®s); + }else{ + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + #if ARM_HF + stack+=add_float_reg(®s,4,0)<0?4:0; + #else + stack+=add_int64_reg(®s); + stack+=add_int64_reg(®s); + #endif + FIX_ALIGN(stack,2); + break; + case DOUBLE_TYPE: + #if ARM_HF + stack+=add_float_reg(®s,2,0)<0?2:0; + #else + stack+=add_int64_reg(®s); + #endif + FIX_ALIGN(stack,2); + break; + case COMPLEX_FLOAT_TYPE:// Though complex alignment is 4, but vfp requires a sequence of regsiters + #if ARM_HF + stack+=add_float_reg(®s,2,1)<0?2:0; + #else + stack+=add_int_reg(®s); + stack+=add_int_reg(®s); + #endif + break; + case FLOAT_TYPE: + #if ARM_HF + stack+=add_float_reg(®s,1,1)<0?1:0; + #else + stack+=add_int_reg(®s); + #endif + break; + case INT64_TYPE: + stack+=add_int64_reg(®s); + FIX_ALIGN(stack,2); + break; + case STRUCT_TYPE:{ + #if ARM_HF + int isfloat; + int hfasize=hfa_size(L,-1,mt,&isfloat); + if(hfasize>0){ + stack+=add_float_reg(®s,2,0)<0?hfasize:0; + if(!isfloat){ + FIX_ALIGN(stack,2); + } + break; + } + #endif + } + case UNION_TYPE:{ + int intsize=(mt->base_size+3)>>2; + if(mt->align_mask>4){//8-byte max alignment + if(regs.ints<MAX_REGS){ + FIX_ALIGN(regs.ints,2); + }else{ + FIX_ALIGN(stack,2); + } + } + + if(regs.ints+intsize<=MAX_REGS){ + regs.ints+=intsize; + }else{ + stack+=regs.ints+intsize-MAX_REGS; + regs.ints=MAX_REGS; + } + break; + } + default: + stack+=add_int_reg(®s);//no need to check type support here + } + } + lua_pop(L,1); + } + FIX_ALIGN(stack,2); + return (regs.ints + #if ARM_HF + /**/||regs.floats + #endif + )?0x40*ARM_HF+0x10+stack*4:0; +} + +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,ret_by_addr, stack_size; + const struct ctype* mt; + void* p; reg_info regs; + + 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); +#if defined __thumb__ //keep frame pointer + dasm_put(Dst, 416); +#else + dasm_put(Dst, 419); +#endif +#if CK_ALGIN + dasm_put(Dst, 422); +#endif + dasm_put(Dst, 424); + + /* Reserve enough stack space for all of the arguments. For hard floating point, + * leave extra 64 bytes + */ + stack_size=calculate_stack(L,ct_usr,nargs); + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + + // Complex types in softfp and structs/unions larger than 4-bytes are return in the address stored in r0 + ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| + (!ARM_HF&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(ARM_HF&&hfa_size(L,-1,mt,NULL)); + lua_pop(L,1); + if(ret_by_addr){ + if(stack_size==0) + stack_size=0x40*ARM_HF+0x10; + stack_size+=8; + } + if(stack_size>0){ + if(stack_size>=1<<12){ + dasm_put(Dst, 426, (unsigned short)(stack_size), (((unsigned int)(stack_size))>>16)); + }else{ + dasm_put(Dst, 432, stack_size); + } + if (ct->has_var_arg){ + dasm_put(Dst, 435, nargs, (unsigned short)("too few arguments"), (((unsigned int)("too few arguments"))>>16)); + } + dasm_put(Dst, 452, 0x40*ARM_HF+0x10); + } + + memset(®s,0,sizeof(reg_info)); + + if (ret_by_addr) { + regs.ints++; + dasm_put(Dst, 455, (unsigned short)(mt), (((unsigned int)(mt))>>16), 0x40*ARM_HF); + } + + + 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|| mt->type==STRUCT_TYPE || mt->type==UNION_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + + dasm_put(Dst, 466, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16), i); + + if (mt->pointers || mt->is_reference) { + dasm_put(Dst, 477); + } else if (mt->type == FUNCTION_PTR_TYPE) { + dasm_put(Dst, 481); + } else if (mt->type == ENUM_TYPE) { + dasm_put(Dst, 485); + }else if(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE){ + if(mt->is_empty) continue; + dasm_put(Dst, 489); + #if ARM_HF + { + int hfasize,isfloat; + hfasize=hfa_size(L,-2,mt,&isfloat); + if(hfasize){ + switch(hfasize){ + case 8: + break; + case 6: + break; + case 4: + break; + case 3: + break; + case 2: + break; + case 1: + break; + + } + save_float(Dst,®s,hfasize,isfloat); + continue; + } + } + #endif + + if(mt->align_mask>4){//8 byte max alignment + if(regs.ints<4){ + FIX_ALIGN(regs.ints,2) + }else if(!ALIGNED(regs.exs,2)){ + int diff=regs.exs; + regs.exs+=4; + dasm_put(Dst, 493); + } + } + int size=ROUND_UP(mt->base_size,4)>>2; + dasm_put(Dst, 495, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); + if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+size<=MAX_REGS)){//to ensure consective memory for the struct + dasm_put(Dst, 505, ((regs.ints<<2)+0x40*ARM_HF)); + }else{ + regs.ints=MAX_REGS; + dasm_put(Dst, 508); + } + dasm_put(Dst, 510); + if(regs.ints+size<=MAX_REGS){ + regs.ints+=size; + }else{ + int ex=regs.ints+size-MAX_REGS; + dasm_put(Dst, 512, (ex)<<2); + regs.exs+=ex; + regs.ints=MAX_REGS; + } + continue; + } + + save_int(Dst,®s); + } else { + lua_pop(L, 1); + dasm_put(Dst, 515, i); + + switch (mt->type) { + case BOOL_TYPE: + dasm_put(Dst, 518); + save_int(Dst,®s); + break; + case INT8_TYPE: + dasm_put(Dst, 524); + if (mt->is_unsigned) { + dasm_put(Dst, 528); + } else { + dasm_put(Dst, 530); + } + save_int(Dst,®s); + break; + + case INT16_TYPE: + dasm_put(Dst, 532); + if (mt->is_unsigned) { + dasm_put(Dst, 536); + } else { + dasm_put(Dst, 538); + } + save_int(Dst,®s); + break; + + case INT32_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 540); + } else { + dasm_put(Dst, 544); + } + save_int(Dst,®s); + break; + case INTPTR_TYPE: + dasm_put(Dst, 548); + save_int(Dst,®s); + break; + + case INT64_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 552); + } else { + dasm_put(Dst, 556); + } + save_int64(Dst,®s); + break; + + case DOUBLE_TYPE: + dasm_put(Dst, 560); + save_float(Dst,®s,2,0); + break; + + case FLOAT_TYPE: + dasm_put(Dst, 564); + save_float(Dst,®s,1,1); + break; + + case COMPLEX_DOUBLE_TYPE: + #if ARM_HF + save_float(Dst,®s,4,0); + #else + FIX_ALIGN(regs.ints,2); + dasm_put(Dst, 568); + if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+4<=MAX_REGS)){ + dasm_put(Dst, 571, (regs.ints<<2)); + }else{ + regs.ints=MAX_REGS; + if(!ALIGNED(regs.exs,2)){ + ++regs.exs; + dasm_put(Dst, 574); + } + dasm_put(Dst, 576); + } + dasm_put(Dst, 578); + regs.ints+=4; + goto FIX_REG; + #endif + break; + case COMPLEX_FLOAT_TYPE: + #if ARM_HF + save_float(Dst,®s,2,1); + #else + dasm_put(Dst, 581); + if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+2<=MAX_REGS)){ + dasm_put(Dst, 584, (regs.ints<<2)); + }else{ + regs.ints=MAX_REGS; + dasm_put(Dst, 587); + } + dasm_put(Dst, 589); + regs.ints+=2; + FIX_REG: + if(regs.ints>MAX_REGS){ + dasm_put(Dst, 592, (regs.ints-4)<<2); + regs.exs+=regs.ints-MAX_REGS; + regs.ints=MAX_REGS; + } + #endif + break; + default: + luaL_error(L, "NYI: call arg type"); + } + } + } + + if (ct->has_var_arg) { + int offset=nargs+1; + dasm_put(Dst, 595, offset); + #if ARM_HF + if(regs.ints==4||regs.float_sealed){ + if(regs.ints<4&®s.float_sealed){//some arg must be loaded to core registers. + } + } + #else + if(regs.ints==4){ + dasm_put(Dst, 598); + } + #endif + else{//no hard floating point in variadic procedure + dasm_put(Dst, 600, ((regs.ints<<2)+ARM_HF*0x40)); + } + + dasm_put(Dst, 603); + regs.ints=4; + } + + #if ARM_HF + switch(ROUND_UP(regs.highest_bit,4)>>1){ + case 8 : + break; + case 7 : + break; + case 6 : + break; + case 5: + break; + case 4 : + break; + case 3 : + break; + case 2 : + break; + case 1 : + break; + } + if(stack_size>0){ + } + #endif + + //pop registers from stack,align 8 for some compiler + assert(regs.ints<=4); + switch(regs.ints){ + case 4: + case 3: + dasm_put(Dst, 608); + break; + case 2: + case 1: + dasm_put(Dst, 610); + #if ARM_HF + if(regs.float_sealed){ + } + #endif + break; + default: + #if ARM_HF + if(regs.float_sealed){ + } + #endif + break; + } + + dasm_put(Dst, 612, (unsigned short)(func), (((unsigned int)(func))>>16)); + + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + + if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + dasm_put(Dst, 618, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + + } else { + switch (mt->type) { + case INT64_TYPE: + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + #if CK_ALGIN + dasm_put(Dst, 633); + #else + dasm_put(Dst, 636); + #endif + dasm_put(Dst, 639); + break; + #else + num_upvals++; + dasm_put(Dst, 644, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + break; + #endif + + case INTPTR_TYPE: + num_upvals++; + dasm_put(Dst, 658, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + break; + + case VOID_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 670); + break; + + case BOOL_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 672); + break; + + case INT8_TYPE: + case INT16_TYPE: + case INT32_TYPE: + case ENUM_TYPE:// value must be narrowed before callee return + lua_pop(L, 1); + + dasm_put(Dst, 678); + if (mt->is_unsigned) { + dasm_put(Dst, 680); + } else { + dasm_put(Dst, 684); + } + + dasm_put(Dst, 688); + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 690); + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + #if CK_ALGIN + dasm_put(Dst, 696); + #else + dasm_put(Dst, 699); + #endif + dasm_put(Dst, 702); + break; + case COMPLEX_DOUBLE_TYPE: + case COMPLEX_FLOAT_TYPE: + case STRUCT_TYPE: + case UNION_TYPE:{ + lua_getuservalue(L,-1); + num_upvals += 2; + #if ARM_HF + { + int isfloat,hfasize=hfa_size(L,-2,mt,&isfloat); + if(hfasize>0){ + switch(hfasize){ + case 8: + break; + case 6: + break; + case 4: + case 3: + break; + case 2: + case 1: + break; + + } + switch(hfasize){ + case 8: + break; + case 6: + break; + case 4: + break; + case 3: + break; + case 2: + break; + case 1: + break; + + } + break; + } + } + + #endif + if(mt->base_size>4){ + // value are stored in return storage in r0 for softfp, set usr value here + if(!lua_isnil(L,-1)){ + dasm_put(Dst, 707, (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + } + }else if(mt->is_empty){ + dasm_put(Dst, 719); + break; + }else{ + dasm_put(Dst, 721, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + } + dasm_put(Dst, 735); + break; + } + default: + luaL_error(L, "NYI: call return type"); + } + } + +#ifdef __thumb__ + dasm_put(Dst, 737); +#else + dasm_put(Dst, 740); +#endif + assert(lua_gettop(L) == top + num_upvals); + { + cfunction f = compile(Dst, L, NULL, 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/source/texk/web2c/luatexdir/luaffi/call_arm64.dasc b/source/texk/web2c/luatexdir/luaffi/call_arm64.dasc index e6198451b..275365e2b 100644 --- a/source/texk/web2c/luatexdir/luaffi/call_arm64.dasc +++ b/source/texk/web2c/luatexdir/luaffi/call_arm64.dasc @@ -1,1496 +1,1496 @@ -/* 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 arm64 - -|.actionlist build_actionlist -|.globalnames globnames -|.externnames extnames - -#define JUMP_SIZE 16 - -//in aarch64 the pc is indicated the current -#define MIN_BRANCH ((INT32_MIN) >> 6) -#define MAX_BRANCH ((INT32_MAX) >> 6) -//arm64 pc has no offset so comparing with next instruction is -4 -#define BRANCH_OFF -4 -#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) - -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 128MB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state. - */ - - //l: ptr - *(cfunction*) code = func; - // ldr x9,#-8 - *(uint32_t*) &code[8] = 0x58FFFFC9; - //br x9 - *(uint32_t*) &code[12] = 0xD61F0120; - -} - -|.define TOP, x19 -|.define DATA,x20 -|.define L_ARG,x21 -|.macro load64, reg, val -//| ldr reg, >5 -//| b >6 -//|5: -//|.long64 val -//|6: -| mov reg, #(unsigned short)(val) -| movk reg, #(((unsigned int)(val))>>16), lsl #16 -| movk reg, #(unsigned short)((unsigned long)(val)>>32), lsl #32 -| movk reg, #(unsigned short)((unsigned long)(val)>>48), lsl #48 -|.endmacro - -|.macro load32, reg, val -| mov reg, #(unsigned short)(val) -| movk reg, #(((unsigned int)(val))>>16), lsl #16 -|.endmacro - -|.macro lcall, func -| mov x0, L_ARG -| bl func -|.endmacro - -void compile_globals(struct jit* jit, lua_State* L) -{ - (void) jit; -} -typedef struct reg_info{ - uint8_t ints; - uint8_t floats; - uint16_t ex; -} reg_info; - -static ALWAYS_INLINE bool is_float_type(int t){ - return t==FLOAT_TYPE||t==DOUBLE_TYPE; -} - -static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ - struct ctype* mt; - int type,ele_count,i,ct_usr; - lua_getuservalue(L,idx); - ct_usr=lua_absindex(L,-1); - lua_rawgeti(L,ct_usr,1); - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - return 0; - } - type=mt->type; - ele_count=(int)(ct->base_size/mt->base_size); - if(ele_count>4||ct->base_size%mt->base_size){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - for (i = 2;i<=4; ++i) { - lua_rawgeti(L,ct_usr,i); - if(lua_isnil(L,-1)){//case have array member; - lua_pop(L,1); - break; - } - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - } - if(isfloat){ - *isfloat=mt->type==FLOAT_TYPE; - } - lua_pop(L,1); - return ele_count; -} - -static reg_info caculate_regs(lua_State* L,int ct_usr,int nargs){ - int i;reg_info regs; - const struct ctype* mt; - for (i = 1,regs.ints=0,regs.floats=0; i <= nargs&&(regs.floats<8||regs.ints<8); ++i){ - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (mt->pointers || mt->is_reference) { - if(regs.ints<8)regs.ints++; - }else{ - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - if(regs.floats<7) - regs.floats+=2; - else if(regs.floats==7) - regs.floats=8; - break; - case FLOAT_TYPE: - case DOUBLE_TYPE: - if(regs.floats<8) ++regs.floats; - break; - case STRUCT_TYPE:{ - int hfasize=hfa_size(L,-1,mt,NULL); - if(hfasize>0){ - regs.floats+=hfasize; - if(regs.floats>8) - regs.floats=8; - break; - } - } - case UNION_TYPE:{ - int size=mt->base_size; - if(size>16){//passed by address - if(regs.ints<8)++regs.ints; - break; - } - if(mt->is_empty){ - break; //ignored empty struct - } - size=(size+7)>>3; - if(regs.ints+size<=8) regs.ints+=size; - break; - } - default: - if(regs.ints<8)++regs.ints;//no need to check type support here - } - } - lua_pop(L,1); - } - - return regs; -} - -// arm store/load range for immediate value is only -256-255 -static ALWAYS_INLINE void load_int(struct jit* Dst,reg_info* regs){ - if(regs->ints<8) - | ldr x1, [sp, #0x60+(regs->ints++<<3)] //64 bit ptr - else - | ldr x1, [DATA], #(regs->ex++,8) -} - -static void load_float(struct jit* Dst,reg_info* regs,int isfloat,int exSize){ - if(regs->floats+exSize<8){ - switch(exSize){ - case 3: - | ldp d2,d3, [sp, #0x30+(regs->floats<<3)] - goto l_dual; - case 2: - | ldr d2, [sp, #0x30+(regs->floats<<3)] - case 1: - l_dual: - | ldp d0,d1, [sp, #0x20+(regs->floats<<3)] - break; - case 0: - | ldr d0, [sp, #0x20+(regs->floats<<3)] - break; - } - regs->floats+=exSize+1; - - }else{ - regs->floats=8; - regs->ex+=exSize+1; - switch(exSize){ - case 3: - if(isfloat){ - | ldp s0,s1, [DATA], #8 - | ldp s2,s3, [DATA], #8 - }else{ - | ldp d0, d1, [DATA], #16 - | ldp d2, d3, [DATA], #16 - } - break; - case 2: - if(isfloat){ //12 bytes rounded to 16 - | ldp s0,s1, [DATA], #8 - | ldr s2, [DATA], #8 - break; - }else { - | ldp d0, d1, [DATA], #16 - | ldr d2, [DATA], #8 - } - break; - case 1: - if(isfloat){ - | ldp s0,s1, [DATA], #8 - }else{ - | ldp d0, d1, [DATA], #16 - } - break; - case 0: - if(isfloat){ - | ldr s0, [DATA], #8 - }else { - | ldr d0, [DATA], #8 - } - break; - } - - } -} - -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,ret_by_addr; - 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"); - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) - && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); - if(ret_by_addr){ - | str x8, [sp, #-16]! //preserve ret address; - } - lua_pop(L,1); - reg_info regs=caculate_regs(L,ct_usr,nargs); - - if(regs.ints||regs.floats){ - | sub sp,sp,#0xa0 - }else{ - | sub sp,sp,#0x20 - } - //8 integer reigsters and 8 floating registers - switch(regs.ints){ - case 8: - case 7: - | stp x6,x7, [sp,#0x90] - case 6: - case 5: - | stp x4,x5, [sp,#0x80] - case 4: - case 3: - | stp x2,x3, [sp,#0x70] - case 2: - case 1: - | stp x0,x1, [sp,#0x60] - } - - switch(regs.floats){ - case 8: - case 7: - | stp d6,d7, [sp,#0x50] - case 6: - case 5: - | stp d4,d5, [sp,#0x40] - case 4: - case 3: - | stp d2,d3, [sp,#0x30] - case 2: - case 1: - | stp d0,d1, [sp,#0x20] - } - | stp DATA, L_ARG,[sp,#0x10] - | stp x29, x30,[sp] - - if(regs.ints==8||regs.floats==8){ // may be overflowed if it's full - | add DATA, sp, #0xa0+ret_by_addr*0x10 - } - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - - | load64 L_ARG, L - | load32 w2, ref - | load32 w1, LUA_REGISTRYINDEX - | lcall extern rawgeti //get the table - - | mov w2, #num_upvals - | movn x1, #0 // -1 - | lcall extern rawgeti //get the function - - - for (i = 1,regs.ints=0,regs.floats=0; 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 w2, #num_upvals-1 // usr value - | movn x1, #i // -i-1, stack is upval table, func, i-1 args - | lcall extern rawgeti - | load64 x2, mt - | movn w1, #0 // -1 - | lcall extern push_cdata - load_int(Dst,®s); - | str x1, [x0] - | movn w1, #1 //-2 - | lcall extern lua_remove // remove the usr value - - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - int isfloat,hfasize=0; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - | mov w2, #num_upvals-1 // usr value - | movn x1, #i // -i-1, stack is upval table, func, i-1 args - | lcall extern rawgeti - | load64 x2, mt - | movn w1, #0 // -1 - | lcall extern push_cdata - - if(hfasize){ - load_float(Dst,®s,isfloat,hfasize-1); - switch(hfasize){ - case 4: - if(isfloat){ - | stp s2, s3, [x0,#8] - }else{ - | stp d2, d3, [x0,#16] - } - goto hfa2; - case 3: - if(isfloat){ - | str s2, [x0,#8] - }else{ - | str d2, [x0,#16] - } - case 2: - hfa2: - if(isfloat){ - | stp s0, s1, [x0] - }else{ - | stp d0, d1, [x0] - } - break; - case 1: - if(isfloat){ - | str s0, [x0] - }else{ - | str d0, [x0] - } - break; - - } - }else if(!mt->is_empty){ - size_t size=mt->base_size; - if(size>16){ - load_int(Dst,®s); - | load64 x2, mt->base_size - | load64 x9, memcpy - | blr x9 - }else{ - size=(size+7)>>3; - if(mt->align_mask>8){ - if(regs.ints&1) regs.ints++; - else if(regs.ex&1) regs.ex++; - } - if(regs.ints+size<=8){ - if(size>1){ - | ldp x1,x2, [sp,#0x60+(regs.ints<<3)] - | stp x1, x2, [x0] - }else{ - | ldr x1, [sp,#0x60+(regs.ints<<3)] - | str x1, [x0] - } - regs.ints+=size; - }else{ - regs.ints=8; - if(size>1){ - | ldp x1,x2, [DATA], #16 - | stp x1, x2, [x0] - }else{ - | ldr x1, [DATA], #8 - | str x1, [x0] - } - - } - } - - - } - - | movn w1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - break; - } - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | mov w2, #num_upvals-1 // usr value - | movn x1, #i // -i-1, stack is upval table, func, i-1 args - | lcall extern rawgeti - | load64 x2, mt - | movn w1, #0 // -1 - | lcall extern push_cdata - load_float(Dst,®s,0,1); - |stp d0,d1,[x0] - | movn w1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - - break; - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | mov w2, #num_upvals-1 // usr value - | movn x1, #i // -i-1, stack is upval table, func, i-1 args - | lcall extern rawgeti - | load64 x2, mt - | movn w1, #0 // -1 - | lcall extern push_cdata - load_float(Dst,®s,1,1); - | stp s0,s1, [x0] - | movn w1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - - break; - case INT64_TYPE: - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - load_int(Dst,®s); - | lcall extern lua_pushinteger - - #else - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | load64 x2, mt - | mov w1, wzr - | lcall extern push_cdata - load_int(Dst,®s); - | str x1, [x0] - | movn w1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - - #endif - break; - - case INTPTR_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | load64 x2, mt - | mov w1, wzr - | lcall extern push_cdata - load_int(Dst,®s); - | str x1, [x0] - | movn w1, #1 // -2 - | lcall extern lua_remove // remove the nil usr - - break; - - case BOOL_TYPE: - lua_pop(L, 1); - - load_int(Dst,®s); - | lcall extern lua_pushboolean - - break; - - case INT8_TYPE:// need to narrow for caller doesn't do it - lua_pop(L, 1); - if(regs.ints<8){ - if (mt->is_unsigned) { - | ldrb w1, [sp,#0x60+(regs.ints++<<3)] - } else { - | ldrsb w1, [sp,#0x60+(regs.ints++<<3)] - } - }else { - if (mt->is_unsigned) { - | ldrb w1, [DATA], #8 - } else { - | ldrsb w1, [DATA], #8 - } - } - | lcall extern push_int - break; - - case INT16_TYPE:// need to narrow for caller doesn't do it - lua_pop(L, 1); - if(regs.ints<8){ - if (mt->is_unsigned) { - | ldrh w1, [sp,#0x60+(regs.ints++<<3)] - } else { - | ldrsh w1, [sp,#0x60+(regs.ints++<<3)] - } - }else { - if (mt->is_unsigned) { - | ldrh w1, [DATA], #8 - } else { - | ldrsh w1, [DATA], #8 - } - } - | lcall extern push_int - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - load_int(Dst,®s); - - | lcall extern push_int - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - load_float(Dst,®s,1,0); - | lcall extern push_float - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - load_float(Dst,®s,0,0); - | 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 w2, #((mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0) - | mov w1, #nargs - | lcall extern lua_call - - |.macro retcdata, func - | mov w2, #num_upvals-1 // usr value - | movn x1, #1 // -2 stack is (upval table, ret val) - | lcall extern rawgeti - | load64 x3, mt - | movn x2, #0 // -1 - ct_usr - | movn x1, #1 // -2 - val - | lcall extern func - |.endmacro - - - 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 */ - - | retcdata check_typed_pointer - goto single_no_pop; - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - int hfasize=0,isfloat; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - | retcdata check_struct - | mov DATA ,x0 - | movn w1, #2 // -3 - | lcall extern lua_settop - if(hfasize){ - switch(hfasize){ - case 4: - if(isfloat){ - | ldp s2,s3, [DATA,#8] - }else{ - | ldp d2,d3, [DATA,#16] - } - goto ld_hfa; - case 3: - if(isfloat){ - | ldr s2, [DATA,#8] - }else{ - | ldr d2, [DATA,#16] - } - case 2: - ld_hfa: - if(isfloat){ - | ldp s0,s1, [DATA] - }else{ - | ldp d0,d1, [DATA] - } - break; - case 1: - if(isfloat){ - | ldr s0, [DATA] - }else{ - | ldr d0, [DATA] - } - break; - } - }else{ - if(mt->base_size>16){ - | ldr x0, [sp, #0x20+((regs.ints||regs.floats)?0x80:0)] - | mov x1, DATA - | load64 x2, mt->base_size - | load64 x9, memcpy - | blr x9 - }else{ - if(mt->base_size>8){ - | ldp x0, x1, [DATA] - }else{ - | ldr x0, [DATA] - } - } - } - break; - } - case ENUM_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - | retcdata check_enum - - goto single_no_pop; - - case VOID_TYPE: - | movn w1,#1 //-2 - | lcall extern lua_settop - lua_pop(L, 1); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: //caller's responsiblity to narrow - | movn w1,#0 - if (mt->is_unsigned) { - | lcall extern check_uint32 - } else { - | lcall extern check_int32 - } - - goto single; - - case INT64_TYPE: - | movn w1,#0 //-1 - if (mt->is_unsigned) { - | lcall extern check_uint64 - } else { - | lcall extern check_int64 - } - - goto single; - - case INTPTR_TYPE: - | movn w1,#0 //-1 - | lcall extern check_uintptr - goto single; - - case FLOAT_TYPE: - | movn w1,#0 //-1 - | lcall extern check_float - - | fmov DATA,d0 - | movn w1, #2 // -3 - | lcall extern lua_settop - | fmov d0,DATA - lua_pop(L, 1); - break; - case DOUBLE_TYPE: - | movn w1,#0 //-1 - | lcall extern check_double - - | fmov DATA,d0 - | movn w1, #2 // -3 - | lcall extern lua_settop - | fmov d0,DATA - - lua_pop(L, 1); - break; - - case COMPLEX_DOUBLE_TYPE: - - | movn w1, #0 // -1 - | lcall extern check_complex_double - - goto complex_ret; - case COMPLEX_FLOAT_TYPE: - | movn w1, #0 // -1 - | lcall extern check_complex_float - - complex_ret: - | mov x0,L_ARG - | movn w1, #2 // -3 - | fmov DATA,d0 - | fmov L_ARG,d1 - | bl extern lua_settop - | fmov d0,DATA - | fmov d1,L_ARG - - lua_pop(L, 1); - break; - single: - lua_pop(L, 1); - single_no_pop: - | mov DATA, x0 - | movn w1, #2 // -3 - | lcall extern lua_settop - | mov x0, DATA - break; - - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - | ldp x29,x30,[sp] - | ldp DATA, L_ARG,[sp,#0x10] - | add sp,sp, # (0x20 +ret_by_addr*0x10+ ((regs.floats!=0)||(regs.ints!=0)) * 0x80) - | ret - - 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; - } -} - -//arm64 argument can only be in stack or registers. An argument can't be splited between stack and register. -static void store_float(struct jit* Dst,reg_info* regs,int isfloat,int ex){ - if(regs->floats+ex<8){ - - switch(ex){ - case 3: - | stp d2,d3, [sp, #0x10+(regs->floats<<3)] - goto sd_dual; - case 2: - | str d2, [sp, #0x10+(regs->floats<<3)] - case 1: - sd_dual: - | stp d0,d1, [sp, #(regs->floats<<3)] - break; - case 0: - | str d0, [sp, #(regs->floats<<3)] - break; - } - regs->floats+=1+ex; - }else { - regs->floats=8; - switch(ex){ - case 3: - if(isfloat){ - | stp s0,s1, [DATA], #8 - | stp s2,s3, [DATA], #8 - }else{ - | stp d0, d1, [DATA], #16 - | stp d2, d3, [DATA], #16 - } - break; - case 2: - if(isfloat){ - | stp s0,s1, [DATA], #8 - | str s2, [DATA], #8 - }else{ - | stp d0, d1,[DATA], #16 - | str d2, [DATA], #8 - } - break; - case 1: - if(isfloat){ - | stp s0,s1, [DATA], #8 - }else{ - | stp d0, d1,[DATA], #16 - } - break; - case 0: - if(isfloat){ - | str s0, [DATA], #8 - }else { - | str d0, [DATA], #8 - } - break; - } - //complex float is packed as one double on stack - regs->ex+=ex+1; - } -} - -static void store_int(struct jit* Dst,reg_info* regs,int intSize){ - switch(intSize){ - case 1: - if(regs->ints<8) - | str w0, [sp,#0x40+(regs->ints++<<3)] - else - | str w0, [DATA], #(regs->ex++,8) - break; - case 2: - if(regs->ints<8) - | str x0, [sp,#0x40+(regs->ints++<<3)] - else - | str x0, [DATA], #(regs->ex++,8) - break; - case 3: - case 4: - if(regs->ints<7){ - | stp x0,x1, [sp,#0x40+(regs->ints<<3)] - regs->ints+=2; - } - else{ - if(regs->ints==7) - regs->ints=8; - | stp x0,x1, [DATA], #16 - regs->ex+=2; - } - - break; - } -} - -static int caculate_stack(lua_State* L,int ct_usr,int nargs){ - int i;reg_info regs={0,0,0}; - const struct ctype* mt;int stack=0,extra=0; - 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) { - if(regs.ints<8)regs.ints++; - else stack++; - }else{ - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - if(regs.floats<7) - regs.floats+=2; - else if(regs.floats==7) - regs.floats=8; - else stack+=mt->base_size>>3; - break; - case FLOAT_TYPE: - case DOUBLE_TYPE: - if(regs.floats<8) ++regs.floats; - else stack++; - break; - case STRUCT_TYPE:{ - int isfloat; - int hfasize=hfa_size(L,-1,mt,&isfloat); - if(hfasize>0){ - if(regs.floats+hfasize<=8) - regs.floats +=hfasize; - else { - regs.floats=8; - stack+=(hfasize*(2-isfloat)+1)>>1; - } - break; - } - } - case UNION_TYPE:{ - int size=mt->base_size; - size=(size+7)>>3; - if(size>2){//passed by address - if(regs.ints<8)++regs.ints; - else stack++; - extra+=size;//extra copy stack; - break; - } - if(mt->is_empty){ - break; //ignored empty struct - } - if(mt->align_mask>8){ - if(regs.ints&1) regs.ints++; - else if(stack&1) stack++; - } - if(regs.ints+size<=8) regs.ints+=size; - else{ - regs.ints=8; - stack+=size; - } - - break; - } - default: - if(regs.ints<8)++regs.ints;//no need to check type support here - else stack++; - } - } - lua_pop(L,1); - } - - return (regs.ints||regs.floats)?((stack+extra+17/*16 for regs, 1 for align*/)>>1)<<4:0;//2 eightbytes align -} - - -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,ret_by_addr; - const struct ctype* mt; - int stack_size,struct_offset; - 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); - - reg_info regs={0,0}; - - | sub sp,sp,#0x30 - | str L_ARG, [sp,#20] - | stp TOP,DATA,[sp,#0x10] - | stp x29,x30,[sp] - | mov x29,sp - | mov L_ARG,x0 - - /* reserve enough stack space for all of the arguments. */ - stack_size=caculate_stack(L,ct_usr,nargs); - struct_offset=0; - if(stack_size>0){ - if(stack_size>=1<<12){ - | load32 x9, stack_size //trick x9 - | sub sp, sp, x9 - } - else{ - | sub sp, sp, #stack_size - } - if (ct->has_var_arg) { - | bl extern lua_gettop - | cmp w0, #nargs - | bge >1 - | load64 x1, "too few arguments" - | lcall extern luaL_error - |1: - | mov TOP, x0 - | add x0, x0, #1 - | bfm x0,xzr, #0, #0 //round up 2 for stack alignment. - | sub sp, sp, x0, lsl #3 - } - | add DATA,sp,#0x80 - } - - for (i = 1,regs.ints=0,regs.floats=0; 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||mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - - - | load64 x3,mt - | load32 w2,lua_upvalueindex(num_upvals) - | mov x1,#i - - if (mt->pointers || mt->is_reference) { - | lcall extern check_typed_pointer - } else{ - switch (mt->type) { - case FUNCTION_PTR_TYPE: { - | lcall extern check_typed_cfunction - break; - } - case ENUM_TYPE:{ - | lcall extern check_enum - break; - } - case STRUCT_TYPE: - case UNION_TYPE:{ - if(mt->is_empty) continue; - - int isfloat; - int hfasize=hfa_size(L,-2,mt,&isfloat); - | lcall extern check_struct - if(hfasize>0){ - switch(hfasize){ - case 4: - if(isfloat){ - | ldp s2,s3, [x0,#8] - }else{ - | ldp d2,d3, [x0,#16] - } - goto ld_hfa; - case 3: - if(isfloat){ - | ldr s2, [x0,#8] - }else{ - | ldr d2, [x0,#16] - } - case 2: - ld_hfa: - if(isfloat){ - | ldp s0,s1, [x0] - }else{ - | ldp d0,d1, [x0] - } - break; - case 1: - if(isfloat){ - | ldr s0, [x0] - }else{ - | ldr d0, [x0] - } - break; - - } - store_float(Dst,®s,isfloat,hfasize-1); - continue; - } - if(mt->base_size>16){ - | mov x1 ,x0 - struct_offset+=(mt->base_size+7)&(~7); - if(struct_offset>=1<<12){ - | load32 x0, struct_offset //trick x0 - | sub x0, x29, x0 - } - else{ - | sub x0, x29, #struct_offset - } - store_int(Dst,®s,2); - | mov x2, #mt->base_size - | load64 x9, memcpy - | blr x9 - }else{ - if(mt->align_mask>8){//==15 - if(regs.ints&1) regs.ints++; - else if(regs.ex&1) regs.ex++; - } - int intSize=(mt->base_size+3)>>2; - switch(intSize){ - case 1: - | ldr w0, [x0] - break; - case 2: - | ldr x0, [x0] - break; - case 3: - case 4: - | ldp x0, x1, [x0] - break; - } - store_int(Dst,®s,intSize); - } - continue; - } - } - } - goto longstore; - - } else { - lua_pop(L, 1); - | mov w1, #i - - switch (mt->type) { - case BOOL_TYPE: - | lcall extern check_uint32 - | cmp w0, wzr - | cset w0, ne - goto intstore; - - case INT8_TYPE: - case INT16_TYPE: //arm64 requires callee to narrow the type - case INT32_TYPE: - - | lcall extern check_int32 - - goto intstore; - - case INT64_TYPE: - - | lcall extern check_int64 - - goto longstore; - - case INTPTR_TYPE: - | lcall extern check_uintptr - - goto longstore; - - case DOUBLE_TYPE: - | lcall extern check_double - store_float(Dst,®s,0,0); - break; - - case FLOAT_TYPE: - | lcall extern check_float - store_float(Dst,®s,1,0); - break; - case COMPLEX_DOUBLE_TYPE: - | lcall extern check_complex_double - store_float(Dst,®s,0,1); - break; - - case COMPLEX_FLOAT_TYPE: - | lcall extern check_complex_float - store_float(Dst,®s,1,1); - break; - - intstore: - store_int(Dst,®s,1); - break; - longstore: - store_int(Dst,®s,2); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { - if(regs.floats<8){ - | add x4, sp ,#regs.floats<<3 - | mov w3, #(8-regs.floats) - | mov x2, TOP - | mov w1, #nargs+1 - | lcall extern unpack_varargs_float - } - if(regs.ints<8){ - | add x4, sp ,#0x40+(regs.ints<<3) - | mov w3, #(8-regs.ints) - | mov x2, TOP - | mov w1, #nargs+1 - | lcall extern unpack_varargs_int - } - |//case when DATA is not allocated, all arg is skipped - | cmp TOP,#(nargs>8?nargs:8) - | ble >1 - | mov x5, DATA - | mov w3, #(8-regs.floats) - | mov w3, #(8-regs.ints) - | mov x2, TOP - | mov w1, #nargs+1 - | lcall extern unpack_varargs_stack_skip - | 1: - regs.floats=regs.ints=8; - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) - && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); - if(ret_by_addr){ - | load64 x2, mt - | mov x1, #0 - | lcall extern push_cdata - | mov x8, x0 - } - - //pop all args in registers - switch(regs.ints){ - case 8: - case 7: - | ldp x6,x7,[sp,#0x70] - case 6: - case 5: - | ldp x4,x5,[sp,#0x60] - case 4: - case 3: - | ldp x2,x3,[sp,#0x50] - case 2: - case 1: - | ldp x0,x1,[sp,#0x40] - } - - switch(regs.floats){ - case 8: - case 7: - | ldp d6,d7,[sp,#0x30] - case 6: - case 5: - | ldp d4,d5,[sp,#0x20] - case 4: - case 3: - | ldp d2,d3,[sp,#0x10] - case 2: - case 1: - | ldp d0,d1,[sp] - } - if(regs.ints==8|| regs.floats==8){// fix stack case registers is full - | add sp,sp,#0x80 - } - - | load64 x9,func - | blr x9 - - |.macro return - | mov sp, x29 - | ldp x29, x30, [sp] - | ldp TOP, DATA, [sp,#0x10] - | ldr L_ARG, [sp,#0x20] - | add sp, sp, #0x30 - | ret - |.endmacro - - if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - | mov DATA, x0 - | load64 x2, mt - | load32 w1, lua_upvalueindex(num_upvals) - | lcall extern push_cdata - | str DATA, [x0] - | mov w0, #1 - | return - - } else { - switch (mt->type) { - case INT64_TYPE: - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - | mov x1, x0 - | lcall extern lua_pushinteger - | mov w0, #1 - | return - break; - #endif - - case INTPTR_TYPE: - num_upvals++; - | mov DATA, x0 - | load64 x2, mt - | mov w1, wzr - | lcall extern push_cdata - | str DATA, [x0] - | mov w0, #1 - | return - break; - case VOID_TYPE: - lua_pop(L, 1); - | mov w0, wzr - | return - break; - - case BOOL_TYPE: - lua_pop(L, 1); - | mov w1, w0 - | lcall extern lua_pushboolean - | mov w0, #1 - | return - break; - - case INT8_TYPE:// we need to narrow the value before return - lua_pop(L, 1); - | mov w1, w0 - if (mt->is_unsigned) { - | uxtb w1, w1 - | lcall extern push_uint - } else { - | sxtb w1, w1 - | lcall extern push_int - } - | mov w0, #1 - | return - break; - case INT16_TYPE:// we need to narrow the value before return - lua_pop(L, 1); - | mov w1, w0 - if (mt->is_unsigned) { - | uxth w1, w1 - | lcall extern push_uint - } else { - | sxth w1, w1 - | lcall extern push_int - } - | mov w0, #1 - | return - break; - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - | mov w1, w0 - if (mt->is_unsigned) { - | lcall extern push_uint - } else { - | lcall extern push_int - } - | mov w0, #1 - | return - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - | lcall extern push_float - | mov w0, #1 - | return - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - | lcall extern lua_pushnumber - | mov w0, #1 - | return - break; - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - num_upvals+=2; - | fmov w0, s0 - | fmov w1, s1 - | orr x0, x0, x1, lsl #32 - | mov DATA, x0 - | load64 x2, mt - | load32 w1, lua_upvalueindex(num_upvals) - | lcall extern push_cdata - | str DATA, [x0] - | mov w0, #1 - | return - break; - - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - num_upvals+=2; - | fmov TOP, d0 - | fmov DATA, d1 - | load64 x2, mt - | load32 w1, lua_upvalueindex(num_upvals) - | lcall extern push_cdata - | stp TOP,DATA, [x0] - | mov w0, #1 - | return - break; - case STRUCT_TYPE: - case UNION_TYPE: - lua_getuservalue(L, -1); - num_upvals+=2; - if(ret_by_addr){ - if(!lua_isnil(L,-1)){ - | load32 w1, lua_upvalueindex(num_upvals) - | lcall extern lua_pushvalue // lua_pushvalue(L,lua_upvalueindex(num_upvals)) - | movn w1, #1 //-2 - | lcall extern lua_setuservalue // lua_setuservalue(L,-2) - } - | mov w0, #1 - | return - }else if(mt->is_empty){ - | mov w0, #0 - | return - }else{ - int isfloat; - int hfasize=hfa_size(L,-2,mt,&isfloat); - if(hfasize){ - switch(hfasize){ - case 4: - | stp d2, d3, [sp, #-16]! - goto hfs_dual; - case 3: - | str d2, [sp, #-16]! - case 2: - hfs_dual: - | fmov TOP, d1 - case 1: - | fmov DATA, d0 - break; - } - }else{ - if(mt->base_size>8){ - | mov TOP, x1 - } - | mov DATA, x0 - - } - | load64 x2, mt - | load32 w1, lua_upvalueindex(num_upvals) - | lcall extern push_cdata - if(hfasize){ - switch(hfasize){ - case 4: - | ldp d0, d1, [sp], #16 - if(isfloat){ - | stp s0,s1, [x0,#8] - }else{ - | stp d0,d1, [x0,#16] - } - goto hfl_dual; - case 3: - | ldr d0, [sp], #16 - if(isfloat){ - | str s0, [x0,#8] - }else{ - | str d0, [x0,#16] - } - case 2: - hfl_dual: - if(isfloat){ - | fmov d0, TOP - | str s0, [x0,#4] - }else{ - | str TOP, [x0,#8] - } - case 1: - if(isfloat){ - | fmov d0, DATA - | str s0, [x0] - }else{ - | str DATA, [x0] - } - break; - } - }else{ - if(mt->base_size>8){ - | str TOP, [x0, #8] - } - | str DATA, [x0] - - } - | mov w0, #1 - | return - } - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, NULL, 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); - } -} - +/* 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 arm64 + +|.actionlist build_actionlist +|.globalnames globnames +|.externnames extnames + +#define JUMP_SIZE 16 + +//in aarch64 the pc is indicated the current +#define MIN_BRANCH ((INT32_MIN) >> 6) +#define MAX_BRANCH ((INT32_MAX) >> 6) +//arm64 pc has no offset so comparing with next instruction is -4 +#define BRANCH_OFF -4 +#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) + +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 128MB. + * + * Note we have to manually set this up since there are commands buffered + * in the jit state. + */ + + //l: ptr + *(cfunction*) code = func; + // ldr x9,#-8 + *(uint32_t*) &code[8] = 0x58FFFFC9; + //br x9 + *(uint32_t*) &code[12] = 0xD61F0120; + +} + +|.define TOP, x19 +|.define DATA,x20 +|.define L_ARG,x21 +|.macro load64, reg, val +//| ldr reg, >5 +//| b >6 +//|5: +//|.long64 val +//|6: +| mov reg, #(unsigned short)(val) +| movk reg, #(((unsigned int)(val))>>16), lsl #16 +| movk reg, #(unsigned short)((unsigned long)(val)>>32), lsl #32 +| movk reg, #(unsigned short)((unsigned long)(val)>>48), lsl #48 +|.endmacro + +|.macro load32, reg, val +| mov reg, #(unsigned short)(val) +| movk reg, #(((unsigned int)(val))>>16), lsl #16 +|.endmacro + +|.macro lcall, func +| mov x0, L_ARG +| bl func +|.endmacro + +void compile_globals(struct jit* jit, lua_State* L) +{ + (void) jit; +} +typedef struct reg_info{ + uint8_t ints; + uint8_t floats; + uint16_t ex; +} reg_info; + +static ALWAYS_INLINE bool is_float_type(int t){ + return t==FLOAT_TYPE||t==DOUBLE_TYPE; +} + +static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ + struct ctype* mt; + int type,ele_count,i,ct_usr; + lua_getuservalue(L,idx); + ct_usr=lua_absindex(L,-1); + lua_rawgeti(L,ct_usr,1); + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + return 0; + } + type=mt->type; + ele_count=(int)(ct->base_size/mt->base_size); + if(ele_count>4||ct->base_size%mt->base_size){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + for (i = 2;i<=4; ++i) { + lua_rawgeti(L,ct_usr,i); + if(lua_isnil(L,-1)){//case have array member; + lua_pop(L,1); + break; + } + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + } + if(isfloat){ + *isfloat=mt->type==FLOAT_TYPE; + } + lua_pop(L,1); + return ele_count; +} + +static reg_info caculate_regs(lua_State* L,int ct_usr,int nargs){ + int i;reg_info regs; + const struct ctype* mt; + for (i = 1,regs.ints=0,regs.floats=0; i <= nargs&&(regs.floats<8||regs.ints<8); ++i){ + lua_rawgeti(L, ct_usr, i); + mt = (const struct ctype*) lua_touserdata(L, -1); + if (mt->pointers || mt->is_reference) { + if(regs.ints<8)regs.ints++; + }else{ + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + case COMPLEX_FLOAT_TYPE: + if(regs.floats<7) + regs.floats+=2; + else if(regs.floats==7) + regs.floats=8; + break; + case FLOAT_TYPE: + case DOUBLE_TYPE: + if(regs.floats<8) ++regs.floats; + break; + case STRUCT_TYPE:{ + int hfasize=hfa_size(L,-1,mt,NULL); + if(hfasize>0){ + regs.floats+=hfasize; + if(regs.floats>8) + regs.floats=8; + break; + } + } + case UNION_TYPE:{ + int size=mt->base_size; + if(size>16){//passed by address + if(regs.ints<8)++regs.ints; + break; + } + if(mt->is_empty){ + break; //ignored empty struct + } + size=(size+7)>>3; + if(regs.ints+size<=8) regs.ints+=size; + break; + } + default: + if(regs.ints<8)++regs.ints;//no need to check type support here + } + } + lua_pop(L,1); + } + + return regs; +} + +// arm store/load range for immediate value is only -256-255 +static ALWAYS_INLINE void load_int(struct jit* Dst,reg_info* regs){ + if(regs->ints<8) + | ldr x1, [sp, #0x60+(regs->ints++<<3)] //64 bit ptr + else + | ldr x1, [DATA], #(regs->ex++,8) +} + +static void load_float(struct jit* Dst,reg_info* regs,int isfloat,int exSize){ + if(regs->floats+exSize<8){ + switch(exSize){ + case 3: + | ldp d2,d3, [sp, #0x30+(regs->floats<<3)] + goto l_dual; + case 2: + | ldr d2, [sp, #0x30+(regs->floats<<3)] + case 1: + l_dual: + | ldp d0,d1, [sp, #0x20+(regs->floats<<3)] + break; + case 0: + | ldr d0, [sp, #0x20+(regs->floats<<3)] + break; + } + regs->floats+=exSize+1; + + }else{ + regs->floats=8; + regs->ex+=exSize+1; + switch(exSize){ + case 3: + if(isfloat){ + | ldp s0,s1, [DATA], #8 + | ldp s2,s3, [DATA], #8 + }else{ + | ldp d0, d1, [DATA], #16 + | ldp d2, d3, [DATA], #16 + } + break; + case 2: + if(isfloat){ //12 bytes rounded to 16 + | ldp s0,s1, [DATA], #8 + | ldr s2, [DATA], #8 + break; + }else { + | ldp d0, d1, [DATA], #16 + | ldr d2, [DATA], #8 + } + break; + case 1: + if(isfloat){ + | ldp s0,s1, [DATA], #8 + }else{ + | ldp d0, d1, [DATA], #16 + } + break; + case 0: + if(isfloat){ + | ldr s0, [DATA], #8 + }else { + | ldr d0, [DATA], #8 + } + break; + } + + } +} + +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,ret_by_addr; + 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"); + } + + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) + && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); + if(ret_by_addr){ + | str x8, [sp, #-16]! //preserve ret address; + } + lua_pop(L,1); + reg_info regs=caculate_regs(L,ct_usr,nargs); + + if(regs.ints||regs.floats){ + | sub sp,sp,#0xa0 + }else{ + | sub sp,sp,#0x20 + } + //8 integer reigsters and 8 floating registers + switch(regs.ints){ + case 8: + case 7: + | stp x6,x7, [sp,#0x90] + case 6: + case 5: + | stp x4,x5, [sp,#0x80] + case 4: + case 3: + | stp x2,x3, [sp,#0x70] + case 2: + case 1: + | stp x0,x1, [sp,#0x60] + } + + switch(regs.floats){ + case 8: + case 7: + | stp d6,d7, [sp,#0x50] + case 6: + case 5: + | stp d4,d5, [sp,#0x40] + case 4: + case 3: + | stp d2,d3, [sp,#0x30] + case 2: + case 1: + | stp d0,d1, [sp,#0x20] + } + | stp DATA, L_ARG,[sp,#0x10] + | stp x29, x30,[sp] + + if(regs.ints==8||regs.floats==8){ // may be overflowed if it's full + | add DATA, sp, #0xa0+ret_by_addr*0x10 + } + + /* get the lua function */ + lua_pushvalue(L, fidx); + lua_rawseti(L, -2, ++num_upvals); + + | load64 L_ARG, L + | load32 w2, ref + | load32 w1, LUA_REGISTRYINDEX + | lcall extern rawgeti //get the table + + | mov w2, #num_upvals + | movn x1, #0 // -1 + | lcall extern rawgeti //get the function + + + for (i = 1,regs.ints=0,regs.floats=0; 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 w2, #num_upvals-1 // usr value + | movn x1, #i // -i-1, stack is upval table, func, i-1 args + | lcall extern rawgeti + | load64 x2, mt + | movn w1, #0 // -1 + | lcall extern push_cdata + load_int(Dst,®s); + | str x1, [x0] + | movn w1, #1 //-2 + | lcall extern lua_remove // remove the usr value + + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + int isfloat,hfasize=0; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + | mov w2, #num_upvals-1 // usr value + | movn x1, #i // -i-1, stack is upval table, func, i-1 args + | lcall extern rawgeti + | load64 x2, mt + | movn w1, #0 // -1 + | lcall extern push_cdata + + if(hfasize){ + load_float(Dst,®s,isfloat,hfasize-1); + switch(hfasize){ + case 4: + if(isfloat){ + | stp s2, s3, [x0,#8] + }else{ + | stp d2, d3, [x0,#16] + } + goto hfa2; + case 3: + if(isfloat){ + | str s2, [x0,#8] + }else{ + | str d2, [x0,#16] + } + case 2: + hfa2: + if(isfloat){ + | stp s0, s1, [x0] + }else{ + | stp d0, d1, [x0] + } + break; + case 1: + if(isfloat){ + | str s0, [x0] + }else{ + | str d0, [x0] + } + break; + + } + }else if(!mt->is_empty){ + size_t size=mt->base_size; + if(size>16){ + load_int(Dst,®s); + | load64 x2, mt->base_size + | load64 x9, memcpy + | blr x9 + }else{ + size=(size+7)>>3; + if(mt->align_mask>8){ + if(regs.ints&1) regs.ints++; + else if(regs.ex&1) regs.ex++; + } + if(regs.ints+size<=8){ + if(size>1){ + | ldp x1,x2, [sp,#0x60+(regs.ints<<3)] + | stp x1, x2, [x0] + }else{ + | ldr x1, [sp,#0x60+(regs.ints<<3)] + | str x1, [x0] + } + regs.ints+=size; + }else{ + regs.ints=8; + if(size>1){ + | ldp x1,x2, [DATA], #16 + | stp x1, x2, [x0] + }else{ + | ldr x1, [DATA], #8 + | str x1, [x0] + } + + } + } + + + } + + | movn w1, #1 // -2 + | lcall extern lua_remove // remove the nil usr + break; + } + case COMPLEX_DOUBLE_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + | mov w2, #num_upvals-1 // usr value + | movn x1, #i // -i-1, stack is upval table, func, i-1 args + | lcall extern rawgeti + | load64 x2, mt + | movn w1, #0 // -1 + | lcall extern push_cdata + load_float(Dst,®s,0,1); + |stp d0,d1,[x0] + | movn w1, #1 // -2 + | lcall extern lua_remove // remove the nil usr + + break; + case COMPLEX_FLOAT_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + | mov w2, #num_upvals-1 // usr value + | movn x1, #i // -i-1, stack is upval table, func, i-1 args + | lcall extern rawgeti + | load64 x2, mt + | movn w1, #0 // -1 + | lcall extern push_cdata + load_float(Dst,®s,1,1); + | stp s0,s1, [x0] + | movn w1, #1 // -2 + | lcall extern lua_remove // remove the nil usr + + break; + case INT64_TYPE: + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + load_int(Dst,®s); + | lcall extern lua_pushinteger + + #else + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + | load64 x2, mt + | mov w1, wzr + | lcall extern push_cdata + load_int(Dst,®s); + | str x1, [x0] + | movn w1, #1 // -2 + | lcall extern lua_remove // remove the nil usr + + #endif + break; + + case INTPTR_TYPE: + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + | load64 x2, mt + | mov w1, wzr + | lcall extern push_cdata + load_int(Dst,®s); + | str x1, [x0] + | movn w1, #1 // -2 + | lcall extern lua_remove // remove the nil usr + + break; + + case BOOL_TYPE: + lua_pop(L, 1); + + load_int(Dst,®s); + | lcall extern lua_pushboolean + + break; + + case INT8_TYPE:// need to narrow for caller doesn't do it + lua_pop(L, 1); + if(regs.ints<8){ + if (mt->is_unsigned) { + | ldrb w1, [sp,#0x60+(regs.ints++<<3)] + } else { + | ldrsb w1, [sp,#0x60+(regs.ints++<<3)] + } + }else { + if (mt->is_unsigned) { + | ldrb w1, [DATA], #8 + } else { + | ldrsb w1, [DATA], #8 + } + } + | lcall extern push_int + break; + + case INT16_TYPE:// need to narrow for caller doesn't do it + lua_pop(L, 1); + if(regs.ints<8){ + if (mt->is_unsigned) { + | ldrh w1, [sp,#0x60+(regs.ints++<<3)] + } else { + | ldrsh w1, [sp,#0x60+(regs.ints++<<3)] + } + }else { + if (mt->is_unsigned) { + | ldrh w1, [DATA], #8 + } else { + | ldrsh w1, [DATA], #8 + } + } + | lcall extern push_int + break; + + case ENUM_TYPE: + case INT32_TYPE: + lua_pop(L, 1); + load_int(Dst,®s); + + | lcall extern push_int + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + load_float(Dst,®s,1,0); + | lcall extern push_float + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + load_float(Dst,®s,0,0); + | 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 w2, #((mt->pointers || mt->is_reference || mt->type != VOID_TYPE) ? 1 : 0) + | mov w1, #nargs + | lcall extern lua_call + + |.macro retcdata, func + | mov w2, #num_upvals-1 // usr value + | movn x1, #1 // -2 stack is (upval table, ret val) + | lcall extern rawgeti + | load64 x3, mt + | movn x2, #0 // -1 - ct_usr + | movn x1, #1 // -2 - val + | lcall extern func + |.endmacro + + + 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 */ + + | retcdata check_typed_pointer + goto single_no_pop; + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + int hfasize=0,isfloat; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + | retcdata check_struct + | mov DATA ,x0 + | movn w1, #2 // -3 + | lcall extern lua_settop + if(hfasize){ + switch(hfasize){ + case 4: + if(isfloat){ + | ldp s2,s3, [DATA,#8] + }else{ + | ldp d2,d3, [DATA,#16] + } + goto ld_hfa; + case 3: + if(isfloat){ + | ldr s2, [DATA,#8] + }else{ + | ldr d2, [DATA,#16] + } + case 2: + ld_hfa: + if(isfloat){ + | ldp s0,s1, [DATA] + }else{ + | ldp d0,d1, [DATA] + } + break; + case 1: + if(isfloat){ + | ldr s0, [DATA] + }else{ + | ldr d0, [DATA] + } + break; + } + }else{ + if(mt->base_size>16){ + | ldr x0, [sp, #0x20+((regs.ints||regs.floats)?0x80:0)] + | mov x1, DATA + | load64 x2, mt->base_size + | load64 x9, memcpy + | blr x9 + }else{ + if(mt->base_size>8){ + | ldp x0, x1, [DATA] + }else{ + | ldr x0, [DATA] + } + } + } + break; + } + case ENUM_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + | retcdata check_enum + + goto single_no_pop; + + case VOID_TYPE: + | movn w1,#1 //-2 + | lcall extern lua_settop + lua_pop(L, 1); + break; + + case BOOL_TYPE: + case INT8_TYPE: + case INT16_TYPE: + case INT32_TYPE: //caller's responsiblity to narrow + | movn w1,#0 + if (mt->is_unsigned) { + | lcall extern check_uint32 + } else { + | lcall extern check_int32 + } + + goto single; + + case INT64_TYPE: + | movn w1,#0 //-1 + if (mt->is_unsigned) { + | lcall extern check_uint64 + } else { + | lcall extern check_int64 + } + + goto single; + + case INTPTR_TYPE: + | movn w1,#0 //-1 + | lcall extern check_uintptr + goto single; + + case FLOAT_TYPE: + | movn w1,#0 //-1 + | lcall extern check_float + + | fmov DATA,d0 + | movn w1, #2 // -3 + | lcall extern lua_settop + | fmov d0,DATA + lua_pop(L, 1); + break; + case DOUBLE_TYPE: + | movn w1,#0 //-1 + | lcall extern check_double + + | fmov DATA,d0 + | movn w1, #2 // -3 + | lcall extern lua_settop + | fmov d0,DATA + + lua_pop(L, 1); + break; + + case COMPLEX_DOUBLE_TYPE: + + | movn w1, #0 // -1 + | lcall extern check_complex_double + + goto complex_ret; + case COMPLEX_FLOAT_TYPE: + | movn w1, #0 // -1 + | lcall extern check_complex_float + + complex_ret: + | mov x0,L_ARG + | movn w1, #2 // -3 + | fmov DATA,d0 + | fmov L_ARG,d1 + | bl extern lua_settop + | fmov d0,DATA + | fmov d1,L_ARG + + lua_pop(L, 1); + break; + single: + lua_pop(L, 1); + single_no_pop: + | mov DATA, x0 + | movn w1, #2 // -3 + | lcall extern lua_settop + | mov x0, DATA + break; + + + default: + luaL_error(L, "NYI: callback return type"); + } + } + + | ldp x29,x30,[sp] + | ldp DATA, L_ARG,[sp,#0x10] + | add sp,sp, # (0x20 +ret_by_addr*0x10+ ((regs.floats!=0)||(regs.ints!=0)) * 0x80) + | ret + + 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; + } +} + +//arm64 argument can only be in stack or registers. An argument can't be splited between stack and register. +static void store_float(struct jit* Dst,reg_info* regs,int isfloat,int ex){ + if(regs->floats+ex<8){ + + switch(ex){ + case 3: + | stp d2,d3, [sp, #0x10+(regs->floats<<3)] + goto sd_dual; + case 2: + | str d2, [sp, #0x10+(regs->floats<<3)] + case 1: + sd_dual: + | stp d0,d1, [sp, #(regs->floats<<3)] + break; + case 0: + | str d0, [sp, #(regs->floats<<3)] + break; + } + regs->floats+=1+ex; + }else { + regs->floats=8; + switch(ex){ + case 3: + if(isfloat){ + | stp s0,s1, [DATA], #8 + | stp s2,s3, [DATA], #8 + }else{ + | stp d0, d1, [DATA], #16 + | stp d2, d3, [DATA], #16 + } + break; + case 2: + if(isfloat){ + | stp s0,s1, [DATA], #8 + | str s2, [DATA], #8 + }else{ + | stp d0, d1,[DATA], #16 + | str d2, [DATA], #8 + } + break; + case 1: + if(isfloat){ + | stp s0,s1, [DATA], #8 + }else{ + | stp d0, d1,[DATA], #16 + } + break; + case 0: + if(isfloat){ + | str s0, [DATA], #8 + }else { + | str d0, [DATA], #8 + } + break; + } + //complex float is packed as one double on stack + regs->ex+=ex+1; + } +} + +static void store_int(struct jit* Dst,reg_info* regs,int intSize){ + switch(intSize){ + case 1: + if(regs->ints<8) + | str w0, [sp,#0x40+(regs->ints++<<3)] + else + | str w0, [DATA], #(regs->ex++,8) + break; + case 2: + if(regs->ints<8) + | str x0, [sp,#0x40+(regs->ints++<<3)] + else + | str x0, [DATA], #(regs->ex++,8) + break; + case 3: + case 4: + if(regs->ints<7){ + | stp x0,x1, [sp,#0x40+(regs->ints<<3)] + regs->ints+=2; + } + else{ + if(regs->ints==7) + regs->ints=8; + | stp x0,x1, [DATA], #16 + regs->ex+=2; + } + + break; + } +} + +static int caculate_stack(lua_State* L,int ct_usr,int nargs){ + int i;reg_info regs={0,0,0}; + const struct ctype* mt;int stack=0,extra=0; + 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) { + if(regs.ints<8)regs.ints++; + else stack++; + }else{ + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + case COMPLEX_FLOAT_TYPE: + if(regs.floats<7) + regs.floats+=2; + else if(regs.floats==7) + regs.floats=8; + else stack+=mt->base_size>>3; + break; + case FLOAT_TYPE: + case DOUBLE_TYPE: + if(regs.floats<8) ++regs.floats; + else stack++; + break; + case STRUCT_TYPE:{ + int isfloat; + int hfasize=hfa_size(L,-1,mt,&isfloat); + if(hfasize>0){ + if(regs.floats+hfasize<=8) + regs.floats +=hfasize; + else { + regs.floats=8; + stack+=(hfasize*(2-isfloat)+1)>>1; + } + break; + } + } + case UNION_TYPE:{ + int size=mt->base_size; + size=(size+7)>>3; + if(size>2){//passed by address + if(regs.ints<8)++regs.ints; + else stack++; + extra+=size;//extra copy stack; + break; + } + if(mt->is_empty){ + break; //ignored empty struct + } + if(mt->align_mask>8){ + if(regs.ints&1) regs.ints++; + else if(stack&1) stack++; + } + if(regs.ints+size<=8) regs.ints+=size; + else{ + regs.ints=8; + stack+=size; + } + + break; + } + default: + if(regs.ints<8)++regs.ints;//no need to check type support here + else stack++; + } + } + lua_pop(L,1); + } + + return (regs.ints||regs.floats)?((stack+extra+17/*16 for regs, 1 for align*/)>>1)<<4:0;//2 eightbytes align +} + + +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,ret_by_addr; + const struct ctype* mt; + int stack_size,struct_offset; + 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); + + reg_info regs={0,0}; + + | sub sp,sp,#0x30 + | str L_ARG, [sp,#20] + | stp TOP,DATA,[sp,#0x10] + | stp x29,x30,[sp] + | mov x29,sp + | mov L_ARG,x0 + + /* reserve enough stack space for all of the arguments. */ + stack_size=caculate_stack(L,ct_usr,nargs); + struct_offset=0; + if(stack_size>0){ + if(stack_size>=1<<12){ + | load32 x9, stack_size //trick x9 + | sub sp, sp, x9 + } + else{ + | sub sp, sp, #stack_size + } + if (ct->has_var_arg) { + | bl extern lua_gettop + | cmp w0, #nargs + | bge >1 + | load64 x1, "too few arguments" + | lcall extern luaL_error + |1: + | mov TOP, x0 + | add x0, x0, #1 + | bfm x0,xzr, #0, #0 //round up 2 for stack alignment. + | sub sp, sp, x0, lsl #3 + } + | add DATA,sp,#0x80 + } + + for (i = 1,regs.ints=0,regs.floats=0; 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||mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + + + | load64 x3,mt + | load32 w2,lua_upvalueindex(num_upvals) + | mov x1,#i + + if (mt->pointers || mt->is_reference) { + | lcall extern check_typed_pointer + } else{ + switch (mt->type) { + case FUNCTION_PTR_TYPE: { + | lcall extern check_typed_cfunction + break; + } + case ENUM_TYPE:{ + | lcall extern check_enum + break; + } + case STRUCT_TYPE: + case UNION_TYPE:{ + if(mt->is_empty) continue; + + int isfloat; + int hfasize=hfa_size(L,-2,mt,&isfloat); + | lcall extern check_struct + if(hfasize>0){ + switch(hfasize){ + case 4: + if(isfloat){ + | ldp s2,s3, [x0,#8] + }else{ + | ldp d2,d3, [x0,#16] + } + goto ld_hfa; + case 3: + if(isfloat){ + | ldr s2, [x0,#8] + }else{ + | ldr d2, [x0,#16] + } + case 2: + ld_hfa: + if(isfloat){ + | ldp s0,s1, [x0] + }else{ + | ldp d0,d1, [x0] + } + break; + case 1: + if(isfloat){ + | ldr s0, [x0] + }else{ + | ldr d0, [x0] + } + break; + + } + store_float(Dst,®s,isfloat,hfasize-1); + continue; + } + if(mt->base_size>16){ + | mov x1 ,x0 + struct_offset+=(mt->base_size+7)&(~7); + if(struct_offset>=1<<12){ + | load32 x0, struct_offset //trick x0 + | sub x0, x29, x0 + } + else{ + | sub x0, x29, #struct_offset + } + store_int(Dst,®s,2); + | mov x2, #mt->base_size + | load64 x9, memcpy + | blr x9 + }else{ + if(mt->align_mask>8){//==15 + if(regs.ints&1) regs.ints++; + else if(regs.ex&1) regs.ex++; + } + int intSize=(mt->base_size+3)>>2; + switch(intSize){ + case 1: + | ldr w0, [x0] + break; + case 2: + | ldr x0, [x0] + break; + case 3: + case 4: + | ldp x0, x1, [x0] + break; + } + store_int(Dst,®s,intSize); + } + continue; + } + } + } + goto longstore; + + } else { + lua_pop(L, 1); + | mov w1, #i + + switch (mt->type) { + case BOOL_TYPE: + | lcall extern check_uint32 + | cmp w0, wzr + | cset w0, ne + goto intstore; + + case INT8_TYPE: + case INT16_TYPE: //arm64 requires callee to narrow the type + case INT32_TYPE: + + | lcall extern check_int32 + + goto intstore; + + case INT64_TYPE: + + | lcall extern check_int64 + + goto longstore; + + case INTPTR_TYPE: + | lcall extern check_uintptr + + goto longstore; + + case DOUBLE_TYPE: + | lcall extern check_double + store_float(Dst,®s,0,0); + break; + + case FLOAT_TYPE: + | lcall extern check_float + store_float(Dst,®s,1,0); + break; + case COMPLEX_DOUBLE_TYPE: + | lcall extern check_complex_double + store_float(Dst,®s,0,1); + break; + + case COMPLEX_FLOAT_TYPE: + | lcall extern check_complex_float + store_float(Dst,®s,1,1); + break; + + intstore: + store_int(Dst,®s,1); + break; + longstore: + store_int(Dst,®s,2); + break; + + default: + luaL_error(L, "NYI: call arg type"); + } + } + } + + if (ct->has_var_arg) { + if(regs.floats<8){ + | add x4, sp ,#regs.floats<<3 + | mov w3, #(8-regs.floats) + | mov x2, TOP + | mov w1, #nargs+1 + | lcall extern unpack_varargs_float + } + if(regs.ints<8){ + | add x4, sp ,#0x40+(regs.ints<<3) + | mov w3, #(8-regs.ints) + | mov x2, TOP + | mov w1, #nargs+1 + | lcall extern unpack_varargs_int + } + |//case when DATA is not allocated, all arg is skipped + | cmp TOP,#(nargs>8?nargs:8) + | ble >1 + | mov x5, DATA + | mov w3, #(8-regs.floats) + | mov w3, #(8-regs.ints) + | mov x2, TOP + | mov w1, #nargs+1 + | lcall extern unpack_varargs_stack_skip + | 1: + regs.floats=regs.ints=8; + } + + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) + && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); + if(ret_by_addr){ + | load64 x2, mt + | mov x1, #0 + | lcall extern push_cdata + | mov x8, x0 + } + + //pop all args in registers + switch(regs.ints){ + case 8: + case 7: + | ldp x6,x7,[sp,#0x70] + case 6: + case 5: + | ldp x4,x5,[sp,#0x60] + case 4: + case 3: + | ldp x2,x3,[sp,#0x50] + case 2: + case 1: + | ldp x0,x1,[sp,#0x40] + } + + switch(regs.floats){ + case 8: + case 7: + | ldp d6,d7,[sp,#0x30] + case 6: + case 5: + | ldp d4,d5,[sp,#0x20] + case 4: + case 3: + | ldp d2,d3,[sp,#0x10] + case 2: + case 1: + | ldp d0,d1,[sp] + } + if(regs.ints==8|| regs.floats==8){// fix stack case registers is full + | add sp,sp,#0x80 + } + + | load64 x9,func + | blr x9 + + |.macro return + | mov sp, x29 + | ldp x29, x30, [sp] + | ldp TOP, DATA, [sp,#0x10] + | ldr L_ARG, [sp,#0x20] + | add sp, sp, #0x30 + | ret + |.endmacro + + if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + | mov DATA, x0 + | load64 x2, mt + | load32 w1, lua_upvalueindex(num_upvals) + | lcall extern push_cdata + | str DATA, [x0] + | mov w0, #1 + | return + + } else { + switch (mt->type) { + case INT64_TYPE: + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + | mov x1, x0 + | lcall extern lua_pushinteger + | mov w0, #1 + | return + break; + #endif + + case INTPTR_TYPE: + num_upvals++; + | mov DATA, x0 + | load64 x2, mt + | mov w1, wzr + | lcall extern push_cdata + | str DATA, [x0] + | mov w0, #1 + | return + break; + case VOID_TYPE: + lua_pop(L, 1); + | mov w0, wzr + | return + break; + + case BOOL_TYPE: + lua_pop(L, 1); + | mov w1, w0 + | lcall extern lua_pushboolean + | mov w0, #1 + | return + break; + + case INT8_TYPE:// we need to narrow the value before return + lua_pop(L, 1); + | mov w1, w0 + if (mt->is_unsigned) { + | uxtb w1, w1 + | lcall extern push_uint + } else { + | sxtb w1, w1 + | lcall extern push_int + } + | mov w0, #1 + | return + break; + case INT16_TYPE:// we need to narrow the value before return + lua_pop(L, 1); + | mov w1, w0 + if (mt->is_unsigned) { + | uxth w1, w1 + | lcall extern push_uint + } else { + | sxth w1, w1 + | lcall extern push_int + } + | mov w0, #1 + | return + break; + case INT32_TYPE: + case ENUM_TYPE: + lua_pop(L, 1); + | mov w1, w0 + if (mt->is_unsigned) { + | lcall extern push_uint + } else { + | lcall extern push_int + } + | mov w0, #1 + | return + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + | lcall extern push_float + | mov w0, #1 + | return + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + | lcall extern lua_pushnumber + | mov w0, #1 + | return + break; + case COMPLEX_FLOAT_TYPE: + lua_getuservalue(L, -1); + num_upvals+=2; + | fmov w0, s0 + | fmov w1, s1 + | orr x0, x0, x1, lsl #32 + | mov DATA, x0 + | load64 x2, mt + | load32 w1, lua_upvalueindex(num_upvals) + | lcall extern push_cdata + | str DATA, [x0] + | mov w0, #1 + | return + break; + + case COMPLEX_DOUBLE_TYPE: + lua_getuservalue(L, -1); + num_upvals+=2; + | fmov TOP, d0 + | fmov DATA, d1 + | load64 x2, mt + | load32 w1, lua_upvalueindex(num_upvals) + | lcall extern push_cdata + | stp TOP,DATA, [x0] + | mov w0, #1 + | return + break; + case STRUCT_TYPE: + case UNION_TYPE: + lua_getuservalue(L, -1); + num_upvals+=2; + if(ret_by_addr){ + if(!lua_isnil(L,-1)){ + | load32 w1, lua_upvalueindex(num_upvals) + | lcall extern lua_pushvalue // lua_pushvalue(L,lua_upvalueindex(num_upvals)) + | movn w1, #1 //-2 + | lcall extern lua_setuservalue // lua_setuservalue(L,-2) + } + | mov w0, #1 + | return + }else if(mt->is_empty){ + | mov w0, #0 + | return + }else{ + int isfloat; + int hfasize=hfa_size(L,-2,mt,&isfloat); + if(hfasize){ + switch(hfasize){ + case 4: + | stp d2, d3, [sp, #-16]! + goto hfs_dual; + case 3: + | str d2, [sp, #-16]! + case 2: + hfs_dual: + | fmov TOP, d1 + case 1: + | fmov DATA, d0 + break; + } + }else{ + if(mt->base_size>8){ + | mov TOP, x1 + } + | mov DATA, x0 + + } + | load64 x2, mt + | load32 w1, lua_upvalueindex(num_upvals) + | lcall extern push_cdata + if(hfasize){ + switch(hfasize){ + case 4: + | ldp d0, d1, [sp], #16 + if(isfloat){ + | stp s0,s1, [x0,#8] + }else{ + | stp d0,d1, [x0,#16] + } + goto hfl_dual; + case 3: + | ldr d0, [sp], #16 + if(isfloat){ + | str s0, [x0,#8] + }else{ + | str d0, [x0,#16] + } + case 2: + hfl_dual: + if(isfloat){ + | fmov d0, TOP + | str s0, [x0,#4] + }else{ + | str TOP, [x0,#8] + } + case 1: + if(isfloat){ + | fmov d0, DATA + | str s0, [x0] + }else{ + | str DATA, [x0] + } + break; + } + }else{ + if(mt->base_size>8){ + | str TOP, [x0, #8] + } + | str DATA, [x0] + + } + | mov w0, #1 + | return + } + break; + + default: + luaL_error(L, "NYI: call return type"); + } + } + + assert(lua_gettop(L) == top + num_upvals); + { + cfunction f = compile(Dst, L, NULL, 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/source/texk/web2c/luatexdir/luaffi/call_arm64.h b/source/texk/web2c/luatexdir/luaffi/call_arm64.h index 748ca6dd3..aee72759e 100644 --- a/source/texk/web2c/luatexdir/luaffi/call_arm64.h +++ b/source/texk/web2c/luatexdir/luaffi/call_arm64.h @@ -1,2438 +1,2438 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.4.0, DynASM arm version 1.4.0 -** DO NOT EDIT! The original file is in "call_arm64.dasc". -*/ - -/* 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 DASM_VERSION != 10400 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -static const unsigned int build_actionlist[1117] = { -0xf84003e1, -0x000f0000, -0x00000000, -0xf8400681, -0x000a812c, -0x00000000, -0x6d400fe2, -0x000a8cef, -0x00000000, -0xfc4003e2, -0x000f0000, -0x00000000, -0x6d4007e0, -0x000a8cef, -0x00000000, -0xfc4003e0, -0x000f0000, -0x00000000, -0x2cc10680, -0x2cc10e82, -0x00000000, -0x6cc10680, -0x6cc10e82, -0x00000000, -0x2cc10680, -0xbc408682, -0x00000000, -0x6cc10680, -0xfc408682, -0x00000000, -0x2cc10680, -0x00000000, -0x6cc10680, -0x00000000, -0xbc408680, -0x00000000, -0xfc408680, -0x00000000, -0xf81f0fe8, -0x00000000, -0xd10283ff, -0x00000000, -0xd10083ff, -0x00000000, -0xa9091fe6, -0x00000000, -0xa90817e4, -0x00000000, -0xa9070fe2, -0x00000000, -0xa90607e0, -0x00000000, -0x6d051fe6, -0x00000000, -0x6d0417e4, -0x00000000, -0x6d030fe2, -0x00000000, -0x6d0207e0, -0x00000000, -0xa90157f4, -0xa9007bfd, -0x00000000, -0x910003f4, -0x000c0000, -0x00000000, -0x52800015, -0x000a0205, -0xf2a00015, -0x000a0205, -0xf2c00015, -0x000a0205, -0xf2e00015, -0x000a0205, -0x52800002, -0x000a0205, -0x72a00002, -0x000a0205, -0x52800001, -0x000a0205, -0x72a00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030000, -0x00000000, -0x52800002, -0x000a0205, -0x92800001, -0xaa1503e0, -0x94000000, -0x00030000, -0x00000000, -0x52800002, -0x000a0205, -0x92800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0xf9000001, -0x12800021, -0xaa1503e0, -0x94000000, -0x00030002, -0x00000000, -0x52800002, -0x000a0205, -0x92800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0x2d010c02, -0x00000000, -0x6d010c02, -0x00000000, -0xbd000802, -0x00000000, -0xfd000802, -0x00000000, -0x2d000400, -0x00000000, -0x6d000400, -0x00000000, -0xbd000000, -0x00000000, -0xfd000000, -0x00000000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800009, -0x000a0205, -0xf2a00009, -0x000a0205, -0xf2c00009, -0x000a0205, -0xf2e00009, -0x000a0205, -0xd63f0120, -0x00000000, -0xa9400be1, -0x000a8cef, -0xa9000801, -0x00000000, -0xf84003e1, -0x000f0000, -0xf9000001, -0x00000000, -0xa8c10a81, -0xa9000801, -0x00000000, -0xf8408681, -0xf9000001, -0x00000000, -0x12800021, -0xaa1503e0, -0x94000000, -0x00030002, -0x00000000, -0x52800002, -0x000a0205, -0x92800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0x6d000400, -0x12800021, -0xaa1503e0, -0x94000000, -0x00030002, -0x00000000, -0x52800002, -0x000a0205, -0x92800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0x2d000400, -0x12800021, -0xaa1503e0, -0x94000000, -0x00030002, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030003, -0x00000000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x2a1f03e1, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0xf9000001, -0x12800021, -0xaa1503e0, -0x94000000, -0x00030002, -0x00000000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x2a1f03e1, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0xf9000001, -0x12800021, -0xaa1503e0, -0x94000000, -0x00030002, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030004, -0x00000000, -0x384003e1, -0x000f0000, -0x00000000, -0x38c003e1, -0x000f0000, -0x00000000, -0x38408681, -0x00000000, -0x38c08681, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030005, -0x00000000, -0x784003e1, -0x000f0000, -0x00000000, -0x78c003e1, -0x000f0000, -0x00000000, -0x78408681, -0x00000000, -0x78c08681, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030005, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030005, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030006, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030007, -0x00000000, -0x52800002, -0x000a0205, -0x52800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030008, -0x00000000, -0x52800002, -0x000a0205, -0x92800021, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800003, -0x000a0205, -0xf2a00003, -0x000a0205, -0xf2c00003, -0x000a0205, -0xf2e00003, -0x000a0205, -0x92800002, -0x92800021, -0xaa1503e0, -0x94000000, -0x00030009, -0x00000000, -0x52800002, -0x000a0205, -0x92800021, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800003, -0x000a0205, -0xf2a00003, -0x000a0205, -0xf2c00003, -0x000a0205, -0xf2e00003, -0x000a0205, -0x92800002, -0x92800021, -0xaa1503e0, -0x94000000, -0x0003000a, -0xaa0003f4, -0x12800041, -0xaa1503e0, -0x94000000, -0x0003000b, -0x00000000, -0x2d410e82, -0x00000000, -0x6d410e82, -0x00000000, -0xbd400a82, -0x00000000, -0xfd400a82, -0x00000000, -0x2d400680, -0x00000000, -0x6d400680, -0x00000000, -0xbd400280, -0x00000000, -0xfd400280, -0x00000000, -0xf84003e0, -0x000f0000, -0xaa1403e1, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800009, -0x000a0205, -0xf2a00009, -0x000a0205, -0xf2c00009, -0x000a0205, -0xf2e00009, -0x000a0205, -0xd63f0120, -0x00000000, -0xa9400680, -0x00000000, -0xf9400280, -0x00000000, -0x52800002, -0x000a0205, -0x92800021, -0xaa1503e0, -0x94000000, -0x00030000, -0x52800003, -0x000a0205, -0xf2a00003, -0x000a0205, -0xf2c00003, -0x000a0205, -0xf2e00003, -0x000a0205, -0x92800002, -0x92800021, -0xaa1503e0, -0x94000000, -0x0003000c, -0x00000000, -0x12800021, -0xaa1503e0, -0x94000000, -0x0003000b, -0x00000000, -0x12800001, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000d, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000e, -0x00000000, -0x12800001, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000f, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030010, -0x00000000, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030011, -0x00000000, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030012, -0x00000000, -0x9e660014, -0x12800041, -0xaa1503e0, -0x94000000, -0x0003000b, -0x9e670280, -0x00000000, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030013, -0x00000000, -0x9e660014, -0x12800041, -0xaa1503e0, -0x94000000, -0x0003000b, -0x9e670280, -0x00000000, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030014, -0x00000000, -0x12800001, -0xaa1503e0, -0x94000000, -0x00030015, -0x00000000, -0xaa1503e0, -0x12800041, -0x9e660014, -0x9e660035, -0x94000000, -0x0003000b, -0x9e670280, -0x9e6702a1, -0x00000000, -0xaa0003f4, -0x12800041, -0xaa1503e0, -0x94000000, -0x0003000b, -0xaa1403e0, -0x00000000, -0xa9407bfd, -0xa94157f4, -0x910003ff, -0x000c0000, -0xd65f03c0, -0x00000000, -0x6d000fe2, -0x000a8cef, -0x00000000, -0xfc0003e2, -0x000f0000, -0x00000000, -0x6d0007e0, -0x000a8cef, -0x00000000, -0xfc0003e0, -0x000f0000, -0x00000000, -0x2c810680, -0x2c810e82, -0x00000000, -0x6c810680, -0x6c810e82, -0x00000000, -0x2c810680, -0xbc008682, -0x00000000, -0x6c810680, -0xfc008682, -0x00000000, -0x2c810680, -0x00000000, -0x6c810680, -0x00000000, -0xbc008680, -0x00000000, -0xfc008680, -0x00000000, -0xb80003e0, -0x000f0000, -0x00000000, -0xb8000680, -0x000a812c, -0x00000000, -0xf80003e0, -0x000f0000, -0x00000000, -0xf8000680, -0x000a812c, -0x00000000, -0xa90007e0, -0x000a8cef, -0x00000000, -0xa8810680, -0x00000000, -0xd100c3ff, -0xf80143f5, -0xa90153f3, -0xa9007bfd, -0x910003fd, -0xaa0003f5, -0x00000000, -0x52800009, -0x000a0205, -0xf2a00009, -0x000a0205, -0xcb2963ff, -0x00000000, -0xd10003ff, -0x000c0000, -0x00000000, -0x94000000, -0x00030016, -0x7100001f, -0x000c0000, -0x5400000a, -0x00050801, -0x52800001, -0x000a0205, -0xf2a00001, -0x000a0205, -0xf2c00001, -0x000a0205, -0xf2e00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030017, -0x0006000b, -0xaa0003f3, -0x91000400, -0xb34003e0, -0xcb206fff, -0x00000000, -0x910203f4, -0x00000000, -0x52800003, -0x000a0205, -0xf2a00003, -0x000a0205, -0xf2c00003, -0x000a0205, -0xf2e00003, -0x000a0205, -0x52800002, -0x000a0205, -0x72a00002, -0x000a0205, -0x52800001, -0x000a0205, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030009, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030018, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000c, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000a, -0x00000000, -0x2d410c02, -0x00000000, -0x6d410c02, -0x00000000, -0xbd400802, -0x00000000, -0xfd400802, -0x00000000, -0x2d400400, -0x00000000, -0x6d400400, -0x00000000, -0xbd400000, -0x00000000, -0xfd400000, -0x00000000, -0xaa0003e1, -0x00000000, -0x52800000, -0x000a0205, -0xf2a00000, -0x000a0205, -0xcb0003a0, -0x00000000, -0xd10003a0, -0x000c0000, -0x00000000, -0x52800002, -0x000a0205, -0x52800009, -0x000a0205, -0xf2a00009, -0x000a0205, -0xf2c00009, -0x000a0205, -0xf2e00009, -0x000a0205, -0xd63f0120, -0x00000000, -0xb9400000, -0x00000000, -0xf9400000, -0x00000000, -0xa9400400, -0x00000000, -0x52800001, -0x000a0205, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000d, -0x6b1f001f, -0x1a9f07e0, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003000e, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030010, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030011, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030013, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030012, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030014, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030015, -0x00000000, -0x910003e4, -0x000c0000, -0x52800003, -0x000a0205, -0xaa1303e2, -0x52800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030019, -0x00000000, -0x910003e4, -0x000c0000, -0x52800003, -0x000a0205, -0xaa1303e2, -0x52800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x0003001a, -0x00000000, -0xf100027f, -0x000c0000, -0x5400000d, -0x00050801, -0xaa1403e5, -0x52800003, -0x000a0205, -0x52800003, -0x000a0205, -0xaa1303e2, -0x52800001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x0003001b, -0x0006000b, -0x00000000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800001, -0xaa1503e0, -0x94000000, -0x00030001, -0xaa0003e8, -0x00000000, -0xa9471fe6, -0x00000000, -0xa94617e4, -0x00000000, -0xa9450fe2, -0x00000000, -0xa94407e0, -0x00000000, -0x6d431fe6, -0x00000000, -0x6d4217e4, -0x00000000, -0x6d410fe2, -0x00000000, -0x6d4007e0, -0x00000000, -0x910203ff, -0x00000000, -0x52800009, -0x000a0205, -0xf2a00009, -0x000a0205, -0xf2c00009, -0x000a0205, -0xf2e00009, -0x000a0205, -0xd63f0120, -0x00000000, -0xaa0003f4, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800001, -0x000a0205, -0x72a00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030001, -0xf9000014, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0xaa0003e1, -0xaa1503e0, -0x94000000, -0x00030003, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0xaa0003f4, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x2a1f03e1, -0xaa1503e0, -0x94000000, -0x00030001, -0xf9000014, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x2a1f03e0, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x2a0003e1, -0xaa1503e0, -0x94000000, -0x00030004, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x2a0003e1, -0x00000000, -0x53001c21, -0xaa1503e0, -0x94000000, -0x0003001c, -0x00000000, -0x13001c21, -0xaa1503e0, -0x94000000, -0x00030005, -0x00000000, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x2a0003e1, -0x00000000, -0x53003c21, -0xaa1503e0, -0x94000000, -0x0003001c, -0x00000000, -0x13003c21, -0xaa1503e0, -0x94000000, -0x00030005, -0x00000000, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x2a0003e1, -0x00000000, -0xaa1503e0, -0x94000000, -0x0003001c, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030005, -0x00000000, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030006, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0xaa1503e0, -0x94000000, -0x00030007, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x1e260000, -0x1e260021, -0xaa018000, -0xaa0003f4, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800001, -0x000a0205, -0x72a00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030001, -0xf9000014, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x9e660013, -0x9e660034, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800001, -0x000a0205, -0x72a00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030001, -0xa9005013, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x52800001, -0x000a0205, -0x72a00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x0003001d, -0x12800021, -0xaa1503e0, -0x94000000, -0x0003001e, -0x00000000, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x52800000, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000, -0x6dbf0fe2, -0x00000000, -0xfc1f0fe2, -0x00000000, -0x9e660033, -0x00000000, -0x9e660014, -0x00000000, -0xaa0103f3, -0x00000000, -0xaa0003f4, -0x00000000, -0x52800002, -0x000a0205, -0xf2a00002, -0x000a0205, -0xf2c00002, -0x000a0205, -0xf2e00002, -0x000a0205, -0x52800001, -0x000a0205, -0x72a00001, -0x000a0205, -0xaa1503e0, -0x94000000, -0x00030001, -0x00000000, -0x6cc107e0, -0x00000000, -0x2d010400, -0x00000000, -0x6d010400, -0x00000000, -0xfc4107e0, -0x00000000, -0xbd000800, -0x00000000, -0xfd000800, -0x00000000, -0x9e670260, -0xbd000400, -0x00000000, -0xf9000413, -0x00000000, -0x9e670280, -0xbd000000, -0x00000000, -0xf9000014, -0x00000000, -0xf9000413, -0x00000000, -0xf9000014, -0x00000000, -0x52800020, -0x910003bf, -0xa9407bfd, -0xa94153f3, -0xf94013f5, -0x9100c3ff, -0xd65f03c0, -0x00000000 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "rawgeti", - "push_cdata", - "lua_remove", - "lua_pushinteger", - "lua_pushboolean", - "push_int", - "push_float", - "lua_pushnumber", - "lua_call", - "check_typed_pointer", - "check_struct", - "lua_settop", - "check_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_uintptr", - "check_float", - "check_double", - "check_complex_double", - "check_complex_float", - "lua_gettop", - "luaL_error", - "check_typed_cfunction", - "unpack_varargs_float", - "unpack_varargs_int", - "unpack_varargs_stack_skip", - "push_uint", - "lua_pushvalue", - "lua_setuservalue", - (const char *)0 -}; - -#define JUMP_SIZE 16 - -//in aarch64 the pc is indicated the current -#define MIN_BRANCH ((INT32_MIN) >> 6) -#define MAX_BRANCH ((INT32_MAX) >> 6) -//arm64 pc has no offset so comparing with next instruction is -4 -#define BRANCH_OFF -4 -#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) - -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 128MB. - * - * Note we have to manually set this up since there are commands buffered - * in the jit state. - */ - - //l: ptr - *(cfunction*) code = func; - // ldr x9,#-8 - *(uint32_t*) &code[8] = 0x58FFFFC9; - //br x9 - *(uint32_t*) &code[12] = 0xD61F0120; - -} - -//| ldr reg, >5 -//| b >6 -//|5: -//|.long64 val -//|6: - - - -void compile_globals(struct jit* jit, lua_State* L) -{ - (void) jit; -} -typedef struct reg_info{ - uint8_t ints; - uint8_t floats; - uint16_t ex; -} reg_info; - -static ALWAYS_INLINE bool is_float_type(int t){ - return t==FLOAT_TYPE||t==DOUBLE_TYPE; -} - -static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ - struct ctype* mt; - int type,ele_count,i,ct_usr; - lua_getuservalue(L,idx); - ct_usr=lua_absindex(L,-1); - lua_rawgeti(L,ct_usr,1); - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - return 0; - } - type=mt->type; - ele_count=(int)(ct->base_size/mt->base_size); - if(ele_count>4||ct->base_size%mt->base_size){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - for (i = 2;i<=4; ++i) { - lua_rawgeti(L,ct_usr,i); - if(lua_isnil(L,-1)){//case have array member; - lua_pop(L,1); - break; - } - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - } - if(isfloat){ - *isfloat=mt->type==FLOAT_TYPE; - } - lua_pop(L,1); - return ele_count; -} - -static reg_info caculate_regs(lua_State* L,int ct_usr,int nargs){ - int i;reg_info regs; - const struct ctype* mt; - for (i = 1,regs.ints=0,regs.floats=0; i <= nargs&&(regs.floats<8||regs.ints<8); ++i){ - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (mt->pointers || mt->is_reference) { - if(regs.ints<8)regs.ints++; - }else{ - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - if(regs.floats<7) - regs.floats+=2; - else if(regs.floats==7) - regs.floats=8; - break; - case FLOAT_TYPE: - case DOUBLE_TYPE: - if(regs.floats<8) ++regs.floats; - break; - case STRUCT_TYPE:{ - int hfasize=hfa_size(L,-1,mt,NULL); - if(hfasize>0){ - regs.floats+=hfasize; - if(regs.floats>8) - regs.floats=8; - break; - } - } - case UNION_TYPE:{ - int size=mt->base_size; - if(size>16){//passed by address - if(regs.ints<8)++regs.ints; - break; - } - if(mt->is_empty){ - break; //ignored empty struct - } - size=(size+7)>>3; - if(regs.ints+size<=8) regs.ints+=size; - break; - } - default: - if(regs.ints<8)++regs.ints;//no need to check type support here - } - } - lua_pop(L,1); - } - - return regs; -} - -// arm store/load range for immediate value is only -256-255 -static ALWAYS_INLINE void load_int(struct jit* Dst,reg_info* regs){ - if(regs->ints<8) - dasm_put(Dst, 0, 0x60+(regs->ints++<<3)); - else - dasm_put(Dst, 3, (regs->ex++,8)); -} - -static void load_float(struct jit* Dst,reg_info* regs,int isfloat,int exSize){ - if(regs->floats+exSize<8){ - switch(exSize){ - case 3: - dasm_put(Dst, 6, 0x30+(regs->floats<<3)); - goto l_dual; - case 2: - dasm_put(Dst, 9, 0x30+(regs->floats<<3)); - case 1: - l_dual: - dasm_put(Dst, 12, 0x20+(regs->floats<<3)); - break; - case 0: - dasm_put(Dst, 15, 0x20+(regs->floats<<3)); - break; - } - regs->floats+=exSize+1; - - }else{ - regs->floats=8; - regs->ex+=exSize+1; - switch(exSize){ - case 3: - if(isfloat){ - dasm_put(Dst, 18); - }else{ - dasm_put(Dst, 21); - } - break; - case 2: - if(isfloat){ //12 bytes rounded to 16 - dasm_put(Dst, 24); - break; - }else { - dasm_put(Dst, 27); - } - break; - case 1: - if(isfloat){ - dasm_put(Dst, 30); - }else{ - dasm_put(Dst, 32); - } - break; - case 0: - if(isfloat){ - dasm_put(Dst, 34); - }else { - dasm_put(Dst, 36); - } - break; - } - - } -} - -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,ret_by_addr; - 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"); - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) - && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); - if(ret_by_addr){ - dasm_put(Dst, 38); - } - lua_pop(L,1); - reg_info regs=caculate_regs(L,ct_usr,nargs); - - if(regs.ints||regs.floats){ - dasm_put(Dst, 40); - }else{ - dasm_put(Dst, 42); - } - //8 integer reigsters and 8 floating registers - switch(regs.ints){ - case 8: - case 7: - dasm_put(Dst, 44); - case 6: - case 5: - dasm_put(Dst, 46); - case 4: - case 3: - dasm_put(Dst, 48); - case 2: - case 1: - dasm_put(Dst, 50); - } - - switch(regs.floats){ - case 8: - case 7: - dasm_put(Dst, 52); - case 6: - case 5: - dasm_put(Dst, 54); - case 4: - case 3: - dasm_put(Dst, 56); - case 2: - case 1: - dasm_put(Dst, 58); - } - dasm_put(Dst, 60); - - if(regs.ints==8||regs.floats==8){ // may be overflowed if it's full - dasm_put(Dst, 63, 0xa0+ret_by_addr*0x10); - } - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - - dasm_put(Dst, 66, (unsigned short)(L), (((unsigned int)(L))>>16), (unsigned short)((unsigned long)(L)>>32), (unsigned short)((unsigned long)(L)>>48), (unsigned short)(ref), (((unsigned int)(ref))>>16), (unsigned short)(LUA_REGISTRYINDEX), (((unsigned int)(LUA_REGISTRYINDEX))>>16)); - - dasm_put(Dst, 86, num_upvals); - - - for (i = 1,regs.ints=0,regs.floats=0; 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, 93, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - load_int(Dst,®s); - dasm_put(Dst, 113); - - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - int isfloat,hfasize=0; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 119, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - - if(hfasize){ - load_float(Dst,®s,isfloat,hfasize-1); - switch(hfasize){ - case 4: - if(isfloat){ - dasm_put(Dst, 139); - }else{ - dasm_put(Dst, 141); - } - goto hfa2; - case 3: - if(isfloat){ - dasm_put(Dst, 143); - }else{ - dasm_put(Dst, 145); - } - case 2: - hfa2: - if(isfloat){ - dasm_put(Dst, 147); - }else{ - dasm_put(Dst, 149); - } - break; - case 1: - if(isfloat){ - dasm_put(Dst, 151); - }else{ - dasm_put(Dst, 153); - } - break; - - } - }else if(!mt->is_empty){ - size_t size=mt->base_size; - if(size>16){ - load_int(Dst,®s); - dasm_put(Dst, 155, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)((unsigned long)(mt->base_size)>>32), (unsigned short)((unsigned long)(mt->base_size)>>48), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16), (unsigned short)((unsigned long)(memcpy)>>32), (unsigned short)((unsigned long)(memcpy)>>48)); - }else{ - size=(size+7)>>3; - if(mt->align_mask>8){ - if(regs.ints&1) regs.ints++; - else if(regs.ex&1) regs.ex++; - } - if(regs.ints+size<=8){ - if(size>1){ - dasm_put(Dst, 173, 0x60+(regs.ints<<3)); - }else{ - dasm_put(Dst, 177, 0x60+(regs.ints<<3)); - } - regs.ints+=size; - }else{ - regs.ints=8; - if(size>1){ - dasm_put(Dst, 181); - }else{ - dasm_put(Dst, 184); - } - - } - } - - - } - - dasm_put(Dst, 187); - break; - } - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 192, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - load_float(Dst,®s,0,1); - dasm_put(Dst, 212); - - break; - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 218, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - load_float(Dst,®s,1,1); - dasm_put(Dst, 238); - - break; - case INT64_TYPE: - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - load_int(Dst,®s); - dasm_put(Dst, 244); - - #else - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 248, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - load_int(Dst,®s); - dasm_put(Dst, 261); - - #endif - break; - - case INTPTR_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 267, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - load_int(Dst,®s); - dasm_put(Dst, 280); - - break; - - case BOOL_TYPE: - lua_pop(L, 1); - - load_int(Dst,®s); - dasm_put(Dst, 286); - - break; - - case INT8_TYPE:// need to narrow for caller doesn't do it - lua_pop(L, 1); - if(regs.ints<8){ - if (mt->is_unsigned) { - dasm_put(Dst, 290, 0x60+(regs.ints++<<3)); - } else { - dasm_put(Dst, 293, 0x60+(regs.ints++<<3)); - } - }else { - if (mt->is_unsigned) { - dasm_put(Dst, 296); - } else { - dasm_put(Dst, 298); - } - } - dasm_put(Dst, 300); - break; - - case INT16_TYPE:// need to narrow for caller doesn't do it - lua_pop(L, 1); - if(regs.ints<8){ - if (mt->is_unsigned) { - dasm_put(Dst, 304, 0x60+(regs.ints++<<3)); - } else { - dasm_put(Dst, 307, 0x60+(regs.ints++<<3)); - } - }else { - if (mt->is_unsigned) { - dasm_put(Dst, 310); - } else { - dasm_put(Dst, 312); - } - } - dasm_put(Dst, 314); - break; - - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - load_int(Dst,®s); - - dasm_put(Dst, 318); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - load_float(Dst,®s,1,0); - dasm_put(Dst, 322); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - load_float(Dst,®s,0,0); - dasm_put(Dst, 326); - 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, 330, ((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, 338, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - goto single_no_pop; - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - int hfasize=0,isfloat; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 358, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - if(hfasize){ - switch(hfasize){ - case 4: - if(isfloat){ - dasm_put(Dst, 383); - }else{ - dasm_put(Dst, 385); - } - goto ld_hfa; - case 3: - if(isfloat){ - dasm_put(Dst, 387); - }else{ - dasm_put(Dst, 389); - } - case 2: - ld_hfa: - if(isfloat){ - dasm_put(Dst, 391); - }else{ - dasm_put(Dst, 393); - } - break; - case 1: - if(isfloat){ - dasm_put(Dst, 395); - }else{ - dasm_put(Dst, 397); - } - break; - } - }else{ - if(mt->base_size>16){ - dasm_put(Dst, 399, 0x20+((regs.ints||regs.floats)?0x80:0), (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)((unsigned long)(mt->base_size)>>32), (unsigned short)((unsigned long)(mt->base_size)>>48), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16), (unsigned short)((unsigned long)(memcpy)>>32), (unsigned short)((unsigned long)(memcpy)>>48)); - }else{ - if(mt->base_size>8){ - dasm_put(Dst, 420); - }else{ - dasm_put(Dst, 422); - } - } - } - break; - } - 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, 424, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - - goto single_no_pop; - - case VOID_TYPE: - dasm_put(Dst, 444); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: //caller's responsiblity to narrow - dasm_put(Dst, 449); - if (mt->is_unsigned) { - dasm_put(Dst, 451); - } else { - dasm_put(Dst, 455); - } - - goto single; - - case INT64_TYPE: - dasm_put(Dst, 459); - if (mt->is_unsigned) { - dasm_put(Dst, 461); - } else { - dasm_put(Dst, 465); - } - - goto single; - - case INTPTR_TYPE: - dasm_put(Dst, 469); - goto single; - - case FLOAT_TYPE: - dasm_put(Dst, 474); - - dasm_put(Dst, 479); - lua_pop(L, 1); - break; - case DOUBLE_TYPE: - dasm_put(Dst, 486); - - dasm_put(Dst, 491); - - lua_pop(L, 1); - break; - - case COMPLEX_DOUBLE_TYPE: - - dasm_put(Dst, 498); - - goto complex_ret; - case COMPLEX_FLOAT_TYPE: - dasm_put(Dst, 503); - - complex_ret: - dasm_put(Dst, 508); - - lua_pop(L, 1); - break; - single: - lua_pop(L, 1); - single_no_pop: - dasm_put(Dst, 517); - break; - - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 524, (0x20 +ret_by_addr*0x10+ ((regs.floats!=0)||(regs.ints!=0)) * 0x80)); - - 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; - } -} - -//arm64 argument can only be in stack or registers. An argument can't be splited between stack and register. -static void store_float(struct jit* Dst,reg_info* regs,int isfloat,int ex){ - if(regs->floats+ex<8){ - - switch(ex){ - case 3: - dasm_put(Dst, 530, 0x10+(regs->floats<<3)); - goto sd_dual; - case 2: - dasm_put(Dst, 533, 0x10+(regs->floats<<3)); - case 1: - sd_dual: - dasm_put(Dst, 536, (regs->floats<<3)); - break; - case 0: - dasm_put(Dst, 539, (regs->floats<<3)); - break; - } - regs->floats+=1+ex; - }else { - regs->floats=8; - switch(ex){ - case 3: - if(isfloat){ - dasm_put(Dst, 542); - }else{ - dasm_put(Dst, 545); - } - break; - case 2: - if(isfloat){ - dasm_put(Dst, 548); - }else{ - dasm_put(Dst, 551); - } - break; - case 1: - if(isfloat){ - dasm_put(Dst, 554); - }else{ - dasm_put(Dst, 556); - } - break; - case 0: - if(isfloat){ - dasm_put(Dst, 558); - }else { - dasm_put(Dst, 560); - } - break; - } - //complex float is packed as one double on stack - regs->ex+=ex+1; - } -} - -static void store_int(struct jit* Dst,reg_info* regs,int intSize){ - switch(intSize){ - case 1: - if(regs->ints<8) - dasm_put(Dst, 562, 0x40+(regs->ints++<<3)); - else - dasm_put(Dst, 565, (regs->ex++,8)); - break; - case 2: - if(regs->ints<8) - dasm_put(Dst, 568, 0x40+(regs->ints++<<3)); - else - dasm_put(Dst, 571, (regs->ex++,8)); - break; - case 3: - case 4: - if(regs->ints<7){ - dasm_put(Dst, 574, 0x40+(regs->ints<<3)); - regs->ints+=2; - } - else{ - if(regs->ints==7) - regs->ints=8; - dasm_put(Dst, 577); - regs->ex+=2; - } - - break; - } -} - -static int caculate_stack(lua_State* L,int ct_usr,int nargs){ - int i;reg_info regs={0,0,0}; - const struct ctype* mt;int stack=0,extra=0; - 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) { - if(regs.ints<8)regs.ints++; - else stack++; - }else{ - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - if(regs.floats<7) - regs.floats+=2; - else if(regs.floats==7) - regs.floats=8; - else stack+=mt->base_size>>3; - break; - case FLOAT_TYPE: - case DOUBLE_TYPE: - if(regs.floats<8) ++regs.floats; - else stack++; - break; - case STRUCT_TYPE:{ - int isfloat; - int hfasize=hfa_size(L,-1,mt,&isfloat); - if(hfasize>0){ - if(regs.floats+hfasize<=8) - regs.floats +=hfasize; - else { - regs.floats=8; - stack+=(hfasize*(2-isfloat)+1)>>1; - } - break; - } - } - case UNION_TYPE:{ - int size=mt->base_size; - size=(size+7)>>3; - if(size>2){//passed by address - if(regs.ints<8)++regs.ints; - else stack++; - extra+=size;//extra copy stack; - break; - } - if(mt->is_empty){ - break; //ignored empty struct - } - if(mt->align_mask>8){ - if(regs.ints&1) regs.ints++; - else if(stack&1) stack++; - } - if(regs.ints+size<=8) regs.ints+=size; - else{ - regs.ints=8; - stack+=size; - } - - break; - } - default: - if(regs.ints<8)++regs.ints;//no need to check type support here - else stack++; - } - } - lua_pop(L,1); - } - - return (regs.ints||regs.floats)?((stack+extra+17/*16 for regs, 1 for align*/)>>1)<<4:0;//2 eightbytes align -} - - -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,ret_by_addr; - const struct ctype* mt; - int stack_size,struct_offset; - 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); - - reg_info regs={0,0}; - - dasm_put(Dst, 579); - - /* reserve enough stack space for all of the arguments. */ - stack_size=caculate_stack(L,ct_usr,nargs); - struct_offset=0; - if(stack_size>0){ - if(stack_size>=1<<12){ - dasm_put(Dst, 586, (unsigned short)(stack_size), (((unsigned int)(stack_size))>>16)); - } - else{ - dasm_put(Dst, 592, stack_size); - } - if (ct->has_var_arg) { - dasm_put(Dst, 595, nargs, (unsigned short)("too few arguments"), (((unsigned int)("too few arguments"))>>16), (unsigned short)((unsigned long)("too few arguments")>>32), (unsigned short)((unsigned long)("too few arguments")>>48)); - } - dasm_put(Dst, 618); - } - - for (i = 1,regs.ints=0,regs.floats=0; 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||mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - - - dasm_put(Dst, 620, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16), i); - - if (mt->pointers || mt->is_reference) { - dasm_put(Dst, 635); - } else{ - switch (mt->type) { - case FUNCTION_PTR_TYPE: { - dasm_put(Dst, 639); - break; - } - case ENUM_TYPE:{ - dasm_put(Dst, 643); - break; - } - case STRUCT_TYPE: - case UNION_TYPE:{ - if(mt->is_empty) continue; - - int isfloat; - int hfasize=hfa_size(L,-2,mt,&isfloat); - dasm_put(Dst, 647); - if(hfasize>0){ - switch(hfasize){ - case 4: - if(isfloat){ - dasm_put(Dst, 651); - }else{ - dasm_put(Dst, 653); - } - goto ld_hfa; - case 3: - if(isfloat){ - dasm_put(Dst, 655); - }else{ - dasm_put(Dst, 657); - } - case 2: - ld_hfa: - if(isfloat){ - dasm_put(Dst, 659); - }else{ - dasm_put(Dst, 661); - } - break; - case 1: - if(isfloat){ - dasm_put(Dst, 663); - }else{ - dasm_put(Dst, 665); - } - break; - - } - store_float(Dst,®s,isfloat,hfasize-1); - continue; - } - if(mt->base_size>16){ - dasm_put(Dst, 667); - struct_offset+=(mt->base_size+7)&(~7); - if(struct_offset>=1<<12){ - dasm_put(Dst, 669, (unsigned short)(struct_offset), (((unsigned int)(struct_offset))>>16)); - } - else{ - dasm_put(Dst, 675, struct_offset); - } - store_int(Dst,®s,2); - dasm_put(Dst, 678, mt->base_size, (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16), (unsigned short)((unsigned long)(memcpy)>>32), (unsigned short)((unsigned long)(memcpy)>>48)); - }else{ - if(mt->align_mask>8){//==15 - if(regs.ints&1) regs.ints++; - else if(regs.ex&1) regs.ex++; - } - int intSize=(mt->base_size+3)>>2; - switch(intSize){ - case 1: - dasm_put(Dst, 690); - break; - case 2: - dasm_put(Dst, 692); - break; - case 3: - case 4: - dasm_put(Dst, 694); - break; - } - store_int(Dst,®s,intSize); - } - continue; - } - } - } - goto longstore; - - } else { - lua_pop(L, 1); - dasm_put(Dst, 696, i); - - switch (mt->type) { - case BOOL_TYPE: - dasm_put(Dst, 699); - goto intstore; - - case INT8_TYPE: - case INT16_TYPE: //arm64 requires callee to narrow the type - case INT32_TYPE: - - dasm_put(Dst, 705); - - goto intstore; - - case INT64_TYPE: - - dasm_put(Dst, 709); - - goto longstore; - - case INTPTR_TYPE: - dasm_put(Dst, 713); - - goto longstore; - - case DOUBLE_TYPE: - dasm_put(Dst, 717); - store_float(Dst,®s,0,0); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 721); - store_float(Dst,®s,1,0); - break; - case COMPLEX_DOUBLE_TYPE: - dasm_put(Dst, 725); - store_float(Dst,®s,0,1); - break; - - case COMPLEX_FLOAT_TYPE: - dasm_put(Dst, 729); - store_float(Dst,®s,1,1); - break; - - intstore: - store_int(Dst,®s,1); - break; - longstore: - store_int(Dst,®s,2); - break; - - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { - if(regs.floats<8){ - dasm_put(Dst, 733, regs.floats<<3, (8-regs.floats), nargs+1); - } - if(regs.ints<8){ - dasm_put(Dst, 744, 0x40+(regs.ints<<3), (8-regs.ints), nargs+1); - } - dasm_put(Dst, 755, (nargs>8?nargs:8), (8-regs.floats), (8-regs.ints), nargs+1); - regs.floats=regs.ints=8; - } - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) - && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); - if(ret_by_addr){ - dasm_put(Dst, 772, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - } - - //pop all args in registers - switch(regs.ints){ - case 8: - case 7: - dasm_put(Dst, 786); - case 6: - case 5: - dasm_put(Dst, 788); - case 4: - case 3: - dasm_put(Dst, 790); - case 2: - case 1: - dasm_put(Dst, 792); - } - - switch(regs.floats){ - case 8: - case 7: - dasm_put(Dst, 794); - case 6: - case 5: - dasm_put(Dst, 796); - case 4: - case 3: - dasm_put(Dst, 798); - case 2: - case 1: - dasm_put(Dst, 800); - } - if(regs.ints==8|| regs.floats==8){// fix stack case registers is full - dasm_put(Dst, 802); - } - - dasm_put(Dst, 804, (unsigned short)(func), (((unsigned int)(func))>>16), (unsigned short)((unsigned long)(func)>>32), (unsigned short)((unsigned long)(func)>>48)); - - - if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 814, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - - } else { - switch (mt->type) { - case INT64_TYPE: - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - dasm_put(Dst, 839); - break; - #endif - - case INTPTR_TYPE: - num_upvals++; - dasm_put(Dst, 851, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); - break; - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 873); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 881); - break; - - case INT8_TYPE:// we need to narrow the value before return - lua_pop(L, 1); - dasm_put(Dst, 893); - if (mt->is_unsigned) { - dasm_put(Dst, 895); - } else { - dasm_put(Dst, 900); - } - dasm_put(Dst, 905); - break; - case INT16_TYPE:// we need to narrow the value before return - lua_pop(L, 1); - dasm_put(Dst, 913); - if (mt->is_unsigned) { - dasm_put(Dst, 915); - } else { - dasm_put(Dst, 920); - } - dasm_put(Dst, 925); - break; - case INT32_TYPE: - case ENUM_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 933); - if (mt->is_unsigned) { - dasm_put(Dst, 935); - } else { - dasm_put(Dst, 939); - } - dasm_put(Dst, 943); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 951); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 962); - break; - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - num_upvals+=2; - dasm_put(Dst, 973, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - break; - - case COMPLEX_DOUBLE_TYPE: - lua_getuservalue(L, -1); - num_upvals+=2; - dasm_put(Dst, 1001, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - break; - case STRUCT_TYPE: - case UNION_TYPE: - lua_getuservalue(L, -1); - num_upvals+=2; - if(ret_by_addr){ - if(!lua_isnil(L,-1)){ - dasm_put(Dst, 1027, (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - } - dasm_put(Dst, 1039); - }else if(mt->is_empty){ - dasm_put(Dst, 1047); - }else{ - int isfloat; - int hfasize=hfa_size(L,-2,mt,&isfloat); - if(hfasize){ - switch(hfasize){ - case 4: - dasm_put(Dst, 1055); - goto hfs_dual; - case 3: - dasm_put(Dst, 1057); - case 2: - hfs_dual: - dasm_put(Dst, 1059); - case 1: - dasm_put(Dst, 1061); - break; - } - }else{ - if(mt->base_size>8){ - dasm_put(Dst, 1063); - } - dasm_put(Dst, 1065); - - } - dasm_put(Dst, 1067, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - if(hfasize){ - switch(hfasize){ - case 4: - dasm_put(Dst, 1083); - if(isfloat){ - dasm_put(Dst, 1085); - }else{ - dasm_put(Dst, 1087); - } - goto hfl_dual; - case 3: - dasm_put(Dst, 1089); - if(isfloat){ - dasm_put(Dst, 1091); - }else{ - dasm_put(Dst, 1093); - } - case 2: - hfl_dual: - if(isfloat){ - dasm_put(Dst, 1095); - }else{ - dasm_put(Dst, 1098); - } - case 1: - if(isfloat){ - dasm_put(Dst, 1100); - }else{ - dasm_put(Dst, 1103); - } - break; - } - }else{ - if(mt->base_size>8){ - dasm_put(Dst, 1105); - } - dasm_put(Dst, 1107); - - } - dasm_put(Dst, 1109); - } - break; - - default: - luaL_error(L, "NYI: call return type"); - } - } - - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, NULL, 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); - } -} - +/* +** This file has been pre-processed with DynASM. +** http://luajit.org/dynasm.html +** DynASM version 1.4.0, DynASM arm version 1.4.0 +** DO NOT EDIT! The original file is in "call_arm64.dasc". +*/ + +/* 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 DASM_VERSION != 10400 +#error "Version mismatch between DynASM and included encoding engine" +#endif + +static const unsigned int build_actionlist[1117] = { +0xf84003e1, +0x000f0000, +0x00000000, +0xf8400681, +0x000a812c, +0x00000000, +0x6d400fe2, +0x000a8cef, +0x00000000, +0xfc4003e2, +0x000f0000, +0x00000000, +0x6d4007e0, +0x000a8cef, +0x00000000, +0xfc4003e0, +0x000f0000, +0x00000000, +0x2cc10680, +0x2cc10e82, +0x00000000, +0x6cc10680, +0x6cc10e82, +0x00000000, +0x2cc10680, +0xbc408682, +0x00000000, +0x6cc10680, +0xfc408682, +0x00000000, +0x2cc10680, +0x00000000, +0x6cc10680, +0x00000000, +0xbc408680, +0x00000000, +0xfc408680, +0x00000000, +0xf81f0fe8, +0x00000000, +0xd10283ff, +0x00000000, +0xd10083ff, +0x00000000, +0xa9091fe6, +0x00000000, +0xa90817e4, +0x00000000, +0xa9070fe2, +0x00000000, +0xa90607e0, +0x00000000, +0x6d051fe6, +0x00000000, +0x6d0417e4, +0x00000000, +0x6d030fe2, +0x00000000, +0x6d0207e0, +0x00000000, +0xa90157f4, +0xa9007bfd, +0x00000000, +0x910003f4, +0x000c0000, +0x00000000, +0x52800015, +0x000a0205, +0xf2a00015, +0x000a0205, +0xf2c00015, +0x000a0205, +0xf2e00015, +0x000a0205, +0x52800002, +0x000a0205, +0x72a00002, +0x000a0205, +0x52800001, +0x000a0205, +0x72a00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030000, +0x00000000, +0x52800002, +0x000a0205, +0x92800001, +0xaa1503e0, +0x94000000, +0x00030000, +0x00000000, +0x52800002, +0x000a0205, +0x92800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0xf9000001, +0x12800021, +0xaa1503e0, +0x94000000, +0x00030002, +0x00000000, +0x52800002, +0x000a0205, +0x92800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0x2d010c02, +0x00000000, +0x6d010c02, +0x00000000, +0xbd000802, +0x00000000, +0xfd000802, +0x00000000, +0x2d000400, +0x00000000, +0x6d000400, +0x00000000, +0xbd000000, +0x00000000, +0xfd000000, +0x00000000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800009, +0x000a0205, +0xf2a00009, +0x000a0205, +0xf2c00009, +0x000a0205, +0xf2e00009, +0x000a0205, +0xd63f0120, +0x00000000, +0xa9400be1, +0x000a8cef, +0xa9000801, +0x00000000, +0xf84003e1, +0x000f0000, +0xf9000001, +0x00000000, +0xa8c10a81, +0xa9000801, +0x00000000, +0xf8408681, +0xf9000001, +0x00000000, +0x12800021, +0xaa1503e0, +0x94000000, +0x00030002, +0x00000000, +0x52800002, +0x000a0205, +0x92800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0x6d000400, +0x12800021, +0xaa1503e0, +0x94000000, +0x00030002, +0x00000000, +0x52800002, +0x000a0205, +0x92800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0x2d000400, +0x12800021, +0xaa1503e0, +0x94000000, +0x00030002, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030003, +0x00000000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x2a1f03e1, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0xf9000001, +0x12800021, +0xaa1503e0, +0x94000000, +0x00030002, +0x00000000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x2a1f03e1, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0xf9000001, +0x12800021, +0xaa1503e0, +0x94000000, +0x00030002, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030004, +0x00000000, +0x384003e1, +0x000f0000, +0x00000000, +0x38c003e1, +0x000f0000, +0x00000000, +0x38408681, +0x00000000, +0x38c08681, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030005, +0x00000000, +0x784003e1, +0x000f0000, +0x00000000, +0x78c003e1, +0x000f0000, +0x00000000, +0x78408681, +0x00000000, +0x78c08681, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030005, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030005, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030006, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030007, +0x00000000, +0x52800002, +0x000a0205, +0x52800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030008, +0x00000000, +0x52800002, +0x000a0205, +0x92800021, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800003, +0x000a0205, +0xf2a00003, +0x000a0205, +0xf2c00003, +0x000a0205, +0xf2e00003, +0x000a0205, +0x92800002, +0x92800021, +0xaa1503e0, +0x94000000, +0x00030009, +0x00000000, +0x52800002, +0x000a0205, +0x92800021, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800003, +0x000a0205, +0xf2a00003, +0x000a0205, +0xf2c00003, +0x000a0205, +0xf2e00003, +0x000a0205, +0x92800002, +0x92800021, +0xaa1503e0, +0x94000000, +0x0003000a, +0xaa0003f4, +0x12800041, +0xaa1503e0, +0x94000000, +0x0003000b, +0x00000000, +0x2d410e82, +0x00000000, +0x6d410e82, +0x00000000, +0xbd400a82, +0x00000000, +0xfd400a82, +0x00000000, +0x2d400680, +0x00000000, +0x6d400680, +0x00000000, +0xbd400280, +0x00000000, +0xfd400280, +0x00000000, +0xf84003e0, +0x000f0000, +0xaa1403e1, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800009, +0x000a0205, +0xf2a00009, +0x000a0205, +0xf2c00009, +0x000a0205, +0xf2e00009, +0x000a0205, +0xd63f0120, +0x00000000, +0xa9400680, +0x00000000, +0xf9400280, +0x00000000, +0x52800002, +0x000a0205, +0x92800021, +0xaa1503e0, +0x94000000, +0x00030000, +0x52800003, +0x000a0205, +0xf2a00003, +0x000a0205, +0xf2c00003, +0x000a0205, +0xf2e00003, +0x000a0205, +0x92800002, +0x92800021, +0xaa1503e0, +0x94000000, +0x0003000c, +0x00000000, +0x12800021, +0xaa1503e0, +0x94000000, +0x0003000b, +0x00000000, +0x12800001, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000d, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000e, +0x00000000, +0x12800001, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000f, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030010, +0x00000000, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030011, +0x00000000, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030012, +0x00000000, +0x9e660014, +0x12800041, +0xaa1503e0, +0x94000000, +0x0003000b, +0x9e670280, +0x00000000, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030013, +0x00000000, +0x9e660014, +0x12800041, +0xaa1503e0, +0x94000000, +0x0003000b, +0x9e670280, +0x00000000, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030014, +0x00000000, +0x12800001, +0xaa1503e0, +0x94000000, +0x00030015, +0x00000000, +0xaa1503e0, +0x12800041, +0x9e660014, +0x9e660035, +0x94000000, +0x0003000b, +0x9e670280, +0x9e6702a1, +0x00000000, +0xaa0003f4, +0x12800041, +0xaa1503e0, +0x94000000, +0x0003000b, +0xaa1403e0, +0x00000000, +0xa9407bfd, +0xa94157f4, +0x910003ff, +0x000c0000, +0xd65f03c0, +0x00000000, +0x6d000fe2, +0x000a8cef, +0x00000000, +0xfc0003e2, +0x000f0000, +0x00000000, +0x6d0007e0, +0x000a8cef, +0x00000000, +0xfc0003e0, +0x000f0000, +0x00000000, +0x2c810680, +0x2c810e82, +0x00000000, +0x6c810680, +0x6c810e82, +0x00000000, +0x2c810680, +0xbc008682, +0x00000000, +0x6c810680, +0xfc008682, +0x00000000, +0x2c810680, +0x00000000, +0x6c810680, +0x00000000, +0xbc008680, +0x00000000, +0xfc008680, +0x00000000, +0xb80003e0, +0x000f0000, +0x00000000, +0xb8000680, +0x000a812c, +0x00000000, +0xf80003e0, +0x000f0000, +0x00000000, +0xf8000680, +0x000a812c, +0x00000000, +0xa90007e0, +0x000a8cef, +0x00000000, +0xa8810680, +0x00000000, +0xd100c3ff, +0xf80143f5, +0xa90153f3, +0xa9007bfd, +0x910003fd, +0xaa0003f5, +0x00000000, +0x52800009, +0x000a0205, +0xf2a00009, +0x000a0205, +0xcb2963ff, +0x00000000, +0xd10003ff, +0x000c0000, +0x00000000, +0x94000000, +0x00030016, +0x7100001f, +0x000c0000, +0x5400000a, +0x00050801, +0x52800001, +0x000a0205, +0xf2a00001, +0x000a0205, +0xf2c00001, +0x000a0205, +0xf2e00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030017, +0x0006000b, +0xaa0003f3, +0x91000400, +0xb34003e0, +0xcb206fff, +0x00000000, +0x910203f4, +0x00000000, +0x52800003, +0x000a0205, +0xf2a00003, +0x000a0205, +0xf2c00003, +0x000a0205, +0xf2e00003, +0x000a0205, +0x52800002, +0x000a0205, +0x72a00002, +0x000a0205, +0x52800001, +0x000a0205, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030009, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030018, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000c, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000a, +0x00000000, +0x2d410c02, +0x00000000, +0x6d410c02, +0x00000000, +0xbd400802, +0x00000000, +0xfd400802, +0x00000000, +0x2d400400, +0x00000000, +0x6d400400, +0x00000000, +0xbd400000, +0x00000000, +0xfd400000, +0x00000000, +0xaa0003e1, +0x00000000, +0x52800000, +0x000a0205, +0xf2a00000, +0x000a0205, +0xcb0003a0, +0x00000000, +0xd10003a0, +0x000c0000, +0x00000000, +0x52800002, +0x000a0205, +0x52800009, +0x000a0205, +0xf2a00009, +0x000a0205, +0xf2c00009, +0x000a0205, +0xf2e00009, +0x000a0205, +0xd63f0120, +0x00000000, +0xb9400000, +0x00000000, +0xf9400000, +0x00000000, +0xa9400400, +0x00000000, +0x52800001, +0x000a0205, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000d, +0x6b1f001f, +0x1a9f07e0, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003000e, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030010, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030011, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030013, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030012, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030014, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030015, +0x00000000, +0x910003e4, +0x000c0000, +0x52800003, +0x000a0205, +0xaa1303e2, +0x52800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030019, +0x00000000, +0x910003e4, +0x000c0000, +0x52800003, +0x000a0205, +0xaa1303e2, +0x52800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x0003001a, +0x00000000, +0xf100027f, +0x000c0000, +0x5400000d, +0x00050801, +0xaa1403e5, +0x52800003, +0x000a0205, +0x52800003, +0x000a0205, +0xaa1303e2, +0x52800001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x0003001b, +0x0006000b, +0x00000000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800001, +0xaa1503e0, +0x94000000, +0x00030001, +0xaa0003e8, +0x00000000, +0xa9471fe6, +0x00000000, +0xa94617e4, +0x00000000, +0xa9450fe2, +0x00000000, +0xa94407e0, +0x00000000, +0x6d431fe6, +0x00000000, +0x6d4217e4, +0x00000000, +0x6d410fe2, +0x00000000, +0x6d4007e0, +0x00000000, +0x910203ff, +0x00000000, +0x52800009, +0x000a0205, +0xf2a00009, +0x000a0205, +0xf2c00009, +0x000a0205, +0xf2e00009, +0x000a0205, +0xd63f0120, +0x00000000, +0xaa0003f4, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800001, +0x000a0205, +0x72a00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030001, +0xf9000014, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0xaa0003e1, +0xaa1503e0, +0x94000000, +0x00030003, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0xaa0003f4, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x2a1f03e1, +0xaa1503e0, +0x94000000, +0x00030001, +0xf9000014, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x2a1f03e0, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x2a0003e1, +0xaa1503e0, +0x94000000, +0x00030004, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x2a0003e1, +0x00000000, +0x53001c21, +0xaa1503e0, +0x94000000, +0x0003001c, +0x00000000, +0x13001c21, +0xaa1503e0, +0x94000000, +0x00030005, +0x00000000, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x2a0003e1, +0x00000000, +0x53003c21, +0xaa1503e0, +0x94000000, +0x0003001c, +0x00000000, +0x13003c21, +0xaa1503e0, +0x94000000, +0x00030005, +0x00000000, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x2a0003e1, +0x00000000, +0xaa1503e0, +0x94000000, +0x0003001c, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030005, +0x00000000, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030006, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0xaa1503e0, +0x94000000, +0x00030007, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x1e260000, +0x1e260021, +0xaa018000, +0xaa0003f4, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800001, +0x000a0205, +0x72a00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030001, +0xf9000014, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x9e660013, +0x9e660034, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800001, +0x000a0205, +0x72a00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030001, +0xa9005013, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x52800001, +0x000a0205, +0x72a00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x0003001d, +0x12800021, +0xaa1503e0, +0x94000000, +0x0003001e, +0x00000000, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x52800000, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000, +0x6dbf0fe2, +0x00000000, +0xfc1f0fe2, +0x00000000, +0x9e660033, +0x00000000, +0x9e660014, +0x00000000, +0xaa0103f3, +0x00000000, +0xaa0003f4, +0x00000000, +0x52800002, +0x000a0205, +0xf2a00002, +0x000a0205, +0xf2c00002, +0x000a0205, +0xf2e00002, +0x000a0205, +0x52800001, +0x000a0205, +0x72a00001, +0x000a0205, +0xaa1503e0, +0x94000000, +0x00030001, +0x00000000, +0x6cc107e0, +0x00000000, +0x2d010400, +0x00000000, +0x6d010400, +0x00000000, +0xfc4107e0, +0x00000000, +0xbd000800, +0x00000000, +0xfd000800, +0x00000000, +0x9e670260, +0xbd000400, +0x00000000, +0xf9000413, +0x00000000, +0x9e670280, +0xbd000000, +0x00000000, +0xf9000014, +0x00000000, +0xf9000413, +0x00000000, +0xf9000014, +0x00000000, +0x52800020, +0x910003bf, +0xa9407bfd, +0xa94153f3, +0xf94013f5, +0x9100c3ff, +0xd65f03c0, +0x00000000 +}; + +static const char *const globnames[] = { + (const char *)0 +}; +static const char *const extnames[] = { + "rawgeti", + "push_cdata", + "lua_remove", + "lua_pushinteger", + "lua_pushboolean", + "push_int", + "push_float", + "lua_pushnumber", + "lua_call", + "check_typed_pointer", + "check_struct", + "lua_settop", + "check_enum", + "check_uint32", + "check_int32", + "check_uint64", + "check_int64", + "check_uintptr", + "check_float", + "check_double", + "check_complex_double", + "check_complex_float", + "lua_gettop", + "luaL_error", + "check_typed_cfunction", + "unpack_varargs_float", + "unpack_varargs_int", + "unpack_varargs_stack_skip", + "push_uint", + "lua_pushvalue", + "lua_setuservalue", + (const char *)0 +}; + +#define JUMP_SIZE 16 + +//in aarch64 the pc is indicated the current +#define MIN_BRANCH ((INT32_MIN) >> 6) +#define MAX_BRANCH ((INT32_MAX) >> 6) +//arm64 pc has no offset so comparing with next instruction is -4 +#define BRANCH_OFF -4 +#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) + +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 128MB. + * + * Note we have to manually set this up since there are commands buffered + * in the jit state. + */ + + //l: ptr + *(cfunction*) code = func; + // ldr x9,#-8 + *(uint32_t*) &code[8] = 0x58FFFFC9; + //br x9 + *(uint32_t*) &code[12] = 0xD61F0120; + +} + +//| ldr reg, >5 +//| b >6 +//|5: +//|.long64 val +//|6: + + + +void compile_globals(struct jit* jit, lua_State* L) +{ + (void) jit; +} +typedef struct reg_info{ + uint8_t ints; + uint8_t floats; + uint16_t ex; +} reg_info; + +static ALWAYS_INLINE bool is_float_type(int t){ + return t==FLOAT_TYPE||t==DOUBLE_TYPE; +} + +static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ + struct ctype* mt; + int type,ele_count,i,ct_usr; + lua_getuservalue(L,idx); + ct_usr=lua_absindex(L,-1); + lua_rawgeti(L,ct_usr,1); + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + return 0; + } + type=mt->type; + ele_count=(int)(ct->base_size/mt->base_size); + if(ele_count>4||ct->base_size%mt->base_size){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + for (i = 2;i<=4; ++i) { + lua_rawgeti(L,ct_usr,i); + if(lua_isnil(L,-1)){//case have array member; + lua_pop(L,1); + break; + } + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + } + if(isfloat){ + *isfloat=mt->type==FLOAT_TYPE; + } + lua_pop(L,1); + return ele_count; +} + +static reg_info caculate_regs(lua_State* L,int ct_usr,int nargs){ + int i;reg_info regs; + const struct ctype* mt; + for (i = 1,regs.ints=0,regs.floats=0; i <= nargs&&(regs.floats<8||regs.ints<8); ++i){ + lua_rawgeti(L, ct_usr, i); + mt = (const struct ctype*) lua_touserdata(L, -1); + if (mt->pointers || mt->is_reference) { + if(regs.ints<8)regs.ints++; + }else{ + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + case COMPLEX_FLOAT_TYPE: + if(regs.floats<7) + regs.floats+=2; + else if(regs.floats==7) + regs.floats=8; + break; + case FLOAT_TYPE: + case DOUBLE_TYPE: + if(regs.floats<8) ++regs.floats; + break; + case STRUCT_TYPE:{ + int hfasize=hfa_size(L,-1,mt,NULL); + if(hfasize>0){ + regs.floats+=hfasize; + if(regs.floats>8) + regs.floats=8; + break; + } + } + case UNION_TYPE:{ + int size=mt->base_size; + if(size>16){//passed by address + if(regs.ints<8)++regs.ints; + break; + } + if(mt->is_empty){ + break; //ignored empty struct + } + size=(size+7)>>3; + if(regs.ints+size<=8) regs.ints+=size; + break; + } + default: + if(regs.ints<8)++regs.ints;//no need to check type support here + } + } + lua_pop(L,1); + } + + return regs; +} + +// arm store/load range for immediate value is only -256-255 +static ALWAYS_INLINE void load_int(struct jit* Dst,reg_info* regs){ + if(regs->ints<8) + dasm_put(Dst, 0, 0x60+(regs->ints++<<3)); + else + dasm_put(Dst, 3, (regs->ex++,8)); +} + +static void load_float(struct jit* Dst,reg_info* regs,int isfloat,int exSize){ + if(regs->floats+exSize<8){ + switch(exSize){ + case 3: + dasm_put(Dst, 6, 0x30+(regs->floats<<3)); + goto l_dual; + case 2: + dasm_put(Dst, 9, 0x30+(regs->floats<<3)); + case 1: + l_dual: + dasm_put(Dst, 12, 0x20+(regs->floats<<3)); + break; + case 0: + dasm_put(Dst, 15, 0x20+(regs->floats<<3)); + break; + } + regs->floats+=exSize+1; + + }else{ + regs->floats=8; + regs->ex+=exSize+1; + switch(exSize){ + case 3: + if(isfloat){ + dasm_put(Dst, 18); + }else{ + dasm_put(Dst, 21); + } + break; + case 2: + if(isfloat){ //12 bytes rounded to 16 + dasm_put(Dst, 24); + break; + }else { + dasm_put(Dst, 27); + } + break; + case 1: + if(isfloat){ + dasm_put(Dst, 30); + }else{ + dasm_put(Dst, 32); + } + break; + case 0: + if(isfloat){ + dasm_put(Dst, 34); + }else { + dasm_put(Dst, 36); + } + break; + } + + } +} + +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,ret_by_addr; + 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"); + } + + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) + && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); + if(ret_by_addr){ + dasm_put(Dst, 38); + } + lua_pop(L,1); + reg_info regs=caculate_regs(L,ct_usr,nargs); + + if(regs.ints||regs.floats){ + dasm_put(Dst, 40); + }else{ + dasm_put(Dst, 42); + } + //8 integer reigsters and 8 floating registers + switch(regs.ints){ + case 8: + case 7: + dasm_put(Dst, 44); + case 6: + case 5: + dasm_put(Dst, 46); + case 4: + case 3: + dasm_put(Dst, 48); + case 2: + case 1: + dasm_put(Dst, 50); + } + + switch(regs.floats){ + case 8: + case 7: + dasm_put(Dst, 52); + case 6: + case 5: + dasm_put(Dst, 54); + case 4: + case 3: + dasm_put(Dst, 56); + case 2: + case 1: + dasm_put(Dst, 58); + } + dasm_put(Dst, 60); + + if(regs.ints==8||regs.floats==8){ // may be overflowed if it's full + dasm_put(Dst, 63, 0xa0+ret_by_addr*0x10); + } + + /* get the lua function */ + lua_pushvalue(L, fidx); + lua_rawseti(L, -2, ++num_upvals); + + dasm_put(Dst, 66, (unsigned short)(L), (((unsigned int)(L))>>16), (unsigned short)((unsigned long)(L)>>32), (unsigned short)((unsigned long)(L)>>48), (unsigned short)(ref), (((unsigned int)(ref))>>16), (unsigned short)(LUA_REGISTRYINDEX), (((unsigned int)(LUA_REGISTRYINDEX))>>16)); + + dasm_put(Dst, 86, num_upvals); + + + for (i = 1,regs.ints=0,regs.floats=0; 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, 93, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + load_int(Dst,®s); + dasm_put(Dst, 113); + + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + int isfloat,hfasize=0; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 119, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + + if(hfasize){ + load_float(Dst,®s,isfloat,hfasize-1); + switch(hfasize){ + case 4: + if(isfloat){ + dasm_put(Dst, 139); + }else{ + dasm_put(Dst, 141); + } + goto hfa2; + case 3: + if(isfloat){ + dasm_put(Dst, 143); + }else{ + dasm_put(Dst, 145); + } + case 2: + hfa2: + if(isfloat){ + dasm_put(Dst, 147); + }else{ + dasm_put(Dst, 149); + } + break; + case 1: + if(isfloat){ + dasm_put(Dst, 151); + }else{ + dasm_put(Dst, 153); + } + break; + + } + }else if(!mt->is_empty){ + size_t size=mt->base_size; + if(size>16){ + load_int(Dst,®s); + dasm_put(Dst, 155, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)((unsigned long)(mt->base_size)>>32), (unsigned short)((unsigned long)(mt->base_size)>>48), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16), (unsigned short)((unsigned long)(memcpy)>>32), (unsigned short)((unsigned long)(memcpy)>>48)); + }else{ + size=(size+7)>>3; + if(mt->align_mask>8){ + if(regs.ints&1) regs.ints++; + else if(regs.ex&1) regs.ex++; + } + if(regs.ints+size<=8){ + if(size>1){ + dasm_put(Dst, 173, 0x60+(regs.ints<<3)); + }else{ + dasm_put(Dst, 177, 0x60+(regs.ints<<3)); + } + regs.ints+=size; + }else{ + regs.ints=8; + if(size>1){ + dasm_put(Dst, 181); + }else{ + dasm_put(Dst, 184); + } + + } + } + + + } + + dasm_put(Dst, 187); + break; + } + case COMPLEX_DOUBLE_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 192, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + load_float(Dst,®s,0,1); + dasm_put(Dst, 212); + + break; + case COMPLEX_FLOAT_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 218, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + load_float(Dst,®s,1,1); + dasm_put(Dst, 238); + + break; + case INT64_TYPE: + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + load_int(Dst,®s); + dasm_put(Dst, 244); + + #else + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 248, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + load_int(Dst,®s); + dasm_put(Dst, 261); + + #endif + break; + + case INTPTR_TYPE: + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 267, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + load_int(Dst,®s); + dasm_put(Dst, 280); + + break; + + case BOOL_TYPE: + lua_pop(L, 1); + + load_int(Dst,®s); + dasm_put(Dst, 286); + + break; + + case INT8_TYPE:// need to narrow for caller doesn't do it + lua_pop(L, 1); + if(regs.ints<8){ + if (mt->is_unsigned) { + dasm_put(Dst, 290, 0x60+(regs.ints++<<3)); + } else { + dasm_put(Dst, 293, 0x60+(regs.ints++<<3)); + } + }else { + if (mt->is_unsigned) { + dasm_put(Dst, 296); + } else { + dasm_put(Dst, 298); + } + } + dasm_put(Dst, 300); + break; + + case INT16_TYPE:// need to narrow for caller doesn't do it + lua_pop(L, 1); + if(regs.ints<8){ + if (mt->is_unsigned) { + dasm_put(Dst, 304, 0x60+(regs.ints++<<3)); + } else { + dasm_put(Dst, 307, 0x60+(regs.ints++<<3)); + } + }else { + if (mt->is_unsigned) { + dasm_put(Dst, 310); + } else { + dasm_put(Dst, 312); + } + } + dasm_put(Dst, 314); + break; + + case ENUM_TYPE: + case INT32_TYPE: + lua_pop(L, 1); + load_int(Dst,®s); + + dasm_put(Dst, 318); + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + load_float(Dst,®s,1,0); + dasm_put(Dst, 322); + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + load_float(Dst,®s,0,0); + dasm_put(Dst, 326); + 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, 330, ((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, 338, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + goto single_no_pop; + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + int hfasize=0,isfloat; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 358, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + if(hfasize){ + switch(hfasize){ + case 4: + if(isfloat){ + dasm_put(Dst, 383); + }else{ + dasm_put(Dst, 385); + } + goto ld_hfa; + case 3: + if(isfloat){ + dasm_put(Dst, 387); + }else{ + dasm_put(Dst, 389); + } + case 2: + ld_hfa: + if(isfloat){ + dasm_put(Dst, 391); + }else{ + dasm_put(Dst, 393); + } + break; + case 1: + if(isfloat){ + dasm_put(Dst, 395); + }else{ + dasm_put(Dst, 397); + } + break; + } + }else{ + if(mt->base_size>16){ + dasm_put(Dst, 399, 0x20+((regs.ints||regs.floats)?0x80:0), (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)((unsigned long)(mt->base_size)>>32), (unsigned short)((unsigned long)(mt->base_size)>>48), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16), (unsigned short)((unsigned long)(memcpy)>>32), (unsigned short)((unsigned long)(memcpy)>>48)); + }else{ + if(mt->base_size>8){ + dasm_put(Dst, 420); + }else{ + dasm_put(Dst, 422); + } + } + } + break; + } + 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, 424, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + + goto single_no_pop; + + case VOID_TYPE: + dasm_put(Dst, 444); + lua_pop(L, 1); + break; + + case BOOL_TYPE: + case INT8_TYPE: + case INT16_TYPE: + case INT32_TYPE: //caller's responsiblity to narrow + dasm_put(Dst, 449); + if (mt->is_unsigned) { + dasm_put(Dst, 451); + } else { + dasm_put(Dst, 455); + } + + goto single; + + case INT64_TYPE: + dasm_put(Dst, 459); + if (mt->is_unsigned) { + dasm_put(Dst, 461); + } else { + dasm_put(Dst, 465); + } + + goto single; + + case INTPTR_TYPE: + dasm_put(Dst, 469); + goto single; + + case FLOAT_TYPE: + dasm_put(Dst, 474); + + dasm_put(Dst, 479); + lua_pop(L, 1); + break; + case DOUBLE_TYPE: + dasm_put(Dst, 486); + + dasm_put(Dst, 491); + + lua_pop(L, 1); + break; + + case COMPLEX_DOUBLE_TYPE: + + dasm_put(Dst, 498); + + goto complex_ret; + case COMPLEX_FLOAT_TYPE: + dasm_put(Dst, 503); + + complex_ret: + dasm_put(Dst, 508); + + lua_pop(L, 1); + break; + single: + lua_pop(L, 1); + single_no_pop: + dasm_put(Dst, 517); + break; + + + default: + luaL_error(L, "NYI: callback return type"); + } + } + + dasm_put(Dst, 524, (0x20 +ret_by_addr*0x10+ ((regs.floats!=0)||(regs.ints!=0)) * 0x80)); + + 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; + } +} + +//arm64 argument can only be in stack or registers. An argument can't be splited between stack and register. +static void store_float(struct jit* Dst,reg_info* regs,int isfloat,int ex){ + if(regs->floats+ex<8){ + + switch(ex){ + case 3: + dasm_put(Dst, 530, 0x10+(regs->floats<<3)); + goto sd_dual; + case 2: + dasm_put(Dst, 533, 0x10+(regs->floats<<3)); + case 1: + sd_dual: + dasm_put(Dst, 536, (regs->floats<<3)); + break; + case 0: + dasm_put(Dst, 539, (regs->floats<<3)); + break; + } + regs->floats+=1+ex; + }else { + regs->floats=8; + switch(ex){ + case 3: + if(isfloat){ + dasm_put(Dst, 542); + }else{ + dasm_put(Dst, 545); + } + break; + case 2: + if(isfloat){ + dasm_put(Dst, 548); + }else{ + dasm_put(Dst, 551); + } + break; + case 1: + if(isfloat){ + dasm_put(Dst, 554); + }else{ + dasm_put(Dst, 556); + } + break; + case 0: + if(isfloat){ + dasm_put(Dst, 558); + }else { + dasm_put(Dst, 560); + } + break; + } + //complex float is packed as one double on stack + regs->ex+=ex+1; + } +} + +static void store_int(struct jit* Dst,reg_info* regs,int intSize){ + switch(intSize){ + case 1: + if(regs->ints<8) + dasm_put(Dst, 562, 0x40+(regs->ints++<<3)); + else + dasm_put(Dst, 565, (regs->ex++,8)); + break; + case 2: + if(regs->ints<8) + dasm_put(Dst, 568, 0x40+(regs->ints++<<3)); + else + dasm_put(Dst, 571, (regs->ex++,8)); + break; + case 3: + case 4: + if(regs->ints<7){ + dasm_put(Dst, 574, 0x40+(regs->ints<<3)); + regs->ints+=2; + } + else{ + if(regs->ints==7) + regs->ints=8; + dasm_put(Dst, 577); + regs->ex+=2; + } + + break; + } +} + +static int caculate_stack(lua_State* L,int ct_usr,int nargs){ + int i;reg_info regs={0,0,0}; + const struct ctype* mt;int stack=0,extra=0; + 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) { + if(regs.ints<8)regs.ints++; + else stack++; + }else{ + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + case COMPLEX_FLOAT_TYPE: + if(regs.floats<7) + regs.floats+=2; + else if(regs.floats==7) + regs.floats=8; + else stack+=mt->base_size>>3; + break; + case FLOAT_TYPE: + case DOUBLE_TYPE: + if(regs.floats<8) ++regs.floats; + else stack++; + break; + case STRUCT_TYPE:{ + int isfloat; + int hfasize=hfa_size(L,-1,mt,&isfloat); + if(hfasize>0){ + if(regs.floats+hfasize<=8) + regs.floats +=hfasize; + else { + regs.floats=8; + stack+=(hfasize*(2-isfloat)+1)>>1; + } + break; + } + } + case UNION_TYPE:{ + int size=mt->base_size; + size=(size+7)>>3; + if(size>2){//passed by address + if(regs.ints<8)++regs.ints; + else stack++; + extra+=size;//extra copy stack; + break; + } + if(mt->is_empty){ + break; //ignored empty struct + } + if(mt->align_mask>8){ + if(regs.ints&1) regs.ints++; + else if(stack&1) stack++; + } + if(regs.ints+size<=8) regs.ints+=size; + else{ + regs.ints=8; + stack+=size; + } + + break; + } + default: + if(regs.ints<8)++regs.ints;//no need to check type support here + else stack++; + } + } + lua_pop(L,1); + } + + return (regs.ints||regs.floats)?((stack+extra+17/*16 for regs, 1 for align*/)>>1)<<4:0;//2 eightbytes align +} + + +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,ret_by_addr; + const struct ctype* mt; + int stack_size,struct_offset; + 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); + + reg_info regs={0,0}; + + dasm_put(Dst, 579); + + /* reserve enough stack space for all of the arguments. */ + stack_size=caculate_stack(L,ct_usr,nargs); + struct_offset=0; + if(stack_size>0){ + if(stack_size>=1<<12){ + dasm_put(Dst, 586, (unsigned short)(stack_size), (((unsigned int)(stack_size))>>16)); + } + else{ + dasm_put(Dst, 592, stack_size); + } + if (ct->has_var_arg) { + dasm_put(Dst, 595, nargs, (unsigned short)("too few arguments"), (((unsigned int)("too few arguments"))>>16), (unsigned short)((unsigned long)("too few arguments")>>32), (unsigned short)((unsigned long)("too few arguments")>>48)); + } + dasm_put(Dst, 618); + } + + for (i = 1,regs.ints=0,regs.floats=0; 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||mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + + + dasm_put(Dst, 620, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16), i); + + if (mt->pointers || mt->is_reference) { + dasm_put(Dst, 635); + } else{ + switch (mt->type) { + case FUNCTION_PTR_TYPE: { + dasm_put(Dst, 639); + break; + } + case ENUM_TYPE:{ + dasm_put(Dst, 643); + break; + } + case STRUCT_TYPE: + case UNION_TYPE:{ + if(mt->is_empty) continue; + + int isfloat; + int hfasize=hfa_size(L,-2,mt,&isfloat); + dasm_put(Dst, 647); + if(hfasize>0){ + switch(hfasize){ + case 4: + if(isfloat){ + dasm_put(Dst, 651); + }else{ + dasm_put(Dst, 653); + } + goto ld_hfa; + case 3: + if(isfloat){ + dasm_put(Dst, 655); + }else{ + dasm_put(Dst, 657); + } + case 2: + ld_hfa: + if(isfloat){ + dasm_put(Dst, 659); + }else{ + dasm_put(Dst, 661); + } + break; + case 1: + if(isfloat){ + dasm_put(Dst, 663); + }else{ + dasm_put(Dst, 665); + } + break; + + } + store_float(Dst,®s,isfloat,hfasize-1); + continue; + } + if(mt->base_size>16){ + dasm_put(Dst, 667); + struct_offset+=(mt->base_size+7)&(~7); + if(struct_offset>=1<<12){ + dasm_put(Dst, 669, (unsigned short)(struct_offset), (((unsigned int)(struct_offset))>>16)); + } + else{ + dasm_put(Dst, 675, struct_offset); + } + store_int(Dst,®s,2); + dasm_put(Dst, 678, mt->base_size, (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16), (unsigned short)((unsigned long)(memcpy)>>32), (unsigned short)((unsigned long)(memcpy)>>48)); + }else{ + if(mt->align_mask>8){//==15 + if(regs.ints&1) regs.ints++; + else if(regs.ex&1) regs.ex++; + } + int intSize=(mt->base_size+3)>>2; + switch(intSize){ + case 1: + dasm_put(Dst, 690); + break; + case 2: + dasm_put(Dst, 692); + break; + case 3: + case 4: + dasm_put(Dst, 694); + break; + } + store_int(Dst,®s,intSize); + } + continue; + } + } + } + goto longstore; + + } else { + lua_pop(L, 1); + dasm_put(Dst, 696, i); + + switch (mt->type) { + case BOOL_TYPE: + dasm_put(Dst, 699); + goto intstore; + + case INT8_TYPE: + case INT16_TYPE: //arm64 requires callee to narrow the type + case INT32_TYPE: + + dasm_put(Dst, 705); + + goto intstore; + + case INT64_TYPE: + + dasm_put(Dst, 709); + + goto longstore; + + case INTPTR_TYPE: + dasm_put(Dst, 713); + + goto longstore; + + case DOUBLE_TYPE: + dasm_put(Dst, 717); + store_float(Dst,®s,0,0); + break; + + case FLOAT_TYPE: + dasm_put(Dst, 721); + store_float(Dst,®s,1,0); + break; + case COMPLEX_DOUBLE_TYPE: + dasm_put(Dst, 725); + store_float(Dst,®s,0,1); + break; + + case COMPLEX_FLOAT_TYPE: + dasm_put(Dst, 729); + store_float(Dst,®s,1,1); + break; + + intstore: + store_int(Dst,®s,1); + break; + longstore: + store_int(Dst,®s,2); + break; + + default: + luaL_error(L, "NYI: call arg type"); + } + } + } + + if (ct->has_var_arg) { + if(regs.floats<8){ + dasm_put(Dst, 733, regs.floats<<3, (8-regs.floats), nargs+1); + } + if(regs.ints<8){ + dasm_put(Dst, 744, 0x40+(regs.ints<<3), (8-regs.ints), nargs+1); + } + dasm_put(Dst, 755, (nargs>8?nargs:8), (8-regs.floats), (8-regs.ints), nargs+1); + regs.floats=regs.ints=8; + } + + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE||mt->type==UNION_TYPE) + && mt->base_size>16&& !(mt->type==STRUCT_TYPE&&hfa_size(L,-1,mt,NULL)!=0); + if(ret_by_addr){ + dasm_put(Dst, 772, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + } + + //pop all args in registers + switch(regs.ints){ + case 8: + case 7: + dasm_put(Dst, 786); + case 6: + case 5: + dasm_put(Dst, 788); + case 4: + case 3: + dasm_put(Dst, 790); + case 2: + case 1: + dasm_put(Dst, 792); + } + + switch(regs.floats){ + case 8: + case 7: + dasm_put(Dst, 794); + case 6: + case 5: + dasm_put(Dst, 796); + case 4: + case 3: + dasm_put(Dst, 798); + case 2: + case 1: + dasm_put(Dst, 800); + } + if(regs.ints==8|| regs.floats==8){// fix stack case registers is full + dasm_put(Dst, 802); + } + + dasm_put(Dst, 804, (unsigned short)(func), (((unsigned int)(func))>>16), (unsigned short)((unsigned long)(func)>>32), (unsigned short)((unsigned long)(func)>>48)); + + + if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + dasm_put(Dst, 814, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + + } else { + switch (mt->type) { + case INT64_TYPE: + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + dasm_put(Dst, 839); + break; + #endif + + case INTPTR_TYPE: + num_upvals++; + dasm_put(Dst, 851, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48)); + break; + case VOID_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 873); + break; + + case BOOL_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 881); + break; + + case INT8_TYPE:// we need to narrow the value before return + lua_pop(L, 1); + dasm_put(Dst, 893); + if (mt->is_unsigned) { + dasm_put(Dst, 895); + } else { + dasm_put(Dst, 900); + } + dasm_put(Dst, 905); + break; + case INT16_TYPE:// we need to narrow the value before return + lua_pop(L, 1); + dasm_put(Dst, 913); + if (mt->is_unsigned) { + dasm_put(Dst, 915); + } else { + dasm_put(Dst, 920); + } + dasm_put(Dst, 925); + break; + case INT32_TYPE: + case ENUM_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 933); + if (mt->is_unsigned) { + dasm_put(Dst, 935); + } else { + dasm_put(Dst, 939); + } + dasm_put(Dst, 943); + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 951); + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 962); + break; + case COMPLEX_FLOAT_TYPE: + lua_getuservalue(L, -1); + num_upvals+=2; + dasm_put(Dst, 973, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + break; + + case COMPLEX_DOUBLE_TYPE: + lua_getuservalue(L, -1); + num_upvals+=2; + dasm_put(Dst, 1001, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + break; + case STRUCT_TYPE: + case UNION_TYPE: + lua_getuservalue(L, -1); + num_upvals+=2; + if(ret_by_addr){ + if(!lua_isnil(L,-1)){ + dasm_put(Dst, 1027, (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + } + dasm_put(Dst, 1039); + }else if(mt->is_empty){ + dasm_put(Dst, 1047); + }else{ + int isfloat; + int hfasize=hfa_size(L,-2,mt,&isfloat); + if(hfasize){ + switch(hfasize){ + case 4: + dasm_put(Dst, 1055); + goto hfs_dual; + case 3: + dasm_put(Dst, 1057); + case 2: + hfs_dual: + dasm_put(Dst, 1059); + case 1: + dasm_put(Dst, 1061); + break; + } + }else{ + if(mt->base_size>8){ + dasm_put(Dst, 1063); + } + dasm_put(Dst, 1065); + + } + dasm_put(Dst, 1067, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)((unsigned long)(mt)>>32), (unsigned short)((unsigned long)(mt)>>48), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + if(hfasize){ + switch(hfasize){ + case 4: + dasm_put(Dst, 1083); + if(isfloat){ + dasm_put(Dst, 1085); + }else{ + dasm_put(Dst, 1087); + } + goto hfl_dual; + case 3: + dasm_put(Dst, 1089); + if(isfloat){ + dasm_put(Dst, 1091); + }else{ + dasm_put(Dst, 1093); + } + case 2: + hfl_dual: + if(isfloat){ + dasm_put(Dst, 1095); + }else{ + dasm_put(Dst, 1098); + } + case 1: + if(isfloat){ + dasm_put(Dst, 1100); + }else{ + dasm_put(Dst, 1103); + } + break; + } + }else{ + if(mt->base_size>8){ + dasm_put(Dst, 1105); + } + dasm_put(Dst, 1107); + + } + dasm_put(Dst, 1109); + } + break; + + default: + luaL_error(L, "NYI: call return type"); + } + } + + assert(lua_gettop(L) == top + num_upvals); + { + cfunction f = compile(Dst, L, NULL, 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/source/texk/web2c/luatexdir/luaffi/call_arm_hf.h b/source/texk/web2c/luatexdir/luaffi/call_arm_hf.h index 00c2c09a7..b9fec4d53 100644 --- a/source/texk/web2c/luatexdir/luaffi/call_arm_hf.h +++ b/source/texk/web2c/luatexdir/luaffi/call_arm_hf.h @@ -1,2530 +1,2530 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.4.0, DynASM arm version 1.4.0 -** DO NOT EDIT! The original file is in "call_arm.dasc". -*/ - -/* 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. - */ - -//The generate code is for arm not for thumb -#if DASM_VERSION != 10400 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -static const unsigned int build_actionlist[951] = { -0xed0d0a00, -0x000f8100, -0x00000000, -0xed4d0a00, -0x000f8100, -0x00000000, -0xed0d1a00, -0x000f8100, -0x00000000, -0xed4d1a00, -0x000f8100, -0x00000000, -0xed0d2a00, -0x000f8100, -0x00000000, -0xed4d2a00, -0x000f8100, -0x00000000, -0xed0d3a00, -0x000f8100, -0x00000000, -0xed4d3a00, -0x000f8100, -0x00000000, -0xed0d4a00, -0x000f8100, -0x00000000, -0xed4d4a00, -0x000f8100, -0x00000000, -0xed0d5a00, -0x000f8100, -0x00000000, -0xed4d5a00, -0x000f8100, -0x00000000, -0xed0d6a00, -0x000f8100, -0x00000000, -0xed4d6a00, -0x000f8100, -0x00000000, -0xed0d7a00, -0x000f8100, -0x00000000, -0xed4d7a00, -0x000f8100, -0x00000000, -0xed0d0b00, -0x000f8100, -0x00000000, -0xed0d1b00, -0x000f8100, -0x00000000, -0xed0d2b00, -0x000f8100, -0x00000000, -0xed0d3b00, -0x000f8100, -0x00000000, -0xed0d4b00, -0x000f8100, -0x00000000, -0xed0d5b00, -0x000f8100, -0x00000000, -0xed0d6b00, -0x000f8100, -0x00000000, -0xed0d7b00, -0x000f8100, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c100e, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c100e, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c0006, -0x00000000, -0xe51d1000, -0x000e8180, -0x00000000, -0xe2866000, -0x000b0000, -0x00000000, -0xe8b6100e, -0x00000000, -0xe8b60006, -0x00000000, -0xe4961004, -0x00000000, -0xed1d0a00, -0x000f8100, -0x00000000, -0xed1d0b00, -0x000f8100, -0x00000000, -0xed160a00, -0xe2866004, -0x00000000, -0xe2866000, -0x000b0000, -0x00000000, -0xed160b00, -0xe2866008, -0x00000000, -0xe1a0c00d, -0xe92d000f, -0x00000000, -0xe24dd040, -0x00000000, -0xe92d5050, -0xe1a0600c, -0xe3004000, -0x000c0200, -0xe3404000, -0x000c0200, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030000, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030000, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe5801000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe8a0100e, -0x00000000, -0xe880100e, -0x00000000, -0xe8a0100e, -0x00000000, -0xe8800006, -0x00000000, -0xe880100e, -0x00000000, -0xe880000e, -0x00000000, -0xe8800006, -0x00000000, -0xe5801000, -0x00000000, -0xe5801000, -0x00000000, -0xe28d1000, -0x000b0000, -0x00000000, -0xe1a01006, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe12fff3c, -0x00000000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe880100e, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe8800006, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c000c, -0x00000000, -0xe2866004, -0x00000000, -0xe8b6000c, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030003, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe8800006, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xe5801000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030002, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030004, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030005, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030006, -0x00000000, -0xe28dc000, -0x000b0000, -0xe89c000c, -0x00000000, -0xe2866004, -0x00000000, -0xe8b6000c, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030007, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3a01000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030008, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3e02000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030009, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3e02000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003000a, -0xe1a06000, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0x00000000, -0xec960b08, -0x00000000, -0xec960b06, -0x00000000, -0xec960b04, -0x00000000, -0xec960a04, -0x00000000, -0xed160b00, -0x00000000, -0xed160a00, -0x00000000, -0xe5960000, -0x00000000, -0xe51d0000, -0x000e8180, -0xe1a01006, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe12fff3c, -0x00000000, -0xe3a02000, -0x000b0000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x00030000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3e02000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003000c, -0x00000000, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003000b, -0x00000000, -0xe3e01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000d, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe3500000, -0x13a00001, -0x00000000, -0xe6ef0070, -0x00000000, -0xe6af0070, -0x00000000, -0xe6ff0070, -0x00000000, -0xe6bf0070, -0x00000000, -0xe3e01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000f, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030010, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030011, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030012, -0x00000000, -0xee106a10, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0xee006a10, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030013, -0x00000000, -0xe1a00004, -0xec564b10, -0xe3e01002, -0xeb000000, -0x0003000b, -0xec464b10, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030014, -0xed2d0b04, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0xecbd0b04, -0x00000000, -0xe3e01000, -0xe1a00004, -0xeb000000, -0x00030015, -0xed2d0a02, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0xecbd0a02, -0x00000000, -0xe1a06000, -0xe3e01002, -0xe1a00004, -0xeb000000, -0x0003000b, -0xe1a00006, -0x00000000, -0xe1a06000, -0xe1a00004, -0xe1a04001, -0xe3e01002, -0xeb000000, -0x0003000b, -0xe1a00006, -0xe1a01004, -0x00000000, -0xe89da050, -0x00000000, -0xe2866004, -0x00000000, -0xe8a60003, -0x00000000, -0xe28dc000, -0x000b0000, -0xe88c0003, -0x00000000, -0xe4860004, -0x00000000, -0xe50d0000, -0x000e8180, -0x00000000, -0xed0d3b00, -0x000f8100, -0x00000000, -0xed0d2b00, -0x000f8100, -0x00000000, -0xed0d1b00, -0x000f8100, -0x00000000, -0xed4d1a00, -0x000f8100, -0x00000000, -0xed0d0b00, -0x000f8100, -0x00000000, -0xed0d0a00, -0x000f8100, -0x00000000, -0xe2866004, -0x00000000, -0xeca60a01, -0x00000000, -0xeca60b02, -0x00000000, -0xeca60a04, -0x00000000, -0xeca60b04, -0x00000000, -0xeca60b06, -0x00000000, -0xeca60b08, -0x00000000, -0xe92d40f0, -0xe28d700c, -0x00000000, -0xe92d4870, -0xe28db00c, -0x00000000, -0xe24dd004, -0x00000000, -0xe1a04000, -0x00000000, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe04dd00c, -0x00000000, -0xe24dd000, -0x000b0000, -0x00000000, -0xeb000000, -0x00030016, -0xe3500000, -0x000b0000, -0xaa000000, -0x00050001, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030017, -0x0006000b, -0xe1a05000, -0xe04dd185, -0x00000000, -0xe28d6000, -0x000b0000, -0x00000000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0xe50d0000, -0x000e8180, -0x00000000, -0xe3003000, -0x000c0200, -0xe3403000, -0x000c0200, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0x000b0000, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030009, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030018, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000c, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000a, -0x00000000, -0xec900b0a, -0x00000000, -0xec900b0a, -0x00000000, -0xec900b06, -0x00000000, -0xec900a04, -0x00000000, -0xed100b00, -0x00000000, -0xed100a00, -0x00000000, -0xe2866004, -0x00000000, -0xe1a01000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0x00000000, -0xe28d0000, -0x000b0000, -0x00000000, -0xe1a00006, -0x00000000, -0xe12fff3c, -0x00000000, -0xe2866000, -0x000b0000, -0x00000000, -0xe3a01000, -0x000b0000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0xe3500000, -0x13a00001, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe6ef0070, -0x00000000, -0xe6af0070, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe6ff0070, -0x00000000, -0xe6bf0070, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000d, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000e, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030011, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003000f, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030010, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030013, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030012, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030014, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030015, -0x00000000, -0xe3a01000, -0x000b0000, -0x00000000, -0xe28d2000, -0x000b0000, -0xe28d3000, -0x000b0000, -0xe1a00004, -0xeb000000, -0x00030019, -0xe2801000, -0x000b0000, -0x00000000, -0xe1a03006, -0x00000000, -0xe28d3000, -0x000b0000, -0x00000000, -0xe1a02005, -0xe1a00004, -0xeb000000, -0x0003001a, -0x00000000, -0xec9d0b10, -0x00000000, -0xec9d0b0e, -0x00000000, -0xec9d0b0c, -0x00000000, -0xec9d0b0a, -0x00000000, -0xec9d0b08, -0x00000000, -0xec9d0b06, -0x00000000, -0xec9d0b04, -0x00000000, -0xed1d0b00, -0x00000000, -0xe28dd040, -0x00000000, -0xe8bd000f, -0x00000000, -0xe8bd0003, -0x00000000, -0xe28dd008, -0x00000000, -0xe28dd010, -0x00000000, -0xe300c000, -0x000c0200, -0xe340c000, -0x000c0200, -0xe12fff3c, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0xe3a00001, -0x00000000, -0xe1a03001, -0xe1a02000, -0x00000000, -0xe1a02001, -0xe1a01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030003, -0xe3a00001, -0x00000000, -0xe1a06000, -0xe1a05001, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0xe5805004, -0xe3a00001, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3a01000, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0xe3a00001, -0x00000000, -0xe3a00000, -0x00000000, -0xe1a01000, -0xe1a00004, -0xeb000000, -0x00030004, -0xe3a00001, -0x00000000, -0xe1a01000, -0x00000000, -0xe1a00004, -0xeb000000, -0x0003001b, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030005, -0x00000000, -0xe3a00001, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030006, -0xe3a00001, -0x00000000, -0xe1a00004, -0xeb000000, -0x00030007, -0xe3a00001, -0x00000000, -0xed2d0b08, -0x00000000, -0xed2d0b06, -0x00000000, -0xed2d0b04, -0x00000000, -0xed2d0b02, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030001, -0x00000000, -0xecbd0b08, -0xec800b08, -0x00000000, -0xecbd0b06, -0xec800b06, -0x00000000, -0xecbd0b04, -0xec800b04, -0x00000000, -0xecbd0b04, -0xec800a04, -0x00000000, -0xecbd0b02, -0xed000b00, -0x00000000, -0xecbd0b02, -0xed000a00, -0x00000000, -0xe3a00001, -0x00000000, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x0003001c, -0xe3e01001, -0xe1a00004, -0xeb000000, -0x0003001d, -0x00000000, -0xe3a00000, -0x00000000, -0xe1a06000, -0xe3002000, -0x000c0200, -0xe3402000, -0x000c0200, -0xe3001000, -0x000c0200, -0xe3401000, -0x000c0200, -0xe1a00004, -0xeb000000, -0x00030001, -0xe5806000, -0x00000000, -0xe3a00001, -0x00000000, -0xe247d00c, -0xe8bd80f0, -0x00000000, -0xe24bd00c, -0xe8bd8870, -0x00000000 -}; - -static const char *const globnames[] = { - (const char *)0 -}; -static const char *const extnames[] = { - "rawgeti", - "push_cdata", - "lua_remove", - "lua_pushinteger", - "lua_pushboolean", - "push_int", - "push_float", - "lua_pushnumber", - "lua_call", - "check_typed_pointer", - "check_struct", - "lua_settop", - "check_enum", - "check_uint32", - "check_int32", - "check_uint64", - "check_int64", - "check_uintptr", - "check_float", - "check_double", - "check_complex_double", - "check_complex_float", - "lua_gettop", - "luaL_error", - "check_typed_cfunction", - "unpack_varargs_bound", - "unpack_varargs_stack", - "push_uint", - "lua_pushvalue", - "lua_setuservalue", - (const char *)0 -}; - -#define JUMP_SIZE 8 - -#define MIN_BRANCH ((INT32_MIN) >> 8) -#define MAX_BRANCH ((INT32_MAX) >> 8) -//arm pc offset 8 so comparing with next instruction is 4, -//unlike x86 which pass in the current instruction address+1 rather than the next instruction -#define BRANCH_OFF 4 - - -#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) -#ifdef TARGET_OS_IPHONE -#define CK_ALGIN 0 -#else -#define CK_ALGIN 1 -#endif -#define ALIGNED(x, align) (!CK_ALGIN||((int)(x) & (align - 1)) == 0) -#if defined(__ARM_PCS_VFP) || (GCC_VERSION==40500||defined(__clang__))&&!defined(__ARM_PCS) && !defined(__SOFTFP__) && !defined(__SOFTFP) && \ - defined(__VFP_FP__) -#define ARM_HF 1 -#else -#define ARM_HF 0 -#endif -#if ARM_HF&&!CK_ALGIN -#error "Unsupported unaligned stack for hard floating point" -#endif - -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; -} - -typedef struct stack_info{ - int extra; - int int_off; - int stack_off; - int float_size; -#if ARM_HF - int float_off; -#endif -} stack_info; -//vfp use back-filling rule for registers until a float value on stack -typedef struct reg_info{ - uint16_t exs; - union{ - uint8_t ints; - uint8_t regs; - }; -#if ARM_HF - uint8_t float_sealed; - short floats;//each bit is a float: s0-s15 or v0-v7 or q0-q3 - uint8_t left_single; - uint8_t highest_bit; -#endif -} reg_info; - -#define MAX_REGS 4 -#define MAX_FLOAT_REGS 16 -#ifndef bool -#define bool uint8_t -#endif - -#define has_bit(x,b) (((x)&(1<<(b)))!=0) -#define set_bit(x,b) (x=((x)|(1<<(b)))) -#define FIX_ALIGN(x,al) \ - if(!ALIGNED((x),al)){\ - x=ROUND_UP(x,al);\ - } -static ALWAYS_INLINE bool is_float_sealed(reg_info* regs){ -#if ARM_HF -return regs->float_sealed; -#else -return regs->regs>=MAX_REGS; -#endif -} -//return size need to put on stack -static ALWAYS_INLINE int add_int_reg(reg_info* regs){ - if(regs->regs<MAX_REGS){ - regs->regs++; - return 0; - } - return 1; - -} -//return size need to put on stack -static ALWAYS_INLINE int add_int64_reg(reg_info* regs){ - if(regs->regs<MAX_REGS-1){ - regs->regs=ROUND_UP(regs->regs,2)+2; - return 0; - }else if(regs->regs==MAX_REGS-1){ - regs->regs=MAX_REGS; - } - - return 2; -} -static ALWAYS_INLINE bool is_float_type(int t){ - return t==FLOAT_TYPE||t==DOUBLE_TYPE; -} -static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ - struct ctype* mt; - int type,ele_count,i,ct_usr; - lua_getuservalue(L,idx); - ct_usr=lua_absindex(L,-1); - lua_rawgeti(L,ct_usr,1); - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - if(ct->type==COMPLEX_DOUBLE_TYPE){ - if(isfloat) *isfloat=0; - return 4; - }else if(ct->type==COMPLEX_FLOAT_TYPE){ - if(isfloat) *isfloat=1; - return 2; - } - return 0; - } - type=mt->type; - ele_count=(int)(ct->base_size/mt->base_size); - if(ele_count>4||ct->base_size%mt->base_size){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - for (i = 2; i <=4 ; ++i) { - lua_rawgeti(L,ct_usr,i); - if(lua_isnil(L,-1)){//case have array member; - lua_pop(L,1); - break; - } - mt=(struct ctype*)lua_touserdata(L,-1); - if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ - lua_pop(L,2); - return 0; - } - lua_pop(L,1); - } - if(isfloat){ - *isfloat=mt->type==FLOAT_TYPE; - } - lua_pop(L,1); - return ele_count*(mt->type==FLOAT_TYPE?1:2); -} -#if ARM_HF -static void save_float_reg(struct jit* Dst,int reg,int size,stack_info* st){ - int sz; - if(reg==-1) return; - for(;size>0;size-=8){ - sz=size>8?8:size; - switch(sz){ - case 4: - switch(reg){ - case 0: - dasm_put(Dst, 0, st->float_size); - break; - case 1: - dasm_put(Dst, 3, st->float_size); - break; - case 2: - dasm_put(Dst, 6, st->float_size); - break; - case 3: - dasm_put(Dst, 9, st->float_size); - break; - case 4: - dasm_put(Dst, 12, st->float_size); - break; - case 5: - dasm_put(Dst, 15, st->float_size); - break; - case 6: - dasm_put(Dst, 18, st->float_size); - break; - case 7: - dasm_put(Dst, 21, st->float_size); - break; - case 8: - dasm_put(Dst, 24, st->float_size); - break; - case 9: - dasm_put(Dst, 27, st->float_size); - break; - case 10: - dasm_put(Dst, 30, st->float_size); - break; - case 11: - dasm_put(Dst, 33, st->float_size); - break; - case 12: - dasm_put(Dst, 36, st->float_size); - break; - case 13: - dasm_put(Dst, 39, st->float_size); - break; - case 14: - dasm_put(Dst, 42, st->float_size); - break; - case 15: - dasm_put(Dst, 45, st->float_size); - break; - } - break; - case 8: - switch(reg>>1){ - case 0: - dasm_put(Dst, 48, st->float_size); - break; - case 1: - dasm_put(Dst, 51, st->float_size); - break; - case 2: - dasm_put(Dst, 54, st->float_size); - break; - case 3: - dasm_put(Dst, 57, st->float_size); - break; - case 4: - dasm_put(Dst, 60, st->float_size); - break; - case 5: - dasm_put(Dst, 63, st->float_size); - break; - case 6: - dasm_put(Dst, 66, st->float_size); - break; - case 7: - dasm_put(Dst, 69, st->float_size); - break; - } - reg+=2; - break; - } - st->float_size+=sz; - } -} - -//128 bit vector type is not supported by this -static int add_float_reg(reg_info* regs,int sz,int isfloat){ - - if(is_float_sealed(regs)) return -1; - int i,ret=-1; - if(sz==1){ - if(regs->left_single){ - int n=regs->highest_bit; - for(i=0;i<n;++i){ - if(!has_bit(regs->floats,i)){ - regs->left_single--; - set_bit(regs->floats,i); - ret=i; - } - } - }else{ - ret=regs->highest_bit; - set_bit(regs->floats,regs->highest_bit); - ++regs->highest_bit; - } - }else{ - if(regs->highest_bit>MAX_FLOAT_REGS-sz){ - regs->highest_bit=MAX_FLOAT_REGS; - }else{ - if(!isfloat&&!ALIGNED(regs->highest_bit, 2)){ - regs->highest_bit++; - regs->left_single++; - } - ret=regs->highest_bit; - for(i=0;i<sz;++i){ - set_bit(regs->floats,regs->highest_bit++); - } - } - } - if(regs->highest_bit==MAX_FLOAT_REGS){ - regs->float_sealed=true; - } - return ret; -} -#endif -static void load_reg(struct jit* Dst,int off,int size){ - if(size==16){ - dasm_put(Dst, 72, off); - }else if(size==12){ - dasm_put(Dst, 76, off); - }else if(size==8){ - dasm_put(Dst, 80, off); - }else{ - dasm_put(Dst, 84, off); - } -} -// arm store/load range for immediate value is only -256-255 -static void load_stack(struct jit* Dst,stack_info* st,int size,int align){ - int off=st->stack_off; - FIX_ALIGN(st->stack_off,align); - if((off=st->stack_off-off)){ - dasm_put(Dst, 87, off); - } - if(size==16){ - dasm_put(Dst, 90); - }else if(size==8){ - dasm_put(Dst, 92); - }else{ - dasm_put(Dst, 94); - } - st->stack_off+=size; -} - -static void load_int(struct jit* Dst,stack_info* st,int size,int align){ - FIX_ALIGN(st->int_off,align); - if(st->int_off<0x40*ARM_HF+MAX_REGS*4&&(!st->stack_off||MAX_REGS*4+size<=0x40*ARM_HF+MAX_REGS*4)){ - load_reg(Dst,st->int_off+st->extra,size); - st->int_off+=size; - }else{ - st->int_off=0x40*ARM_HF+MAX_REGS*4; - load_stack(Dst,st,size,align); - } - -} - -static void load_float(struct jit* Dst,stack_info* st,int size,int vfp,int align){ - #if ARM_HF - if(st->float_off<st->float_size){ - if(vfp){ - if(size==4){//float - dasm_put(Dst, 96, st->float_off+st->extra); - }else if(size==8){//double - dasm_put(Dst, 99, st->float_off+st->extra); - } - }else load_reg(Dst,st->float_off+st->extra,size); - st->float_off+=size; - }else if(vfp){ - if(size==4){//float - dasm_put(Dst, 102); - }else if(size==8){//double - int off=st->stack_off; - FIX_ALIGN(st->stack_off,align); - if((off=st->stack_off-off)){ - dasm_put(Dst, 105, off); - } - dasm_put(Dst, 108); - } - }else{ - load_stack(Dst,st,size,align); - } - #else - load_int(Dst,st,size,align); - #endif -} -#if ARM_HF -static void push_regs(lua_State* L,struct jit* Dst,int ct_usr,int nargs,stack_info* st){ - const struct ctype* mt; - reg_info regs;int i; - memset(®s,0,sizeof(reg_info)); - for (i = 1; i <= nargs&&!is_float_sealed(®s); ++i){ - lua_rawgeti(L, ct_usr, i); - mt = (const struct ctype*) lua_touserdata(L, -1); - if (!mt->pointers &&! mt->is_reference) { - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - save_float_reg(Dst,add_float_reg(®s,4,0),16,st); - break; - case DOUBLE_TYPE: - save_float_reg(Dst,add_float_reg(®s,2,0),8,st); - break; - case COMPLEX_FLOAT_TYPE: - save_float_reg(Dst,add_float_reg(®s,2,1),8,st); - break; - case FLOAT_TYPE: - save_float_reg(Dst,add_float_reg(®s,1,1),4,st); - break; - case STRUCT_TYPE: - { - int isfloat,hfasize=hfa_size(L,-1,mt,&isfloat); - if(hfasize){ - save_float_reg(Dst,add_float_reg(®s,hfasize,isfloat),4*hfasize,st); - break; - } - } - case UNION_TYPE: - break; - case INT64_TYPE: - //add_int64_reg(®s); - break; - default: - //add_int_reg(®s);//no need to check type support here - break; - } - } - lua_pop(L,1); - } - st->float_off+=st->int_off; - st->int_off+=0x40; -} -#endif -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; - stack_info st; - - 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"); - } - memset(&st,0,sizeof(stack_info)); - st.extra=0x10; - /* prolog and get the upval table */ - dasm_put(Dst, 111); -#if ARM_HF - dasm_put(Dst, 114); - push_regs(L,Dst,ct_usr,nargs,&st); -#endif - - dasm_put(Dst, 116, (unsigned short)(L), (((unsigned int)(L))>>16), (unsigned short)(ref), (((unsigned int)(ref))>>16), (unsigned short)(LUA_REGISTRYINDEX), (((unsigned int)(LUA_REGISTRYINDEX))>>16)); - - /* get the lua function */ - lua_pushvalue(L, fidx); - lua_rawseti(L, -2, ++num_upvals); - - - dasm_put(Dst, 134, num_upvals); - - // Complex type is return in the address stored in r0 for softfp - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - if(!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| - (!1&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(1&&hfa_size(L,-1,mt,NULL))){ - st.int_off+=4; - } - lua_pop(L,1); - - //whether 64 bit type requires 8 bytes alignment in stack is defined by compiler.android compiler reqiures only 4 byte alignment; - //actually the stack it self may reqiures 8 bytes alignment - 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, 141, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_int(Dst,&st,4,4); - dasm_put(Dst, 157); - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - #if ARM_HF - int isfloat,hfasize=0; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - #endif - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 163, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - #if ARM_HF - if(hfasize){ - if(hfasize<=4)load_float(Dst,&st,4*hfasize,0,4*(2-isfloat)); - switch(hfasize){ - case 8: - load_float(Dst,&st,16,0,8); - dasm_put(Dst, 179); - load_float(Dst,&st,16,0,8); - dasm_put(Dst, 181); - break; - case 6: - load_float(Dst,&st,16,0,8); - dasm_put(Dst, 183); - load_float(Dst,&st,8,0,8); - dasm_put(Dst, 185); - break; - case 4: - dasm_put(Dst, 187); - break; - case 3: - dasm_put(Dst, 189); - break; - case 2: - dasm_put(Dst, 191); - break; - case 1: - dasm_put(Dst, 193); - break; - } - }else - #endif - if(!mt->is_empty){ - int size=mt->base_size; - if(size<=4){ - load_int(Dst,&st,4,4); - dasm_put(Dst, 195); - }else{ - size=ROUND_UP(size,4); - if(mt->align_mask>4){//8 byte max alignment - if(st.int_off<0x40*ARM_HF+MAX_REGS*4){FIX_ALIGN(st.int_off,8);} - else {FIX_ALIGN(st.stack_off,8);} - } - - if(st.int_off<0x40*ARM_HF+MAX_REGS*4&&(!st.stack_off||st.int_off+size<=0x40*ARM_HF+MAX_REGS*4)){//to ensure consective memory for the struct - dasm_put(Dst, 197, st.int_off+st.extra); - st.int_off+=size; - }else{ - st.int_off=0x40*ARM_HF+MAX_REGS*4; - dasm_put(Dst, 200); - st.stack_off+=size; - } - dasm_put(Dst, 202, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); - } - } - dasm_put(Dst, 212); - break; - } - - case COMPLEX_DOUBLE_TYPE: - - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 217, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_float(Dst,&st,16,0,8); - dasm_put(Dst, 233); - break; - case COMPLEX_FLOAT_TYPE: - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 239, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_float(Dst,&st,8,0,4); - dasm_put(Dst, 255); - break; - case INT64_TYPE: - - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - - #if CK_ALGIN - FIX_ALIGN(st.int_off,8); - if(st.int_off<16){ - dasm_put(Dst, 261, st.int_off+st.extra); - st.int_off+=8; - }else{ - if(!ALIGNED(st.stack_off,8)){ - st.stack_off+=4; - dasm_put(Dst, 265); - } - dasm_put(Dst, 267); - st.stack_off+=8; - } - #else - load_int(Dst,st,8,8); - #endif - dasm_put(Dst, 269); - #else - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 273, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_int(Dst,&st,8,8); - dasm_put(Dst, 282); - #endif - break; - - case INTPTR_TYPE: - lua_rawseti(L, -2, ++num_upvals); /* mt */ - - dasm_put(Dst, 288, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - load_int(Dst,&st,4,4); - dasm_put(Dst, 297); - - break; - - case BOOL_TYPE: - lua_pop(L, 1); - - load_int(Dst,&st,4,4); - dasm_put(Dst, 303); - break; - - case INT8_TYPE: // no need to narrow cause narrowed by caller - case INT16_TYPE: // no need to narrow cause narrowed by caller - case ENUM_TYPE: - case INT32_TYPE: - lua_pop(L, 1); - - load_int(Dst,&st,4,4); - dasm_put(Dst, 307); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - - load_float(Dst,&st,4,ARM_HF,4); - dasm_put(Dst, 311); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - - #if ARM_HF - load_float(Dst,&st,8,ARM_HF,8); - #elif CK_ALGIN - FIX_ALIGN(st.int_off,8); - if(st.int_off<16){ - dasm_put(Dst, 315, st.int_off+st.extra); - st.int_off+=8; - }else{ - if(!ALIGNED(st.stack_off,8)){ - st.stack_off+=4; - dasm_put(Dst, 319); - } - dasm_put(Dst, 321); - st.stack_off+=8; - } - #else - load_float(Dst,&st,8,ARM_HF,8); - #endif - dasm_put(Dst, 323); - 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, 327, ((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, 335, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - goto single_no_pop; - } else { - switch (mt->type) { - case STRUCT_TYPE: - case UNION_TYPE:{ - int isfloat,hfasize=0; - if(mt->type!=UNION_TYPE){ - hfasize=hfa_size(L,-1,mt,&isfloat); - } - lua_getuservalue(L, -1); - lua_rawseti(L, -3, ++num_upvals); /* usr value */ - lua_rawseti(L, -2, ++num_upvals); /* mt */ - dasm_put(Dst, 351, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - #if ARM_HF - if(hfasize>0){ - switch(hfasize){ - case 8: - dasm_put(Dst, 372); - break; - case 6: - dasm_put(Dst, 374); - break; - case 4: - dasm_put(Dst, 376); - break; - case 3: - dasm_put(Dst, 378); - break; - case 2: - dasm_put(Dst, 380); - break; - case 1: - dasm_put(Dst, 382); - break; - } - }else - #endif - if(!mt->is_empty){ - if(mt->base_size<=4){ - dasm_put(Dst, 384); - }else{ - dasm_put(Dst, 386, st.extra+0x40*1, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); - } - } - break; - } - 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, 399, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - - goto single_no_pop; - - case VOID_TYPE: - dasm_put(Dst, 415); - lua_pop(L, 1); - break; - - case BOOL_TYPE: - case INT8_TYPE:// narrow it - case INT16_TYPE:// narrow it - case INT32_TYPE: - dasm_put(Dst, 420); - if (mt->is_unsigned) { - dasm_put(Dst, 422); - } else { - dasm_put(Dst, 426); - } - switch(mt->type){ - case BOOL_TYPE: - dasm_put(Dst, 430); - break; - case INT8_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 433); - } else { - dasm_put(Dst, 435); - } - break; - case INT16_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 437); - } else { - dasm_put(Dst, 439); - } - break; - } - goto single; - - case INT64_TYPE: - dasm_put(Dst, 441); - if (mt->is_unsigned) { - dasm_put(Dst, 443); - } else { - dasm_put(Dst, 447); - } - goto dual; - - case INTPTR_TYPE: - dasm_put(Dst, 451); - goto single; - - case FLOAT_TYPE: - dasm_put(Dst, 456); - #if ARM_HF - dasm_put(Dst, 461); - lua_pop(L, 1); - #else - goto single; - #endif - break; - case DOUBLE_TYPE: - dasm_put(Dst, 468); - #if ARM_HF - dasm_put(Dst, 473); - lua_pop(L, 1); - #else - goto dual; - #endif - break; - case COMPLEX_DOUBLE_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 480); - break; - case COMPLEX_FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 491); - break; - - single: - lua_pop(L, 1); - single_no_pop: - dasm_put(Dst, 502); - - break; - dual: - dasm_put(Dst, 509); - - lua_pop(L, 1); - break; - - - - default: - luaL_error(L, "NYI: callback return type"); - } - } - - dasm_put(Dst, 518); - - 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; - } -} - -static ALWAYS_INLINE void save_int64_stack_align(struct jit* Dst,reg_info* regs,int align){ - if(align&&!ALIGNED(regs->exs,2)){ - regs->exs++; - dasm_put(Dst, 520); - } - dasm_put(Dst, 522); - regs->exs+=2; -} - -static ALWAYS_INLINE void save_int64_align(struct jit* Dst,reg_info* regs,int align){ - if((align&&!ALIGNED(regs->ints,2))||(regs->ints==MAX_REGS-1&®s->exs/*to ensure consective memory*/)){ - regs->ints++; - } - if(regs->ints<MAX_REGS){ - dasm_put(Dst, 524, ((regs->ints<<2)+0x40*1)); - regs->ints+=2; - }else{ - save_int64_stack_align(Dst,regs,align); - } - -} - -static ALWAYS_INLINE void save_int64(struct jit* Dst,reg_info* regs){ - save_int64_align(Dst,regs,1); -} - -static ALWAYS_INLINE void save_int_stack_align(struct jit* Dst,reg_info* regs){ - dasm_put(Dst, 528); - regs->exs++; -} - -static ALWAYS_INLINE void save_int(struct jit* Dst,reg_info* regs){ - if(regs->ints<MAX_REGS){ - dasm_put(Dst, 530, ((regs->ints++<<2)+0x40*1)); - }else{ - save_int_stack_align(Dst,regs); - } -} - -static void save_float(struct jit* Dst,reg_info* regs,int size,int isfloat){ -#if ARM_HF - if(!regs->float_sealed){ - int reg=add_float_reg(regs,size,isfloat); - if(reg<0) goto SAVE_STACK; - switch(size){ - case 8: - dasm_put(Dst, 533, (reg<<2)+24); - case 6: - dasm_put(Dst, 536, (reg<<2)+16); - case 4: - dasm_put(Dst, 539, (reg<<2)+8); - goto sf_2; - case 3: - dasm_put(Dst, 542, (reg<<2)+8); - case 2: - sf_2: - dasm_put(Dst, 545, (reg<<2)); - break; - case 1: - dasm_put(Dst, 548, (reg<<2)); - break; - } - return; - } - SAVE_STACK: - - if(!isfloat&&!ALIGNED(regs->exs,2)){ - regs->exs++; - dasm_put(Dst, 551); - } - switch(size){ - case 1: - dasm_put(Dst, 553); - break; - case 2: - dasm_put(Dst, 555); - break; - case 3: - dasm_put(Dst, 557); - break; - case 4: - dasm_put(Dst, 559); - break; - case 6: - dasm_put(Dst, 561); - break; - case 8: - dasm_put(Dst, 563); - break; - - } - regs->exs+=size; - -#else - if(size==1){ - save_int(Dst,regs); - }else if(size==2){ - save_int64_align(Dst,regs,!isfloat); - } -#endif -} - -static int calculate_stack(lua_State* L,int ct_usr,int nargs){ - const struct ctype* mt; - reg_info regs;int i,stack=0; - memset(®s,0,sizeof(reg_info)); - 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) { - stack+=add_int_reg(®s); - }else{ - switch(mt->type){ - case COMPLEX_DOUBLE_TYPE: - #if ARM_HF - stack+=add_float_reg(®s,4,0)<0?4:0; - #else - stack+=add_int64_reg(®s); - stack+=add_int64_reg(®s); - #endif - FIX_ALIGN(stack,2); - break; - case DOUBLE_TYPE: - #if ARM_HF - stack+=add_float_reg(®s,2,0)<0?2:0; - #else - stack+=add_int64_reg(®s); - #endif - FIX_ALIGN(stack,2); - break; - case COMPLEX_FLOAT_TYPE:// Though complex alignment is 4, but vfp requires a sequence of regsiters - #if ARM_HF - stack+=add_float_reg(®s,2,1)<0?2:0; - #else - stack+=add_int_reg(®s); - stack+=add_int_reg(®s); - #endif - break; - case FLOAT_TYPE: - #if ARM_HF - stack+=add_float_reg(®s,1,1)<0?1:0; - #else - stack+=add_int_reg(®s); - #endif - break; - case INT64_TYPE: - stack+=add_int64_reg(®s); - FIX_ALIGN(stack,2); - break; - case STRUCT_TYPE:{ - #if ARM_HF - int isfloat; - int hfasize=hfa_size(L,-1,mt,&isfloat); - if(hfasize>0){ - stack+=add_float_reg(®s,2,0)<0?hfasize:0; - if(!isfloat){ - FIX_ALIGN(stack,2); - } - break; - } - #endif - } - case UNION_TYPE:{ - int intsize=(mt->base_size+3)>>2; - if(mt->align_mask>4){//8-byte max alignment - if(regs.ints<MAX_REGS){ - FIX_ALIGN(regs.ints,2); - }else{ - FIX_ALIGN(stack,2); - } - } - - if(regs.ints+intsize<=MAX_REGS){ - regs.ints+=intsize; - }else{ - stack+=regs.ints+intsize-MAX_REGS; - regs.ints=MAX_REGS; - } - break; - } - default: - stack+=add_int_reg(®s);//no need to check type support here - } - } - lua_pop(L,1); - } - FIX_ALIGN(stack,2); - return (regs.ints - #if ARM_HF - /**/||regs.floats - #endif - )?0x40*ARM_HF+0x10+stack*4:0; -} - -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,ret_by_addr, stack_size; - const struct ctype* mt; - void* p; reg_info regs; - - 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); -#if defined __thumb__ //keep frame pointer - dasm_put(Dst, 565); -#else - dasm_put(Dst, 568); -#endif -#if CK_ALGIN - dasm_put(Dst, 571); -#endif - dasm_put(Dst, 573); - - /* Reserve enough stack space for all of the arguments. For hard floating point, - * leave extra 64 bytes - */ - stack_size=calculate_stack(L,ct_usr,nargs); - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - // Complex types in softfp and structs/unions larger than 4-bytes are return in the address stored in r0 - ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| - (!ARM_HF&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(ARM_HF&&hfa_size(L,-1,mt,NULL)); - lua_pop(L,1); - if(ret_by_addr){ - if(stack_size==0) - stack_size=0x40*ARM_HF+0x10; - stack_size+=8; - } - if(stack_size>0){ - if(stack_size>=1<<12){ - dasm_put(Dst, 575, (unsigned short)(stack_size), (((unsigned int)(stack_size))>>16)); - }else{ - dasm_put(Dst, 581, stack_size); - } - if (ct->has_var_arg){ - dasm_put(Dst, 584, nargs, (unsigned short)("too few arguments"), (((unsigned int)("too few arguments"))>>16)); - } - dasm_put(Dst, 601, 0x40*1+0x10); - } - - memset(®s,0,sizeof(reg_info)); - - if (ret_by_addr) { - regs.ints++; - dasm_put(Dst, 604, (unsigned short)(mt), (((unsigned int)(mt))>>16), 0x40*1); - } - - - 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|| mt->type==STRUCT_TYPE || mt->type==UNION_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - - dasm_put(Dst, 615, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16), i); - - if (mt->pointers || mt->is_reference) { - dasm_put(Dst, 626); - } else if (mt->type == FUNCTION_PTR_TYPE) { - dasm_put(Dst, 630); - } else if (mt->type == ENUM_TYPE) { - dasm_put(Dst, 634); - }else if(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE){ - if(mt->is_empty) continue; - dasm_put(Dst, 638); - #if ARM_HF - { - int hfasize,isfloat; - hfasize=hfa_size(L,-2,mt,&isfloat); - if(hfasize){ - switch(hfasize){ - case 8: - dasm_put(Dst, 642); - break; - case 6: - dasm_put(Dst, 644); - break; - case 4: - dasm_put(Dst, 646); - break; - case 3: - dasm_put(Dst, 648); - break; - case 2: - dasm_put(Dst, 650); - break; - case 1: - dasm_put(Dst, 652); - break; - - } - save_float(Dst,®s,hfasize,isfloat); - continue; - } - } - #endif - - if(mt->align_mask>4){//8 byte max alignment - if(regs.ints<4){ - FIX_ALIGN(regs.ints,2) - }else if(!ALIGNED(regs.exs,2)){ - int diff=regs.exs; - regs.exs+=4; - dasm_put(Dst, 654); - } - } - int size=ROUND_UP(mt->base_size,4)>>2; - dasm_put(Dst, 656, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); - if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+size<=MAX_REGS)){//to ensure consective memory for the struct - dasm_put(Dst, 666, ((regs.ints<<2)+0x40*1)); - }else{ - regs.ints=MAX_REGS; - dasm_put(Dst, 669); - } - dasm_put(Dst, 671); - if(regs.ints+size<=MAX_REGS){ - regs.ints+=size; - }else{ - int ex=regs.ints+size-MAX_REGS; - dasm_put(Dst, 673, (ex)<<2); - regs.exs+=ex; - regs.ints=MAX_REGS; - } - continue; - } - - save_int(Dst,®s); - } else { - lua_pop(L, 1); - dasm_put(Dst, 676, i); - - switch (mt->type) { - case BOOL_TYPE: - dasm_put(Dst, 679); - save_int(Dst,®s); - break; - case INT8_TYPE: - dasm_put(Dst, 685); - if (mt->is_unsigned) { - dasm_put(Dst, 689); - } else { - dasm_put(Dst, 691); - } - save_int(Dst,®s); - break; - - case INT16_TYPE: - dasm_put(Dst, 693); - if (mt->is_unsigned) { - dasm_put(Dst, 697); - } else { - dasm_put(Dst, 699); - } - save_int(Dst,®s); - break; - - case INT32_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 701); - } else { - dasm_put(Dst, 705); - } - save_int(Dst,®s); - break; - case INTPTR_TYPE: - dasm_put(Dst, 709); - save_int(Dst,®s); - break; - - case INT64_TYPE: - if (mt->is_unsigned) { - dasm_put(Dst, 713); - } else { - dasm_put(Dst, 717); - } - save_int64(Dst,®s); - break; - - case DOUBLE_TYPE: - dasm_put(Dst, 721); - save_float(Dst,®s,2,0); - break; - - case FLOAT_TYPE: - dasm_put(Dst, 725); - save_float(Dst,®s,1,1); - break; - - case COMPLEX_DOUBLE_TYPE: - #if ARM_HF - dasm_put(Dst, 729); - save_float(Dst,®s,4,0); - #else - FIX_ALIGN(regs.ints,2); - if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+4<=MAX_REGS)){ - }else{ - regs.ints=MAX_REGS; - if(!ALIGNED(regs.exs,2)){ - ++regs.exs; - } - } - regs.ints+=4; - goto FIX_REG; - #endif - break; - case COMPLEX_FLOAT_TYPE: - #if ARM_HF - dasm_put(Dst, 733); - save_float(Dst,®s,2,1); - #else - if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+2<=MAX_REGS)){ - }else{ - regs.ints=MAX_REGS; - } - regs.ints+=2; - FIX_REG: - if(regs.ints>MAX_REGS){ - regs.exs+=regs.ints-MAX_REGS; - regs.ints=MAX_REGS; - } - #endif - break; - default: - luaL_error(L, "NYI: call arg type"); - } - } - } - - if (ct->has_var_arg) { - int offset=nargs+1; - dasm_put(Dst, 737, offset); - #if ARM_HF - if(regs.ints==4||regs.float_sealed){ - if(regs.ints<4&®s.float_sealed){//some arg must be loaded to core registers. - dasm_put(Dst, 740, ((regs.ints<<2)+0x40), (0x10+0x40), offset); - } - dasm_put(Dst, 750); - } - #else - if(regs.ints==4){ - } - #endif - else{//no hard floating point in variadic procedure - dasm_put(Dst, 752, ((regs.ints<<2)+1*0x40)); - } - - dasm_put(Dst, 755); - regs.ints=4; - } - - #if ARM_HF - switch(ROUND_UP(regs.highest_bit,4)>>1){ - case 8 : - dasm_put(Dst, 760); - break; - case 7 : - dasm_put(Dst, 762); - break; - case 6 : - dasm_put(Dst, 764); - break; - case 5: - dasm_put(Dst, 766); - break; - case 4 : - dasm_put(Dst, 768); - break; - case 3 : - dasm_put(Dst, 770); - break; - case 2 : - dasm_put(Dst, 772); - break; - case 1 : - dasm_put(Dst, 774); - break; - } - if(stack_size>0){ - dasm_put(Dst, 776); - } - #endif - - //pop registers from stack,align 8 for some compiler - assert(regs.ints<=4); - switch(regs.ints){ - case 4: - case 3: - dasm_put(Dst, 778); - break; - case 2: - case 1: - dasm_put(Dst, 780); - #if ARM_HF - if(regs.float_sealed){ - dasm_put(Dst, 782); - } - #endif - break; - default: - #if ARM_HF - if(regs.float_sealed){ - dasm_put(Dst, 784); - } - #endif - break; - } - - dasm_put(Dst, 786, (unsigned short)(func), (((unsigned int)(func))>>16)); - - lua_rawgeti(L, ct_usr, 0); - mt = (const struct ctype*) lua_touserdata(L, -1); - - if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { - lua_getuservalue(L, -1); - num_upvals += 2; - dasm_put(Dst, 792, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - - } else { - switch (mt->type) { - case INT64_TYPE: - #if LUA_VERSION_NUM>=503 - lua_pop(L, 1); - #if CK_ALGIN - dasm_put(Dst, 807); - #else - dasm_put(Dst, 810); - #endif - dasm_put(Dst, 813); - break; - #else - num_upvals++; - dasm_put(Dst, 818, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - break; - #endif - - case INTPTR_TYPE: - num_upvals++; - dasm_put(Dst, 832, (unsigned short)(mt), (((unsigned int)(mt))>>16)); - break; - - case VOID_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 844); - break; - - case BOOL_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 846); - break; - - case INT8_TYPE: - case INT16_TYPE: - case INT32_TYPE: - case ENUM_TYPE:// value must be narrowed before callee return - lua_pop(L, 1); - - dasm_put(Dst, 852); - if (mt->is_unsigned) { - dasm_put(Dst, 854); - } else { - dasm_put(Dst, 858); - } - - dasm_put(Dst, 862); - break; - - case FLOAT_TYPE: - lua_pop(L, 1); - dasm_put(Dst, 864); - break; - - case DOUBLE_TYPE: - lua_pop(L, 1); - #if CK_ALGIN - #else - #endif - dasm_put(Dst, 869); - break; - case COMPLEX_DOUBLE_TYPE: - case COMPLEX_FLOAT_TYPE: - case STRUCT_TYPE: - case UNION_TYPE:{ - lua_getuservalue(L,-1); - num_upvals += 2; - #if ARM_HF - { - int isfloat,hfasize=hfa_size(L,-2,mt,&isfloat); - if(hfasize>0){ - switch(hfasize){ - case 8: - dasm_put(Dst, 874); - break; - case 6: - dasm_put(Dst, 876); - break; - case 4: - case 3: - dasm_put(Dst, 878); - break; - case 2: - case 1: - dasm_put(Dst, 880); - break; - - } - dasm_put(Dst, 882, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - switch(hfasize){ - case 8: - dasm_put(Dst, 895); - break; - case 6: - dasm_put(Dst, 898); - break; - case 4: - dasm_put(Dst, 901); - break; - case 3: - dasm_put(Dst, 904); - break; - case 2: - dasm_put(Dst, 907); - break; - case 1: - dasm_put(Dst, 910); - break; - - } - dasm_put(Dst, 913); - break; - } - } - - #endif - if(mt->base_size>4){ - // value are stored in return storage in r0 for softfp, set usr value here - if(!lua_isnil(L,-1)){ - dasm_put(Dst, 915, (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - } - }else if(mt->is_empty){ - dasm_put(Dst, 927); - break; - }else{ - dasm_put(Dst, 929, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); - } - dasm_put(Dst, 943); - break; - } - default: - luaL_error(L, "NYI: call return type"); - } - } - -#ifdef __thumb__ - dasm_put(Dst, 945); -#else - dasm_put(Dst, 948); -#endif - assert(lua_gettop(L) == top + num_upvals); - { - cfunction f = compile(Dst, L, NULL, 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); - } -} - +/* +** This file has been pre-processed with DynASM. +** http://luajit.org/dynasm.html +** DynASM version 1.4.0, DynASM arm version 1.4.0 +** DO NOT EDIT! The original file is in "call_arm.dasc". +*/ + +/* 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. + */ + +//The generate code is for arm not for thumb +#if DASM_VERSION != 10400 +#error "Version mismatch between DynASM and included encoding engine" +#endif + +static const unsigned int build_actionlist[951] = { +0xed0d0a00, +0x000f8100, +0x00000000, +0xed4d0a00, +0x000f8100, +0x00000000, +0xed0d1a00, +0x000f8100, +0x00000000, +0xed4d1a00, +0x000f8100, +0x00000000, +0xed0d2a00, +0x000f8100, +0x00000000, +0xed4d2a00, +0x000f8100, +0x00000000, +0xed0d3a00, +0x000f8100, +0x00000000, +0xed4d3a00, +0x000f8100, +0x00000000, +0xed0d4a00, +0x000f8100, +0x00000000, +0xed4d4a00, +0x000f8100, +0x00000000, +0xed0d5a00, +0x000f8100, +0x00000000, +0xed4d5a00, +0x000f8100, +0x00000000, +0xed0d6a00, +0x000f8100, +0x00000000, +0xed4d6a00, +0x000f8100, +0x00000000, +0xed0d7a00, +0x000f8100, +0x00000000, +0xed4d7a00, +0x000f8100, +0x00000000, +0xed0d0b00, +0x000f8100, +0x00000000, +0xed0d1b00, +0x000f8100, +0x00000000, +0xed0d2b00, +0x000f8100, +0x00000000, +0xed0d3b00, +0x000f8100, +0x00000000, +0xed0d4b00, +0x000f8100, +0x00000000, +0xed0d5b00, +0x000f8100, +0x00000000, +0xed0d6b00, +0x000f8100, +0x00000000, +0xed0d7b00, +0x000f8100, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c100e, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c100e, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c0006, +0x00000000, +0xe51d1000, +0x000e8180, +0x00000000, +0xe2866000, +0x000b0000, +0x00000000, +0xe8b6100e, +0x00000000, +0xe8b60006, +0x00000000, +0xe4961004, +0x00000000, +0xed1d0a00, +0x000f8100, +0x00000000, +0xed1d0b00, +0x000f8100, +0x00000000, +0xed160a00, +0xe2866004, +0x00000000, +0xe2866000, +0x000b0000, +0x00000000, +0xed160b00, +0xe2866008, +0x00000000, +0xe1a0c00d, +0xe92d000f, +0x00000000, +0xe24dd040, +0x00000000, +0xe92d5050, +0xe1a0600c, +0xe3004000, +0x000c0200, +0xe3404000, +0x000c0200, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030000, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030000, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe5801000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe8a0100e, +0x00000000, +0xe880100e, +0x00000000, +0xe8a0100e, +0x00000000, +0xe8800006, +0x00000000, +0xe880100e, +0x00000000, +0xe880000e, +0x00000000, +0xe8800006, +0x00000000, +0xe5801000, +0x00000000, +0xe5801000, +0x00000000, +0xe28d1000, +0x000b0000, +0x00000000, +0xe1a01006, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe12fff3c, +0x00000000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe880100e, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe8800006, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c000c, +0x00000000, +0xe2866004, +0x00000000, +0xe8b6000c, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030003, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe8800006, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xe5801000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030002, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030004, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030005, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030006, +0x00000000, +0xe28dc000, +0x000b0000, +0xe89c000c, +0x00000000, +0xe2866004, +0x00000000, +0xe8b6000c, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030007, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3a01000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030008, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3e02000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030009, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3e02000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003000a, +0xe1a06000, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0x00000000, +0xec960b08, +0x00000000, +0xec960b06, +0x00000000, +0xec960b04, +0x00000000, +0xec960a04, +0x00000000, +0xed160b00, +0x00000000, +0xed160a00, +0x00000000, +0xe5960000, +0x00000000, +0xe51d0000, +0x000e8180, +0xe1a01006, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe12fff3c, +0x00000000, +0xe3a02000, +0x000b0000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x00030000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3e02000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003000c, +0x00000000, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003000b, +0x00000000, +0xe3e01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000d, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe3500000, +0x13a00001, +0x00000000, +0xe6ef0070, +0x00000000, +0xe6af0070, +0x00000000, +0xe6ff0070, +0x00000000, +0xe6bf0070, +0x00000000, +0xe3e01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000f, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030010, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030011, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030012, +0x00000000, +0xee106a10, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0xee006a10, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030013, +0x00000000, +0xe1a00004, +0xec564b10, +0xe3e01002, +0xeb000000, +0x0003000b, +0xec464b10, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030014, +0xed2d0b04, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0xecbd0b04, +0x00000000, +0xe3e01000, +0xe1a00004, +0xeb000000, +0x00030015, +0xed2d0a02, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0xecbd0a02, +0x00000000, +0xe1a06000, +0xe3e01002, +0xe1a00004, +0xeb000000, +0x0003000b, +0xe1a00006, +0x00000000, +0xe1a06000, +0xe1a00004, +0xe1a04001, +0xe3e01002, +0xeb000000, +0x0003000b, +0xe1a00006, +0xe1a01004, +0x00000000, +0xe89da050, +0x00000000, +0xe2866004, +0x00000000, +0xe8a60003, +0x00000000, +0xe28dc000, +0x000b0000, +0xe88c0003, +0x00000000, +0xe4860004, +0x00000000, +0xe50d0000, +0x000e8180, +0x00000000, +0xed0d3b00, +0x000f8100, +0x00000000, +0xed0d2b00, +0x000f8100, +0x00000000, +0xed0d1b00, +0x000f8100, +0x00000000, +0xed4d1a00, +0x000f8100, +0x00000000, +0xed0d0b00, +0x000f8100, +0x00000000, +0xed0d0a00, +0x000f8100, +0x00000000, +0xe2866004, +0x00000000, +0xeca60a01, +0x00000000, +0xeca60b02, +0x00000000, +0xeca60a04, +0x00000000, +0xeca60b04, +0x00000000, +0xeca60b06, +0x00000000, +0xeca60b08, +0x00000000, +0xe92d40f0, +0xe28d700c, +0x00000000, +0xe92d4870, +0xe28db00c, +0x00000000, +0xe24dd004, +0x00000000, +0xe1a04000, +0x00000000, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe04dd00c, +0x00000000, +0xe24dd000, +0x000b0000, +0x00000000, +0xeb000000, +0x00030016, +0xe3500000, +0x000b0000, +0xaa000000, +0x00050001, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030017, +0x0006000b, +0xe1a05000, +0xe04dd185, +0x00000000, +0xe28d6000, +0x000b0000, +0x00000000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0xe50d0000, +0x000e8180, +0x00000000, +0xe3003000, +0x000c0200, +0xe3403000, +0x000c0200, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0x000b0000, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030009, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030018, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000c, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000a, +0x00000000, +0xec900b0a, +0x00000000, +0xec900b0a, +0x00000000, +0xec900b06, +0x00000000, +0xec900a04, +0x00000000, +0xed100b00, +0x00000000, +0xed100a00, +0x00000000, +0xe2866004, +0x00000000, +0xe1a01000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0x00000000, +0xe28d0000, +0x000b0000, +0x00000000, +0xe1a00006, +0x00000000, +0xe12fff3c, +0x00000000, +0xe2866000, +0x000b0000, +0x00000000, +0xe3a01000, +0x000b0000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0xe3500000, +0x13a00001, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe6ef0070, +0x00000000, +0xe6af0070, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe6ff0070, +0x00000000, +0xe6bf0070, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000d, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000e, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030011, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003000f, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030010, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030013, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030012, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030014, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030015, +0x00000000, +0xe3a01000, +0x000b0000, +0x00000000, +0xe28d2000, +0x000b0000, +0xe28d3000, +0x000b0000, +0xe1a00004, +0xeb000000, +0x00030019, +0xe2801000, +0x000b0000, +0x00000000, +0xe1a03006, +0x00000000, +0xe28d3000, +0x000b0000, +0x00000000, +0xe1a02005, +0xe1a00004, +0xeb000000, +0x0003001a, +0x00000000, +0xec9d0b10, +0x00000000, +0xec9d0b0e, +0x00000000, +0xec9d0b0c, +0x00000000, +0xec9d0b0a, +0x00000000, +0xec9d0b08, +0x00000000, +0xec9d0b06, +0x00000000, +0xec9d0b04, +0x00000000, +0xed1d0b00, +0x00000000, +0xe28dd040, +0x00000000, +0xe8bd000f, +0x00000000, +0xe8bd0003, +0x00000000, +0xe28dd008, +0x00000000, +0xe28dd010, +0x00000000, +0xe300c000, +0x000c0200, +0xe340c000, +0x000c0200, +0xe12fff3c, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0xe3a00001, +0x00000000, +0xe1a03001, +0xe1a02000, +0x00000000, +0xe1a02001, +0xe1a01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030003, +0xe3a00001, +0x00000000, +0xe1a06000, +0xe1a05001, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0xe5805004, +0xe3a00001, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3a01000, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0xe3a00001, +0x00000000, +0xe3a00000, +0x00000000, +0xe1a01000, +0xe1a00004, +0xeb000000, +0x00030004, +0xe3a00001, +0x00000000, +0xe1a01000, +0x00000000, +0xe1a00004, +0xeb000000, +0x0003001b, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030005, +0x00000000, +0xe3a00001, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030006, +0xe3a00001, +0x00000000, +0xe1a00004, +0xeb000000, +0x00030007, +0xe3a00001, +0x00000000, +0xed2d0b08, +0x00000000, +0xed2d0b06, +0x00000000, +0xed2d0b04, +0x00000000, +0xed2d0b02, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030001, +0x00000000, +0xecbd0b08, +0xec800b08, +0x00000000, +0xecbd0b06, +0xec800b06, +0x00000000, +0xecbd0b04, +0xec800b04, +0x00000000, +0xecbd0b04, +0xec800a04, +0x00000000, +0xecbd0b02, +0xed000b00, +0x00000000, +0xecbd0b02, +0xed000a00, +0x00000000, +0xe3a00001, +0x00000000, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x0003001c, +0xe3e01001, +0xe1a00004, +0xeb000000, +0x0003001d, +0x00000000, +0xe3a00000, +0x00000000, +0xe1a06000, +0xe3002000, +0x000c0200, +0xe3402000, +0x000c0200, +0xe3001000, +0x000c0200, +0xe3401000, +0x000c0200, +0xe1a00004, +0xeb000000, +0x00030001, +0xe5806000, +0x00000000, +0xe3a00001, +0x00000000, +0xe247d00c, +0xe8bd80f0, +0x00000000, +0xe24bd00c, +0xe8bd8870, +0x00000000 +}; + +static const char *const globnames[] = { + (const char *)0 +}; +static const char *const extnames[] = { + "rawgeti", + "push_cdata", + "lua_remove", + "lua_pushinteger", + "lua_pushboolean", + "push_int", + "push_float", + "lua_pushnumber", + "lua_call", + "check_typed_pointer", + "check_struct", + "lua_settop", + "check_enum", + "check_uint32", + "check_int32", + "check_uint64", + "check_int64", + "check_uintptr", + "check_float", + "check_double", + "check_complex_double", + "check_complex_float", + "lua_gettop", + "luaL_error", + "check_typed_cfunction", + "unpack_varargs_bound", + "unpack_varargs_stack", + "push_uint", + "lua_pushvalue", + "lua_setuservalue", + (const char *)0 +}; + +#define JUMP_SIZE 8 + +#define MIN_BRANCH ((INT32_MIN) >> 8) +#define MAX_BRANCH ((INT32_MAX) >> 8) +//arm pc offset 8 so comparing with next instruction is 4, +//unlike x86 which pass in the current instruction address+1 rather than the next instruction +#define BRANCH_OFF 4 + + +#define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) +#ifdef TARGET_OS_IPHONE +#define CK_ALGIN 0 +#else +#define CK_ALGIN 1 +#endif +#define ALIGNED(x, align) (!CK_ALGIN||((int)(x) & (align - 1)) == 0) +#if defined(__ARM_PCS_VFP) || (GCC_VERSION==40500||defined(__clang__))&&!defined(__ARM_PCS) && !defined(__SOFTFP__) && !defined(__SOFTFP) && \ + defined(__VFP_FP__) +#define ARM_HF 1 +#else +#define ARM_HF 0 +#endif +#if ARM_HF&&!CK_ALGIN +#error "Unsupported unaligned stack for hard floating point" +#endif + +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; +} + +typedef struct stack_info{ + int extra; + int int_off; + int stack_off; + int float_size; +#if ARM_HF + int float_off; +#endif +} stack_info; +//vfp use back-filling rule for registers until a float value on stack +typedef struct reg_info{ + uint16_t exs; + union{ + uint8_t ints; + uint8_t regs; + }; +#if ARM_HF + uint8_t float_sealed; + short floats;//each bit is a float: s0-s15 or v0-v7 or q0-q3 + uint8_t left_single; + uint8_t highest_bit; +#endif +} reg_info; + +#define MAX_REGS 4 +#define MAX_FLOAT_REGS 16 +#ifndef bool +#define bool uint8_t +#endif + +#define has_bit(x,b) (((x)&(1<<(b)))!=0) +#define set_bit(x,b) (x=((x)|(1<<(b)))) +#define FIX_ALIGN(x,al) \ + if(!ALIGNED((x),al)){\ + x=ROUND_UP(x,al);\ + } +static ALWAYS_INLINE bool is_float_sealed(reg_info* regs){ +#if ARM_HF +return regs->float_sealed; +#else +return regs->regs>=MAX_REGS; +#endif +} +//return size need to put on stack +static ALWAYS_INLINE int add_int_reg(reg_info* regs){ + if(regs->regs<MAX_REGS){ + regs->regs++; + return 0; + } + return 1; + +} +//return size need to put on stack +static ALWAYS_INLINE int add_int64_reg(reg_info* regs){ + if(regs->regs<MAX_REGS-1){ + regs->regs=ROUND_UP(regs->regs,2)+2; + return 0; + }else if(regs->regs==MAX_REGS-1){ + regs->regs=MAX_REGS; + } + + return 2; +} +static ALWAYS_INLINE bool is_float_type(int t){ + return t==FLOAT_TYPE||t==DOUBLE_TYPE; +} +static int hfa_size(lua_State* L,int idx, const struct ctype* ct,int* isfloat){ + struct ctype* mt; + int type,ele_count,i,ct_usr; + lua_getuservalue(L,idx); + ct_usr=lua_absindex(L,-1); + lua_rawgeti(L,ct_usr,1); + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt==NULL||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + if(ct->type==COMPLEX_DOUBLE_TYPE){ + if(isfloat) *isfloat=0; + return 4; + }else if(ct->type==COMPLEX_FLOAT_TYPE){ + if(isfloat) *isfloat=1; + return 2; + } + return 0; + } + type=mt->type; + ele_count=(int)(ct->base_size/mt->base_size); + if(ele_count>4||ct->base_size%mt->base_size){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + for (i = 2; i <=4 ; ++i) { + lua_rawgeti(L,ct_usr,i); + if(lua_isnil(L,-1)){//case have array member; + lua_pop(L,1); + break; + } + mt=(struct ctype*)lua_touserdata(L,-1); + if(mt->type!=type||(mt->pointers&&!mt->is_array)||mt->is_reference||!is_float_type(mt->type)){ + lua_pop(L,2); + return 0; + } + lua_pop(L,1); + } + if(isfloat){ + *isfloat=mt->type==FLOAT_TYPE; + } + lua_pop(L,1); + return ele_count*(mt->type==FLOAT_TYPE?1:2); +} +#if ARM_HF +static void save_float_reg(struct jit* Dst,int reg,int size,stack_info* st){ + int sz; + if(reg==-1) return; + for(;size>0;size-=8){ + sz=size>8?8:size; + switch(sz){ + case 4: + switch(reg){ + case 0: + dasm_put(Dst, 0, st->float_size); + break; + case 1: + dasm_put(Dst, 3, st->float_size); + break; + case 2: + dasm_put(Dst, 6, st->float_size); + break; + case 3: + dasm_put(Dst, 9, st->float_size); + break; + case 4: + dasm_put(Dst, 12, st->float_size); + break; + case 5: + dasm_put(Dst, 15, st->float_size); + break; + case 6: + dasm_put(Dst, 18, st->float_size); + break; + case 7: + dasm_put(Dst, 21, st->float_size); + break; + case 8: + dasm_put(Dst, 24, st->float_size); + break; + case 9: + dasm_put(Dst, 27, st->float_size); + break; + case 10: + dasm_put(Dst, 30, st->float_size); + break; + case 11: + dasm_put(Dst, 33, st->float_size); + break; + case 12: + dasm_put(Dst, 36, st->float_size); + break; + case 13: + dasm_put(Dst, 39, st->float_size); + break; + case 14: + dasm_put(Dst, 42, st->float_size); + break; + case 15: + dasm_put(Dst, 45, st->float_size); + break; + } + break; + case 8: + switch(reg>>1){ + case 0: + dasm_put(Dst, 48, st->float_size); + break; + case 1: + dasm_put(Dst, 51, st->float_size); + break; + case 2: + dasm_put(Dst, 54, st->float_size); + break; + case 3: + dasm_put(Dst, 57, st->float_size); + break; + case 4: + dasm_put(Dst, 60, st->float_size); + break; + case 5: + dasm_put(Dst, 63, st->float_size); + break; + case 6: + dasm_put(Dst, 66, st->float_size); + break; + case 7: + dasm_put(Dst, 69, st->float_size); + break; + } + reg+=2; + break; + } + st->float_size+=sz; + } +} + +//128 bit vector type is not supported by this +static int add_float_reg(reg_info* regs,int sz,int isfloat){ + + if(is_float_sealed(regs)) return -1; + int i,ret=-1; + if(sz==1){ + if(regs->left_single){ + int n=regs->highest_bit; + for(i=0;i<n;++i){ + if(!has_bit(regs->floats,i)){ + regs->left_single--; + set_bit(regs->floats,i); + ret=i; + } + } + }else{ + ret=regs->highest_bit; + set_bit(regs->floats,regs->highest_bit); + ++regs->highest_bit; + } + }else{ + if(regs->highest_bit>MAX_FLOAT_REGS-sz){ + regs->highest_bit=MAX_FLOAT_REGS; + }else{ + if(!isfloat&&!ALIGNED(regs->highest_bit, 2)){ + regs->highest_bit++; + regs->left_single++; + } + ret=regs->highest_bit; + for(i=0;i<sz;++i){ + set_bit(regs->floats,regs->highest_bit++); + } + } + } + if(regs->highest_bit==MAX_FLOAT_REGS){ + regs->float_sealed=true; + } + return ret; +} +#endif +static void load_reg(struct jit* Dst,int off,int size){ + if(size==16){ + dasm_put(Dst, 72, off); + }else if(size==12){ + dasm_put(Dst, 76, off); + }else if(size==8){ + dasm_put(Dst, 80, off); + }else{ + dasm_put(Dst, 84, off); + } +} +// arm store/load range for immediate value is only -256-255 +static void load_stack(struct jit* Dst,stack_info* st,int size,int align){ + int off=st->stack_off; + FIX_ALIGN(st->stack_off,align); + if((off=st->stack_off-off)){ + dasm_put(Dst, 87, off); + } + if(size==16){ + dasm_put(Dst, 90); + }else if(size==8){ + dasm_put(Dst, 92); + }else{ + dasm_put(Dst, 94); + } + st->stack_off+=size; +} + +static void load_int(struct jit* Dst,stack_info* st,int size,int align){ + FIX_ALIGN(st->int_off,align); + if(st->int_off<0x40*ARM_HF+MAX_REGS*4&&(!st->stack_off||MAX_REGS*4+size<=0x40*ARM_HF+MAX_REGS*4)){ + load_reg(Dst,st->int_off+st->extra,size); + st->int_off+=size; + }else{ + st->int_off=0x40*ARM_HF+MAX_REGS*4; + load_stack(Dst,st,size,align); + } + +} + +static void load_float(struct jit* Dst,stack_info* st,int size,int vfp,int align){ + #if ARM_HF + if(st->float_off<st->float_size){ + if(vfp){ + if(size==4){//float + dasm_put(Dst, 96, st->float_off+st->extra); + }else if(size==8){//double + dasm_put(Dst, 99, st->float_off+st->extra); + } + }else load_reg(Dst,st->float_off+st->extra,size); + st->float_off+=size; + }else if(vfp){ + if(size==4){//float + dasm_put(Dst, 102); + }else if(size==8){//double + int off=st->stack_off; + FIX_ALIGN(st->stack_off,align); + if((off=st->stack_off-off)){ + dasm_put(Dst, 105, off); + } + dasm_put(Dst, 108); + } + }else{ + load_stack(Dst,st,size,align); + } + #else + load_int(Dst,st,size,align); + #endif +} +#if ARM_HF +static void push_regs(lua_State* L,struct jit* Dst,int ct_usr,int nargs,stack_info* st){ + const struct ctype* mt; + reg_info regs;int i; + memset(®s,0,sizeof(reg_info)); + for (i = 1; i <= nargs&&!is_float_sealed(®s); ++i){ + lua_rawgeti(L, ct_usr, i); + mt = (const struct ctype*) lua_touserdata(L, -1); + if (!mt->pointers &&! mt->is_reference) { + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + save_float_reg(Dst,add_float_reg(®s,4,0),16,st); + break; + case DOUBLE_TYPE: + save_float_reg(Dst,add_float_reg(®s,2,0),8,st); + break; + case COMPLEX_FLOAT_TYPE: + save_float_reg(Dst,add_float_reg(®s,2,1),8,st); + break; + case FLOAT_TYPE: + save_float_reg(Dst,add_float_reg(®s,1,1),4,st); + break; + case STRUCT_TYPE: + { + int isfloat,hfasize=hfa_size(L,-1,mt,&isfloat); + if(hfasize){ + save_float_reg(Dst,add_float_reg(®s,hfasize,isfloat),4*hfasize,st); + break; + } + } + case UNION_TYPE: + break; + case INT64_TYPE: + //add_int64_reg(®s); + break; + default: + //add_int_reg(®s);//no need to check type support here + break; + } + } + lua_pop(L,1); + } + st->float_off+=st->int_off; + st->int_off+=0x40; +} +#endif +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; + stack_info st; + + 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"); + } + memset(&st,0,sizeof(stack_info)); + st.extra=0x10; + /* prolog and get the upval table */ + dasm_put(Dst, 111); +#if ARM_HF + dasm_put(Dst, 114); + push_regs(L,Dst,ct_usr,nargs,&st); +#endif + + dasm_put(Dst, 116, (unsigned short)(L), (((unsigned int)(L))>>16), (unsigned short)(ref), (((unsigned int)(ref))>>16), (unsigned short)(LUA_REGISTRYINDEX), (((unsigned int)(LUA_REGISTRYINDEX))>>16)); + + /* get the lua function */ + lua_pushvalue(L, fidx); + lua_rawseti(L, -2, ++num_upvals); + + + dasm_put(Dst, 134, num_upvals); + + // Complex type is return in the address stored in r0 for softfp + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + if(!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| + (!1&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(1&&hfa_size(L,-1,mt,NULL))){ + st.int_off+=4; + } + lua_pop(L,1); + + //whether 64 bit type requires 8 bytes alignment in stack is defined by compiler.android compiler reqiures only 4 byte alignment; + //actually the stack it self may reqiures 8 bytes alignment + 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, 141, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_int(Dst,&st,4,4); + dasm_put(Dst, 157); + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + #if ARM_HF + int isfloat,hfasize=0; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + #endif + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 163, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + #if ARM_HF + if(hfasize){ + if(hfasize<=4)load_float(Dst,&st,4*hfasize,0,4*(2-isfloat)); + switch(hfasize){ + case 8: + load_float(Dst,&st,16,0,8); + dasm_put(Dst, 179); + load_float(Dst,&st,16,0,8); + dasm_put(Dst, 181); + break; + case 6: + load_float(Dst,&st,16,0,8); + dasm_put(Dst, 183); + load_float(Dst,&st,8,0,8); + dasm_put(Dst, 185); + break; + case 4: + dasm_put(Dst, 187); + break; + case 3: + dasm_put(Dst, 189); + break; + case 2: + dasm_put(Dst, 191); + break; + case 1: + dasm_put(Dst, 193); + break; + } + }else + #endif + if(!mt->is_empty){ + int size=mt->base_size; + if(size<=4){ + load_int(Dst,&st,4,4); + dasm_put(Dst, 195); + }else{ + size=ROUND_UP(size,4); + if(mt->align_mask>4){//8 byte max alignment + if(st.int_off<0x40*ARM_HF+MAX_REGS*4){FIX_ALIGN(st.int_off,8);} + else {FIX_ALIGN(st.stack_off,8);} + } + + if(st.int_off<0x40*ARM_HF+MAX_REGS*4&&(!st.stack_off||st.int_off+size<=0x40*ARM_HF+MAX_REGS*4)){//to ensure consective memory for the struct + dasm_put(Dst, 197, st.int_off+st.extra); + st.int_off+=size; + }else{ + st.int_off=0x40*ARM_HF+MAX_REGS*4; + dasm_put(Dst, 200); + st.stack_off+=size; + } + dasm_put(Dst, 202, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); + } + } + dasm_put(Dst, 212); + break; + } + + case COMPLEX_DOUBLE_TYPE: + + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 217, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_float(Dst,&st,16,0,8); + dasm_put(Dst, 233); + break; + case COMPLEX_FLOAT_TYPE: + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 239, num_upvals-1, i, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_float(Dst,&st,8,0,4); + dasm_put(Dst, 255); + break; + case INT64_TYPE: + + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + + #if CK_ALGIN + FIX_ALIGN(st.int_off,8); + if(st.int_off<16){ + dasm_put(Dst, 261, st.int_off+st.extra); + st.int_off+=8; + }else{ + if(!ALIGNED(st.stack_off,8)){ + st.stack_off+=4; + dasm_put(Dst, 265); + } + dasm_put(Dst, 267); + st.stack_off+=8; + } + #else + load_int(Dst,st,8,8); + #endif + dasm_put(Dst, 269); + #else + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 273, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_int(Dst,&st,8,8); + dasm_put(Dst, 282); + #endif + break; + + case INTPTR_TYPE: + lua_rawseti(L, -2, ++num_upvals); /* mt */ + + dasm_put(Dst, 288, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + load_int(Dst,&st,4,4); + dasm_put(Dst, 297); + + break; + + case BOOL_TYPE: + lua_pop(L, 1); + + load_int(Dst,&st,4,4); + dasm_put(Dst, 303); + break; + + case INT8_TYPE: // no need to narrow cause narrowed by caller + case INT16_TYPE: // no need to narrow cause narrowed by caller + case ENUM_TYPE: + case INT32_TYPE: + lua_pop(L, 1); + + load_int(Dst,&st,4,4); + dasm_put(Dst, 307); + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + + load_float(Dst,&st,4,ARM_HF,4); + dasm_put(Dst, 311); + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + + #if ARM_HF + load_float(Dst,&st,8,ARM_HF,8); + #elif CK_ALGIN + FIX_ALIGN(st.int_off,8); + if(st.int_off<16){ + dasm_put(Dst, 315, st.int_off+st.extra); + st.int_off+=8; + }else{ + if(!ALIGNED(st.stack_off,8)){ + st.stack_off+=4; + dasm_put(Dst, 319); + } + dasm_put(Dst, 321); + st.stack_off+=8; + } + #else + load_float(Dst,&st,8,ARM_HF,8); + #endif + dasm_put(Dst, 323); + 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, 327, ((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, 335, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + goto single_no_pop; + } else { + switch (mt->type) { + case STRUCT_TYPE: + case UNION_TYPE:{ + int isfloat,hfasize=0; + if(mt->type!=UNION_TYPE){ + hfasize=hfa_size(L,-1,mt,&isfloat); + } + lua_getuservalue(L, -1); + lua_rawseti(L, -3, ++num_upvals); /* usr value */ + lua_rawseti(L, -2, ++num_upvals); /* mt */ + dasm_put(Dst, 351, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + #if ARM_HF + if(hfasize>0){ + switch(hfasize){ + case 8: + dasm_put(Dst, 372); + break; + case 6: + dasm_put(Dst, 374); + break; + case 4: + dasm_put(Dst, 376); + break; + case 3: + dasm_put(Dst, 378); + break; + case 2: + dasm_put(Dst, 380); + break; + case 1: + dasm_put(Dst, 382); + break; + } + }else + #endif + if(!mt->is_empty){ + if(mt->base_size<=4){ + dasm_put(Dst, 384); + }else{ + dasm_put(Dst, 386, st.extra+0x40*1, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); + } + } + break; + } + 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, 399, num_upvals-1, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + + goto single_no_pop; + + case VOID_TYPE: + dasm_put(Dst, 415); + lua_pop(L, 1); + break; + + case BOOL_TYPE: + case INT8_TYPE:// narrow it + case INT16_TYPE:// narrow it + case INT32_TYPE: + dasm_put(Dst, 420); + if (mt->is_unsigned) { + dasm_put(Dst, 422); + } else { + dasm_put(Dst, 426); + } + switch(mt->type){ + case BOOL_TYPE: + dasm_put(Dst, 430); + break; + case INT8_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 433); + } else { + dasm_put(Dst, 435); + } + break; + case INT16_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 437); + } else { + dasm_put(Dst, 439); + } + break; + } + goto single; + + case INT64_TYPE: + dasm_put(Dst, 441); + if (mt->is_unsigned) { + dasm_put(Dst, 443); + } else { + dasm_put(Dst, 447); + } + goto dual; + + case INTPTR_TYPE: + dasm_put(Dst, 451); + goto single; + + case FLOAT_TYPE: + dasm_put(Dst, 456); + #if ARM_HF + dasm_put(Dst, 461); + lua_pop(L, 1); + #else + goto single; + #endif + break; + case DOUBLE_TYPE: + dasm_put(Dst, 468); + #if ARM_HF + dasm_put(Dst, 473); + lua_pop(L, 1); + #else + goto dual; + #endif + break; + case COMPLEX_DOUBLE_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 480); + break; + case COMPLEX_FLOAT_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 491); + break; + + single: + lua_pop(L, 1); + single_no_pop: + dasm_put(Dst, 502); + + break; + dual: + dasm_put(Dst, 509); + + lua_pop(L, 1); + break; + + + + default: + luaL_error(L, "NYI: callback return type"); + } + } + + dasm_put(Dst, 518); + + 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; + } +} + +static ALWAYS_INLINE void save_int64_stack_align(struct jit* Dst,reg_info* regs,int align){ + if(align&&!ALIGNED(regs->exs,2)){ + regs->exs++; + dasm_put(Dst, 520); + } + dasm_put(Dst, 522); + regs->exs+=2; +} + +static ALWAYS_INLINE void save_int64_align(struct jit* Dst,reg_info* regs,int align){ + if((align&&!ALIGNED(regs->ints,2))||(regs->ints==MAX_REGS-1&®s->exs/*to ensure consective memory*/)){ + regs->ints++; + } + if(regs->ints<MAX_REGS){ + dasm_put(Dst, 524, ((regs->ints<<2)+0x40*1)); + regs->ints+=2; + }else{ + save_int64_stack_align(Dst,regs,align); + } + +} + +static ALWAYS_INLINE void save_int64(struct jit* Dst,reg_info* regs){ + save_int64_align(Dst,regs,1); +} + +static ALWAYS_INLINE void save_int_stack_align(struct jit* Dst,reg_info* regs){ + dasm_put(Dst, 528); + regs->exs++; +} + +static ALWAYS_INLINE void save_int(struct jit* Dst,reg_info* regs){ + if(regs->ints<MAX_REGS){ + dasm_put(Dst, 530, ((regs->ints++<<2)+0x40*1)); + }else{ + save_int_stack_align(Dst,regs); + } +} + +static void save_float(struct jit* Dst,reg_info* regs,int size,int isfloat){ +#if ARM_HF + if(!regs->float_sealed){ + int reg=add_float_reg(regs,size,isfloat); + if(reg<0) goto SAVE_STACK; + switch(size){ + case 8: + dasm_put(Dst, 533, (reg<<2)+24); + case 6: + dasm_put(Dst, 536, (reg<<2)+16); + case 4: + dasm_put(Dst, 539, (reg<<2)+8); + goto sf_2; + case 3: + dasm_put(Dst, 542, (reg<<2)+8); + case 2: + sf_2: + dasm_put(Dst, 545, (reg<<2)); + break; + case 1: + dasm_put(Dst, 548, (reg<<2)); + break; + } + return; + } + SAVE_STACK: + + if(!isfloat&&!ALIGNED(regs->exs,2)){ + regs->exs++; + dasm_put(Dst, 551); + } + switch(size){ + case 1: + dasm_put(Dst, 553); + break; + case 2: + dasm_put(Dst, 555); + break; + case 3: + dasm_put(Dst, 557); + break; + case 4: + dasm_put(Dst, 559); + break; + case 6: + dasm_put(Dst, 561); + break; + case 8: + dasm_put(Dst, 563); + break; + + } + regs->exs+=size; + +#else + if(size==1){ + save_int(Dst,regs); + }else if(size==2){ + save_int64_align(Dst,regs,!isfloat); + } +#endif +} + +static int calculate_stack(lua_State* L,int ct_usr,int nargs){ + const struct ctype* mt; + reg_info regs;int i,stack=0; + memset(®s,0,sizeof(reg_info)); + 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) { + stack+=add_int_reg(®s); + }else{ + switch(mt->type){ + case COMPLEX_DOUBLE_TYPE: + #if ARM_HF + stack+=add_float_reg(®s,4,0)<0?4:0; + #else + stack+=add_int64_reg(®s); + stack+=add_int64_reg(®s); + #endif + FIX_ALIGN(stack,2); + break; + case DOUBLE_TYPE: + #if ARM_HF + stack+=add_float_reg(®s,2,0)<0?2:0; + #else + stack+=add_int64_reg(®s); + #endif + FIX_ALIGN(stack,2); + break; + case COMPLEX_FLOAT_TYPE:// Though complex alignment is 4, but vfp requires a sequence of regsiters + #if ARM_HF + stack+=add_float_reg(®s,2,1)<0?2:0; + #else + stack+=add_int_reg(®s); + stack+=add_int_reg(®s); + #endif + break; + case FLOAT_TYPE: + #if ARM_HF + stack+=add_float_reg(®s,1,1)<0?1:0; + #else + stack+=add_int_reg(®s); + #endif + break; + case INT64_TYPE: + stack+=add_int64_reg(®s); + FIX_ALIGN(stack,2); + break; + case STRUCT_TYPE:{ + #if ARM_HF + int isfloat; + int hfasize=hfa_size(L,-1,mt,&isfloat); + if(hfasize>0){ + stack+=add_float_reg(®s,2,0)<0?hfasize:0; + if(!isfloat){ + FIX_ALIGN(stack,2); + } + break; + } + #endif + } + case UNION_TYPE:{ + int intsize=(mt->base_size+3)>>2; + if(mt->align_mask>4){//8-byte max alignment + if(regs.ints<MAX_REGS){ + FIX_ALIGN(regs.ints,2); + }else{ + FIX_ALIGN(stack,2); + } + } + + if(regs.ints+intsize<=MAX_REGS){ + regs.ints+=intsize; + }else{ + stack+=regs.ints+intsize-MAX_REGS; + regs.ints=MAX_REGS; + } + break; + } + default: + stack+=add_int_reg(®s);//no need to check type support here + } + } + lua_pop(L,1); + } + FIX_ALIGN(stack,2); + return (regs.ints + #if ARM_HF + /**/||regs.floats + #endif + )?0x40*ARM_HF+0x10+stack*4:0; +} + +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,ret_by_addr, stack_size; + const struct ctype* mt; + void* p; reg_info regs; + + 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); +#if defined __thumb__ //keep frame pointer + dasm_put(Dst, 565); +#else + dasm_put(Dst, 568); +#endif +#if CK_ALGIN + dasm_put(Dst, 571); +#endif + dasm_put(Dst, 573); + + /* Reserve enough stack space for all of the arguments. For hard floating point, + * leave extra 64 bytes + */ + stack_size=calculate_stack(L,ct_usr,nargs); + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + + // Complex types in softfp and structs/unions larger than 4-bytes are return in the address stored in r0 + ret_by_addr=!mt->pointers && !mt->is_reference &&(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE|| + (!ARM_HF&&(mt->type==COMPLEX_DOUBLE_TYPE||mt->type==COMPLEX_FLOAT_TYPE)))&&mt->base_size>4&&!(ARM_HF&&hfa_size(L,-1,mt,NULL)); + lua_pop(L,1); + if(ret_by_addr){ + if(stack_size==0) + stack_size=0x40*ARM_HF+0x10; + stack_size+=8; + } + if(stack_size>0){ + if(stack_size>=1<<12){ + dasm_put(Dst, 575, (unsigned short)(stack_size), (((unsigned int)(stack_size))>>16)); + }else{ + dasm_put(Dst, 581, stack_size); + } + if (ct->has_var_arg){ + dasm_put(Dst, 584, nargs, (unsigned short)("too few arguments"), (((unsigned int)("too few arguments"))>>16)); + } + dasm_put(Dst, 601, 0x40*1+0x10); + } + + memset(®s,0,sizeof(reg_info)); + + if (ret_by_addr) { + regs.ints++; + dasm_put(Dst, 604, (unsigned short)(mt), (((unsigned int)(mt))>>16), 0x40*1); + } + + + 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|| mt->type==STRUCT_TYPE || mt->type==UNION_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + + dasm_put(Dst, 615, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16), i); + + if (mt->pointers || mt->is_reference) { + dasm_put(Dst, 626); + } else if (mt->type == FUNCTION_PTR_TYPE) { + dasm_put(Dst, 630); + } else if (mt->type == ENUM_TYPE) { + dasm_put(Dst, 634); + }else if(mt->type==STRUCT_TYPE || mt->type==UNION_TYPE){ + if(mt->is_empty) continue; + dasm_put(Dst, 638); + #if ARM_HF + { + int hfasize,isfloat; + hfasize=hfa_size(L,-2,mt,&isfloat); + if(hfasize){ + switch(hfasize){ + case 8: + dasm_put(Dst, 642); + break; + case 6: + dasm_put(Dst, 644); + break; + case 4: + dasm_put(Dst, 646); + break; + case 3: + dasm_put(Dst, 648); + break; + case 2: + dasm_put(Dst, 650); + break; + case 1: + dasm_put(Dst, 652); + break; + + } + save_float(Dst,®s,hfasize,isfloat); + continue; + } + } + #endif + + if(mt->align_mask>4){//8 byte max alignment + if(regs.ints<4){ + FIX_ALIGN(regs.ints,2) + }else if(!ALIGNED(regs.exs,2)){ + int diff=regs.exs; + regs.exs+=4; + dasm_put(Dst, 654); + } + } + int size=ROUND_UP(mt->base_size,4)>>2; + dasm_put(Dst, 656, (unsigned short)(mt->base_size), (((unsigned int)(mt->base_size))>>16), (unsigned short)(memcpy), (((unsigned int)(memcpy))>>16)); + if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+size<=MAX_REGS)){//to ensure consective memory for the struct + dasm_put(Dst, 666, ((regs.ints<<2)+0x40*1)); + }else{ + regs.ints=MAX_REGS; + dasm_put(Dst, 669); + } + dasm_put(Dst, 671); + if(regs.ints+size<=MAX_REGS){ + regs.ints+=size; + }else{ + int ex=regs.ints+size-MAX_REGS; + dasm_put(Dst, 673, (ex)<<2); + regs.exs+=ex; + regs.ints=MAX_REGS; + } + continue; + } + + save_int(Dst,®s); + } else { + lua_pop(L, 1); + dasm_put(Dst, 676, i); + + switch (mt->type) { + case BOOL_TYPE: + dasm_put(Dst, 679); + save_int(Dst,®s); + break; + case INT8_TYPE: + dasm_put(Dst, 685); + if (mt->is_unsigned) { + dasm_put(Dst, 689); + } else { + dasm_put(Dst, 691); + } + save_int(Dst,®s); + break; + + case INT16_TYPE: + dasm_put(Dst, 693); + if (mt->is_unsigned) { + dasm_put(Dst, 697); + } else { + dasm_put(Dst, 699); + } + save_int(Dst,®s); + break; + + case INT32_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 701); + } else { + dasm_put(Dst, 705); + } + save_int(Dst,®s); + break; + case INTPTR_TYPE: + dasm_put(Dst, 709); + save_int(Dst,®s); + break; + + case INT64_TYPE: + if (mt->is_unsigned) { + dasm_put(Dst, 713); + } else { + dasm_put(Dst, 717); + } + save_int64(Dst,®s); + break; + + case DOUBLE_TYPE: + dasm_put(Dst, 721); + save_float(Dst,®s,2,0); + break; + + case FLOAT_TYPE: + dasm_put(Dst, 725); + save_float(Dst,®s,1,1); + break; + + case COMPLEX_DOUBLE_TYPE: + #if ARM_HF + dasm_put(Dst, 729); + save_float(Dst,®s,4,0); + #else + FIX_ALIGN(regs.ints,2); + if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+4<=MAX_REGS)){ + }else{ + regs.ints=MAX_REGS; + if(!ALIGNED(regs.exs,2)){ + ++regs.exs; + } + } + regs.ints+=4; + goto FIX_REG; + #endif + break; + case COMPLEX_FLOAT_TYPE: + #if ARM_HF + dasm_put(Dst, 733); + save_float(Dst,®s,2,1); + #else + if(regs.ints<MAX_REGS&&(!regs.exs||regs.ints+2<=MAX_REGS)){ + }else{ + regs.ints=MAX_REGS; + } + regs.ints+=2; + FIX_REG: + if(regs.ints>MAX_REGS){ + regs.exs+=regs.ints-MAX_REGS; + regs.ints=MAX_REGS; + } + #endif + break; + default: + luaL_error(L, "NYI: call arg type"); + } + } + } + + if (ct->has_var_arg) { + int offset=nargs+1; + dasm_put(Dst, 737, offset); + #if ARM_HF + if(regs.ints==4||regs.float_sealed){ + if(regs.ints<4&®s.float_sealed){//some arg must be loaded to core registers. + dasm_put(Dst, 740, ((regs.ints<<2)+0x40), (0x10+0x40), offset); + } + dasm_put(Dst, 750); + } + #else + if(regs.ints==4){ + } + #endif + else{//no hard floating point in variadic procedure + dasm_put(Dst, 752, ((regs.ints<<2)+1*0x40)); + } + + dasm_put(Dst, 755); + regs.ints=4; + } + + #if ARM_HF + switch(ROUND_UP(regs.highest_bit,4)>>1){ + case 8 : + dasm_put(Dst, 760); + break; + case 7 : + dasm_put(Dst, 762); + break; + case 6 : + dasm_put(Dst, 764); + break; + case 5: + dasm_put(Dst, 766); + break; + case 4 : + dasm_put(Dst, 768); + break; + case 3 : + dasm_put(Dst, 770); + break; + case 2 : + dasm_put(Dst, 772); + break; + case 1 : + dasm_put(Dst, 774); + break; + } + if(stack_size>0){ + dasm_put(Dst, 776); + } + #endif + + //pop registers from stack,align 8 for some compiler + assert(regs.ints<=4); + switch(regs.ints){ + case 4: + case 3: + dasm_put(Dst, 778); + break; + case 2: + case 1: + dasm_put(Dst, 780); + #if ARM_HF + if(regs.float_sealed){ + dasm_put(Dst, 782); + } + #endif + break; + default: + #if ARM_HF + if(regs.float_sealed){ + dasm_put(Dst, 784); + } + #endif + break; + } + + dasm_put(Dst, 786, (unsigned short)(func), (((unsigned int)(func))>>16)); + + lua_rawgeti(L, ct_usr, 0); + mt = (const struct ctype*) lua_touserdata(L, -1); + + if (mt->pointers || mt->is_reference || mt->type==FUNCTION_PTR_TYPE) { + lua_getuservalue(L, -1); + num_upvals += 2; + dasm_put(Dst, 792, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + + } else { + switch (mt->type) { + case INT64_TYPE: + #if LUA_VERSION_NUM>=503 + lua_pop(L, 1); + #if CK_ALGIN + dasm_put(Dst, 807); + #else + dasm_put(Dst, 810); + #endif + dasm_put(Dst, 813); + break; + #else + num_upvals++; + dasm_put(Dst, 818, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + break; + #endif + + case INTPTR_TYPE: + num_upvals++; + dasm_put(Dst, 832, (unsigned short)(mt), (((unsigned int)(mt))>>16)); + break; + + case VOID_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 844); + break; + + case BOOL_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 846); + break; + + case INT8_TYPE: + case INT16_TYPE: + case INT32_TYPE: + case ENUM_TYPE:// value must be narrowed before callee return + lua_pop(L, 1); + + dasm_put(Dst, 852); + if (mt->is_unsigned) { + dasm_put(Dst, 854); + } else { + dasm_put(Dst, 858); + } + + dasm_put(Dst, 862); + break; + + case FLOAT_TYPE: + lua_pop(L, 1); + dasm_put(Dst, 864); + break; + + case DOUBLE_TYPE: + lua_pop(L, 1); + #if CK_ALGIN + #else + #endif + dasm_put(Dst, 869); + break; + case COMPLEX_DOUBLE_TYPE: + case COMPLEX_FLOAT_TYPE: + case STRUCT_TYPE: + case UNION_TYPE:{ + lua_getuservalue(L,-1); + num_upvals += 2; + #if ARM_HF + { + int isfloat,hfasize=hfa_size(L,-2,mt,&isfloat); + if(hfasize>0){ + switch(hfasize){ + case 8: + dasm_put(Dst, 874); + break; + case 6: + dasm_put(Dst, 876); + break; + case 4: + case 3: + dasm_put(Dst, 878); + break; + case 2: + case 1: + dasm_put(Dst, 880); + break; + + } + dasm_put(Dst, 882, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + switch(hfasize){ + case 8: + dasm_put(Dst, 895); + break; + case 6: + dasm_put(Dst, 898); + break; + case 4: + dasm_put(Dst, 901); + break; + case 3: + dasm_put(Dst, 904); + break; + case 2: + dasm_put(Dst, 907); + break; + case 1: + dasm_put(Dst, 910); + break; + + } + dasm_put(Dst, 913); + break; + } + } + + #endif + if(mt->base_size>4){ + // value are stored in return storage in r0 for softfp, set usr value here + if(!lua_isnil(L,-1)){ + dasm_put(Dst, 915, (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + } + }else if(mt->is_empty){ + dasm_put(Dst, 927); + break; + }else{ + dasm_put(Dst, 929, (unsigned short)(mt), (((unsigned int)(mt))>>16), (unsigned short)(lua_upvalueindex(num_upvals)), (((unsigned int)(lua_upvalueindex(num_upvals)))>>16)); + } + dasm_put(Dst, 943); + break; + } + default: + luaL_error(L, "NYI: call return type"); + } + } + +#ifdef __thumb__ + dasm_put(Dst, 945); +#else + dasm_put(Dst, 948); +#endif + assert(lua_gettop(L) == top + num_upvals); + { + cfunction f = compile(Dst, L, NULL, 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/source/texk/web2c/luatexdir/luaffi/ctype.c b/source/texk/web2c/luatexdir/luaffi/ctype.c index 18ad5f21e..e53513eb4 100644 --- a/source/texk/web2c/luatexdir/luaffi/ctype.c +++ b/source/texk/web2c/luatexdir/luaffi/ctype.c @@ -1,315 +1,315 @@ -/* 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 <ctype.h> -#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); - } -} -void setup_ctype(lua_State* L,int ct_usr,const struct ctype* 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); - } -} -struct member_type* push_member_type(lua_State* L, int ct_usr, const struct member_type* mt) -{ - struct member_type* ret; - ct_usr = lua_absindex(L, ct_usr); - - ret = (struct member_type*) lua_newuserdata(L, sizeof(struct member_type)); - *ret = *mt; - - setup_ctype(L,ct_usr,&mt->ct); - - return ret; -} - -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; - - setup_ctype(L,ct_usr,ct); - - 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. - */ - /* Changed:To allow fast write to memory for struct in 64-bit machine in jit - */ - //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;char ch; - 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, 0); - ch=P.next[0]; - if(ch&&!isspace(ch)){ - luaL_error(L,"unexpected end of type name :%s",P.next); - } - 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); -} - -static ALWAYS_INLINE int is_cdata(lua_State* L, int idx){ - if (!lua_isuserdata(L, idx) || !lua_getmetatable(L, idx)) { - lua_pushnil(L); - return 0; - } - - if (!equals_upval(L, -1, &cdata_mt_key)) { - lua_pop(L, 1); /* mt */ - lua_pushnil(L); - return 0; - } - lua_pop(L, 1); /* mt */ - return 1; -} - -/** - * get_ctype return the type for the c_data on idx - * @param L - * @param idx - * @return - */ -const struct ctype* get_ctype(lua_State* L, int idx){ - - if(!is_cdata(L,idx)) - return NULL; - - return &((struct cdata*) lua_touserdata(L, idx))->type; - -} -/* 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(!is_cdata(L,idx)) - return NULL; - - cd = (struct cdata*) lua_touserdata(L, idx); - *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; -} - +/* 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 <ctype.h> +#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); + } +} +void setup_ctype(lua_State* L,int ct_usr,const struct ctype* 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); + } +} +struct member_type* push_member_type(lua_State* L, int ct_usr, const struct member_type* mt) +{ + struct member_type* ret; + ct_usr = lua_absindex(L, ct_usr); + + ret = (struct member_type*) lua_newuserdata(L, sizeof(struct member_type)); + *ret = *mt; + + setup_ctype(L,ct_usr,&mt->ct); + + return ret; +} + +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; + + setup_ctype(L,ct_usr,ct); + + 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. + */ + /* Changed:To allow fast write to memory for struct in 64-bit machine in jit + */ + //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;char ch; + 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, 0); + ch=P.next[0]; + if(ch&&!isspace(ch)){ + luaL_error(L,"unexpected end of type name :%s",P.next); + } + 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); +} + +static ALWAYS_INLINE int is_cdata(lua_State* L, int idx){ + if (!lua_isuserdata(L, idx) || !lua_getmetatable(L, idx)) { + lua_pushnil(L); + return 0; + } + + if (!equals_upval(L, -1, &cdata_mt_key)) { + lua_pop(L, 1); /* mt */ + lua_pushnil(L); + return 0; + } + lua_pop(L, 1); /* mt */ + return 1; +} + +/** + * get_ctype return the type for the c_data on idx + * @param L + * @param idx + * @return + */ +const struct ctype* get_ctype(lua_State* L, int idx){ + + if(!is_cdata(L,idx)) + return NULL; + + return &((struct cdata*) lua_touserdata(L, idx))->type; + +} +/* 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(!is_cdata(L,idx)) + return NULL; + + cd = (struct cdata*) lua_touserdata(L, idx); + *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/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.c b/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.c index 405c12a0c..6ee97b827 100644 --- a/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.c +++ b/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.c @@ -1,165 +1,165 @@ - - -#include "fake_dlfcn.h" - -#include <stdio.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <elf.h> -#include <android/log.h> - -#define TAG_NAME "Osl_DL" -#ifdef NDEBUG -#define log_info(fmt,args...) -#define log_err(fmt,args...) -#else -#define log_info(fmt,args...) __android_log_print(ANDROID_LOG_INFO, TAG_NAME, (const char *) fmt, ##args) -#define log_err(fmt,args...) __android_log_print(ANDROID_LOG_ERROR, TAG_NAME, (const char *) fmt, ##args) -#endif -//#ifdef LOG_DBG -#define log_dbg log_info -//#else -//#define log_dbg(...) -//#endif - -#ifdef __LP64__ -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#else -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#endif - -struct ctx { - void *load_addr; - void *dynstr; - void *dynsym; - int nsyms; - off_t bias; -}; - -//extern "C" { -void fake_dlclose(void *handle) { - if (handle) { - struct ctx *ctx = (struct ctx *) handle; - if (ctx->dynsym) free(ctx->dynsym); /* we're saving dynsym and dynstr */ - if (ctx->dynstr) free(ctx->dynstr); /* from library file just in case */ - free(ctx); - } -} - -/* flags are ignored */ - -void *fake_dlopen(const char *libpath, int flags) { - FILE *maps; - char buff[256]; - struct ctx *ctx = 0; - off_t load_addr, size; - int k, fd = -1, found = 0; - void *shoff; - Elf_Ehdr *elf = (Elf_Ehdr *) MAP_FAILED; - -#define fatal(fmt, args...) do { log_err(fmt,##args); goto err_exit; } while(0) - - maps = fopen("/proc/self/maps", "r"); - if (!maps) fatal("failed to open maps"); - - while (!found && fgets(buff, sizeof(buff), maps)) - if (strstr(buff, "r-xp") && strstr(buff, libpath)) found = 1; - - fclose(maps); - - if (!found) fatal("%s not found in my userspace", libpath); - - if (sscanf(buff, "%lx", &load_addr) != 1) - fatal("failed to read load address for %s", libpath); - - log_info("%s loaded in Android at 0x%08lx", libpath, load_addr); - - /* Now, mmap the same library once again */ - - fd = open(libpath, O_RDONLY); - if (fd < 0) fatal("failed to open %s", libpath); - - size = lseek(fd, 0, SEEK_END); - if (size <= 0) fatal("lseek() failed for %s", libpath); - - elf = (Elf_Ehdr *) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - fd = -1; - - if (elf == MAP_FAILED) fatal("mmap() failed for %s", libpath); - - ctx = (struct ctx *) calloc(1, sizeof(struct ctx)); - if (!ctx) fatal("no memory for %s", libpath); - - ctx->load_addr = (void *) load_addr; - shoff = ((void *) elf) + elf->e_shoff; - for (k = 0; k < elf->e_shnum; k++, shoff += elf->e_shentsize) { - - Elf_Shdr *sh = (Elf_Shdr *) shoff; - //log_dbg("%s: k=%d shdr=%p type=%x", __func__, k, sh, sh->sh_type); - - switch (sh->sh_type) { - - case SHT_DYNSYM: - if (ctx->dynsym) fatal("%s: duplicate DYNSYM sections", libpath); /* .dynsym */ - ctx->dynsym = malloc(sh->sh_size); - if (!ctx->dynsym) fatal("%s: no memory for .dynsym", libpath); - memcpy(ctx->dynsym, ((void *) elf) + sh->sh_offset, sh->sh_size); - ctx->nsyms = (sh->sh_size / sizeof(Elf_Sym)); - break; - - case SHT_STRTAB: - if (ctx->dynstr) break; /* .dynstr is guaranteed to be the first STRTAB */ - ctx->dynstr = malloc(sh->sh_size); - if (!ctx->dynstr) fatal("%s: no memory for .dynstr", libpath); - memcpy(ctx->dynstr, ((void *) elf) + sh->sh_offset, sh->sh_size); - break; - - case SHT_PROGBITS: - if (!ctx->dynstr || !ctx->dynsym) break; - /* won't even bother checking against the section name */ - ctx->bias = (off_t) sh->sh_addr - (off_t) sh->sh_offset; - k = elf->e_shnum; /* exit for */ - break; - } - } - - munmap(elf, size); - elf = 0; - - if (!ctx->dynstr || !ctx->dynsym) fatal("dynamic sections not found in %s", libpath); - -#undef fatal - - log_dbg("%s: ok, dynsym = %p, dynstr = %p", libpath, ctx->dynsym, ctx->dynstr); - - return ctx; - - err_exit: - if (fd >= 0) close(fd); - if (elf != MAP_FAILED) munmap(elf, size); - fake_dlclose(ctx); - return 0; -} - -void *fake_dlsym(void *handle, const char *name) { - int k; - struct ctx *ctx = (struct ctx *) handle; - Elf_Sym *sym = (Elf_Sym *) ctx->dynsym; - char *strings = (char *) ctx->dynstr; - - for (k = 0; k < ctx->nsyms; k++, sym++) - if (strcmp(strings + sym->st_name, name) == 0) { - /* NB: sym->st_value is an offset into the section for relocatables, - but a VMA for shared libs or exe files, so we have to subtract the bias */ - void *ret = ctx->load_addr + sym->st_value - ctx->bias; - log_info("%s found at %p", name, ret); - return ret; - } - return 0; -} + + +#include "fake_dlfcn.h" + +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <elf.h> +#include <android/log.h> + +#define TAG_NAME "Osl_DL" +#ifdef NDEBUG +#define log_info(fmt,args...) +#define log_err(fmt,args...) +#else +#define log_info(fmt,args...) __android_log_print(ANDROID_LOG_INFO, TAG_NAME, (const char *) fmt, ##args) +#define log_err(fmt,args...) __android_log_print(ANDROID_LOG_ERROR, TAG_NAME, (const char *) fmt, ##args) +#endif +//#ifdef LOG_DBG +#define log_dbg log_info +//#else +//#define log_dbg(...) +//#endif + +#ifdef __LP64__ +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#else +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#endif + +struct ctx { + void *load_addr; + void *dynstr; + void *dynsym; + int nsyms; + off_t bias; +}; + +//extern "C" { +void fake_dlclose(void *handle) { + if (handle) { + struct ctx *ctx = (struct ctx *) handle; + if (ctx->dynsym) free(ctx->dynsym); /* we're saving dynsym and dynstr */ + if (ctx->dynstr) free(ctx->dynstr); /* from library file just in case */ + free(ctx); + } +} + +/* flags are ignored */ + +void *fake_dlopen(const char *libpath, int flags) { + FILE *maps; + char buff[256]; + struct ctx *ctx = 0; + off_t load_addr, size; + int k, fd = -1, found = 0; + void *shoff; + Elf_Ehdr *elf = (Elf_Ehdr *) MAP_FAILED; + +#define fatal(fmt, args...) do { log_err(fmt,##args); goto err_exit; } while(0) + + maps = fopen("/proc/self/maps", "r"); + if (!maps) fatal("failed to open maps"); + + while (!found && fgets(buff, sizeof(buff), maps)) + if (strstr(buff, "r-xp") && strstr(buff, libpath)) found = 1; + + fclose(maps); + + if (!found) fatal("%s not found in my userspace", libpath); + + if (sscanf(buff, "%lx", &load_addr) != 1) + fatal("failed to read load address for %s", libpath); + + log_info("%s loaded in Android at 0x%08lx", libpath, load_addr); + + /* Now, mmap the same library once again */ + + fd = open(libpath, O_RDONLY); + if (fd < 0) fatal("failed to open %s", libpath); + + size = lseek(fd, 0, SEEK_END); + if (size <= 0) fatal("lseek() failed for %s", libpath); + + elf = (Elf_Ehdr *) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + fd = -1; + + if (elf == MAP_FAILED) fatal("mmap() failed for %s", libpath); + + ctx = (struct ctx *) calloc(1, sizeof(struct ctx)); + if (!ctx) fatal("no memory for %s", libpath); + + ctx->load_addr = (void *) load_addr; + shoff = ((void *) elf) + elf->e_shoff; + for (k = 0; k < elf->e_shnum; k++, shoff += elf->e_shentsize) { + + Elf_Shdr *sh = (Elf_Shdr *) shoff; + //log_dbg("%s: k=%d shdr=%p type=%x", __func__, k, sh, sh->sh_type); + + switch (sh->sh_type) { + + case SHT_DYNSYM: + if (ctx->dynsym) fatal("%s: duplicate DYNSYM sections", libpath); /* .dynsym */ + ctx->dynsym = malloc(sh->sh_size); + if (!ctx->dynsym) fatal("%s: no memory for .dynsym", libpath); + memcpy(ctx->dynsym, ((void *) elf) + sh->sh_offset, sh->sh_size); + ctx->nsyms = (sh->sh_size / sizeof(Elf_Sym)); + break; + + case SHT_STRTAB: + if (ctx->dynstr) break; /* .dynstr is guaranteed to be the first STRTAB */ + ctx->dynstr = malloc(sh->sh_size); + if (!ctx->dynstr) fatal("%s: no memory for .dynstr", libpath); + memcpy(ctx->dynstr, ((void *) elf) + sh->sh_offset, sh->sh_size); + break; + + case SHT_PROGBITS: + if (!ctx->dynstr || !ctx->dynsym) break; + /* won't even bother checking against the section name */ + ctx->bias = (off_t) sh->sh_addr - (off_t) sh->sh_offset; + k = elf->e_shnum; /* exit for */ + break; + } + } + + munmap(elf, size); + elf = 0; + + if (!ctx->dynstr || !ctx->dynsym) fatal("dynamic sections not found in %s", libpath); + +#undef fatal + + log_dbg("%s: ok, dynsym = %p, dynstr = %p", libpath, ctx->dynsym, ctx->dynstr); + + return ctx; + + err_exit: + if (fd >= 0) close(fd); + if (elf != MAP_FAILED) munmap(elf, size); + fake_dlclose(ctx); + return 0; +} + +void *fake_dlsym(void *handle, const char *name) { + int k; + struct ctx *ctx = (struct ctx *) handle; + Elf_Sym *sym = (Elf_Sym *) ctx->dynsym; + char *strings = (char *) ctx->dynstr; + + for (k = 0; k < ctx->nsyms; k++, sym++) + if (strcmp(strings + sym->st_name, name) == 0) { + /* NB: sym->st_value is an offset into the section for relocatables, + but a VMA for shared libs or exe files, so we have to subtract the bias */ + void *ret = ctx->load_addr + sym->st_value - ctx->bias; + log_info("%s found at %p", name, ret); + return ret; + } + return 0; +} //} \ No newline at end of file diff --git a/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.h b/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.h index b8fb6e36b..f2eae6c95 100644 --- a/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.h +++ b/source/texk/web2c/luatexdir/luaffi/fake_dlfcn.h @@ -1,20 +1,20 @@ - - -#ifndef HOOKMANAGER_FAKE_DLFCN_H -#define HOOKMANAGER_FAKE_DLFCN_H - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <jni.h> - -#ifdef __cplusplus -extern "C" { -#endif -__attribute__ ((visibility ("default"))) void *fake_dlopen(const char *libpath, int flags); -__attribute__ ((visibility ("default"))) void fake_dlclose(void* handle); -__attribute__ ((visibility ("default"))) void *fake_dlsym(void *handle, const char *name); -#ifdef __cplusplus -}; -#endif -#endif //HOOKMANAGER_FAKE_DLFCN_H + + +#ifndef HOOKMANAGER_FAKE_DLFCN_H +#define HOOKMANAGER_FAKE_DLFCN_H + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <jni.h> + +#ifdef __cplusplus +extern "C" { +#endif +__attribute__ ((visibility ("default"))) void *fake_dlopen(const char *libpath, int flags); +__attribute__ ((visibility ("default"))) void fake_dlclose(void* handle); +__attribute__ ((visibility ("default"))) void *fake_dlsym(void *handle, const char *name); +#ifdef __cplusplus +}; +#endif +#endif //HOOKMANAGER_FAKE_DLFCN_H diff --git a/source/texk/web2c/luatexdir/luatex_svnversion.h b/source/texk/web2c/luatexdir/luatex_svnversion.h index e79a15c30..deef2e2d6 100644 --- a/source/texk/web2c/luatexdir/luatex_svnversion.h +++ b/source/texk/web2c/luatexdir/luatex_svnversion.h @@ -1,4 +1,4 @@ #ifndef luatex_svn_revision_h #define luatex_svn_revision_h -#define luatex_svn_revision 7636 +#define luatex_svn_revision 7637 #endif -- GitLab