mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-02-16 10:40:46 +00:00
Lot of work and added MS Detours
This commit is contained in:
2
.github/workflows/cmake-windows.yml
vendored
2
.github/workflows/cmake-windows.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: lukka/run-vcpkg@v7
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgArguments: 'zlib discord-rpc rapidjson openssl'
|
||||
vcpkgArguments: 'zlib discord-rpc rapidjson openssl detours'
|
||||
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
|
||||
vcpkgGitCommitId: '75522bb1f2e7d863078bcd06322348f053a9e33f'
|
||||
vcpkgTriplet: 'x64-windows-static'
|
||||
|
||||
2
.github/workflows/release-build.yml
vendored
2
.github/workflows/release-build.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
uses: lukka/run-vcpkg@main
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgArguments: 'zlib discord-rpc rapidjson openssl'
|
||||
vcpkgArguments: 'zlib discord-rpc rapidjson openssl detours'
|
||||
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
|
||||
vcpkgGitCommitId: '75522bb1f2e7d863078bcd06322348f053a9e33f'
|
||||
vcpkgTriplet: 'x64-windows-static'
|
||||
|
||||
@@ -32,23 +32,25 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
add_executable(${PROJECT_NAME}
|
||||
src/main.cpp include/easyloggingpp/src/easylogging++.cc
|
||||
src/Launcher.cpp include/Launcher.h
|
||||
src/Memory/Memory.cpp include/Memory/Memory.h include/Memory/Patterns.h
|
||||
src/Memory/Detours.cpp include/Memory/Detours.h
|
||||
src/Memory/BeamNG.cpp include/Memory/BeamNG.h
|
||||
src/Logger.cpp include/Logger.h
|
||||
src/gui/Gui.cpp include/Json.h
|
||||
src/gui/gifs.cpp src/gui/gifs.h
|
||||
src/Network/Http.cpp include/Http.h
|
||||
src/Network/Login.cpp src/Network/Update.cpp
|
||||
src/Discord.cpp src/Config.cpp
|
||||
src/BeamNG.cpp include/BeamNG.h
|
||||
)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${VcpkgRoot}/lib/discord-rpc.lib
|
||||
ZLIB::ZLIB discord-rpc OpenSSL::SSL OpenSSL::Crypto ws2_32 wx::net wx::core wx::base Dbghelp comsuppw)
|
||||
ZLIB::ZLIB discord-rpc OpenSSL::SSL OpenSSL::Crypto ws2_32 wx::net wx::core wx::base Dbghelp comsuppw detours)
|
||||
else(WIN32) #MINGW
|
||||
add_definitions("-D_WIN32_WINNT=0x0600")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -s --static")
|
||||
target_link_libraries(${PROJECT_NAME} discord-rpc ssl crypto ws2_32 ssp crypt32 z Dbghelp comsuppw)
|
||||
target_link_libraries(${PROJECT_NAME} discord-rpc ssl crypto ws2_32 ssp crypt32 z Dbghelp comsuppw detours)
|
||||
endif(WIN32)
|
||||
add_definitions(-DELPP_NO_DEFAULT_LOG_FILE)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE "include")
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 6/17/21
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
class BeamNG {
|
||||
public:
|
||||
static size_t GetModuleBase(const char* Name);
|
||||
static uint32_t GetProcessID();
|
||||
};
|
||||
static void EntryPoint();
|
||||
};
|
||||
17
include/Memory/Detours.h
Normal file
17
include/Memory/Detours.h
Normal file
@@ -0,0 +1,17 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#pragma once
|
||||
class Detours{
|
||||
void* targetPtr;
|
||||
void* detourFunc;
|
||||
public:
|
||||
Detours(void* src, void* dest) : targetPtr(src), detourFunc(dest){};
|
||||
void Attach();
|
||||
void Detach();
|
||||
|
||||
private:
|
||||
bool Attached = false;
|
||||
};
|
||||
18
include/Memory/Memory.h
Normal file
18
include/Memory/Memory.h
Normal file
@@ -0,0 +1,18 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
class Memory{
|
||||
public:
|
||||
static uint64_t FindByPattern(const char* module, const char* Pattern, const char* Mask);
|
||||
static uint64_t GetModuleBase(const char* Name);
|
||||
static void Print(const std::string& msg);
|
||||
static void Inject(uint32_t PID);
|
||||
static uint32_t GetBeamNGPID();
|
||||
static uint32_t EntryPoint();
|
||||
static uint32_t GetPID();
|
||||
};
|
||||
28
include/Memory/Patterns.h
Normal file
28
include/Memory/Patterns.h
Normal file
@@ -0,0 +1,28 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#pragma once
|
||||
namespace Patterns {
|
||||
const char* GetTickCount[2] {
|
||||
"\x48\xff\x25\x00\x00\x00\x00\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x48\x83\xec\x00\x48\x8d\x4c\x24",
|
||||
"xxx????xxxxxxxxxxxx?xxxx"
|
||||
};
|
||||
const char* open_jit[2] {
|
||||
"\x48\x89\x5c\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xec\x00\x48\x8b\x05\x00\x00\x00\x00\x48\x33\xc4\x48\x89\x44\x24\x00\x48\x8b\x71\x00\x48\x8d\x54\x24",
|
||||
"xxxx?xxxx?xxxx?xxx????xxxxxxx?xxx?xxxx"
|
||||
};
|
||||
const char* get_field[2] {
|
||||
"\x48\x89\x5c\x24\x00\x57\x48\x83\xec\x00\x4d\x8b\xd0\x48\x8b\xd9\xe8\x00\x00\x00\x00\x48\x8b\xf8\x49\xc7\xc0\x00\x00\x00\x00\x90\x49\xff\xc0\x43\x80\x3c\x02\x00\x75\x00\x49\x8b\xd2\x48\x8b\xcb\xe8\x00\x00\x00\x00\x48\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x4c\x8d\x44\x24\x00\x48\x0b\xc1\x48\x8b\xd7\x48\x8b\xcb\x48\x89\x44\x24\x00\xe8\x00\x00\x00\x00\x48\x85\xc0",
|
||||
"xxxx?xxxx?xxxxxxx????xxxxxx????xxxxxxxx?x?xxxxxxx????xx????????xxxx?xxxxxxxxxxxxx?x????xxx"
|
||||
};
|
||||
const char* push_fstring[2] {
|
||||
"\x48\x89\x54\x24\x00\x4c\x89\x44\x24\x00\x4c\x89\x4c\x24\x00\x53\x48\x83\xec\x00\x4c\x8b\x41",
|
||||
"xxxx?xxxx?xxxx?xxxx?xxx"
|
||||
};
|
||||
const char* p_call[2] {
|
||||
"\x48\x89\x5c\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xec\x00\x48\x8b\x59\x00\x41\x8b\xf0\x4c\x63\xda",
|
||||
"xxxx?xxxx?xxxx?xxx?xxxxxx"
|
||||
};
|
||||
}
|
||||
161
include/lua/lauxlib.h
Normal file
161
include/lua/lauxlib.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l);
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
||||
lua_Integer def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
||||
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
|
||||
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
|
||||
const char *fname, int szhint);
|
||||
|
||||
/* From Lua 5.2. */
|
||||
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int luaL_execresult(lua_State *L, int stat);
|
||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||
int level);
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define luaL_argcheck(L, cond,numarg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
/* From Lua 5.2. */
|
||||
#define luaL_newlibtable(L, l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *p; /* current position in buffer */
|
||||
int lvl; /* number of strings in the stack (level) */
|
||||
lua_State *L;
|
||||
char buffer[LUAL_BUFFERSIZE];
|
||||
} luaL_Buffer;
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
|
||||
(*(B)->p++ = (char)(c)))
|
||||
|
||||
/* compatibility only */
|
||||
#define luaL_putchar(B,c) luaL_addchar(B,c)
|
||||
|
||||
#define luaL_addsize(B,n) ((B)->p += (n))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
||||
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
#endif
|
||||
17
include/lua/lj_alloc.h
Normal file
17
include/lua/lj_alloc.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
** Bundled memory allocator.
|
||||
** Donated to the public domain.
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ALLOC_H
|
||||
#define _LJ_ALLOC_H
|
||||
|
||||
#include "lj_def.h"
|
||||
|
||||
#ifndef LUAJIT_USE_SYSMALLOC
|
||||
LJ_FUNC void *lj_alloc_create(void);
|
||||
LJ_FUNC void lj_alloc_destroy(void *msp);
|
||||
LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
567
include/lua/lj_arch.h
Normal file
567
include/lua/lj_arch.h
Normal file
@@ -0,0 +1,567 @@
|
||||
/*
|
||||
** Target architecture selection.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ARCH_H
|
||||
#define _LJ_ARCH_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
/* Target endianess. */
|
||||
#define LUAJIT_LE 0
|
||||
#define LUAJIT_BE 1
|
||||
|
||||
/* Target architectures. */
|
||||
#define LUAJIT_ARCH_X86 1
|
||||
#define LUAJIT_ARCH_x86 1
|
||||
#define LUAJIT_ARCH_X64 2
|
||||
#define LUAJIT_ARCH_x64 2
|
||||
#define LUAJIT_ARCH_ARM 3
|
||||
#define LUAJIT_ARCH_arm 3
|
||||
#define LUAJIT_ARCH_ARM64 4
|
||||
#define LUAJIT_ARCH_arm64 4
|
||||
#define LUAJIT_ARCH_PPC 5
|
||||
#define LUAJIT_ARCH_ppc 5
|
||||
#define LUAJIT_ARCH_MIPS 6
|
||||
#define LUAJIT_ARCH_mips 6
|
||||
#define LUAJIT_ARCH_MIPS32 6
|
||||
#define LUAJIT_ARCH_mips32 6
|
||||
#define LUAJIT_ARCH_MIPS64 7
|
||||
#define LUAJIT_ARCH_mips64 7
|
||||
|
||||
/* Target OS. */
|
||||
#define LUAJIT_OS_OTHER 0
|
||||
#define LUAJIT_OS_WINDOWS 1
|
||||
#define LUAJIT_OS_LINUX 2
|
||||
#define LUAJIT_OS_OSX 3
|
||||
#define LUAJIT_OS_BSD 4
|
||||
#define LUAJIT_OS_POSIX 5
|
||||
|
||||
/* Select native target if no target defined. */
|
||||
#ifndef LUAJIT_TARGET
|
||||
|
||||
#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_X86
|
||||
#elif defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_X64
|
||||
#elif defined(__arm__) || defined(__arm) || defined(__ARM__) || defined(__ARM)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_ARM
|
||||
#elif defined(__aarch64__)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_ARM64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__PPC__) || defined(__PPC) || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__POWERPC) || defined(_M_PPC)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_PPC
|
||||
#elif defined(__mips64__) || defined(__mips64) || defined(__MIPS64__) || defined(__MIPS64)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS64
|
||||
#elif defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(__MIPS)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS32
|
||||
#else
|
||||
#error "No support for this architecture (yet)"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Select native OS if no target OS defined. */
|
||||
#ifndef LUAJIT_OS
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX_VER)
|
||||
#define LUAJIT_OS LUAJIT_OS_WINDOWS
|
||||
#elif defined(__linux__)
|
||||
#define LUAJIT_OS LUAJIT_OS_LINUX
|
||||
#elif defined(__MACH__) && defined(__APPLE__)
|
||||
#define LUAJIT_OS LUAJIT_OS_OSX
|
||||
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__)) && !defined(__ORBIS__)
|
||||
#define LUAJIT_OS LUAJIT_OS_BSD
|
||||
#elif (defined(__sun__) && defined(__svr4__)) || defined(__HAIKU__)
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#elif defined(__CYGWIN__)
|
||||
#define LJ_TARGET_CYGWIN 1
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#else
|
||||
#define LUAJIT_OS LUAJIT_OS_OTHER
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Set target OS properties. */
|
||||
#if LUAJIT_OS == LUAJIT_OS_WINDOWS
|
||||
#define LJ_OS_NAME "Windows"
|
||||
#elif LUAJIT_OS == LUAJIT_OS_LINUX
|
||||
#define LJ_OS_NAME "Linux"
|
||||
#elif LUAJIT_OS == LUAJIT_OS_OSX
|
||||
#define LJ_OS_NAME "OSX"
|
||||
#elif LUAJIT_OS == LUAJIT_OS_BSD
|
||||
#define LJ_OS_NAME "BSD"
|
||||
#elif LUAJIT_OS == LUAJIT_OS_POSIX
|
||||
#define LJ_OS_NAME "POSIX"
|
||||
#else
|
||||
#define LJ_OS_NAME "Other"
|
||||
#endif
|
||||
|
||||
#define LJ_TARGET_WINDOWS (LUAJIT_OS == LUAJIT_OS_WINDOWS)
|
||||
#define LJ_TARGET_LINUX (LUAJIT_OS == LUAJIT_OS_LINUX)
|
||||
#define LJ_TARGET_OSX (LUAJIT_OS == LUAJIT_OS_OSX)
|
||||
#define LJ_TARGET_IOS (LJ_TARGET_OSX && (LUAJIT_TARGET == LUAJIT_ARCH_ARM || LUAJIT_TARGET == LUAJIT_ARCH_ARM64))
|
||||
#define LJ_TARGET_POSIX (LUAJIT_OS > LUAJIT_OS_WINDOWS)
|
||||
#define LJ_TARGET_DLOPEN LJ_TARGET_POSIX
|
||||
|
||||
#ifdef __CELLOS_LV2__
|
||||
#define LJ_TARGET_PS3 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#ifdef __ORBIS__
|
||||
#define LJ_TARGET_PS4 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
#undef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#ifdef __psp2__
|
||||
#define LJ_TARGET_PSVITA 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#if _XBOX_VER >= 200
|
||||
#define LJ_TARGET_XBOX360 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#ifdef _DURANGO
|
||||
#define LJ_TARGET_XBOXONE 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
|
||||
#define LJ_NUMMODE_SINGLE 0 /* Single-number mode only. */
|
||||
#define LJ_NUMMODE_SINGLE_DUAL 1 /* Default to single-number mode. */
|
||||
#define LJ_NUMMODE_DUAL 2 /* Dual-number mode only. */
|
||||
#define LJ_NUMMODE_DUAL_SINGLE 3 /* Default to dual-number mode. */
|
||||
|
||||
/* Set target architecture properties. */
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_X86
|
||||
|
||||
#define LJ_ARCH_NAME "x86"
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
||||
#define LJ_ABI_WIN 1
|
||||
#else
|
||||
#define LJ_ABI_WIN 0
|
||||
#endif
|
||||
#define LJ_TARGET_X86 1
|
||||
#define LJ_TARGET_X86ORX64 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNALIGNED 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_X64
|
||||
|
||||
#define LJ_ARCH_NAME "x64"
|
||||
#define LJ_ARCH_BITS 64
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
||||
#define LJ_ABI_WIN 1
|
||||
#else
|
||||
#define LJ_ABI_WIN 0
|
||||
#endif
|
||||
#define LJ_TARGET_X64 1
|
||||
#define LJ_TARGET_X86ORX64 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
#define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNALIGNED 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
|
||||
#ifdef LUAJIT_ENABLE_GC64
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM
|
||||
|
||||
#define LJ_ARCH_NAME "arm"
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#if !defined(LJ_ARCH_HASFPU) && __SOFTFP__
|
||||
#define LJ_ARCH_HASFPU 0
|
||||
#endif
|
||||
#if !defined(LJ_ABI_SOFTFP) && !__ARM_PCS_VFP
|
||||
#define LJ_ABI_SOFTFP 1
|
||||
#endif
|
||||
#define LJ_ABI_EABI 1
|
||||
#define LJ_TARGET_ARM 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
||||
#define LJ_TARGET_MASKSHIFT 0
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#if __ARM_ARCH____ARM_ARCH_8__ || __ARM_ARCH_8A__
|
||||
#define LJ_ARCH_VERSION 80
|
||||
#elif __ARM_ARCH_7__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH_7S__ || __ARM_ARCH_7VE__
|
||||
#define LJ_ARCH_VERSION 70
|
||||
#elif __ARM_ARCH_6T2__
|
||||
#define LJ_ARCH_VERSION 61
|
||||
#elif __ARM_ARCH_6__ || __ARM_ARCH_6J__ || __ARM_ARCH_6K__ || __ARM_ARCH_6Z__ || __ARM_ARCH_6ZK__
|
||||
#define LJ_ARCH_VERSION 60
|
||||
#else
|
||||
#define LJ_ARCH_VERSION 50
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
|
||||
|
||||
#define LJ_ARCH_BITS 64
|
||||
#if defined(__AARCH64EB__)
|
||||
#define LJ_ARCH_NAME "arm64be"
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#else
|
||||
#define LJ_ARCH_NAME "arm64"
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#endif
|
||||
#define LJ_TARGET_ARM64 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
#define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_TARGET_GC64 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#define LJ_ARCH_VERSION 80
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_PPC
|
||||
|
||||
#ifndef LJ_ARCH_ENDIAN
|
||||
#if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#else
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _LP64
|
||||
#define LJ_ARCH_BITS 64
|
||||
#if LJ_ARCH_ENDIAN == LUAJIT_LE
|
||||
#define LJ_ARCH_NAME "ppc64le"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "ppc64"
|
||||
#endif
|
||||
#else
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_NAME "ppc"
|
||||
#endif
|
||||
|
||||
#define LJ_TARGET_PPC 1
|
||||
#define LJ_TARGET_EHRETREG 3
|
||||
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
||||
#define LJ_TARGET_MASKSHIFT 0
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 1 /* Want only IR_BROL. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE
|
||||
|
||||
#if LJ_TARGET_CONSOLE
|
||||
#define LJ_ARCH_PPC32ON64 1
|
||||
#define LJ_ARCH_NOFFI 1
|
||||
#elif LJ_ARCH_BITS == 64
|
||||
#define LJ_ARCH_PPC64 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
||||
#endif
|
||||
|
||||
#if _ARCH_PWR7
|
||||
#define LJ_ARCH_VERSION 70
|
||||
#elif _ARCH_PWR6
|
||||
#define LJ_ARCH_VERSION 60
|
||||
#elif _ARCH_PWR5X
|
||||
#define LJ_ARCH_VERSION 51
|
||||
#elif _ARCH_PWR5
|
||||
#define LJ_ARCH_VERSION 50
|
||||
#elif _ARCH_PWR4
|
||||
#define LJ_ARCH_VERSION 40
|
||||
#else
|
||||
#define LJ_ARCH_VERSION 0
|
||||
#endif
|
||||
#if _ARCH_PPCSQ
|
||||
#define LJ_ARCH_SQRT 1
|
||||
#endif
|
||||
#if _ARCH_PWR5X
|
||||
#define LJ_ARCH_ROUND 1
|
||||
#endif
|
||||
#if __PPU__
|
||||
#define LJ_ARCH_CELL 1
|
||||
#endif
|
||||
#if LJ_TARGET_XBOX360
|
||||
#define LJ_ARCH_XENON 1
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS32 || LUAJIT_TARGET == LUAJIT_ARCH_MIPS64
|
||||
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_NAME "mipsel"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips64el"
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#else
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_NAME "mips"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips64"
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ARCH_HASFPU)
|
||||
#ifdef __mips_soft_float
|
||||
#define LJ_ARCH_HASFPU 0
|
||||
#else
|
||||
#define LJ_ARCH_HASFPU 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ABI_SOFTFP)
|
||||
#ifdef __mips_soft_float
|
||||
#define LJ_ABI_SOFTFP 1
|
||||
#else
|
||||
#define LJ_ABI_SOFTFP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_TARGET_MIPS32 1
|
||||
#else
|
||||
#if LJ_ABI_SOFTFP || !LJ_ARCH_HASFPU
|
||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
||||
#endif
|
||||
#define LJ_ARCH_BITS 64
|
||||
#define LJ_TARGET_MIPS64 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
#define LJ_TARGET_MIPS 1
|
||||
#define LJ_TARGET_EHRETREG 4
|
||||
#define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#if _MIPS_ARCH_MIPS32R2 || _MIPS_ARCH_MIPS64R2
|
||||
#define LJ_ARCH_VERSION 20
|
||||
#else
|
||||
#define LJ_ARCH_VERSION 10
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error "No target architecture defined"
|
||||
#endif
|
||||
|
||||
#ifndef LJ_PAGESIZE
|
||||
#define LJ_PAGESIZE 4096
|
||||
#endif
|
||||
|
||||
/* Check for minimum required compiler versions. */
|
||||
#if defined(__GNUC__)
|
||||
#if LJ_TARGET_X86
|
||||
#if (__GNUC__ < 3) || ((__GNUC__ == 3) && __GNUC_MINOR__ < 4)
|
||||
#error "Need at least GCC 3.4 or newer"
|
||||
#endif
|
||||
#elif LJ_TARGET_X64
|
||||
#if __GNUC__ < 4
|
||||
#error "Need at least GCC 4.0 or newer"
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM
|
||||
#if (__GNUC__ < 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ < 2)
|
||||
#error "Need at least GCC 4.2 or newer"
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM64
|
||||
#if __clang__
|
||||
#if ((__clang_major__ < 3) || ((__clang_major__ == 3) && __clang_minor__ < 5)) && !defined(__NX_TOOLCHAIN_MAJOR__)
|
||||
#error "Need at least Clang 3.5 or newer"
|
||||
#endif
|
||||
#else
|
||||
#if (__GNUC__ < 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ < 8)
|
||||
#error "Need at least GCC 4.8 or newer"
|
||||
#endif
|
||||
#endif
|
||||
#elif !LJ_TARGET_PS3
|
||||
#if (__GNUC__ < 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ < 3)
|
||||
#error "Need at least GCC 4.3 or newer"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Check target-specific constraints. */
|
||||
#ifndef _BUILDVM_H
|
||||
#if LJ_TARGET_X64
|
||||
#if __USING_SJLJ_EXCEPTIONS__
|
||||
#error "Need a C compiler with native exception handling on x64"
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM
|
||||
#if defined(__ARMEB__)
|
||||
#error "No support for big-endian ARM"
|
||||
#endif
|
||||
#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__
|
||||
#error "No support for Cortex-M CPUs"
|
||||
#endif
|
||||
#if !(__ARM_EABI__ || LJ_TARGET_IOS)
|
||||
#error "Only ARM EABI or iOS 3.0+ ABI is supported"
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM64
|
||||
#if defined(_ILP32)
|
||||
#error "No support for ILP32 model on ARM64"
|
||||
#endif
|
||||
#elif LJ_TARGET_PPC
|
||||
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
|
||||
#error "No support for PowerPC CPUs without double-precision FPU"
|
||||
#endif
|
||||
#if !LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_LE
|
||||
#error "No support for little-endian PPC32"
|
||||
#endif
|
||||
#if LJ_ARCH_PPC64
|
||||
#error "No support for PowerPC 64 bit mode (yet)"
|
||||
#endif
|
||||
#ifdef __NO_FPRS__
|
||||
#error "No support for PPC/e500 anymore (use LuaJIT 2.0)"
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS32
|
||||
#if !((defined(_MIPS_SIM_ABI32) && _MIPS_SIM == _MIPS_SIM_ABI32) || (defined(_ABIO32) && _MIPS_SIM == _ABIO32))
|
||||
#error "Only o32 ABI supported for MIPS32"
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS64
|
||||
#if !((defined(_MIPS_SIM_ABI64) && _MIPS_SIM == _MIPS_SIM_ABI64) || (defined(_ABI64) && _MIPS_SIM == _ABI64))
|
||||
#error "Only n64 ABI supported for MIPS64"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Enable or disable the dual-number mode for the VM. */
|
||||
#if (LJ_ARCH_NUMMODE == LJ_NUMMODE_SINGLE && LUAJIT_NUMMODE == 2) || \
|
||||
(LJ_ARCH_NUMMODE == LJ_NUMMODE_DUAL && LUAJIT_NUMMODE == 1)
|
||||
#error "No support for this number mode on this architecture"
|
||||
#endif
|
||||
#if LJ_ARCH_NUMMODE == LJ_NUMMODE_DUAL || \
|
||||
(LJ_ARCH_NUMMODE == LJ_NUMMODE_DUAL_SINGLE && LUAJIT_NUMMODE != 1) || \
|
||||
(LJ_ARCH_NUMMODE == LJ_NUMMODE_SINGLE_DUAL && LUAJIT_NUMMODE == 2)
|
||||
#define LJ_DUALNUM 1
|
||||
#else
|
||||
#define LJ_DUALNUM 0
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_IOS || LJ_TARGET_CONSOLE
|
||||
/* Runtime code generation is restricted on iOS. Complain to Apple, not me. */
|
||||
/* Ditto for the consoles. Complain to Sony or MS, not me. */
|
||||
#ifndef LUAJIT_ENABLE_JIT
|
||||
#define LJ_OS_NOJIT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* 64 bit GC references. */
|
||||
#if LJ_TARGET_GC64
|
||||
#define LJ_GC64 1
|
||||
#else
|
||||
#define LJ_GC64 1
|
||||
#endif
|
||||
|
||||
/* 2-slot frame info. */
|
||||
#if LJ_GC64
|
||||
#define LJ_FR2 1
|
||||
#else
|
||||
#define LJ_FR2 0
|
||||
#endif
|
||||
|
||||
/* Disable or enable the JIT compiler. */
|
||||
#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT)
|
||||
#define LJ_HASJIT 0
|
||||
#else
|
||||
#define LJ_HASJIT 1
|
||||
#endif
|
||||
|
||||
/* Disable or enable the FFI extension. */
|
||||
#if defined(LUAJIT_DISABLE_FFI) || defined(LJ_ARCH_NOFFI)
|
||||
#define LJ_HASFFI 0
|
||||
#else
|
||||
#define LJ_HASFFI 1
|
||||
#endif
|
||||
|
||||
#if defined(LUAJIT_DISABLE_PROFILE)
|
||||
#define LJ_HASPROFILE 0
|
||||
#elif LJ_TARGET_POSIX
|
||||
#define LJ_HASPROFILE 1
|
||||
#define LJ_PROFILE_SIGPROF 1
|
||||
#elif LJ_TARGET_PS3
|
||||
#define LJ_HASPROFILE 1
|
||||
#define LJ_PROFILE_PTHREAD 1
|
||||
#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOX360
|
||||
#define LJ_HASPROFILE 1
|
||||
#define LJ_PROFILE_WTHREAD 1
|
||||
#else
|
||||
#define LJ_HASPROFILE 0
|
||||
#endif
|
||||
|
||||
#ifndef LJ_ARCH_HASFPU
|
||||
#define LJ_ARCH_HASFPU 1
|
||||
#endif
|
||||
#ifndef LJ_ABI_SOFTFP
|
||||
#define LJ_ABI_SOFTFP 0
|
||||
#endif
|
||||
#define LJ_SOFTFP (!LJ_ARCH_HASFPU)
|
||||
|
||||
#if LJ_ARCH_ENDIAN == LUAJIT_BE
|
||||
#define LJ_LE 0
|
||||
#define LJ_BE 1
|
||||
#define LJ_ENDIAN_SELECT(le, be) be
|
||||
#define LJ_ENDIAN_LOHI(lo, hi) hi lo
|
||||
#else
|
||||
#define LJ_LE 1
|
||||
#define LJ_BE 0
|
||||
#define LJ_ENDIAN_SELECT(le, be) le
|
||||
#define LJ_ENDIAN_LOHI(lo, hi) lo hi
|
||||
#endif
|
||||
|
||||
#if LJ_ARCH_BITS == 32
|
||||
#define LJ_32 1
|
||||
#define LJ_64 0
|
||||
#else
|
||||
#define LJ_32 0
|
||||
#define LJ_64 1
|
||||
#endif
|
||||
|
||||
#ifndef LJ_TARGET_UNALIGNED
|
||||
#define LJ_TARGET_UNALIGNED 0
|
||||
#endif
|
||||
|
||||
/* Various workarounds for embedded operating systems or weak C runtimes. */
|
||||
#if defined(__ANDROID__) || defined(__symbian__) || LJ_TARGET_XBOX360 || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_LOG2
|
||||
#endif
|
||||
#if defined(__symbian__) || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_EXP2
|
||||
#endif
|
||||
#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)
|
||||
#define LJ_NO_SYSTEM 1
|
||||
#endif
|
||||
|
||||
#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__
|
||||
/* NYI: no support for compact unwind specification, yet. */
|
||||
#define LUAJIT_NO_UNWIND 1
|
||||
#endif
|
||||
|
||||
#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
|
||||
#define LJ_NO_UNWIND 1
|
||||
#endif
|
||||
|
||||
/* Compatibility with Lua 5.1 vs. 5.2. */
|
||||
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||
#define LJ_52 1
|
||||
#else
|
||||
#define LJ_52 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
17
include/lua/lj_asm.h
Normal file
17
include/lua/lj_asm.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
** IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ASM_H
|
||||
#define _LJ_ASM_H
|
||||
|
||||
#include "lj_jit.h"
|
||||
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC void lj_asm_trace(jit_State *J, GCtrace *T);
|
||||
LJ_FUNC void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno,
|
||||
MCode *target);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2210
include/lua/lj_asm_arm.h
Normal file
2210
include/lua/lj_asm_arm.h
Normal file
File diff suppressed because it is too large
Load Diff
2022
include/lua/lj_asm_arm64.h
Normal file
2022
include/lua/lj_asm_arm64.h
Normal file
File diff suppressed because it is too large
Load Diff
2505
include/lua/lj_asm_mips.h
Normal file
2505
include/lua/lj_asm_mips.h
Normal file
File diff suppressed because it is too large
Load Diff
2016
include/lua/lj_asm_ppc.h
Normal file
2016
include/lua/lj_asm_ppc.h
Normal file
File diff suppressed because it is too large
Load Diff
3120
include/lua/lj_asm_x86.h
Normal file
3120
include/lua/lj_asm_x86.h
Normal file
File diff suppressed because it is too large
Load Diff
265
include/lua/lj_bc.h
Normal file
265
include/lua/lj_bc.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
** Bytecode instruction format.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_BC_H
|
||||
#define _LJ_BC_H
|
||||
|
||||
#include "lj_def.h"
|
||||
#include "lj_arch.h"
|
||||
|
||||
/* Bytecode instruction format, 32 bit wide, fields of 8 or 16 bit:
|
||||
**
|
||||
** +----+----+----+----+
|
||||
** | B | C | A | OP | Format ABC
|
||||
** +----+----+----+----+
|
||||
** | D | A | OP | Format AD
|
||||
** +--------------------
|
||||
** MSB LSB
|
||||
**
|
||||
** In-memory instructions are always stored in host byte order.
|
||||
*/
|
||||
|
||||
/* Operand ranges and related constants. */
|
||||
#define BCMAX_A 0xff
|
||||
#define BCMAX_B 0xff
|
||||
#define BCMAX_C 0xff
|
||||
#define BCMAX_D 0xffff
|
||||
#define BCBIAS_J 0x8000
|
||||
#define NO_REG BCMAX_A
|
||||
#define NO_JMP (~(BCPos)0)
|
||||
|
||||
/* Macros to get instruction fields. */
|
||||
#define bc_op(i) ((BCOp)((i)&0xff))
|
||||
#define bc_a(i) ((BCReg)(((i)>>8)&0xff))
|
||||
#define bc_b(i) ((BCReg)((i)>>24))
|
||||
#define bc_c(i) ((BCReg)(((i)>>16)&0xff))
|
||||
#define bc_d(i) ((BCReg)((i)>>16))
|
||||
#define bc_j(i) ((ptrdiff_t)bc_d(i)-BCBIAS_J)
|
||||
|
||||
/* Macros to set instruction fields. */
|
||||
#define setbc_byte(p, x, ofs) \
|
||||
((uint8_t *)(p))[LJ_ENDIAN_SELECT(ofs, 3-ofs)] = (uint8_t)(x)
|
||||
#define setbc_op(p, x) setbc_byte(p, (x), 0)
|
||||
#define setbc_a(p, x) setbc_byte(p, (x), 1)
|
||||
#define setbc_b(p, x) setbc_byte(p, (x), 3)
|
||||
#define setbc_c(p, x) setbc_byte(p, (x), 2)
|
||||
#define setbc_d(p, x) \
|
||||
((uint16_t *)(p))[LJ_ENDIAN_SELECT(1, 0)] = (uint16_t)(x)
|
||||
#define setbc_j(p, x) setbc_d(p, (BCPos)((int32_t)(x)+BCBIAS_J))
|
||||
|
||||
/* Macros to compose instructions. */
|
||||
#define BCINS_ABC(o, a, b, c) \
|
||||
(((BCIns)(o))|((BCIns)(a)<<8)|((BCIns)(b)<<24)|((BCIns)(c)<<16))
|
||||
#define BCINS_AD(o, a, d) \
|
||||
(((BCIns)(o))|((BCIns)(a)<<8)|((BCIns)(d)<<16))
|
||||
#define BCINS_AJ(o, a, j) BCINS_AD(o, a, (BCPos)((int32_t)(j)+BCBIAS_J))
|
||||
|
||||
/* Bytecode instruction definition. Order matters, see below.
|
||||
**
|
||||
** (name, filler, Amode, Bmode, Cmode or Dmode, metamethod)
|
||||
**
|
||||
** The opcode name suffixes specify the type for RB/RC or RD:
|
||||
** V = variable slot
|
||||
** S = string const
|
||||
** N = number const
|
||||
** P = primitive type (~itype)
|
||||
** B = unsigned byte literal
|
||||
** M = multiple args/results
|
||||
*/
|
||||
#define BCDEF(_) \
|
||||
/* Comparison ops. ORDER OPR. */ \
|
||||
_(ISLT, var, ___, var, lt) \
|
||||
_(ISGE, var, ___, var, lt) \
|
||||
_(ISLE, var, ___, var, le) \
|
||||
_(ISGT, var, ___, var, le) \
|
||||
\
|
||||
_(ISEQV, var, ___, var, eq) \
|
||||
_(ISNEV, var, ___, var, eq) \
|
||||
_(ISEQS, var, ___, str, eq) \
|
||||
_(ISNES, var, ___, str, eq) \
|
||||
_(ISEQN, var, ___, num, eq) \
|
||||
_(ISNEN, var, ___, num, eq) \
|
||||
_(ISEQP, var, ___, pri, eq) \
|
||||
_(ISNEP, var, ___, pri, eq) \
|
||||
\
|
||||
/* Unary test and copy ops. */ \
|
||||
_(ISTC, dst, ___, var, ___) \
|
||||
_(ISFC, dst, ___, var, ___) \
|
||||
_(IST, ___, ___, var, ___) \
|
||||
_(ISF, ___, ___, var, ___) \
|
||||
_(ISTYPE, var, ___, lit, ___) \
|
||||
_(ISNUM, var, ___, lit, ___) \
|
||||
\
|
||||
/* Unary ops. */ \
|
||||
_(MOV, dst, ___, var, ___) \
|
||||
_(NOT, dst, ___, var, ___) \
|
||||
_(UNM, dst, ___, var, unm) \
|
||||
_(LEN, dst, ___, var, len) \
|
||||
\
|
||||
/* Binary ops. ORDER OPR. VV last, POW must be next. */ \
|
||||
_(ADDVN, dst, var, num, add) \
|
||||
_(SUBVN, dst, var, num, sub) \
|
||||
_(MULVN, dst, var, num, mul) \
|
||||
_(DIVVN, dst, var, num, div) \
|
||||
_(MODVN, dst, var, num, mod) \
|
||||
\
|
||||
_(ADDNV, dst, var, num, add) \
|
||||
_(SUBNV, dst, var, num, sub) \
|
||||
_(MULNV, dst, var, num, mul) \
|
||||
_(DIVNV, dst, var, num, div) \
|
||||
_(MODNV, dst, var, num, mod) \
|
||||
\
|
||||
_(ADDVV, dst, var, var, add) \
|
||||
_(SUBVV, dst, var, var, sub) \
|
||||
_(MULVV, dst, var, var, mul) \
|
||||
_(DIVVV, dst, var, var, div) \
|
||||
_(MODVV, dst, var, var, mod) \
|
||||
\
|
||||
_(POW, dst, var, var, pow) \
|
||||
_(CAT, dst, rbase, rbase, concat) \
|
||||
\
|
||||
/* Constant ops. */ \
|
||||
_(KSTR, dst, ___, str, ___) \
|
||||
_(KCDATA, dst, ___, cdata, ___) \
|
||||
_(KSHORT, dst, ___, lits, ___) \
|
||||
_(KNUM, dst, ___, num, ___) \
|
||||
_(KPRI, dst, ___, pri, ___) \
|
||||
_(KNIL, base, ___, base, ___) \
|
||||
\
|
||||
/* Upvalue and function ops. */ \
|
||||
_(UGET, dst, ___, uv, ___) \
|
||||
_(USETV, uv, ___, var, ___) \
|
||||
_(USETS, uv, ___, str, ___) \
|
||||
_(USETN, uv, ___, num, ___) \
|
||||
_(USETP, uv, ___, pri, ___) \
|
||||
_(UCLO, rbase, ___, jump, ___) \
|
||||
_(FNEW, dst, ___, func, gc) \
|
||||
\
|
||||
/* Table ops. */ \
|
||||
_(TNEW, dst, ___, lit, gc) \
|
||||
_(TDUP, dst, ___, tab, gc) \
|
||||
_(GGET, dst, ___, str, index) \
|
||||
_(GSET, var, ___, str, newindex) \
|
||||
_(TGETV, dst, var, var, index) \
|
||||
_(TGETS, dst, var, str, index) \
|
||||
_(TGETB, dst, var, lit, index) \
|
||||
_(TGETR, dst, var, var, index) \
|
||||
_(TSETV, var, var, var, newindex) \
|
||||
_(TSETS, var, var, str, newindex) \
|
||||
_(TSETB, var, var, lit, newindex) \
|
||||
_(TSETM, base, ___, num, newindex) \
|
||||
_(TSETR, var, var, var, newindex) \
|
||||
\
|
||||
/* Calls and vararg handling. T = tail call. */ \
|
||||
_(CALLM, base, lit, lit, call) \
|
||||
_(CALL, base, lit, lit, call) \
|
||||
_(CALLMT, base, ___, lit, call) \
|
||||
_(CALLT, base, ___, lit, call) \
|
||||
_(ITERC, base, lit, lit, call) \
|
||||
_(ITERN, base, lit, lit, call) \
|
||||
_(VARG, base, lit, lit, ___) \
|
||||
_(ISNEXT, base, ___, jump, ___) \
|
||||
\
|
||||
/* Returns. */ \
|
||||
_(RETM, base, ___, lit, ___) \
|
||||
_(RET, rbase, ___, lit, ___) \
|
||||
_(RET0, rbase, ___, lit, ___) \
|
||||
_(RET1, rbase, ___, lit, ___) \
|
||||
\
|
||||
/* Loops and branches. I/J = interp/JIT, I/C/L = init/call/loop. */ \
|
||||
_(FORI, base, ___, jump, ___) \
|
||||
_(JFORI, base, ___, jump, ___) \
|
||||
\
|
||||
_(FORL, base, ___, jump, ___) \
|
||||
_(IFORL, base, ___, jump, ___) \
|
||||
_(JFORL, base, ___, lit, ___) \
|
||||
\
|
||||
_(ITERL, base, ___, jump, ___) \
|
||||
_(IITERL, base, ___, jump, ___) \
|
||||
_(JITERL, base, ___, lit, ___) \
|
||||
\
|
||||
_(LOOP, rbase, ___, jump, ___) \
|
||||
_(ILOOP, rbase, ___, jump, ___) \
|
||||
_(JLOOP, rbase, ___, lit, ___) \
|
||||
\
|
||||
_(JMP, rbase, ___, jump, ___) \
|
||||
\
|
||||
/* Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. */ \
|
||||
_(FUNCF, rbase, ___, ___, ___) \
|
||||
_(IFUNCF, rbase, ___, ___, ___) \
|
||||
_(JFUNCF, rbase, ___, lit, ___) \
|
||||
_(FUNCV, rbase, ___, ___, ___) \
|
||||
_(IFUNCV, rbase, ___, ___, ___) \
|
||||
_(JFUNCV, rbase, ___, lit, ___) \
|
||||
_(FUNCC, rbase, ___, ___, ___) \
|
||||
_(FUNCCW, rbase, ___, ___, ___)
|
||||
|
||||
/* Bytecode opcode numbers. */
|
||||
typedef enum {
|
||||
#define BCENUM(name, ma, mb, mc, mt) BC_##name,
|
||||
BCDEF(BCENUM)
|
||||
#undef BCENUM
|
||||
BC__MAX
|
||||
} BCOp;
|
||||
|
||||
LJ_STATIC_ASSERT((int)BC_ISEQV+1 == (int)BC_ISNEV);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISEQV^1) == (int)BC_ISNEV);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISEQS^1) == (int)BC_ISNES);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISEQN^1) == (int)BC_ISNEN);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISEQP^1) == (int)BC_ISNEP);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISLT^1) == (int)BC_ISGE);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISLE^1) == (int)BC_ISGT);
|
||||
LJ_STATIC_ASSERT(((int)BC_ISLT^3) == (int)BC_ISGT);
|
||||
LJ_STATIC_ASSERT((int)BC_IST-(int)BC_ISTC == (int)BC_ISF-(int)BC_ISFC);
|
||||
LJ_STATIC_ASSERT((int)BC_CALLT-(int)BC_CALL == (int)BC_CALLMT-(int)BC_CALLM);
|
||||
LJ_STATIC_ASSERT((int)BC_CALLMT + 1 == (int)BC_CALLT);
|
||||
LJ_STATIC_ASSERT((int)BC_RETM + 1 == (int)BC_RET);
|
||||
LJ_STATIC_ASSERT((int)BC_FORL + 1 == (int)BC_IFORL);
|
||||
LJ_STATIC_ASSERT((int)BC_FORL + 2 == (int)BC_JFORL);
|
||||
LJ_STATIC_ASSERT((int)BC_ITERL + 1 == (int)BC_IITERL);
|
||||
LJ_STATIC_ASSERT((int)BC_ITERL + 2 == (int)BC_JITERL);
|
||||
LJ_STATIC_ASSERT((int)BC_LOOP + 1 == (int)BC_ILOOP);
|
||||
LJ_STATIC_ASSERT((int)BC_LOOP + 2 == (int)BC_JLOOP);
|
||||
LJ_STATIC_ASSERT((int)BC_FUNCF + 1 == (int)BC_IFUNCF);
|
||||
LJ_STATIC_ASSERT((int)BC_FUNCF + 2 == (int)BC_JFUNCF);
|
||||
LJ_STATIC_ASSERT((int)BC_FUNCV + 1 == (int)BC_IFUNCV);
|
||||
LJ_STATIC_ASSERT((int)BC_FUNCV + 2 == (int)BC_JFUNCV);
|
||||
|
||||
/* This solves a circular dependency problem, change as needed. */
|
||||
#define FF_next_N 4
|
||||
|
||||
/* Stack slots used by FORI/FORL, relative to operand A. */
|
||||
enum {
|
||||
FORL_IDX, FORL_STOP, FORL_STEP, FORL_EXT
|
||||
};
|
||||
|
||||
/* Bytecode operand modes. ORDER BCMode */
|
||||
typedef enum {
|
||||
BCMnone, BCMdst, BCMbase, BCMvar, BCMrbase, BCMuv, /* Mode A must be <= 7 */
|
||||
BCMlit, BCMlits, BCMpri, BCMnum, BCMstr, BCMtab, BCMfunc, BCMjump, BCMcdata,
|
||||
BCM_max
|
||||
} BCMode;
|
||||
#define BCM___ BCMnone
|
||||
|
||||
#define bcmode_a(op) ((BCMode)(lj_bc_mode[op] & 7))
|
||||
#define bcmode_b(op) ((BCMode)((lj_bc_mode[op]>>3) & 15))
|
||||
#define bcmode_c(op) ((BCMode)((lj_bc_mode[op]>>7) & 15))
|
||||
#define bcmode_d(op) bcmode_c(op)
|
||||
#define bcmode_hasd(op) ((lj_bc_mode[op] & (15<<3)) == (BCMnone<<3))
|
||||
#define bcmode_mm(op) ((MMS)(lj_bc_mode[op]>>11))
|
||||
|
||||
#define BCMODE(name, ma, mb, mc, mm) \
|
||||
(BCM##ma|(BCM##mb<<3)|(BCM##mc<<7)|(MM_##mm<<11)),
|
||||
#define BCMODE_FF 0
|
||||
|
||||
static LJ_AINLINE int bc_isret(BCOp op)
|
||||
{
|
||||
return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1);
|
||||
}
|
||||
|
||||
LJ_DATA const uint16_t lj_bc_mode[];
|
||||
LJ_DATA const uint16_t lj_bc_ofs[];
|
||||
|
||||
#endif
|
||||
220
include/lua/lj_bcdef.h
Normal file
220
include/lua/lj_bcdef.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/* This is a generated file. DO NOT EDIT! */
|
||||
|
||||
LJ_DATADEF const uint16_t lj_bc_ofs[] = {
|
||||
0,
|
||||
71,
|
||||
142,
|
||||
213,
|
||||
284,
|
||||
422,
|
||||
563,
|
||||
624,
|
||||
685,
|
||||
752,
|
||||
819,
|
||||
871,
|
||||
922,
|
||||
972,
|
||||
1022,
|
||||
1062,
|
||||
1102,
|
||||
1129,
|
||||
1160,
|
||||
1185,
|
||||
1216,
|
||||
1275,
|
||||
1348,
|
||||
1400,
|
||||
1452,
|
||||
1504,
|
||||
1556,
|
||||
1613,
|
||||
1665,
|
||||
1717,
|
||||
1769,
|
||||
1821,
|
||||
1856,
|
||||
1922,
|
||||
1988,
|
||||
2054,
|
||||
2120,
|
||||
2169,
|
||||
2248,
|
||||
2325,
|
||||
2359,
|
||||
2393,
|
||||
2422,
|
||||
2449,
|
||||
2473,
|
||||
2515,
|
||||
2550,
|
||||
2633,
|
||||
2712,
|
||||
2748,
|
||||
2781,
|
||||
2831,
|
||||
2894,
|
||||
3002,
|
||||
3091,
|
||||
3108,
|
||||
3125,
|
||||
3272,
|
||||
3394,
|
||||
3492,
|
||||
3545,
|
||||
3715,
|
||||
3944,
|
||||
4065,
|
||||
4199,
|
||||
4283,
|
||||
4328,
|
||||
4369,
|
||||
4373,
|
||||
4514,
|
||||
4581,
|
||||
4733,
|
||||
4913,
|
||||
5000,
|
||||
5004,
|
||||
5129,
|
||||
5217,
|
||||
5318,
|
||||
5414,
|
||||
5518,
|
||||
5537,
|
||||
5606,
|
||||
5672,
|
||||
5691,
|
||||
5734,
|
||||
5772,
|
||||
5791,
|
||||
5808,
|
||||
5929,
|
||||
5953,
|
||||
5972,
|
||||
6033,
|
||||
6086,
|
||||
6086,
|
||||
6203,
|
||||
6204,
|
||||
6286,
|
||||
8042,
|
||||
8109,
|
||||
8612,
|
||||
8716,
|
||||
8773,
|
||||
8904,
|
||||
8175,
|
||||
8335,
|
||||
8425,
|
||||
8478,
|
||||
8509,
|
||||
8962,
|
||||
9002,
|
||||
9622,
|
||||
9057,
|
||||
9366,
|
||||
9674,
|
||||
9800,
|
||||
9824,
|
||||
9851,
|
||||
9922,
|
||||
9962,
|
||||
10002,
|
||||
10042,
|
||||
10082,
|
||||
10122,
|
||||
10162,
|
||||
10202,
|
||||
10242,
|
||||
10282,
|
||||
10322,
|
||||
10585,
|
||||
10733,
|
||||
9882,
|
||||
10420,
|
||||
10362,
|
||||
10478,
|
||||
10536,
|
||||
10832,
|
||||
10891,
|
||||
11531,
|
||||
11929,
|
||||
11876,
|
||||
11998,
|
||||
12077,
|
||||
12159,
|
||||
12241,
|
||||
12323,
|
||||
11585,
|
||||
11682,
|
||||
11779,
|
||||
10950,
|
||||
10997,
|
||||
11118,
|
||||
11285,
|
||||
11367,
|
||||
11449
|
||||
};
|
||||
|
||||
LJ_DATADEF const uint16_t lj_bc_mode[] = {
|
||||
BCDEF(BCMODE)
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF,
|
||||
BCMODE_FF
|
||||
};
|
||||
|
||||
68
include/lua/lj_bcdump.h
Normal file
68
include/lua/lj_bcdump.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
** Bytecode dump definitions.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_BCDUMP_H
|
||||
#define _LJ_BCDUMP_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_lex.h"
|
||||
|
||||
/* -- Bytecode dump format ------------------------------------------------ */
|
||||
|
||||
/*
|
||||
** dump = header proto+ 0U
|
||||
** header = ESC 'L' 'J' versionB flagsU [namelenU nameB*]
|
||||
** proto = lengthU pdata
|
||||
** pdata = phead bcinsW* uvdataH* kgc* knum* [debugB*]
|
||||
** phead = flagsB numparamsB framesizeB numuvB numkgcU numknU numbcU
|
||||
** [debuglenU [firstlineU numlineU]]
|
||||
** kgc = kgctypeU { ktab | (loU hiU) | (rloU rhiU iloU ihiU) | strB* }
|
||||
** knum = intU0 | (loU1 hiU)
|
||||
** ktab = narrayU nhashU karray* khash*
|
||||
** karray = ktabk
|
||||
** khash = ktabk ktabk
|
||||
** ktabk = ktabtypeU { intU | (loU hiU) | strB* }
|
||||
**
|
||||
** B = 8 bit, H = 16 bit, W = 32 bit, U = ULEB128 of W, U0/U1 = ULEB128 of W+1
|
||||
*/
|
||||
|
||||
/* Bytecode dump header. */
|
||||
#define BCDUMP_HEAD1 0x1b
|
||||
#define BCDUMP_HEAD2 0x4c
|
||||
#define BCDUMP_HEAD3 0x4a
|
||||
|
||||
/* If you perform *any* kind of private modifications to the bytecode itself
|
||||
** or to the dump format, you *must* set BCDUMP_VERSION to 0x80 or higher.
|
||||
*/
|
||||
#define BCDUMP_VERSION 2
|
||||
|
||||
/* Compatibility flags. */
|
||||
#define BCDUMP_F_BE 0x01
|
||||
#define BCDUMP_F_STRIP 0x02
|
||||
#define BCDUMP_F_FFI 0x04
|
||||
#define BCDUMP_F_FR2 0x08
|
||||
|
||||
#define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1)
|
||||
|
||||
/* Type codes for the GC constants of a prototype. Plus length for strings. */
|
||||
enum {
|
||||
BCDUMP_KGC_CHILD, BCDUMP_KGC_TAB, BCDUMP_KGC_I64, BCDUMP_KGC_U64,
|
||||
BCDUMP_KGC_COMPLEX, BCDUMP_KGC_STR
|
||||
};
|
||||
|
||||
/* Type codes for the keys/values of a constant table. */
|
||||
enum {
|
||||
BCDUMP_KTAB_NIL, BCDUMP_KTAB_FALSE, BCDUMP_KTAB_TRUE,
|
||||
BCDUMP_KTAB_INT, BCDUMP_KTAB_NUM, BCDUMP_KTAB_STR
|
||||
};
|
||||
|
||||
/* -- Bytecode reader/writer ---------------------------------------------- */
|
||||
|
||||
LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer,
|
||||
void *data, int strip);
|
||||
LJ_FUNC GCproto *lj_bcread_proto(LexState *ls);
|
||||
LJ_FUNC GCproto *lj_bcread(LexState *ls);
|
||||
|
||||
#endif
|
||||
103
include/lua/lj_buf.h
Normal file
103
include/lua/lj_buf.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
** Buffer handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_BUF_H
|
||||
#define _LJ_BUF_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_str.h"
|
||||
|
||||
/* Resizable string buffers. Struct definition in lj_obj.h. */
|
||||
#define sbufB(sb) (mref((sb)->b, char))
|
||||
#define sbufP(sb) (mref((sb)->p, char))
|
||||
#define sbufE(sb) (mref((sb)->e, char))
|
||||
#define sbufL(sb) (mref((sb)->L, lua_State))
|
||||
#define sbufsz(sb) ((MSize)(sbufE((sb)) - sbufB((sb))))
|
||||
#define sbuflen(sb) ((MSize)(sbufP((sb)) - sbufB((sb))))
|
||||
#define sbufleft(sb) ((MSize)(sbufE((sb)) - sbufP((sb))))
|
||||
#define setsbufP(sb, q) (setmref((sb)->p, (q)))
|
||||
#define setsbufL(sb, l) (setmref((sb)->L, (l)))
|
||||
|
||||
/* Buffer management */
|
||||
LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz);
|
||||
LJ_FUNC char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz);
|
||||
LJ_FUNC void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb);
|
||||
LJ_FUNC char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz);
|
||||
|
||||
static LJ_AINLINE void lj_buf_init(lua_State *L, SBuf *sb)
|
||||
{
|
||||
setsbufL(sb, L);
|
||||
setmref(sb->p, NULL); setmref(sb->e, NULL); setmref(sb->b, NULL);
|
||||
}
|
||||
|
||||
static LJ_AINLINE void lj_buf_reset(SBuf *sb)
|
||||
{
|
||||
setmrefr(sb->p, sb->b);
|
||||
}
|
||||
|
||||
static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
|
||||
{
|
||||
SBuf *sb = &G(L)->tmpbuf;
|
||||
setsbufL(sb, L);
|
||||
lj_buf_reset(sb);
|
||||
return sb;
|
||||
}
|
||||
|
||||
static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
|
||||
{
|
||||
lj_mem_free(g, sbufB(sb), sbufsz(sb));
|
||||
}
|
||||
|
||||
static LJ_AINLINE char *lj_buf_need(SBuf *sb, MSize sz)
|
||||
{
|
||||
if (LJ_UNLIKELY(sz > sbufsz(sb)))
|
||||
return lj_buf_need2(sb, sz);
|
||||
return sbufB(sb);
|
||||
}
|
||||
|
||||
static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz)
|
||||
{
|
||||
if (LJ_UNLIKELY(sz > sbufleft(sb)))
|
||||
return lj_buf_more2(sb, sz);
|
||||
return sbufP(sb);
|
||||
}
|
||||
|
||||
/* Low-level buffer put operations */
|
||||
LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len);
|
||||
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c);
|
||||
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s);
|
||||
|
||||
static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len)
|
||||
{
|
||||
return (char *)memcpy(p, q, len) + len;
|
||||
}
|
||||
|
||||
static LJ_AINLINE void lj_buf_putb(SBuf *sb, int c)
|
||||
{
|
||||
char *p = lj_buf_more(sb, 1);
|
||||
*p++ = (char)c;
|
||||
setsbufP(sb, p);
|
||||
}
|
||||
|
||||
/* High-level buffer put operations */
|
||||
LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s);
|
||||
LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s);
|
||||
LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s);
|
||||
LJ_FUNC SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep);
|
||||
LJ_FUNC SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep,
|
||||
int32_t i, int32_t e);
|
||||
|
||||
/* Miscellaneous buffer operations */
|
||||
LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb);
|
||||
LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2);
|
||||
LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp);
|
||||
|
||||
static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
|
||||
{
|
||||
return lj_str_new(L, sbufB(sb), sbuflen(sb));
|
||||
}
|
||||
|
||||
#endif
|
||||
37
include/lua/lj_carith.h
Normal file
37
include/lua/lj_carith.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
** C data arithmetic.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CARITH_H
|
||||
#define _LJ_CARITH_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
LJ_FUNC int lj_carith_op(lua_State *L, MMS mm);
|
||||
|
||||
#if LJ_32
|
||||
LJ_FUNC uint64_t lj_carith_shl64(uint64_t x, int32_t sh);
|
||||
LJ_FUNC uint64_t lj_carith_shr64(uint64_t x, int32_t sh);
|
||||
LJ_FUNC uint64_t lj_carith_sar64(uint64_t x, int32_t sh);
|
||||
LJ_FUNC uint64_t lj_carith_rol64(uint64_t x, int32_t sh);
|
||||
LJ_FUNC uint64_t lj_carith_ror64(uint64_t x, int32_t sh);
|
||||
#endif
|
||||
LJ_FUNC uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op);
|
||||
LJ_FUNC uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id);
|
||||
|
||||
#if LJ_32 && LJ_HASJIT
|
||||
LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k);
|
||||
#endif
|
||||
LJ_FUNC uint64_t lj_carith_divu64(uint64_t a, uint64_t b);
|
||||
LJ_FUNC int64_t lj_carith_divi64(int64_t a, int64_t b);
|
||||
LJ_FUNC uint64_t lj_carith_modu64(uint64_t a, uint64_t b);
|
||||
LJ_FUNC int64_t lj_carith_modi64(int64_t a, int64_t b);
|
||||
LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k);
|
||||
LJ_FUNC int64_t lj_carith_powi64(int64_t x, int64_t k);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
194
include/lua/lj_ccall.h
Normal file
194
include/lua/lj_ccall.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
** FFI C call handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CCALL_H
|
||||
#define _LJ_CCALL_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_ctype.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* -- C calling conventions ----------------------------------------------- */
|
||||
|
||||
#if LJ_TARGET_X86ORX64
|
||||
|
||||
#if LJ_TARGET_X86
|
||||
#define CCALL_NARG_GPR 2 /* For fastcall arguments. */
|
||||
#define CCALL_NARG_FPR 0
|
||||
#define CCALL_NRET_GPR 2
|
||||
#define CCALL_NRET_FPR 1 /* For FP results on x87 stack. */
|
||||
#define CCALL_ALIGN_STACKARG 0 /* Don't align argument on stack. */
|
||||
#elif LJ_ABI_WIN
|
||||
#define CCALL_NARG_GPR 4
|
||||
#define CCALL_NARG_FPR 4
|
||||
#define CCALL_NRET_GPR 1
|
||||
#define CCALL_NRET_FPR 1
|
||||
#define CCALL_SPS_EXTRA 4
|
||||
#else
|
||||
#define CCALL_NARG_GPR 6
|
||||
#define CCALL_NARG_FPR 8
|
||||
#define CCALL_NRET_GPR 2
|
||||
#define CCALL_NRET_FPR 2
|
||||
#define CCALL_VECTOR_REG 1 /* Pass vectors in registers. */
|
||||
#endif
|
||||
|
||||
#define CCALL_SPS_FREE 1
|
||||
#define CCALL_ALIGN_CALLSTATE 16
|
||||
|
||||
typedef LJ_ALIGN(16) union FPRArg {
|
||||
double d[2];
|
||||
float f[4];
|
||||
uint8_t b[16];
|
||||
uint16_t s[8];
|
||||
int i[4];
|
||||
int64_t l[2];
|
||||
} FPRArg;
|
||||
|
||||
typedef intptr_t GPRArg;
|
||||
|
||||
#elif LJ_TARGET_ARM
|
||||
|
||||
#define CCALL_NARG_GPR 4
|
||||
#define CCALL_NRET_GPR 2 /* For softfp double. */
|
||||
#if LJ_ABI_SOFTFP
|
||||
#define CCALL_NARG_FPR 0
|
||||
#define CCALL_NRET_FPR 0
|
||||
#else
|
||||
#define CCALL_NARG_FPR 8
|
||||
#define CCALL_NRET_FPR 4
|
||||
#endif
|
||||
#define CCALL_SPS_FREE 0
|
||||
|
||||
typedef intptr_t GPRArg;
|
||||
typedef union FPRArg {
|
||||
double d;
|
||||
float f[2];
|
||||
} FPRArg;
|
||||
|
||||
#elif LJ_TARGET_ARM64
|
||||
|
||||
#define CCALL_NARG_GPR 8
|
||||
#define CCALL_NRET_GPR 2
|
||||
#define CCALL_NARG_FPR 8
|
||||
#define CCALL_NRET_FPR 4
|
||||
#define CCALL_SPS_FREE 0
|
||||
|
||||
typedef intptr_t GPRArg;
|
||||
typedef union FPRArg {
|
||||
double d;
|
||||
struct { LJ_ENDIAN_LOHI(float f; , float g;) };
|
||||
struct { LJ_ENDIAN_LOHI(uint32_t lo; , uint32_t hi;) };
|
||||
} FPRArg;
|
||||
|
||||
#elif LJ_TARGET_PPC
|
||||
|
||||
#define CCALL_NARG_GPR 8
|
||||
#define CCALL_NARG_FPR 8
|
||||
#define CCALL_NRET_GPR 4 /* For complex double. */
|
||||
#define CCALL_NRET_FPR 1
|
||||
#define CCALL_SPS_EXTRA 4
|
||||
#define CCALL_SPS_FREE 0
|
||||
|
||||
typedef intptr_t GPRArg;
|
||||
typedef double FPRArg;
|
||||
|
||||
#elif LJ_TARGET_MIPS32
|
||||
|
||||
#define CCALL_NARG_GPR 4
|
||||
#define CCALL_NARG_FPR (LJ_ABI_SOFTFP ? 0 : 2)
|
||||
#define CCALL_NRET_GPR (LJ_ABI_SOFTFP ? 4 : 2)
|
||||
#define CCALL_NRET_FPR (LJ_ABI_SOFTFP ? 0 : 2)
|
||||
#define CCALL_SPS_EXTRA 7
|
||||
#define CCALL_SPS_FREE 1
|
||||
|
||||
typedef intptr_t GPRArg;
|
||||
typedef union FPRArg {
|
||||
double d;
|
||||
struct { LJ_ENDIAN_LOHI(float f; , float g;) };
|
||||
} FPRArg;
|
||||
|
||||
#elif LJ_TARGET_MIPS64
|
||||
|
||||
/* FP args are positional and overlay the GPR array. */
|
||||
#define CCALL_NARG_GPR 8
|
||||
#define CCALL_NARG_FPR 0
|
||||
#define CCALL_NRET_GPR 2
|
||||
#define CCALL_NRET_FPR (LJ_ABI_SOFTFP ? 0 : 2)
|
||||
#define CCALL_SPS_EXTRA 3
|
||||
#define CCALL_SPS_FREE 1
|
||||
|
||||
typedef intptr_t GPRArg;
|
||||
typedef union FPRArg {
|
||||
double d;
|
||||
struct { LJ_ENDIAN_LOHI(float f; , float g;) };
|
||||
} FPRArg;
|
||||
|
||||
#else
|
||||
#error "Missing calling convention definitions for this architecture"
|
||||
#endif
|
||||
|
||||
#ifndef CCALL_SPS_EXTRA
|
||||
#define CCALL_SPS_EXTRA 0
|
||||
#endif
|
||||
#ifndef CCALL_VECTOR_REG
|
||||
#define CCALL_VECTOR_REG 0
|
||||
#endif
|
||||
#ifndef CCALL_ALIGN_STACKARG
|
||||
#define CCALL_ALIGN_STACKARG 1
|
||||
#endif
|
||||
#ifndef CCALL_ALIGN_CALLSTATE
|
||||
#define CCALL_ALIGN_CALLSTATE 8
|
||||
#endif
|
||||
|
||||
#define CCALL_NUM_GPR \
|
||||
(CCALL_NARG_GPR > CCALL_NRET_GPR ? CCALL_NARG_GPR : CCALL_NRET_GPR)
|
||||
#define CCALL_NUM_FPR \
|
||||
(CCALL_NARG_FPR > CCALL_NRET_FPR ? CCALL_NARG_FPR : CCALL_NRET_FPR)
|
||||
|
||||
/* Check against constants in lj_ctype.h. */
|
||||
LJ_STATIC_ASSERT(CCALL_NUM_GPR <= CCALL_MAX_GPR);
|
||||
LJ_STATIC_ASSERT(CCALL_NUM_FPR <= CCALL_MAX_FPR);
|
||||
|
||||
#define CCALL_MAXSTACK 32
|
||||
|
||||
/* -- C call state -------------------------------------------------------- */
|
||||
|
||||
typedef LJ_ALIGN(CCALL_ALIGN_CALLSTATE) struct CCallState {
|
||||
void (*func)(void); /* Pointer to called function. */
|
||||
uint32_t spadj; /* Stack pointer adjustment. */
|
||||
uint8_t nsp; /* Number of stack slots. */
|
||||
uint8_t retref; /* Return value by reference. */
|
||||
#if LJ_TARGET_X64
|
||||
uint8_t ngpr; /* Number of arguments in GPRs. */
|
||||
uint8_t nfpr; /* Number of arguments in FPRs. */
|
||||
#elif LJ_TARGET_X86
|
||||
uint8_t resx87; /* Result on x87 stack: 1:float, 2:double. */
|
||||
#elif LJ_TARGET_ARM64
|
||||
void *retp; /* Aggregate return pointer in x8. */
|
||||
#elif LJ_TARGET_PPC
|
||||
uint8_t nfpr; /* Number of arguments in FPRs. */
|
||||
#endif
|
||||
#if LJ_32
|
||||
int32_t align1;
|
||||
#endif
|
||||
#if CCALL_NUM_FPR
|
||||
FPRArg fpr[CCALL_NUM_FPR]; /* Arguments/results in FPRs. */
|
||||
#endif
|
||||
GPRArg gpr[CCALL_NUM_GPR]; /* Arguments/results in GPRs. */
|
||||
GPRArg stack[CCALL_MAXSTACK]; /* Stack slots. */
|
||||
} CCallState;
|
||||
|
||||
/* -- C call handling ----------------------------------------------------- */
|
||||
|
||||
/* Really belongs to lj_vm.h. */
|
||||
LJ_ASMF void LJ_FASTCALL lj_vm_ffi_call(CCallState *cc);
|
||||
|
||||
LJ_FUNC CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o);
|
||||
LJ_FUNC int lj_ccall_func(lua_State *L, GCcdata *cd);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
25
include/lua/lj_ccallback.h
Normal file
25
include/lua/lj_ccallback.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
** FFI C callback handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CCALLBACK_H
|
||||
#define _LJ_CCALLBACK_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_ctype.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* Really belongs to lj_vm.h. */
|
||||
LJ_ASMF void lj_vm_ffi_callback(void);
|
||||
|
||||
LJ_FUNC MSize lj_ccallback_ptr2slot(CTState *cts, void *p);
|
||||
LJ_FUNCA lua_State * LJ_FASTCALL lj_ccallback_enter(CTState *cts, void *cf);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_ccallback_leave(CTState *cts, TValue *o);
|
||||
LJ_FUNC void *lj_ccallback_new(CTState *cts, CType *ct, GCfunc *fn);
|
||||
LJ_FUNC void lj_ccallback_mcode_free(CTState *cts);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
70
include/lua/lj_cconv.h
Normal file
70
include/lua/lj_cconv.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
** C type conversions.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CCONV_H
|
||||
#define _LJ_CCONV_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_ctype.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* Compressed C type index. ORDER CCX. */
|
||||
enum {
|
||||
CCX_B, /* Bool. */
|
||||
CCX_I, /* Integer. */
|
||||
CCX_F, /* Floating-point number. */
|
||||
CCX_C, /* Complex. */
|
||||
CCX_V, /* Vector. */
|
||||
CCX_P, /* Pointer. */
|
||||
CCX_A, /* Refarray. */
|
||||
CCX_S /* Struct/union. */
|
||||
};
|
||||
|
||||
/* Convert C type info to compressed C type index. ORDER CT. ORDER CCX. */
|
||||
static LJ_AINLINE uint32_t cconv_idx(CTInfo info)
|
||||
{
|
||||
uint32_t idx = ((info >> 26) & 15u); /* Dispatch bits. */
|
||||
lua_assert(ctype_type(info) <= CT_MAYCONVERT);
|
||||
#if LJ_64
|
||||
idx = ((uint32_t)(U64x(f436fff5,fff7f021) >> 4*idx) & 15u);
|
||||
#else
|
||||
idx = (((idx < 8 ? 0xfff7f021u : 0xf436fff5) >> 4*(idx & 7u)) & 15u);
|
||||
#endif
|
||||
lua_assert(idx < 8);
|
||||
return idx;
|
||||
}
|
||||
|
||||
#define cconv_idx2(dinfo, sinfo) \
|
||||
((cconv_idx((dinfo)) << 3) + cconv_idx((sinfo)))
|
||||
|
||||
#define CCX(dst, src) ((CCX_##dst << 3) + CCX_##src)
|
||||
|
||||
/* Conversion flags. */
|
||||
#define CCF_CAST 0x00000001u
|
||||
#define CCF_FROMTV 0x00000002u
|
||||
#define CCF_SAME 0x00000004u
|
||||
#define CCF_IGNQUAL 0x00000008u
|
||||
|
||||
#define CCF_ARG_SHIFT 8
|
||||
#define CCF_ARG(n) ((n) << CCF_ARG_SHIFT)
|
||||
#define CCF_GETARG(f) ((f) >> CCF_ARG_SHIFT)
|
||||
|
||||
LJ_FUNC int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags);
|
||||
LJ_FUNC void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s,
|
||||
uint8_t *dp, uint8_t *sp, CTInfo flags);
|
||||
LJ_FUNC int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid,
|
||||
TValue *o, uint8_t *sp);
|
||||
LJ_FUNC int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp);
|
||||
LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d,
|
||||
uint8_t *dp, TValue *o, CTInfo flags);
|
||||
LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o);
|
||||
LJ_FUNC int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o);
|
||||
LJ_FUNC void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz,
|
||||
uint8_t *dp, TValue *o, MSize len);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
78
include/lua/lj_cdata.h
Normal file
78
include/lua/lj_cdata.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
** C data management.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CDATA_H
|
||||
#define _LJ_CDATA_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_ctype.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* Get C data pointer. */
|
||||
static LJ_AINLINE void *cdata_getptr(void *p, CTSize sz)
|
||||
{
|
||||
if (LJ_64 && sz == 4) { /* Support 32 bit pointers on 64 bit targets. */
|
||||
return ((void *)(uintptr_t)*(uint32_t *)p);
|
||||
} else {
|
||||
lua_assert(sz == CTSIZE_PTR);
|
||||
return *(void **)p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set C data pointer. */
|
||||
static LJ_AINLINE void cdata_setptr(void *p, CTSize sz, const void *v)
|
||||
{
|
||||
if (LJ_64 && sz == 4) { /* Support 32 bit pointers on 64 bit targets. */
|
||||
*(uint32_t *)p = (uint32_t)(uintptr_t)v;
|
||||
} else {
|
||||
lua_assert(sz == CTSIZE_PTR);
|
||||
*(void **)p = (void *)v;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate fixed-size C data object. */
|
||||
static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz)
|
||||
{
|
||||
GCcdata *cd;
|
||||
#ifdef LUA_USE_ASSERT
|
||||
CType *ct = ctype_raw(cts, id);
|
||||
lua_assert((ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR) == sz);
|
||||
#endif
|
||||
cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz);
|
||||
cd->gct = ~LJ_TCDATA;
|
||||
cd->ctypeid = ctype_check(cts, id);
|
||||
return cd;
|
||||
}
|
||||
|
||||
/* Variant which works without a valid CTState. */
|
||||
static LJ_AINLINE GCcdata *lj_cdata_new_(lua_State *L, CTypeID id, CTSize sz)
|
||||
{
|
||||
GCcdata *cd = (GCcdata *)lj_mem_newgco(L, sizeof(GCcdata) + sz);
|
||||
cd->gct = ~LJ_TCDATA;
|
||||
cd->ctypeid = id;
|
||||
return cd;
|
||||
}
|
||||
|
||||
LJ_FUNC GCcdata *lj_cdata_newref(CTState *cts, const void *pp, CTypeID id);
|
||||
LJ_FUNC GCcdata *lj_cdata_newv(lua_State *L, CTypeID id, CTSize sz,
|
||||
CTSize align);
|
||||
LJ_FUNC GCcdata *lj_cdata_newx(CTState *cts, CTypeID id, CTSize sz,
|
||||
CTInfo info);
|
||||
|
||||
LJ_FUNC void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd);
|
||||
LJ_FUNC void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj,
|
||||
uint32_t it);
|
||||
|
||||
LJ_FUNC CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key,
|
||||
uint8_t **pp, CTInfo *qual);
|
||||
LJ_FUNC int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp);
|
||||
LJ_FUNC void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o,
|
||||
CTInfo qual);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
42
include/lua/lj_char.h
Normal file
42
include/lua/lj_char.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
** Character types.
|
||||
** Donated to the public domain.
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CHAR_H
|
||||
#define _LJ_CHAR_H
|
||||
|
||||
#include "lj_def.h"
|
||||
|
||||
#define LJ_CHAR_CNTRL 0x01
|
||||
#define LJ_CHAR_SPACE 0x02
|
||||
#define LJ_CHAR_PUNCT 0x04
|
||||
#define LJ_CHAR_DIGIT 0x08
|
||||
#define LJ_CHAR_XDIGIT 0x10
|
||||
#define LJ_CHAR_UPPER 0x20
|
||||
#define LJ_CHAR_LOWER 0x40
|
||||
#define LJ_CHAR_IDENT 0x80
|
||||
#define LJ_CHAR_ALPHA (LJ_CHAR_LOWER|LJ_CHAR_UPPER)
|
||||
#define LJ_CHAR_ALNUM (LJ_CHAR_ALPHA|LJ_CHAR_DIGIT)
|
||||
#define LJ_CHAR_GRAPH (LJ_CHAR_ALNUM|LJ_CHAR_PUNCT)
|
||||
|
||||
/* Only pass -1 or 0..255 to these macros. Never pass a signed char! */
|
||||
#define lj_char_isa(c, t) ((lj_char_bits+1)[(c)] & t)
|
||||
#define lj_char_iscntrl(c) lj_char_isa((c), LJ_CHAR_CNTRL)
|
||||
#define lj_char_isspace(c) lj_char_isa((c), LJ_CHAR_SPACE)
|
||||
#define lj_char_ispunct(c) lj_char_isa((c), LJ_CHAR_PUNCT)
|
||||
#define lj_char_isdigit(c) lj_char_isa((c), LJ_CHAR_DIGIT)
|
||||
#define lj_char_isxdigit(c) lj_char_isa((c), LJ_CHAR_XDIGIT)
|
||||
#define lj_char_isupper(c) lj_char_isa((c), LJ_CHAR_UPPER)
|
||||
#define lj_char_islower(c) lj_char_isa((c), LJ_CHAR_LOWER)
|
||||
#define lj_char_isident(c) lj_char_isa((c), LJ_CHAR_IDENT)
|
||||
#define lj_char_isalpha(c) lj_char_isa((c), LJ_CHAR_ALPHA)
|
||||
#define lj_char_isalnum(c) lj_char_isa((c), LJ_CHAR_ALNUM)
|
||||
#define lj_char_isgraph(c) lj_char_isa((c), LJ_CHAR_GRAPH)
|
||||
|
||||
#define lj_char_toupper(c) ((c) - (lj_char_islower(c) >> 1))
|
||||
#define lj_char_tolower(c) ((c) + lj_char_isupper(c))
|
||||
|
||||
LJ_DATA const uint8_t lj_char_bits[257];
|
||||
|
||||
#endif
|
||||
29
include/lua/lj_clib.h
Normal file
29
include/lua/lj_clib.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
** FFI C library loader.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CLIB_H
|
||||
#define _LJ_CLIB_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* Namespace for C library indexing. */
|
||||
#define CLNS_INDEX ((1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
|
||||
|
||||
/* C library namespace. */
|
||||
typedef struct CLibrary {
|
||||
void *handle; /* Opaque handle for dynamic library loader. */
|
||||
GCtab *cache; /* Cache for resolved symbols. Anchored in ud->env. */
|
||||
} CLibrary;
|
||||
|
||||
LJ_FUNC TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name);
|
||||
LJ_FUNC void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global);
|
||||
LJ_FUNC void lj_clib_unload(CLibrary *cl);
|
||||
LJ_FUNC void lj_clib_default(lua_State *L, GCtab *mt);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
65
include/lua/lj_cparse.h
Normal file
65
include/lua/lj_cparse.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
** C declaration parser.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CPARSE_H
|
||||
#define _LJ_CPARSE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_ctype.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* C parser limits. */
|
||||
#define CPARSE_MAX_BUF 32768 /* Max. token buffer size. */
|
||||
#define CPARSE_MAX_DECLSTACK 100 /* Max. declaration stack depth. */
|
||||
#define CPARSE_MAX_DECLDEPTH 20 /* Max. recursive declaration depth. */
|
||||
#define CPARSE_MAX_PACKSTACK 7 /* Max. pack pragma stack depth. */
|
||||
|
||||
/* Flags for C parser mode. */
|
||||
#define CPARSE_MODE_MULTI 1 /* Process multiple declarations. */
|
||||
#define CPARSE_MODE_ABSTRACT 2 /* Accept abstract declarators. */
|
||||
#define CPARSE_MODE_DIRECT 4 /* Accept direct declarators. */
|
||||
#define CPARSE_MODE_FIELD 8 /* Accept field width in bits, too. */
|
||||
#define CPARSE_MODE_NOIMPLICIT 16 /* Reject implicit declarations. */
|
||||
#define CPARSE_MODE_SKIP 32 /* Skip definitions, ignore errors. */
|
||||
|
||||
typedef int CPChar; /* C parser character. Unsigned ext. from char. */
|
||||
typedef int CPToken; /* C parser token. */
|
||||
|
||||
/* C parser internal value representation. */
|
||||
typedef struct CPValue {
|
||||
union {
|
||||
int32_t i32; /* Value for CTID_INT32. */
|
||||
uint32_t u32; /* Value for CTID_UINT32. */
|
||||
};
|
||||
CTypeID id; /* C Type ID of the value. */
|
||||
} CPValue;
|
||||
|
||||
/* C parser state. */
|
||||
typedef struct CPState {
|
||||
CPChar c; /* Current character. */
|
||||
CPToken tok; /* Current token. */
|
||||
CPValue val; /* Token value. */
|
||||
GCstr *str; /* Interned string of identifier/keyword. */
|
||||
CType *ct; /* C type table entry. */
|
||||
const char *p; /* Current position in input buffer. */
|
||||
SBuf sb; /* String buffer for tokens. */
|
||||
lua_State *L; /* Lua state. */
|
||||
CTState *cts; /* C type state. */
|
||||
TValue *param; /* C type parameters. */
|
||||
const char *srcname; /* Current source name. */
|
||||
BCLine linenumber; /* Input line counter. */
|
||||
int depth; /* Recursive declaration depth. */
|
||||
uint32_t tmask; /* Type mask for next identifier. */
|
||||
uint32_t mode; /* C parser mode. */
|
||||
uint8_t packstack[CPARSE_MAX_PACKSTACK]; /* Stack for pack pragmas. */
|
||||
uint8_t curpack; /* Current position in pack pragma stack. */
|
||||
} CPState;
|
||||
|
||||
LJ_FUNC int lj_cparse(CPState *cp);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
38
include/lua/lj_crecord.h
Normal file
38
include/lua/lj_crecord.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
** Trace recorder for C data operations.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CRECORD_H
|
||||
#define _LJ_CRECORD_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_jit.h"
|
||||
#include "lj_ffrecord.h"
|
||||
|
||||
#if LJ_HASJIT && LJ_HASFFI
|
||||
LJ_FUNC void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_errno(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_typeof(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd);
|
||||
|
||||
LJ_FUNC void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd);
|
||||
LJ_FUNC TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr);
|
||||
|
||||
LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
461
include/lua/lj_ctype.h
Normal file
461
include/lua/lj_ctype.h
Normal file
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
** C type management.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_CTYPE_H
|
||||
#define _LJ_CTYPE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
|
||||
#if LJ_HASFFI
|
||||
|
||||
/* -- C type definitions -------------------------------------------------- */
|
||||
|
||||
/* C type numbers. Highest 4 bits of C type info. ORDER CT. */
|
||||
enum {
|
||||
/* Externally visible types. */
|
||||
CT_NUM, /* Integer or floating-point numbers. */
|
||||
CT_STRUCT, /* Struct or union. */
|
||||
CT_PTR, /* Pointer or reference. */
|
||||
CT_ARRAY, /* Array or complex type. */
|
||||
CT_MAYCONVERT = CT_ARRAY,
|
||||
CT_VOID, /* Void type. */
|
||||
CT_ENUM, /* Enumeration. */
|
||||
CT_HASSIZE = CT_ENUM, /* Last type where ct->size holds the actual size. */
|
||||
CT_FUNC, /* Function. */
|
||||
CT_TYPEDEF, /* Typedef. */
|
||||
CT_ATTRIB, /* Miscellaneous attributes. */
|
||||
/* Internal element types. */
|
||||
CT_FIELD, /* Struct/union field or function parameter. */
|
||||
CT_BITFIELD, /* Struct/union bitfield. */
|
||||
CT_CONSTVAL, /* Constant value. */
|
||||
CT_EXTERN, /* External reference. */
|
||||
CT_KW /* Keyword. */
|
||||
};
|
||||
|
||||
LJ_STATIC_ASSERT(((int)CT_PTR & (int)CT_ARRAY) == CT_PTR);
|
||||
LJ_STATIC_ASSERT(((int)CT_STRUCT & (int)CT_ARRAY) == CT_STRUCT);
|
||||
|
||||
/*
|
||||
** ---------- info ------------
|
||||
** |type flags... A cid | size | sib | next | name |
|
||||
** +----------------------------+--------+-------+-------+-------+--
|
||||
** |NUM BFcvUL.. A | size | | type | |
|
||||
** |STRUCT ..cvU..V A | size | field | name? | name? |
|
||||
** |PTR ..cvR... A cid | size | | type | |
|
||||
** |ARRAY VCcv...V A cid | size | | type | |
|
||||
** |VOID ..cv.... A | size | | type | |
|
||||
** |ENUM A cid | size | const | name? | name? |
|
||||
** |FUNC ....VS.. cc cid | nargs | field | name? | name? |
|
||||
** |TYPEDEF cid | | | name | name |
|
||||
** |ATTRIB attrnum cid | attr | sib? | type? | |
|
||||
** |FIELD cid | offset | field | | name? |
|
||||
** |BITFIELD B.cvU csz bsz pos | offset | field | | name? |
|
||||
** |CONSTVAL c cid | value | const | name | name |
|
||||
** |EXTERN cid | | sib? | name | name |
|
||||
** |KW tok | size | | name | name |
|
||||
** +----------------------------+--------+-------+-------+-------+--
|
||||
** ^^ ^^--- bits used for C type conversion dispatch
|
||||
*/
|
||||
|
||||
/* C type info flags. TFFArrrr */
|
||||
#define CTF_BOOL 0x08000000u /* Boolean: NUM, BITFIELD. */
|
||||
#define CTF_FP 0x04000000u /* Floating-point: NUM. */
|
||||
#define CTF_CONST 0x02000000u /* Const qualifier. */
|
||||
#define CTF_VOLATILE 0x01000000u /* Volatile qualifier. */
|
||||
#define CTF_UNSIGNED 0x00800000u /* Unsigned: NUM, BITFIELD. */
|
||||
#define CTF_LONG 0x00400000u /* Long: NUM. */
|
||||
#define CTF_VLA 0x00100000u /* Variable-length: ARRAY, STRUCT. */
|
||||
#define CTF_REF 0x00800000u /* Reference: PTR. */
|
||||
#define CTF_VECTOR 0x08000000u /* Vector: ARRAY. */
|
||||
#define CTF_COMPLEX 0x04000000u /* Complex: ARRAY. */
|
||||
#define CTF_UNION 0x00800000u /* Union: STRUCT. */
|
||||
#define CTF_VARARG 0x00800000u /* Vararg: FUNC. */
|
||||
#define CTF_SSEREGPARM 0x00400000u /* SSE register parameters: FUNC. */
|
||||
|
||||
#define CTF_QUAL (CTF_CONST|CTF_VOLATILE)
|
||||
#define CTF_ALIGN (CTMASK_ALIGN<<CTSHIFT_ALIGN)
|
||||
#define CTF_UCHAR ((char)-1 > 0 ? CTF_UNSIGNED : 0)
|
||||
|
||||
/* Flags used in parser. .F.Ammvf cp->attr */
|
||||
#define CTFP_ALIGNED 0x00000001u /* cp->attr + ALIGN */
|
||||
#define CTFP_PACKED 0x00000002u /* cp->attr */
|
||||
/* ...C...f cp->fattr */
|
||||
#define CTFP_CCONV 0x00000001u /* cp->fattr + CCONV/[SSE]REGPARM */
|
||||
|
||||
/* C type info bitfields. */
|
||||
#define CTMASK_CID 0x0000ffffu /* Max. 65536 type IDs. */
|
||||
#define CTMASK_NUM 0xf0000000u /* Max. 16 type numbers. */
|
||||
#define CTSHIFT_NUM 28
|
||||
#define CTMASK_ALIGN 15 /* Max. alignment is 2^15. */
|
||||
#define CTSHIFT_ALIGN 16
|
||||
#define CTMASK_ATTRIB 255 /* Max. 256 attributes. */
|
||||
#define CTSHIFT_ATTRIB 16
|
||||
#define CTMASK_CCONV 3 /* Max. 4 calling conventions. */
|
||||
#define CTSHIFT_CCONV 16
|
||||
#define CTMASK_REGPARM 3 /* Max. 0-3 regparms. */
|
||||
#define CTSHIFT_REGPARM 18
|
||||
/* Bitfields only used in parser. */
|
||||
#define CTMASK_VSIZEP 15 /* Max. vector size is 2^15. */
|
||||
#define CTSHIFT_VSIZEP 4
|
||||
#define CTMASK_MSIZEP 255 /* Max. type size (via mode) is 128. */
|
||||
#define CTSHIFT_MSIZEP 8
|
||||
|
||||
/* Info bits for BITFIELD. Max. size of bitfield is 64 bits. */
|
||||
#define CTBSZ_MAX 32 /* Max. size of bitfield is 32 bit. */
|
||||
#define CTBSZ_FIELD 127 /* Temp. marker for regular field. */
|
||||
#define CTMASK_BITPOS 127
|
||||
#define CTMASK_BITBSZ 127
|
||||
#define CTMASK_BITCSZ 127
|
||||
#define CTSHIFT_BITPOS 0
|
||||
#define CTSHIFT_BITBSZ 8
|
||||
#define CTSHIFT_BITCSZ 16
|
||||
|
||||
#define CTF_INSERT(info, field, val) \
|
||||
info = (info & ~(CTMASK_##field<<CTSHIFT_##field)) | \
|
||||
(((CTSize)(val) & CTMASK_##field) << CTSHIFT_##field)
|
||||
|
||||
/* Calling conventions. ORDER CC */
|
||||
enum { CTCC_CDECL, CTCC_THISCALL, CTCC_FASTCALL, CTCC_STDCALL };
|
||||
|
||||
/* Attribute numbers. */
|
||||
enum {
|
||||
CTA_NONE, /* Ignored attribute. Must be zero. */
|
||||
CTA_QUAL, /* Unmerged qualifiers. */
|
||||
CTA_ALIGN, /* Alignment override. */
|
||||
CTA_SUBTYPE, /* Transparent sub-type. */
|
||||
CTA_REDIR, /* Redirected symbol name. */
|
||||
CTA_BAD, /* To catch bad IDs. */
|
||||
CTA__MAX
|
||||
};
|
||||
|
||||
/* Special sizes. */
|
||||
#define CTSIZE_INVALID 0xffffffffu
|
||||
|
||||
typedef uint32_t CTInfo; /* Type info. */
|
||||
typedef uint32_t CTSize; /* Type size. */
|
||||
typedef uint32_t CTypeID; /* Type ID. */
|
||||
typedef uint16_t CTypeID1; /* Minimum-sized type ID. */
|
||||
|
||||
/* C type table element. */
|
||||
typedef struct CType {
|
||||
CTInfo info; /* Type info. */
|
||||
CTSize size; /* Type size or other info. */
|
||||
CTypeID1 sib; /* Sibling element. */
|
||||
CTypeID1 next; /* Next element in hash chain. */
|
||||
GCRef name; /* Element name (GCstr). */
|
||||
} CType;
|
||||
|
||||
#define CTHASH_SIZE 128 /* Number of hash anchors. */
|
||||
#define CTHASH_MASK (CTHASH_SIZE-1)
|
||||
|
||||
/* Simplify target-specific configuration. Checked in lj_ccall.h. */
|
||||
#define CCALL_MAX_GPR 8
|
||||
#define CCALL_MAX_FPR 8
|
||||
|
||||
typedef LJ_ALIGN(8) union FPRCBArg { double d; float f[2]; } FPRCBArg;
|
||||
|
||||
/* C callback state. Defined here, to avoid dragging in lj_ccall.h. */
|
||||
|
||||
typedef LJ_ALIGN(8) struct CCallback {
|
||||
FPRCBArg fpr[CCALL_MAX_FPR]; /* Arguments/results in FPRs. */
|
||||
intptr_t gpr[CCALL_MAX_GPR]; /* Arguments/results in GPRs. */
|
||||
intptr_t *stack; /* Pointer to arguments on stack. */
|
||||
void *mcode; /* Machine code for callback func. pointers. */
|
||||
CTypeID1 *cbid; /* Callback type table. */
|
||||
MSize sizeid; /* Size of callback type table. */
|
||||
MSize topid; /* Highest unused callback type table slot. */
|
||||
MSize slot; /* Current callback slot. */
|
||||
} CCallback;
|
||||
|
||||
/* C type state. */
|
||||
typedef struct CTState {
|
||||
CType *tab; /* C type table. */
|
||||
CTypeID top; /* Current top of C type table. */
|
||||
MSize sizetab; /* Size of C type table. */
|
||||
lua_State *L; /* Lua state (needed for errors and allocations). */
|
||||
global_State *g; /* Global state. */
|
||||
GCtab *finalizer; /* Map of cdata to finalizer. */
|
||||
GCtab *miscmap; /* Map of -CTypeID to metatable and cb slot to func. */
|
||||
CCallback cb; /* Temporary callback state. */
|
||||
CTypeID1 hash[CTHASH_SIZE]; /* Hash anchors for C type table. */
|
||||
} CTState;
|
||||
|
||||
#define CTINFO(ct, flags) (((CTInfo)(ct) << CTSHIFT_NUM) + (flags))
|
||||
#define CTALIGN(al) ((CTSize)(al) << CTSHIFT_ALIGN)
|
||||
#define CTATTRIB(at) ((CTInfo)(at) << CTSHIFT_ATTRIB)
|
||||
|
||||
#define ctype_type(info) ((info) >> CTSHIFT_NUM)
|
||||
#define ctype_cid(info) ((CTypeID)((info) & CTMASK_CID))
|
||||
#define ctype_align(info) (((info) >> CTSHIFT_ALIGN) & CTMASK_ALIGN)
|
||||
#define ctype_attrib(info) (((info) >> CTSHIFT_ATTRIB) & CTMASK_ATTRIB)
|
||||
#define ctype_bitpos(info) (((info) >> CTSHIFT_BITPOS) & CTMASK_BITPOS)
|
||||
#define ctype_bitbsz(info) (((info) >> CTSHIFT_BITBSZ) & CTMASK_BITBSZ)
|
||||
#define ctype_bitcsz(info) (((info) >> CTSHIFT_BITCSZ) & CTMASK_BITCSZ)
|
||||
#define ctype_vsizeP(info) (((info) >> CTSHIFT_VSIZEP) & CTMASK_VSIZEP)
|
||||
#define ctype_msizeP(info) (((info) >> CTSHIFT_MSIZEP) & CTMASK_MSIZEP)
|
||||
#define ctype_cconv(info) (((info) >> CTSHIFT_CCONV) & CTMASK_CCONV)
|
||||
|
||||
/* Simple type checks. */
|
||||
#define ctype_isnum(info) (ctype_type((info)) == CT_NUM)
|
||||
#define ctype_isvoid(info) (ctype_type((info)) == CT_VOID)
|
||||
#define ctype_isptr(info) (ctype_type((info)) == CT_PTR)
|
||||
#define ctype_isarray(info) (ctype_type((info)) == CT_ARRAY)
|
||||
#define ctype_isstruct(info) (ctype_type((info)) == CT_STRUCT)
|
||||
#define ctype_isfunc(info) (ctype_type((info)) == CT_FUNC)
|
||||
#define ctype_isenum(info) (ctype_type((info)) == CT_ENUM)
|
||||
#define ctype_istypedef(info) (ctype_type((info)) == CT_TYPEDEF)
|
||||
#define ctype_isattrib(info) (ctype_type((info)) == CT_ATTRIB)
|
||||
#define ctype_isfield(info) (ctype_type((info)) == CT_FIELD)
|
||||
#define ctype_isbitfield(info) (ctype_type((info)) == CT_BITFIELD)
|
||||
#define ctype_isconstval(info) (ctype_type((info)) == CT_CONSTVAL)
|
||||
#define ctype_isextern(info) (ctype_type((info)) == CT_EXTERN)
|
||||
#define ctype_hassize(info) (ctype_type((info)) <= CT_HASSIZE)
|
||||
|
||||
/* Combined type and flag checks. */
|
||||
#define ctype_isinteger(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_BOOL|CTF_FP)) == CTINFO(CT_NUM, 0))
|
||||
#define ctype_isinteger_or_bool(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_FP)) == CTINFO(CT_NUM, 0))
|
||||
#define ctype_isbool(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_BOOL)) == CTINFO(CT_NUM, CTF_BOOL))
|
||||
#define ctype_isfp(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_FP)) == CTINFO(CT_NUM, CTF_FP))
|
||||
|
||||
#define ctype_ispointer(info) \
|
||||
((ctype_type(info) >> 1) == (CT_PTR >> 1)) /* Pointer or array. */
|
||||
#define ctype_isref(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_REF)) == CTINFO(CT_PTR, CTF_REF))
|
||||
|
||||
#define ctype_isrefarray(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_VECTOR|CTF_COMPLEX)) == CTINFO(CT_ARRAY, 0))
|
||||
#define ctype_isvector(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_VECTOR)) == CTINFO(CT_ARRAY, CTF_VECTOR))
|
||||
#define ctype_iscomplex(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_COMPLEX)) == CTINFO(CT_ARRAY, CTF_COMPLEX))
|
||||
|
||||
#define ctype_isvltype(info) \
|
||||
(((info) & ((CTMASK_NUM|CTF_VLA) - (2u<<CTSHIFT_NUM))) == \
|
||||
CTINFO(CT_STRUCT, CTF_VLA)) /* VL array or VL struct. */
|
||||
#define ctype_isvlarray(info) \
|
||||
(((info) & (CTMASK_NUM|CTF_VLA)) == CTINFO(CT_ARRAY, CTF_VLA))
|
||||
|
||||
#define ctype_isxattrib(info, at) \
|
||||
(((info) & (CTMASK_NUM|CTATTRIB(CTMASK_ATTRIB))) == \
|
||||
CTINFO(CT_ATTRIB, CTATTRIB(at)))
|
||||
|
||||
/* Target-dependent sizes and alignments. */
|
||||
#if LJ_64
|
||||
#define CTSIZE_PTR 8
|
||||
#define CTALIGN_PTR CTALIGN(3)
|
||||
#else
|
||||
#define CTSIZE_PTR 4
|
||||
#define CTALIGN_PTR CTALIGN(2)
|
||||
#endif
|
||||
|
||||
#define CTINFO_REF(ref) \
|
||||
CTINFO(CT_PTR, (CTF_CONST|CTF_REF|CTALIGN_PTR) + (ref))
|
||||
|
||||
#define CT_MEMALIGN 3 /* Alignment guaranteed by memory allocator. */
|
||||
|
||||
/* -- Predefined types ---------------------------------------------------- */
|
||||
|
||||
/* Target-dependent types. */
|
||||
#if LJ_TARGET_PPC
|
||||
#define CTTYDEFP(_) \
|
||||
_(LINT32, 4, CT_NUM, CTF_LONG|CTALIGN(2))
|
||||
#else
|
||||
#define CTTYDEFP(_)
|
||||
#endif
|
||||
|
||||
/* Common types. */
|
||||
#define CTTYDEF(_) \
|
||||
_(NONE, 0, CT_ATTRIB, CTATTRIB(CTA_BAD)) \
|
||||
_(VOID, -1, CT_VOID, CTALIGN(0)) \
|
||||
_(CVOID, -1, CT_VOID, CTF_CONST|CTALIGN(0)) \
|
||||
_(BOOL, 1, CT_NUM, CTF_BOOL|CTF_UNSIGNED|CTALIGN(0)) \
|
||||
_(CCHAR, 1, CT_NUM, CTF_CONST|CTF_UCHAR|CTALIGN(0)) \
|
||||
_(INT8, 1, CT_NUM, CTALIGN(0)) \
|
||||
_(UINT8, 1, CT_NUM, CTF_UNSIGNED|CTALIGN(0)) \
|
||||
_(INT16, 2, CT_NUM, CTALIGN(1)) \
|
||||
_(UINT16, 2, CT_NUM, CTF_UNSIGNED|CTALIGN(1)) \
|
||||
_(INT32, 4, CT_NUM, CTALIGN(2)) \
|
||||
_(UINT32, 4, CT_NUM, CTF_UNSIGNED|CTALIGN(2)) \
|
||||
_(INT64, 8, CT_NUM, CTF_LONG|CTALIGN(3)) \
|
||||
_(UINT64, 8, CT_NUM, CTF_UNSIGNED|CTF_LONG|CTALIGN(3)) \
|
||||
_(FLOAT, 4, CT_NUM, CTF_FP|CTALIGN(2)) \
|
||||
_(DOUBLE, 8, CT_NUM, CTF_FP|CTALIGN(3)) \
|
||||
_(COMPLEX_FLOAT, 8, CT_ARRAY, CTF_COMPLEX|CTALIGN(2)|CTID_FLOAT) \
|
||||
_(COMPLEX_DOUBLE, 16, CT_ARRAY, CTF_COMPLEX|CTALIGN(3)|CTID_DOUBLE) \
|
||||
_(P_VOID, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_VOID) \
|
||||
_(P_CVOID, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_CVOID) \
|
||||
_(P_CCHAR, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_CCHAR) \
|
||||
_(A_CCHAR, -1, CT_ARRAY, CTF_CONST|CTALIGN(0)|CTID_CCHAR) \
|
||||
_(CTYPEID, 4, CT_ENUM, CTALIGN(2)|CTID_INT32) \
|
||||
CTTYDEFP(_) \
|
||||
/* End of type list. */
|
||||
|
||||
/* Public predefined type IDs. */
|
||||
enum {
|
||||
#define CTTYIDDEF(id, sz, ct, info) CTID_##id,
|
||||
CTTYDEF(CTTYIDDEF)
|
||||
#undef CTTYIDDEF
|
||||
/* Predefined typedefs and keywords follow. */
|
||||
CTID_MAX = 65536
|
||||
};
|
||||
|
||||
/* Target-dependent type IDs. */
|
||||
#if LJ_64
|
||||
#define CTID_INT_PSZ CTID_INT64
|
||||
#define CTID_UINT_PSZ CTID_UINT64
|
||||
#else
|
||||
#define CTID_INT_PSZ CTID_INT32
|
||||
#define CTID_UINT_PSZ CTID_UINT32
|
||||
#endif
|
||||
|
||||
#if LJ_ABI_WIN
|
||||
#define CTID_WCHAR CTID_UINT16
|
||||
#elif LJ_TARGET_PPC
|
||||
#define CTID_WCHAR CTID_LINT32
|
||||
#else
|
||||
#define CTID_WCHAR CTID_INT32
|
||||
#endif
|
||||
|
||||
/* -- C tokens and keywords ----------------------------------------------- */
|
||||
|
||||
/* C lexer keywords. */
|
||||
#define CTOKDEF(_) \
|
||||
_(IDENT, "<identifier>") _(STRING, "<string>") \
|
||||
_(INTEGER, "<integer>") _(EOF, "<eof>") \
|
||||
_(OROR, "||") _(ANDAND, "&&") _(EQ, "==") _(NE, "!=") \
|
||||
_(LE, "<=") _(GE, ">=") _(SHL, "<<") _(SHR, ">>") _(DEREF, "->")
|
||||
|
||||
/* Simple declaration specifiers. */
|
||||
#define CDSDEF(_) \
|
||||
_(VOID) _(BOOL) _(CHAR) _(INT) _(FP) \
|
||||
_(LONG) _(LONGLONG) _(SHORT) _(COMPLEX) _(SIGNED) _(UNSIGNED) \
|
||||
_(CONST) _(VOLATILE) _(RESTRICT) _(INLINE) \
|
||||
_(TYPEDEF) _(EXTERN) _(STATIC) _(AUTO) _(REGISTER)
|
||||
|
||||
/* C keywords. */
|
||||
#define CKWDEF(_) \
|
||||
CDSDEF(_) _(EXTENSION) _(ASM) _(ATTRIBUTE) \
|
||||
_(DECLSPEC) _(CCDECL) _(PTRSZ) \
|
||||
_(STRUCT) _(UNION) _(ENUM) \
|
||||
_(SIZEOF) _(ALIGNOF)
|
||||
|
||||
/* C token numbers. */
|
||||
enum {
|
||||
CTOK_OFS = 255,
|
||||
#define CTOKNUM(name, sym) CTOK_##name,
|
||||
#define CKWNUM(name) CTOK_##name,
|
||||
CTOKDEF(CTOKNUM)
|
||||
CKWDEF(CKWNUM)
|
||||
#undef CTOKNUM
|
||||
#undef CKWNUM
|
||||
CTOK_FIRSTDECL = CTOK_VOID,
|
||||
CTOK_FIRSTSCL = CTOK_TYPEDEF,
|
||||
CTOK_LASTDECLFLAG = CTOK_REGISTER,
|
||||
CTOK_LASTDECL = CTOK_ENUM
|
||||
};
|
||||
|
||||
/* Declaration specifier flags. */
|
||||
enum {
|
||||
#define CDSFLAG(name) CDF_##name = (1u << (CTOK_##name - CTOK_FIRSTDECL)),
|
||||
CDSDEF(CDSFLAG)
|
||||
#undef CDSFLAG
|
||||
CDF__END
|
||||
};
|
||||
|
||||
#define CDF_SCL (CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC|CDF_AUTO|CDF_REGISTER)
|
||||
|
||||
/* -- C type management --------------------------------------------------- */
|
||||
|
||||
#define ctype_ctsG(g) (mref((g)->ctype_state, CTState))
|
||||
|
||||
/* Get C type state. */
|
||||
static LJ_AINLINE CTState *ctype_cts(lua_State *L)
|
||||
{
|
||||
CTState *cts = ctype_ctsG(G(L));
|
||||
cts->L = L; /* Save L for errors and allocations. */
|
||||
return cts;
|
||||
}
|
||||
|
||||
/* Save and restore state of C type table. */
|
||||
#define LJ_CTYPE_SAVE(cts) CTState savects_ = *(cts)
|
||||
#define LJ_CTYPE_RESTORE(cts) \
|
||||
((cts)->top = savects_.top, \
|
||||
memcpy((cts)->hash, savects_.hash, sizeof(savects_.hash)))
|
||||
|
||||
/* Check C type ID for validity when assertions are enabled. */
|
||||
static LJ_AINLINE CTypeID ctype_check(CTState *cts, CTypeID id)
|
||||
{
|
||||
lua_assert(id > 0 && id < cts->top); UNUSED(cts);
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Get C type for C type ID. */
|
||||
static LJ_AINLINE CType *ctype_get(CTState *cts, CTypeID id)
|
||||
{
|
||||
return &cts->tab[ctype_check(cts, id)];
|
||||
}
|
||||
|
||||
/* Get C type ID for a C type. */
|
||||
#define ctype_typeid(cts, ct) ((CTypeID)((ct) - (cts)->tab))
|
||||
|
||||
/* Get child C type. */
|
||||
static LJ_AINLINE CType *ctype_child(CTState *cts, CType *ct)
|
||||
{
|
||||
lua_assert(!(ctype_isvoid(ct->info) || ctype_isstruct(ct->info) ||
|
||||
ctype_isbitfield(ct->info))); /* These don't have children. */
|
||||
return ctype_get(cts, ctype_cid(ct->info));
|
||||
}
|
||||
|
||||
/* Get raw type for a C type ID. */
|
||||
static LJ_AINLINE CType *ctype_raw(CTState *cts, CTypeID id)
|
||||
{
|
||||
CType *ct = ctype_get(cts, id);
|
||||
while (ctype_isattrib(ct->info)) ct = ctype_child(cts, ct);
|
||||
return ct;
|
||||
}
|
||||
|
||||
/* Get raw type of the child of a C type. */
|
||||
static LJ_AINLINE CType *ctype_rawchild(CTState *cts, CType *ct)
|
||||
{
|
||||
do { ct = ctype_child(cts, ct); } while (ctype_isattrib(ct->info));
|
||||
return ct;
|
||||
}
|
||||
|
||||
/* Set the name of a C type table element. */
|
||||
static LJ_AINLINE void ctype_setname(CType *ct, GCstr *s)
|
||||
{
|
||||
/* NOBARRIER: mark string as fixed -- the C type table is never collected. */
|
||||
fixstring(s);
|
||||
setgcref(ct->name, obj2gco(s));
|
||||
}
|
||||
|
||||
LJ_FUNC CTypeID lj_ctype_new(CTState *cts, CType **ctp);
|
||||
LJ_FUNC CTypeID lj_ctype_intern(CTState *cts, CTInfo info, CTSize size);
|
||||
LJ_FUNC void lj_ctype_addname(CTState *cts, CType *ct, CTypeID id);
|
||||
LJ_FUNC CTypeID lj_ctype_getname(CTState *cts, CType **ctp, GCstr *name,
|
||||
uint32_t tmask);
|
||||
LJ_FUNC CType *lj_ctype_getfieldq(CTState *cts, CType *ct, GCstr *name,
|
||||
CTSize *ofs, CTInfo *qual);
|
||||
#define lj_ctype_getfield(cts, ct, name, ofs) \
|
||||
lj_ctype_getfieldq((cts), (ct), (name), (ofs), NULL)
|
||||
LJ_FUNC CType *lj_ctype_rawref(CTState *cts, CTypeID id);
|
||||
LJ_FUNC CTSize lj_ctype_size(CTState *cts, CTypeID id);
|
||||
LJ_FUNC CTSize lj_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem);
|
||||
LJ_FUNC CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp);
|
||||
LJ_FUNC cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm);
|
||||
LJ_FUNC GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name);
|
||||
LJ_FUNC GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned);
|
||||
LJ_FUNC GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size);
|
||||
LJ_FUNC CTState *lj_ctype_init(lua_State *L);
|
||||
LJ_FUNC void lj_ctype_freestate(global_State *g);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
65
include/lua/lj_debug.h
Normal file
65
include/lua/lj_debug.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
** Debugging and introspection.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_DEBUG_H
|
||||
#define _LJ_DEBUG_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
typedef struct lj_Debug {
|
||||
/* Common fields. Must be in the same order as in lua.h. */
|
||||
int event;
|
||||
const char *name;
|
||||
const char *namewhat;
|
||||
const char *what;
|
||||
const char *source;
|
||||
int currentline;
|
||||
int nups;
|
||||
int linedefined;
|
||||
int lastlinedefined;
|
||||
char short_src[LUA_IDSIZE];
|
||||
int i_ci;
|
||||
/* Extended fields. Only valid if lj_debug_getinfo() is called with ext = 1.*/
|
||||
int nparams;
|
||||
int isvararg;
|
||||
} lj_Debug;
|
||||
|
||||
LJ_FUNC cTValue *lj_debug_frame(lua_State *L, int level, int *size);
|
||||
LJ_FUNC BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc);
|
||||
LJ_FUNC const char *lj_debug_uvname(GCproto *pt, uint32_t idx);
|
||||
LJ_FUNC const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp);
|
||||
LJ_FUNC const char *lj_debug_slotname(GCproto *pt, const BCIns *pc,
|
||||
BCReg slot, const char **name);
|
||||
LJ_FUNC const char *lj_debug_funcname(lua_State *L, cTValue *frame,
|
||||
const char **name);
|
||||
LJ_FUNC void lj_debug_shortname(char *out, GCstr *str, BCLine line);
|
||||
LJ_FUNC void lj_debug_addloc(lua_State *L, const char *msg,
|
||||
cTValue *frame, cTValue *nextframe);
|
||||
LJ_FUNC void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc);
|
||||
LJ_FUNC int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar,
|
||||
int ext);
|
||||
#if LJ_HASPROFILE
|
||||
LJ_FUNC void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt,
|
||||
int depth);
|
||||
#endif
|
||||
|
||||
/* Fixed internal variable names. */
|
||||
#define VARNAMEDEF(_) \
|
||||
_(FOR_IDX, "(for index)") \
|
||||
_(FOR_STOP, "(for limit)") \
|
||||
_(FOR_STEP, "(for step)") \
|
||||
_(FOR_GEN, "(for generator)") \
|
||||
_(FOR_STATE, "(for state)") \
|
||||
_(FOR_CTL, "(for control)")
|
||||
|
||||
enum {
|
||||
VARNAME_END,
|
||||
#define VARNAMEENUM(name, str) VARNAME_##name,
|
||||
VARNAMEDEF(VARNAMEENUM)
|
||||
#undef VARNAMEENUM
|
||||
VARNAME__MAX
|
||||
};
|
||||
|
||||
#endif
|
||||
362
include/lua/lj_def.h
Normal file
362
include/lua/lj_def.h
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
** LuaJIT common internal definitions.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_DEF_H
|
||||
#define _LJ_DEF_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */
|
||||
//typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#ifdef _WIN64
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else
|
||||
typedef __int32 intptr_t;
|
||||
typedef unsigned __int32 uintptr_t;
|
||||
#endif
|
||||
#elif defined(__symbian__)
|
||||
/* Cough. */
|
||||
typedef signed char int8_t;
|
||||
typedef short int int16_t;
|
||||
typedef int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Needed everywhere. */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Various VM limits. */
|
||||
#define LJ_MAX_MEM32 0x7fffff00 /* Max. 32 bit memory allocation. */
|
||||
#define LJ_MAX_MEM64 ((uint64_t)1<<47) /* Max. 64 bit memory allocation. */
|
||||
/* Max. total memory allocation. */
|
||||
#define LJ_MAX_MEM (LJ_GC64 ? LJ_MAX_MEM64 : LJ_MAX_MEM32)
|
||||
#define LJ_MAX_ALLOC LJ_MAX_MEM /* Max. individual allocation length. */
|
||||
#define LJ_MAX_STR LJ_MAX_MEM32 /* Max. string length. */
|
||||
#define LJ_MAX_BUF LJ_MAX_MEM32 /* Max. buffer length. */
|
||||
#define LJ_MAX_UDATA LJ_MAX_MEM32 /* Max. userdata length. */
|
||||
|
||||
#define LJ_MAX_STRTAB (1<<26) /* Max. string table size. */
|
||||
#define LJ_MAX_HBITS 26 /* Max. hash bits. */
|
||||
#define LJ_MAX_ABITS 28 /* Max. bits of array key. */
|
||||
#define LJ_MAX_ASIZE ((1<<(LJ_MAX_ABITS-1))+1) /* Max. array part size. */
|
||||
#define LJ_MAX_COLOSIZE 16 /* Max. elems for colocated array. */
|
||||
|
||||
#define LJ_MAX_LINE LJ_MAX_MEM32 /* Max. source code line number. */
|
||||
#define LJ_MAX_XLEVEL 200 /* Max. syntactic nesting level. */
|
||||
#define LJ_MAX_BCINS (1<<26) /* Max. # of bytecode instructions. */
|
||||
#define LJ_MAX_SLOTS 250 /* Max. # of slots in a Lua func. */
|
||||
#define LJ_MAX_LOCVAR 200 /* Max. # of local variables. */
|
||||
#define LJ_MAX_UPVAL 60 /* Max. # of upvalues. */
|
||||
|
||||
#define LJ_MAX_IDXCHAIN 100 /* __index/__newindex chain limit. */
|
||||
#define LJ_STACK_EXTRA (5+2*LJ_FR2) /* Extra stack space (metamethods). */
|
||||
|
||||
#define LJ_NUM_CBPAGE 1 /* Number of FFI callback pages. */
|
||||
|
||||
/* Minimum table/buffer sizes. */
|
||||
#define LJ_MIN_GLOBAL 6 /* Min. global table size (hbits). */
|
||||
#define LJ_MIN_REGISTRY 2 /* Min. registry size (hbits). */
|
||||
#define LJ_MIN_STRTAB 256 /* Min. string table size (pow2). */
|
||||
#define LJ_MIN_SBUF 32 /* Min. string buffer length. */
|
||||
#define LJ_MIN_VECSZ 8 /* Min. size for growable vectors. */
|
||||
#define LJ_MIN_IRSZ 32 /* Min. size for growable IR. */
|
||||
#define LJ_MIN_K64SZ 16 /* Min. size for chained K64Array. */
|
||||
|
||||
/* JIT compiler limits. */
|
||||
#define LJ_MAX_JSLOTS 250 /* Max. # of stack slots for a trace. */
|
||||
#define LJ_MAX_PHI 64 /* Max. # of PHIs for a loop. */
|
||||
#define LJ_MAX_EXITSTUBGR 16 /* Max. # of exit stub groups. */
|
||||
|
||||
/* Various macros. */
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
|
||||
#endif
|
||||
|
||||
#define U64x(hi, lo) (((uint64_t)0x##hi << 32) + (uint64_t)0x##lo)
|
||||
#define i32ptr(p) ((int32_t)(intptr_t)(void *)(p))
|
||||
#define u32ptr(p) ((uint32_t)(intptr_t)(void *)(p))
|
||||
#define i64ptr(p) ((int64_t)(intptr_t)(void *)(p))
|
||||
#define u64ptr(p) ((uint64_t)(intptr_t)(void *)(p))
|
||||
#define igcptr(p) (LJ_GC64 ? i64ptr(p) : i32ptr(p))
|
||||
|
||||
#define checki8(x) ((x) == (int32_t)(int8_t)(x))
|
||||
#define checku8(x) ((x) == (int32_t)(uint8_t)(x))
|
||||
#define checki16(x) ((x) == (int32_t)(int16_t)(x))
|
||||
#define checku16(x) ((x) == (int32_t)(uint16_t)(x))
|
||||
#define checki32(x) ((x) == (int32_t)(x))
|
||||
#define checku32(x) ((x) == (uint32_t)(x))
|
||||
#define checkptr32(x) ((uintptr_t)(x) == (uint32_t)(uintptr_t)(x))
|
||||
#define checkptr47(x) (((uint64_t)(uintptr_t)(x) >> 47) == 0)
|
||||
#define checkptrGC(x) (LJ_GC64 ? checkptr47((x)) : LJ_64 ? checkptr32((x)) :1)
|
||||
|
||||
/* Every half-decent C compiler transforms this into a rotate instruction. */
|
||||
#define lj_rol(x, n) (((x)<<(n)) | ((x)>>(-(int)(n)&(8*sizeof(x)-1))))
|
||||
#define lj_ror(x, n) (((x)<<(-(int)(n)&(8*sizeof(x)-1))) | ((x)>>(n)))
|
||||
|
||||
/* A really naive Bloom filter. But sufficient for our needs. */
|
||||
typedef uintptr_t BloomFilter;
|
||||
#define BLOOM_MASK (8*sizeof(BloomFilter) - 1)
|
||||
#define bloombit(x) ((uintptr_t)1 << ((x) & BLOOM_MASK))
|
||||
#define bloomset(b, x) ((b) |= bloombit((x)))
|
||||
#define bloomtest(b, x) ((b) & bloombit((x)))
|
||||
|
||||
#if defined(__GNUC__) || defined(__psp2__)
|
||||
|
||||
#define LJ_NORET __attribute__((noreturn))
|
||||
#define LJ_ALIGN(n) __attribute__((aligned(n)))
|
||||
#define LJ_INLINE inline
|
||||
#define LJ_AINLINE inline __attribute__((always_inline))
|
||||
#define LJ_NOINLINE __attribute__((noinline))
|
||||
|
||||
#if defined(__ELF__) || defined(__MACH__) || defined(__psp2__)
|
||||
#if !((defined(__sun__) && defined(__svr4__)) || defined(__CELLOS_LV2__))
|
||||
#define LJ_NOAPI extern __attribute__((visibility("hidden")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Note: it's only beneficial to use fastcall on x86 and then only for up to
|
||||
** two non-FP args. The amalgamated compile covers all LJ_FUNC cases. Only
|
||||
** indirect calls and related tail-called C functions are marked as fastcall.
|
||||
*/
|
||||
#if defined(__i386__)
|
||||
#define LJ_FASTCALL __attribute__((fastcall))
|
||||
#endif
|
||||
|
||||
#define LJ_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define LJ_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define lj_ffs(x) ((uint32_t)__builtin_ctz(x))
|
||||
/* Don't ask ... */
|
||||
#if defined(__INTEL_COMPILER) && (defined(__i386__) || defined(__x86_64__))
|
||||
static LJ_AINLINE uint32_t lj_fls(uint32_t x)
|
||||
{
|
||||
uint32_t r; __asm__("bsrl %1, %0" : "=r" (r) : "rm" (x) : "cc"); return r;
|
||||
}
|
||||
#else
|
||||
#define lj_fls(x) ((uint32_t)(__builtin_clz(x)^31))
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
static LJ_AINLINE uint32_t lj_bswap(uint32_t x)
|
||||
{
|
||||
#if defined(__psp2__)
|
||||
return __builtin_rev(x);
|
||||
#else
|
||||
uint32_t r;
|
||||
#if __ARM_ARCH_6__ || __ARM_ARCH_6J__ || __ARM_ARCH_6T2__ || __ARM_ARCH_6Z__ ||\
|
||||
__ARM_ARCH_6ZK__ || __ARM_ARCH_7__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__
|
||||
__asm__("rev %0, %1" : "=r" (r) : "r" (x));
|
||||
return r;
|
||||
#else
|
||||
#ifdef __thumb__
|
||||
r = x ^ lj_ror(x, 16);
|
||||
#else
|
||||
__asm__("eor %0, %1, %1, ror #16" : "=r" (r) : "r" (x));
|
||||
#endif
|
||||
return ((r & 0xff00ffffu) >> 8) ^ lj_ror(x, 8);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static LJ_AINLINE uint64_t lj_bswap64(uint64_t x)
|
||||
{
|
||||
return ((uint64_t)lj_bswap((uint32_t)x)<<32) | lj_bswap((uint32_t)(x>>32));
|
||||
}
|
||||
#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
static LJ_AINLINE uint32_t lj_bswap(uint32_t x)
|
||||
{
|
||||
return (uint32_t)__builtin_bswap32((int32_t)x);
|
||||
}
|
||||
|
||||
static LJ_AINLINE uint64_t lj_bswap64(uint64_t x)
|
||||
{
|
||||
return (uint64_t)__builtin_bswap64((int64_t)x);
|
||||
}
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
static LJ_AINLINE uint32_t lj_bswap(uint32_t x)
|
||||
{
|
||||
uint32_t r; __asm__("bswap %0" : "=r" (r) : "0" (x)); return r;
|
||||
}
|
||||
|
||||
#if defined(__i386__)
|
||||
static LJ_AINLINE uint64_t lj_bswap64(uint64_t x)
|
||||
{
|
||||
return ((uint64_t)lj_bswap((uint32_t)x)<<32) | lj_bswap((uint32_t)(x>>32));
|
||||
}
|
||||
#else
|
||||
static LJ_AINLINE uint64_t lj_bswap64(uint64_t x)
|
||||
{
|
||||
uint64_t r; __asm__("bswap %0" : "=r" (r) : "0" (x)); return r;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
static LJ_AINLINE uint32_t lj_bswap(uint32_t x)
|
||||
{
|
||||
return (x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | (x >> 24);
|
||||
}
|
||||
|
||||
static LJ_AINLINE uint64_t lj_bswap64(uint64_t x)
|
||||
{
|
||||
return (uint64_t)lj_bswap((uint32_t)(x >> 32)) |
|
||||
((uint64_t)lj_bswap((uint32_t)x) << 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef union __attribute__((packed)) Unaligned16 {
|
||||
uint16_t u;
|
||||
uint8_t b[2];
|
||||
} Unaligned16;
|
||||
|
||||
typedef union __attribute__((packed)) Unaligned32 {
|
||||
uint32_t u;
|
||||
uint8_t b[4];
|
||||
} Unaligned32;
|
||||
|
||||
/* Unaligned load of uint16_t. */
|
||||
static LJ_AINLINE uint16_t lj_getu16(const void *p)
|
||||
{
|
||||
return ((const Unaligned16 *)p)->u;
|
||||
}
|
||||
|
||||
/* Unaligned load of uint32_t. */
|
||||
static LJ_AINLINE uint32_t lj_getu32(const void *p)
|
||||
{
|
||||
return ((const Unaligned32 *)p)->u;
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#define LJ_NORET __declspec(noreturn)
|
||||
#define LJ_ALIGN(n) __declspec(align(n))
|
||||
#define LJ_INLINE __inline
|
||||
#define LJ_AINLINE __forceinline
|
||||
#define LJ_NOINLINE __declspec(noinline)
|
||||
#if defined(_M_IX86)
|
||||
#define LJ_FASTCALL __fastcall
|
||||
#endif
|
||||
|
||||
#ifdef _M_PPC
|
||||
unsigned int _CountLeadingZeros(long);
|
||||
#pragma intrinsic(_CountLeadingZeros)
|
||||
static LJ_AINLINE uint32_t lj_fls(uint32_t x)
|
||||
{
|
||||
return _CountLeadingZeros(x) ^ 31;
|
||||
}
|
||||
#else
|
||||
unsigned char _BitScanForward(uint32_t *, unsigned long);
|
||||
unsigned char _BitScanReverse(uint32_t *, unsigned long);
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#pragma intrinsic(_BitScanReverse)
|
||||
|
||||
static LJ_AINLINE uint32_t lj_ffs(uint32_t x)
|
||||
{
|
||||
uint32_t r; _BitScanForward(&r, x); return r;
|
||||
}
|
||||
|
||||
static LJ_AINLINE uint32_t lj_fls(uint32_t x)
|
||||
{
|
||||
uint32_t r; _BitScanReverse(&r, x); return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long _byteswap_ulong(unsigned long);
|
||||
uint64_t _byteswap_uint64(uint64_t);
|
||||
#define lj_bswap(x) (_byteswap_ulong((x)))
|
||||
#define lj_bswap64(x) (_byteswap_uint64((x)))
|
||||
|
||||
#if defined(_M_PPC) && defined(LUAJIT_NO_UNALIGNED)
|
||||
/*
|
||||
** Replacement for unaligned loads on Xbox 360. Disabled by default since it's
|
||||
** usually more costly than the occasional stall when crossing a cache-line.
|
||||
*/
|
||||
static LJ_AINLINE uint16_t lj_getu16(const void *v)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)v;
|
||||
return (uint16_t)((p[0]<<8) | p[1]);
|
||||
}
|
||||
static LJ_AINLINE uint32_t lj_getu32(const void *v)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)v;
|
||||
return (uint32_t)((p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]);
|
||||
}
|
||||
#else
|
||||
/* Unaligned loads are generally ok on x86/x64. */
|
||||
#define lj_getu16(p) (*(uint16_t *)(p))
|
||||
#define lj_getu32(p) (*(uint32_t *)(p))
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error "missing defines for your compiler"
|
||||
#endif
|
||||
|
||||
/* Optional defines. */
|
||||
#ifndef LJ_FASTCALL
|
||||
#define LJ_FASTCALL
|
||||
#endif
|
||||
#ifndef LJ_NORET
|
||||
#define LJ_NORET
|
||||
#endif
|
||||
#ifndef LJ_NOAPI
|
||||
#define LJ_NOAPI extern
|
||||
#endif
|
||||
#ifndef LJ_LIKELY
|
||||
#define LJ_LIKELY(x) (x)
|
||||
#define LJ_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
/* Attributes for internal functions. */
|
||||
#define LJ_DATA LJ_NOAPI
|
||||
#define LJ_DATADEF
|
||||
#define LJ_ASMF LJ_NOAPI
|
||||
#define LJ_FUNCA LJ_NOAPI
|
||||
#if defined(ljamalg_c)
|
||||
#define LJ_FUNC static
|
||||
#else
|
||||
#define LJ_FUNC LJ_NOAPI
|
||||
#endif
|
||||
#define LJ_FUNC_NORET LJ_FUNC LJ_NORET
|
||||
#define LJ_FUNCA_NORET LJ_FUNCA LJ_NORET
|
||||
#define LJ_ASMF_NORET LJ_ASMF LJ_NORET
|
||||
|
||||
/* Runtime assertions. */
|
||||
#ifdef lua_assert
|
||||
#define check_exp(c, e) (lua_assert(c), (e))
|
||||
#define api_check(l, e) lua_assert(e)
|
||||
#else
|
||||
#define lua_assert(c) ((void)0)
|
||||
#define check_exp(c, e) (e)
|
||||
#define api_check luai_apicheck
|
||||
#endif
|
||||
|
||||
/* Static assertions. */
|
||||
#define LJ_ASSERT_NAME2(name, line) name ## line
|
||||
#define LJ_ASSERT_NAME(line) LJ_ASSERT_NAME2(lj_assert_, line)
|
||||
#ifdef __COUNTER__
|
||||
#define LJ_STATIC_ASSERT(cond) \
|
||||
//extern void LJ_ASSERT_NAME(__COUNTER__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1])
|
||||
#else
|
||||
#define LJ_STATIC_ASSERT(cond) \
|
||||
extern void LJ_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1])
|
||||
#endif
|
||||
|
||||
#endif
|
||||
156
include/lua/lj_dispatch.h
Normal file
156
include/lua/lj_dispatch.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
** Instruction dispatch handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_DISPATCH_H
|
||||
#define _LJ_DISPATCH_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_bc.h"
|
||||
#if LJ_HASJIT
|
||||
#include "lj_jit.h"
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_MIPS
|
||||
/* Need our own global offset table for the dreaded MIPS calling conventions. */
|
||||
|
||||
#ifndef _LJ_VM_H
|
||||
LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b);
|
||||
#endif
|
||||
|
||||
#if LJ_SOFTFP
|
||||
#ifndef _LJ_IRCALL_H
|
||||
extern double __adddf3(double a, double b);
|
||||
extern double __subdf3(double a, double b);
|
||||
extern double __muldf3(double a, double b);
|
||||
extern double __divdf3(double a, double b);
|
||||
#endif
|
||||
#define SFGOTDEF(_) _(sqrt) _(__adddf3) _(__subdf3) _(__muldf3) _(__divdf3)
|
||||
#else
|
||||
#define SFGOTDEF(_)
|
||||
#endif
|
||||
#if LJ_HASJIT
|
||||
#define JITGOTDEF(_) _(lj_trace_exit) _(lj_trace_hot)
|
||||
#else
|
||||
#define JITGOTDEF(_)
|
||||
#endif
|
||||
#if LJ_HASFFI
|
||||
#define FFIGOTDEF(_) \
|
||||
_(lj_meta_equal_cd) _(lj_ccallback_enter) _(lj_ccallback_leave)
|
||||
#else
|
||||
#define FFIGOTDEF(_)
|
||||
#endif
|
||||
#define GOTDEF(_) \
|
||||
_(floor) _(ceil) _(trunc) _(log) _(log10) _(exp) _(sin) _(cos) _(tan) \
|
||||
_(asin) _(acos) _(atan) _(sinh) _(cosh) _(tanh) _(frexp) _(modf) _(atan2) \
|
||||
_(pow) _(fmod) _(ldexp) _(lj_vm_modi) \
|
||||
_(lj_dispatch_call) _(lj_dispatch_ins) _(lj_dispatch_stitch) \
|
||||
_(lj_dispatch_profile) _(lj_err_throw) \
|
||||
_(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \
|
||||
_(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \
|
||||
_(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \
|
||||
_(lj_meta_for) _(lj_meta_istype) _(lj_meta_len) _(lj_meta_tget) \
|
||||
_(lj_meta_tset) _(lj_state_growstack) _(lj_strfmt_number) \
|
||||
_(lj_str_new) _(lj_tab_dup) _(lj_tab_get) _(lj_tab_getinth) _(lj_tab_len) \
|
||||
_(lj_tab_new) _(lj_tab_newkey) _(lj_tab_next) _(lj_tab_reasize) \
|
||||
_(lj_tab_setinth) _(lj_buf_putstr_reverse) _(lj_buf_putstr_lower) \
|
||||
_(lj_buf_putstr_upper) _(lj_buf_tostr) \
|
||||
JITGOTDEF(_) FFIGOTDEF(_) SFGOTDEF(_)
|
||||
|
||||
enum {
|
||||
#define GOTENUM(name) LJ_GOT_##name,
|
||||
GOTDEF(GOTENUM)
|
||||
#undef GOTENUM
|
||||
LJ_GOT__MAX
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Type of hot counter. Must match the code in the assembler VM. */
|
||||
/* 16 bits are sufficient. Only 0.0015% overhead with maximum slot penalty. */
|
||||
typedef uint16_t HotCount;
|
||||
|
||||
/* Number of hot counter hash table entries (must be a power of two). */
|
||||
#define HOTCOUNT_SIZE 64
|
||||
#define HOTCOUNT_PCMASK ((HOTCOUNT_SIZE-1)*sizeof(HotCount))
|
||||
|
||||
/* Hotcount decrements. */
|
||||
#define HOTCOUNT_LOOP 2
|
||||
#define HOTCOUNT_CALL 1
|
||||
|
||||
/* This solves a circular dependency problem -- bump as needed. Sigh. */
|
||||
#define GG_NUM_ASMFF 57
|
||||
|
||||
#define GG_LEN_DDISP (BC__MAX + GG_NUM_ASMFF)
|
||||
#define GG_LEN_SDISP BC_FUNCF
|
||||
#define GG_LEN_DISP (GG_LEN_DDISP + GG_LEN_SDISP)
|
||||
|
||||
/* Global state, main thread and extra fields are allocated together. */
|
||||
typedef struct GG_State {
|
||||
lua_State L; /* Main thread. */
|
||||
global_State g; /* Global state. */
|
||||
#if LJ_TARGET_MIPS
|
||||
ASMFunction got[LJ_GOT__MAX]; /* Global offset table. */
|
||||
#endif
|
||||
#if LJ_HASJIT
|
||||
jit_State J; /* JIT state. */
|
||||
HotCount hotcount[HOTCOUNT_SIZE]; /* Hot counters. */
|
||||
#endif
|
||||
ASMFunction dispatch[GG_LEN_DISP]; /* Instruction dispatch tables. */
|
||||
BCIns bcff[GG_NUM_ASMFF]; /* Bytecode for ASM fast functions. */
|
||||
} GG_State;
|
||||
|
||||
#define GG_OFS(field) ((int)offsetof(GG_State, field))
|
||||
#define G2GG(gl) ((GG_State *)((char *)(gl) - GG_OFS(g)))
|
||||
#define J2GG(j) ((GG_State *)((char *)(j) - GG_OFS(J)))
|
||||
#define L2GG(L) (G2GG(G(L)))
|
||||
#define J2G(J) (&J2GG(J)->g)
|
||||
#define G2J(gl) (&G2GG(gl)->J)
|
||||
#define L2J(L) (&L2GG(L)->J)
|
||||
#define GG_G2J (GG_OFS(J) - GG_OFS(g))
|
||||
#define GG_G2DISP (GG_OFS(dispatch) - GG_OFS(g))
|
||||
#define GG_DISP2G (GG_OFS(g) - GG_OFS(dispatch))
|
||||
#define GG_DISP2J (GG_OFS(J) - GG_OFS(dispatch))
|
||||
#define GG_DISP2HOT (GG_OFS(hotcount) - GG_OFS(dispatch))
|
||||
#define GG_DISP2STATIC (GG_LEN_DDISP*(int)sizeof(ASMFunction))
|
||||
|
||||
#define hotcount_get(gg, pc) \
|
||||
(gg)->hotcount[(u32ptr(pc)>>2) & (HOTCOUNT_SIZE-1)]
|
||||
#define hotcount_set(gg, pc, val) \
|
||||
(hotcount_get((gg), (pc)) = (HotCount)(val))
|
||||
|
||||
/* Dispatch table management. */
|
||||
LJ_FUNC void lj_dispatch_init(GG_State *GG);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC void lj_dispatch_init_hotcount(global_State *g);
|
||||
#endif
|
||||
LJ_FUNC void lj_dispatch_update(global_State *g);
|
||||
|
||||
/* Instruction dispatch callback for hooks or when recording. */
|
||||
LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc);
|
||||
LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNCA void LJ_FASTCALL lj_dispatch_stitch(jit_State *J, const BCIns *pc);
|
||||
#endif
|
||||
#if LJ_HASPROFILE
|
||||
LJ_FUNCA void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc);
|
||||
#endif
|
||||
|
||||
#if LJ_HASFFI && !defined(_BUILDVM_H)
|
||||
/* Save/restore errno and GetLastError() around hooks, exits and recording. */
|
||||
#include <errno.h>
|
||||
#if LJ_TARGET_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define ERRNO_SAVE int olderr = errno; DWORD oldwerr = GetLastError();
|
||||
#define ERRNO_RESTORE errno = olderr; SetLastError(oldwerr);
|
||||
#else
|
||||
#define ERRNO_SAVE int olderr = errno;
|
||||
#define ERRNO_RESTORE errno = olderr;
|
||||
#endif
|
||||
#else
|
||||
#define ERRNO_SAVE
|
||||
#define ERRNO_RESTORE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
357
include/lua/lj_emit_arm.h
Normal file
357
include/lua/lj_emit_arm.h
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
** ARM instruction emitter.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* -- Constant encoding --------------------------------------------------- */
|
||||
|
||||
static uint8_t emit_invai[16] = {
|
||||
/* AND */ (ARMI_AND^ARMI_BIC) >> 21,
|
||||
/* EOR */ 0,
|
||||
/* SUB */ (ARMI_SUB^ARMI_ADD) >> 21,
|
||||
/* RSB */ 0,
|
||||
/* ADD */ (ARMI_ADD^ARMI_SUB) >> 21,
|
||||
/* ADC */ (ARMI_ADC^ARMI_SBC) >> 21,
|
||||
/* SBC */ (ARMI_SBC^ARMI_ADC) >> 21,
|
||||
/* RSC */ 0,
|
||||
/* TST */ 0,
|
||||
/* TEQ */ 0,
|
||||
/* CMP */ (ARMI_CMP^ARMI_CMN) >> 21,
|
||||
/* CMN */ (ARMI_CMN^ARMI_CMP) >> 21,
|
||||
/* ORR */ 0,
|
||||
/* MOV */ (ARMI_MOV^ARMI_MVN) >> 21,
|
||||
/* BIC */ (ARMI_BIC^ARMI_AND) >> 21,
|
||||
/* MVN */ (ARMI_MVN^ARMI_MOV) >> 21
|
||||
};
|
||||
|
||||
/* Encode constant in K12 format for data processing instructions. */
|
||||
static uint32_t emit_isk12(ARMIns ai, int32_t n)
|
||||
{
|
||||
uint32_t invai, i, m = (uint32_t)n;
|
||||
/* K12: unsigned 8 bit value, rotated in steps of two bits. */
|
||||
for (i = 0; i < 4096; i += 256, m = lj_rol(m, 2))
|
||||
if (m <= 255) return ARMI_K12|m|i;
|
||||
/* Otherwise try negation/complement with the inverse instruction. */
|
||||
invai = emit_invai[((ai >> 21) & 15)];
|
||||
if (!invai) return 0; /* Failed. No inverse instruction. */
|
||||
m = ~(uint32_t)n;
|
||||
if (invai == ((ARMI_SUB^ARMI_ADD) >> 21) ||
|
||||
invai == (ARMI_CMP^ARMI_CMN) >> 21) m++;
|
||||
for (i = 0; i < 4096; i += 256, m = lj_rol(m, 2))
|
||||
if (m <= 255) return ARMI_K12|(invai<<21)|m|i;
|
||||
return 0; /* Failed. */
|
||||
}
|
||||
|
||||
/* -- Emit basic instructions --------------------------------------------- */
|
||||
|
||||
static void emit_dnm(ASMState *as, ARMIns ai, Reg rd, Reg rn, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_D(rd) | ARMF_N(rn) | ARMF_M(rm);
|
||||
}
|
||||
|
||||
static void emit_dm(ASMState *as, ARMIns ai, Reg rd, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_D(rd) | ARMF_M(rm);
|
||||
}
|
||||
|
||||
static void emit_dn(ASMState *as, ARMIns ai, Reg rd, Reg rn)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_D(rd) | ARMF_N(rn);
|
||||
}
|
||||
|
||||
static void emit_nm(ASMState *as, ARMIns ai, Reg rn, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_N(rn) | ARMF_M(rm);
|
||||
}
|
||||
|
||||
static void emit_d(ASMState *as, ARMIns ai, Reg rd)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_D(rd);
|
||||
}
|
||||
|
||||
static void emit_n(ASMState *as, ARMIns ai, Reg rn)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_N(rn);
|
||||
}
|
||||
|
||||
static void emit_m(ASMState *as, ARMIns ai, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | ARMF_M(rm);
|
||||
}
|
||||
|
||||
static void emit_lsox(ASMState *as, ARMIns ai, Reg rd, Reg rn, int32_t ofs)
|
||||
{
|
||||
lua_assert(ofs >= -255 && ofs <= 255);
|
||||
if (ofs < 0) ofs = -ofs; else ai |= ARMI_LS_U;
|
||||
*--as->mcp = ai | ARMI_LS_P | ARMI_LSX_I | ARMF_D(rd) | ARMF_N(rn) |
|
||||
((ofs & 0xf0) << 4) | (ofs & 0x0f);
|
||||
}
|
||||
|
||||
static void emit_lso(ASMState *as, ARMIns ai, Reg rd, Reg rn, int32_t ofs)
|
||||
{
|
||||
lua_assert(ofs >= -4095 && ofs <= 4095);
|
||||
/* Combine LDR/STR pairs to LDRD/STRD. */
|
||||
if (*as->mcp == (ai|ARMI_LS_P|ARMI_LS_U|ARMF_D(rd^1)|ARMF_N(rn)|(ofs^4)) &&
|
||||
(ai & ~(ARMI_LDR^ARMI_STR)) == ARMI_STR && rd != rn &&
|
||||
(uint32_t)ofs <= 252 && !(ofs & 3) && !((rd ^ (ofs >>2)) & 1) &&
|
||||
as->mcp != as->mcloop) {
|
||||
as->mcp++;
|
||||
emit_lsox(as, ai == ARMI_LDR ? ARMI_LDRD : ARMI_STRD, rd&~1, rn, ofs&~4);
|
||||
return;
|
||||
}
|
||||
if (ofs < 0) ofs = -ofs; else ai |= ARMI_LS_U;
|
||||
*--as->mcp = ai | ARMI_LS_P | ARMF_D(rd) | ARMF_N(rn) | ofs;
|
||||
}
|
||||
|
||||
#if !LJ_SOFTFP
|
||||
static void emit_vlso(ASMState *as, ARMIns ai, Reg rd, Reg rn, int32_t ofs)
|
||||
{
|
||||
lua_assert(ofs >= -1020 && ofs <= 1020 && (ofs&3) == 0);
|
||||
if (ofs < 0) ofs = -ofs; else ai |= ARMI_LS_U;
|
||||
*--as->mcp = ai | ARMI_LS_P | ARMF_D(rd & 15) | ARMF_N(rn) | (ofs >> 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Emit loads/stores --------------------------------------------------- */
|
||||
|
||||
/* Prefer spills of BASE/L. */
|
||||
#define emit_canremat(ref) ((ref) < ASMREF_L)
|
||||
|
||||
/* Try to find a one step delta relative to another constant. */
|
||||
static int emit_kdelta1(ASMState *as, Reg d, int32_t i)
|
||||
{
|
||||
RegSet work = ~as->freeset & RSET_GPR;
|
||||
while (work) {
|
||||
Reg r = rset_picktop(work);
|
||||
IRRef ref = regcost_ref(as->cost[r]);
|
||||
lua_assert(r != d);
|
||||
if (emit_canremat(ref)) {
|
||||
int32_t delta = i - (ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i);
|
||||
uint32_t k = emit_isk12(ARMI_ADD, delta);
|
||||
if (k) {
|
||||
if (k == ARMI_K12)
|
||||
emit_dm(as, ARMI_MOV, d, r);
|
||||
else
|
||||
emit_dn(as, ARMI_ADD^k, d, r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
}
|
||||
return 0; /* Failed. */
|
||||
}
|
||||
|
||||
/* Try to find a two step delta relative to another constant. */
|
||||
static int emit_kdelta2(ASMState *as, Reg d, int32_t i)
|
||||
{
|
||||
RegSet work = ~as->freeset & RSET_GPR;
|
||||
while (work) {
|
||||
Reg r = rset_picktop(work);
|
||||
IRRef ref = regcost_ref(as->cost[r]);
|
||||
lua_assert(r != d);
|
||||
if (emit_canremat(ref)) {
|
||||
int32_t other = ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i;
|
||||
if (other) {
|
||||
int32_t delta = i - other;
|
||||
uint32_t sh, inv = 0, k2, k;
|
||||
if (delta < 0) { delta = -delta; inv = ARMI_ADD^ARMI_SUB; }
|
||||
sh = lj_ffs(delta) & ~1;
|
||||
k2 = emit_isk12(0, delta & (255 << sh));
|
||||
k = emit_isk12(0, delta & ~(255 << sh));
|
||||
if (k) {
|
||||
emit_dn(as, ARMI_ADD^k2^inv, d, d);
|
||||
emit_dn(as, ARMI_ADD^k^inv, d, r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
}
|
||||
return 0; /* Failed. */
|
||||
}
|
||||
|
||||
/* Load a 32 bit constant into a GPR. */
|
||||
static void emit_loadi(ASMState *as, Reg r, int32_t i)
|
||||
{
|
||||
uint32_t k = emit_isk12(ARMI_MOV, i);
|
||||
lua_assert(rset_test(as->freeset, r) || r == RID_TMP);
|
||||
if (k) {
|
||||
/* Standard K12 constant. */
|
||||
emit_d(as, ARMI_MOV^k, r);
|
||||
} else if ((as->flags & JIT_F_ARMV6T2) && (uint32_t)i < 0x00010000u) {
|
||||
/* 16 bit loword constant for ARMv6T2. */
|
||||
emit_d(as, ARMI_MOVW|(i & 0x0fff)|((i & 0xf000)<<4), r);
|
||||
} else if (emit_kdelta1(as, r, i)) {
|
||||
/* One step delta relative to another constant. */
|
||||
} else if ((as->flags & JIT_F_ARMV6T2)) {
|
||||
/* 32 bit hiword/loword constant for ARMv6T2. */
|
||||
emit_d(as, ARMI_MOVT|((i>>16) & 0x0fff)|(((i>>16) & 0xf000)<<4), r);
|
||||
emit_d(as, ARMI_MOVW|(i & 0x0fff)|((i & 0xf000)<<4), r);
|
||||
} else if (emit_kdelta2(as, r, i)) {
|
||||
/* Two step delta relative to another constant. */
|
||||
} else {
|
||||
/* Otherwise construct the constant with up to 4 instructions. */
|
||||
/* NYI: use mvn+bic, use pc-relative loads. */
|
||||
for (;;) {
|
||||
uint32_t sh = lj_ffs(i) & ~1;
|
||||
int32_t m = i & (255 << sh);
|
||||
i &= ~(255 << sh);
|
||||
if (i == 0) {
|
||||
emit_d(as, ARMI_MOV ^ emit_isk12(0, m), r);
|
||||
break;
|
||||
}
|
||||
emit_dn(as, ARMI_ORR ^ emit_isk12(0, m), r, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define emit_loada(as, r, addr) emit_loadi(as, (r), i32ptr((addr)))
|
||||
|
||||
static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
|
||||
|
||||
/* Get/set from constant pointer. */
|
||||
static void emit_lsptr(ASMState *as, ARMIns ai, Reg r, void *p)
|
||||
{
|
||||
int32_t i = i32ptr(p);
|
||||
emit_lso(as, ai, r, ra_allock(as, (i & ~4095), rset_exclude(RSET_GPR, r)),
|
||||
(i & 4095));
|
||||
}
|
||||
|
||||
#if !LJ_SOFTFP
|
||||
/* Load a number constant into an FPR. */
|
||||
static void emit_loadk64(ASMState *as, Reg r, IRIns *ir)
|
||||
{
|
||||
cTValue *tv = ir_knum(ir);
|
||||
int32_t i;
|
||||
if ((as->flags & JIT_F_VFPV3) && !tv->u32.lo) {
|
||||
uint32_t hi = tv->u32.hi;
|
||||
uint32_t b = ((hi >> 22) & 0x1ff);
|
||||
if (!(hi & 0xffff) && (b == 0x100 || b == 0x0ff)) {
|
||||
*--as->mcp = ARMI_VMOVI_D | ARMF_D(r & 15) |
|
||||
((tv->u32.hi >> 12) & 0x00080000) |
|
||||
((tv->u32.hi >> 4) & 0x00070000) |
|
||||
((tv->u32.hi >> 16) & 0x0000000f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
i = i32ptr(tv);
|
||||
emit_vlso(as, ARMI_VLDR_D, r,
|
||||
ra_allock(as, (i & ~1020), RSET_GPR), (i & 1020));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get/set global_State fields. */
|
||||
#define emit_getgl(as, r, field) \
|
||||
emit_lsptr(as, ARMI_LDR, (r), (void *)&J2G(as->J)->field)
|
||||
#define emit_setgl(as, r, field) \
|
||||
emit_lsptr(as, ARMI_STR, (r), (void *)&J2G(as->J)->field)
|
||||
|
||||
/* Trace number is determined from pc of exit instruction. */
|
||||
#define emit_setvmstate(as, i) UNUSED(i)
|
||||
|
||||
/* -- Emit control-flow instructions -------------------------------------- */
|
||||
|
||||
/* Label for internal jumps. */
|
||||
typedef MCode *MCLabel;
|
||||
|
||||
/* Return label pointing to current PC. */
|
||||
#define emit_label(as) ((as)->mcp)
|
||||
|
||||
static void emit_branch(ASMState *as, ARMIns ai, MCode *target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
ptrdiff_t delta = (target - p) - 1;
|
||||
lua_assert(((delta + 0x00800000) >> 24) == 0);
|
||||
*--p = ai | ((uint32_t)delta & 0x00ffffffu);
|
||||
as->mcp = p;
|
||||
}
|
||||
|
||||
#define emit_jmp(as, target) emit_branch(as, ARMI_B, (target))
|
||||
|
||||
static void emit_call(ASMState *as, void *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = ((char *)target - (char *)p) - 8;
|
||||
if ((((delta>>2) + 0x00800000) >> 24) == 0) {
|
||||
if ((delta & 1))
|
||||
*p = ARMI_BLX | ((uint32_t)(delta>>2) & 0x00ffffffu) | ((delta&2) << 23);
|
||||
else
|
||||
*p = ARMI_BL | ((uint32_t)(delta>>2) & 0x00ffffffu);
|
||||
} else { /* Target out of range: need indirect call. But don't use R0-R3. */
|
||||
Reg r = ra_allock(as, i32ptr(target), RSET_RANGE(RID_R4, RID_R12+1));
|
||||
*p = ARMI_BLXr | ARMF_M(r);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Emit generic operations --------------------------------------------- */
|
||||
|
||||
/* Generic move between two regs. */
|
||||
static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src)
|
||||
{
|
||||
#if LJ_SOFTFP
|
||||
lua_assert(!irt_isnum(ir->t)); UNUSED(ir);
|
||||
#else
|
||||
if (dst >= RID_MAX_GPR) {
|
||||
emit_dm(as, irt_isnum(ir->t) ? ARMI_VMOV_D : ARMI_VMOV_S,
|
||||
(dst & 15), (src & 15));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (as->mcp != as->mcloop) { /* Swap early registers for loads/stores. */
|
||||
MCode ins = *as->mcp, swp = (src^dst);
|
||||
if ((ins & 0x0c000000) == 0x04000000 && (ins & 0x02000010) != 0x02000010) {
|
||||
if (!((ins ^ (dst << 16)) & 0x000f0000))
|
||||
*as->mcp = ins ^ (swp << 16); /* Swap N in load/store. */
|
||||
if (!(ins & 0x00100000) && !((ins ^ (dst << 12)) & 0x0000f000))
|
||||
*as->mcp = ins ^ (swp << 12); /* Swap D in store. */
|
||||
}
|
||||
}
|
||||
emit_dm(as, ARMI_MOV, dst, src);
|
||||
}
|
||||
|
||||
/* Generic load of register with base and (small) offset address. */
|
||||
static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
#if LJ_SOFTFP
|
||||
lua_assert(!irt_isnum(ir->t)); UNUSED(ir);
|
||||
#else
|
||||
if (r >= RID_MAX_GPR)
|
||||
emit_vlso(as, irt_isnum(ir->t) ? ARMI_VLDR_D : ARMI_VLDR_S, r, base, ofs);
|
||||
else
|
||||
#endif
|
||||
emit_lso(as, ARMI_LDR, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Generic store of register with base and (small) offset address. */
|
||||
static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
#if LJ_SOFTFP
|
||||
lua_assert(!irt_isnum(ir->t)); UNUSED(ir);
|
||||
#else
|
||||
if (r >= RID_MAX_GPR)
|
||||
emit_vlso(as, irt_isnum(ir->t) ? ARMI_VSTR_D : ARMI_VSTR_S, r, base, ofs);
|
||||
else
|
||||
#endif
|
||||
emit_lso(as, ARMI_STR, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Emit an arithmetic/logic operation with a constant operand. */
|
||||
static void emit_opk(ASMState *as, ARMIns ai, Reg dest, Reg src,
|
||||
int32_t i, RegSet allow)
|
||||
{
|
||||
uint32_t k = emit_isk12(ai, i);
|
||||
if (k)
|
||||
emit_dn(as, ai^k, dest, src);
|
||||
else
|
||||
emit_dnm(as, ai, dest, src, ra_allock(as, i, allow));
|
||||
}
|
||||
|
||||
/* Add offset to pointer. */
|
||||
static void emit_addptr(ASMState *as, Reg r, int32_t ofs)
|
||||
{
|
||||
if (ofs)
|
||||
emit_opk(as, ARMI_ADD, r, r, ofs, rset_exclude(RSET_GPR, r));
|
||||
}
|
||||
|
||||
#define emit_spsub(as, ofs) emit_addptr(as, RID_SP, -(ofs))
|
||||
|
||||
419
include/lua/lj_emit_arm64.h
Normal file
419
include/lua/lj_emit_arm64.h
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
** ARM64 instruction emitter.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
||||
** Sponsored by Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
/* -- Constant encoding --------------------------------------------------- */
|
||||
|
||||
static uint64_t get_k64val(IRIns *ir)
|
||||
{
|
||||
if (ir->o == IR_KINT64) {
|
||||
return ir_kint64(ir)->u64;
|
||||
} else if (ir->o == IR_KGC) {
|
||||
return (uint64_t)ir_kgc(ir);
|
||||
} else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) {
|
||||
return (uint64_t)ir_kptr(ir);
|
||||
} else {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KNULL);
|
||||
return ir->i; /* Sign-extended. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode constant in K12 format for data processing instructions. */
|
||||
static uint32_t emit_isk12(int64_t n)
|
||||
{
|
||||
uint64_t k = (n < 0) ? -n : n;
|
||||
uint32_t m = (n < 0) ? 0x40000000 : 0;
|
||||
if (k < 0x1000) {
|
||||
return A64I_K12|m|A64F_U12(k);
|
||||
} else if ((k & 0xfff000) == k) {
|
||||
return A64I_K12|m|0x400000|A64F_U12(k>>12);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define emit_clz64(n) __builtin_clzll(n)
|
||||
#define emit_ctz64(n) __builtin_ctzll(n)
|
||||
|
||||
/* Encode constant in K13 format for logical data processing instructions. */
|
||||
static uint32_t emit_isk13(uint64_t n, int is64)
|
||||
{
|
||||
int inv = 0, w = 128, lz, tz;
|
||||
if (n & 1) { n = ~n; w = 64; inv = 1; } /* Avoid wrap-around of ones. */
|
||||
if (!n) return 0; /* Neither all-zero nor all-ones are allowed. */
|
||||
do { /* Find the repeat width. */
|
||||
if (is64 && (uint32_t)(n^(n>>32))) break;
|
||||
n = (uint32_t)n;
|
||||
if (!n) return 0; /* Ditto when passing n=0xffffffff and is64=0. */
|
||||
w = 32; if ((n^(n>>16)) & 0xffff) break;
|
||||
n = n & 0xffff; w = 16; if ((n^(n>>8)) & 0xff) break;
|
||||
n = n & 0xff; w = 8; if ((n^(n>>4)) & 0xf) break;
|
||||
n = n & 0xf; w = 4; if ((n^(n>>2)) & 0x3) break;
|
||||
n = n & 0x3; w = 2;
|
||||
} while (0);
|
||||
lz = emit_clz64(n);
|
||||
tz = emit_ctz64(n);
|
||||
if ((int64_t)(n << lz) >> (lz+tz) != -1ll) return 0; /* Non-contiguous? */
|
||||
if (inv)
|
||||
return A64I_K13 | (((lz-w) & 127) << 16) | (((lz+tz-w-1) & 63) << 10);
|
||||
else
|
||||
return A64I_K13 | ((w-tz) << 16) | (((63-lz-tz-w-w) & 63) << 10);
|
||||
}
|
||||
|
||||
static uint32_t emit_isfpk64(uint64_t n)
|
||||
{
|
||||
uint64_t etop9 = ((n >> 54) & 0x1ff);
|
||||
if ((n << 16) == 0 && (etop9 == 0x100 || etop9 == 0x0ff)) {
|
||||
return (uint32_t)(((n >> 48) & 0x7f) | ((n >> 56) & 0x80));
|
||||
}
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
/* -- Emit basic instructions --------------------------------------------- */
|
||||
|
||||
static void emit_dnma(ASMState *as, A64Ins ai, Reg rd, Reg rn, Reg rm, Reg ra)
|
||||
{
|
||||
*--as->mcp = ai | A64F_D(rd) | A64F_N(rn) | A64F_M(rm) | A64F_A(ra);
|
||||
}
|
||||
|
||||
static void emit_dnm(ASMState *as, A64Ins ai, Reg rd, Reg rn, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | A64F_D(rd) | A64F_N(rn) | A64F_M(rm);
|
||||
}
|
||||
|
||||
static void emit_dm(ASMState *as, A64Ins ai, Reg rd, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | A64F_D(rd) | A64F_M(rm);
|
||||
}
|
||||
|
||||
static void emit_dn(ASMState *as, A64Ins ai, Reg rd, Reg rn)
|
||||
{
|
||||
*--as->mcp = ai | A64F_D(rd) | A64F_N(rn);
|
||||
}
|
||||
|
||||
static void emit_nm(ASMState *as, A64Ins ai, Reg rn, Reg rm)
|
||||
{
|
||||
*--as->mcp = ai | A64F_N(rn) | A64F_M(rm);
|
||||
}
|
||||
|
||||
static void emit_d(ASMState *as, A64Ins ai, Reg rd)
|
||||
{
|
||||
*--as->mcp = ai | A64F_D(rd);
|
||||
}
|
||||
|
||||
static void emit_n(ASMState *as, A64Ins ai, Reg rn)
|
||||
{
|
||||
*--as->mcp = ai | A64F_N(rn);
|
||||
}
|
||||
|
||||
static int emit_checkofs(A64Ins ai, int64_t ofs)
|
||||
{
|
||||
int scale = (ai >> 30) & 3;
|
||||
if (ofs < 0 || (ofs & ((1<<scale)-1))) {
|
||||
return (ofs >= -256 && ofs <= 255) ? -1 : 0;
|
||||
} else {
|
||||
return (ofs < (4096<<scale)) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_lso(ASMState *as, A64Ins ai, Reg rd, Reg rn, int64_t ofs)
|
||||
{
|
||||
int ot = emit_checkofs(ai, ofs), sc = (ai >> 30) & 3;
|
||||
lua_assert(ot);
|
||||
/* Combine LDR/STR pairs to LDP/STP. */
|
||||
if ((sc == 2 || sc == 3) &&
|
||||
(!(ai & 0x400000) || rd != rn) &&
|
||||
as->mcp != as->mcloop) {
|
||||
uint32_t prev = *as->mcp & ~A64F_D(31);
|
||||
int ofsm = ofs - (1<<sc), ofsp = ofs + (1<<sc);
|
||||
A64Ins aip;
|
||||
if (prev == (ai | A64F_N(rn) | A64F_U12(ofsm>>sc)) ||
|
||||
prev == ((ai^A64I_LS_U) | A64F_N(rn) | A64F_S9(ofsm&0x1ff))) {
|
||||
aip = (A64F_A(rd) | A64F_D(*as->mcp & 31));
|
||||
} else if (prev == (ai | A64F_N(rn) | A64F_U12(ofsp>>sc)) ||
|
||||
prev == ((ai^A64I_LS_U) | A64F_N(rn) | A64F_S9(ofsp&0x1ff))) {
|
||||
aip = (A64F_D(rd) | A64F_A(*as->mcp & 31));
|
||||
ofsm = ofs;
|
||||
} else {
|
||||
goto nopair;
|
||||
}
|
||||
if (ofsm >= (int)((unsigned int)-64<<sc) && ofsm <= (63<<sc)) {
|
||||
*as->mcp = aip | A64F_N(rn) | ((ofsm >> sc) << 15) |
|
||||
(ai ^ ((ai == A64I_LDRx || ai == A64I_STRx) ? 0x50000000 : 0x90000000));
|
||||
return;
|
||||
}
|
||||
}
|
||||
nopair:
|
||||
if (ot == 1)
|
||||
*--as->mcp = ai | A64F_D(rd) | A64F_N(rn) | A64F_U12(ofs >> sc);
|
||||
else
|
||||
*--as->mcp = (ai^A64I_LS_U) | A64F_D(rd) | A64F_N(rn) | A64F_S9(ofs & 0x1ff);
|
||||
}
|
||||
|
||||
/* -- Emit loads/stores --------------------------------------------------- */
|
||||
|
||||
/* Prefer rematerialization of BASE/L from global_State over spills. */
|
||||
#define emit_canremat(ref) ((ref) <= ASMREF_L)
|
||||
|
||||
/* Try to find an N-step delta relative to other consts with N < lim. */
|
||||
static int emit_kdelta(ASMState *as, Reg rd, uint64_t k, int lim)
|
||||
{
|
||||
RegSet work = ~as->freeset & RSET_GPR;
|
||||
if (lim <= 1) return 0; /* Can't beat that. */
|
||||
while (work) {
|
||||
Reg r = rset_picktop(work);
|
||||
IRRef ref = regcost_ref(as->cost[r]);
|
||||
lua_assert(r != rd);
|
||||
if (ref < REF_TRUE) {
|
||||
uint64_t kx = ra_iskref(ref) ? (uint64_t)ra_krefk(as, ref) :
|
||||
get_k64val(IR(ref));
|
||||
int64_t delta = (int64_t)(k - kx);
|
||||
if (delta == 0) {
|
||||
emit_dm(as, A64I_MOVx, rd, r);
|
||||
return 1;
|
||||
} else {
|
||||
uint32_t k12 = emit_isk12(delta < 0 ? -delta : delta);
|
||||
if (k12) {
|
||||
emit_dn(as, (delta < 0 ? A64I_SUBx : A64I_ADDx)^k12, rd, r);
|
||||
return 1;
|
||||
}
|
||||
/* Do other ops or multi-step deltas pay off? Probably not.
|
||||
** E.g. XOR rarely helps with pointer consts.
|
||||
*/
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
}
|
||||
return 0; /* Failed. */
|
||||
}
|
||||
|
||||
static void emit_loadk(ASMState *as, Reg rd, uint64_t u64, int is64)
|
||||
{
|
||||
uint32_t k13 = emit_isk13(u64, is64);
|
||||
if (k13) { /* Can the constant be represented as a bitmask immediate? */
|
||||
emit_dn(as, (is64|A64I_ORRw)^k13, rd, RID_ZERO);
|
||||
} else {
|
||||
int i, zeros = 0, ones = 0, neg;
|
||||
if (!is64) u64 = (int64_t)(int32_t)u64; /* Sign-extend. */
|
||||
/* Count homogeneous 16 bit fragments. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
uint64_t frag = (u64 >> i*16) & 0xffff;
|
||||
zeros += (frag == 0);
|
||||
ones += (frag == 0xffff);
|
||||
}
|
||||
neg = ones > zeros; /* Use MOVN if it pays off. */
|
||||
if (!emit_kdelta(as, rd, u64, 4 - (neg ? ones : zeros))) {
|
||||
int shift = 0, lshift = 0;
|
||||
uint64_t n64 = neg ? ~u64 : u64;
|
||||
if (n64 != 0) {
|
||||
/* Find first/last fragment to be filled. */
|
||||
shift = (63-emit_clz64(n64)) & ~15;
|
||||
lshift = emit_ctz64(n64) & ~15;
|
||||
}
|
||||
/* MOVK requires the original value (u64). */
|
||||
while (shift > lshift) {
|
||||
uint32_t u16 = (u64 >> shift) & 0xffff;
|
||||
/* Skip fragments that are correctly filled by MOVN/MOVZ. */
|
||||
if (u16 != (neg ? 0xffff : 0))
|
||||
emit_d(as, is64 | A64I_MOVKw | A64F_U16(u16) | A64F_LSL16(shift), rd);
|
||||
shift -= 16;
|
||||
}
|
||||
/* But MOVN needs an inverted value (n64). */
|
||||
emit_d(as, (neg ? A64I_MOVNx : A64I_MOVZx) |
|
||||
A64F_U16((n64 >> lshift) & 0xffff) | A64F_LSL16(lshift), rd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Load a 32 bit constant into a GPR. */
|
||||
#define emit_loadi(as, rd, i) emit_loadk(as, rd, i, 0)
|
||||
|
||||
/* Load a 64 bit constant into a GPR. */
|
||||
#define emit_loadu64(as, rd, i) emit_loadk(as, rd, i, A64I_X)
|
||||
|
||||
#define emit_loada(as, r, addr) emit_loadu64(as, (r), (uintptr_t)(addr))
|
||||
|
||||
#define glofs(as, k) \
|
||||
((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g))
|
||||
#define mcpofs(as, k) \
|
||||
((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1)))
|
||||
#define checkmcpofs(as, k) \
|
||||
((((mcpofs(as, k)>>2) + 0x00040000) >> 19) == 0)
|
||||
|
||||
static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
|
||||
|
||||
/* Get/set from constant pointer. */
|
||||
static void emit_lsptr(ASMState *as, A64Ins ai, Reg r, void *p)
|
||||
{
|
||||
/* First, check if ip + offset is in range. */
|
||||
if ((ai & 0x00400000) && checkmcpofs(as, p)) {
|
||||
emit_d(as, A64I_LDRLx | A64F_S19(mcpofs(as, p)>>2), r);
|
||||
} else {
|
||||
Reg base = RID_GL; /* Next, try GL + offset. */
|
||||
int64_t ofs = glofs(as, p);
|
||||
if (!emit_checkofs(ai, ofs)) { /* Else split up into base reg + offset. */
|
||||
int64_t i64 = i64ptr(p);
|
||||
base = ra_allock(as, (i64 & ~0x7fffull), rset_exclude(RSET_GPR, r));
|
||||
ofs = i64 & 0x7fffull;
|
||||
}
|
||||
emit_lso(as, ai, r, base, ofs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load 64 bit IR constant into register. */
|
||||
static void emit_loadk64(ASMState *as, Reg r, IRIns *ir)
|
||||
{
|
||||
const uint64_t *k = &ir_k64(ir)->u64;
|
||||
int64_t ofs;
|
||||
if (r >= RID_MAX_GPR) {
|
||||
uint32_t fpk = emit_isfpk64(*k);
|
||||
if (fpk != ~0u) {
|
||||
emit_d(as, A64I_FMOV_DI | A64F_FP8(fpk), (r & 31));
|
||||
return;
|
||||
}
|
||||
}
|
||||
ofs = glofs(as, k);
|
||||
if (emit_checkofs(A64I_LDRx, ofs)) {
|
||||
emit_lso(as, r >= RID_MAX_GPR ? A64I_LDRd : A64I_LDRx,
|
||||
(r & 31), RID_GL, ofs);
|
||||
} else {
|
||||
if (r >= RID_MAX_GPR) {
|
||||
emit_dn(as, A64I_FMOV_D_R, (r & 31), RID_TMP);
|
||||
r = RID_TMP;
|
||||
}
|
||||
if (checkmcpofs(as, k))
|
||||
emit_d(as, A64I_LDRLx | A64F_S19(mcpofs(as, k)>>2), r);
|
||||
else
|
||||
emit_loadu64(as, r, *k);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get/set global_State fields. */
|
||||
#define emit_getgl(as, r, field) \
|
||||
emit_lsptr(as, A64I_LDRx, (r), (void *)&J2G(as->J)->field)
|
||||
#define emit_setgl(as, r, field) \
|
||||
emit_lsptr(as, A64I_STRx, (r), (void *)&J2G(as->J)->field)
|
||||
|
||||
/* Trace number is determined from pc of exit instruction. */
|
||||
#define emit_setvmstate(as, i) UNUSED(i)
|
||||
|
||||
/* -- Emit control-flow instructions -------------------------------------- */
|
||||
|
||||
/* Label for internal jumps. */
|
||||
typedef MCode *MCLabel;
|
||||
|
||||
/* Return label pointing to current PC. */
|
||||
#define emit_label(as) ((as)->mcp)
|
||||
|
||||
static void emit_cond_branch(ASMState *as, A64CC cond, MCode *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(((delta + 0x40000) >> 19) == 0);
|
||||
*p = A64I_BCC | A64F_S19(delta) | cond;
|
||||
}
|
||||
|
||||
static void emit_branch(ASMState *as, A64Ins ai, MCode *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(((delta + 0x02000000) >> 26) == 0);
|
||||
*p = ai | ((uint32_t)delta & 0x03ffffffu);
|
||||
}
|
||||
|
||||
static void emit_tnb(ASMState *as, A64Ins ai, Reg r, uint32_t bit, MCode *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(bit < 63 && ((delta + 0x2000) >> 14) == 0);
|
||||
if (bit > 31) ai |= A64I_X;
|
||||
*p = ai | A64F_BIT(bit & 31) | A64F_S14((uint32_t)delta & 0x3fffu) | r;
|
||||
}
|
||||
|
||||
static void emit_cnb(ASMState *as, A64Ins ai, Reg r, MCode *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(((delta + 0x40000) >> 19) == 0);
|
||||
*p = ai | A64F_S19(delta) | r;
|
||||
}
|
||||
|
||||
#define emit_jmp(as, target) emit_branch(as, A64I_B, (target))
|
||||
|
||||
static void emit_call(ASMState *as, void *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = (char *)target - (char *)p;
|
||||
if ((((delta>>2) + 0x02000000) >> 26) == 0) {
|
||||
*p = A64I_BL | ((uint32_t)(delta>>2) & 0x03ffffffu);
|
||||
} else { /* Target out of range: need indirect call. But don't use R0-R7. */
|
||||
Reg r = ra_allock(as, i64ptr(target),
|
||||
RSET_RANGE(RID_X8, RID_MAX_GPR)-RSET_FIXED);
|
||||
*p = A64I_BLR | A64F_N(r);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Emit generic operations --------------------------------------------- */
|
||||
|
||||
/* Generic move between two regs. */
|
||||
static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src)
|
||||
{
|
||||
if (dst >= RID_MAX_GPR) {
|
||||
emit_dn(as, irt_isnum(ir->t) ? A64I_FMOV_D : A64I_FMOV_S,
|
||||
(dst & 31), (src & 31));
|
||||
return;
|
||||
}
|
||||
if (as->mcp != as->mcloop) { /* Swap early registers for loads/stores. */
|
||||
MCode ins = *as->mcp, swp = (src^dst);
|
||||
if ((ins & 0xbf800000) == 0xb9000000) {
|
||||
if (!((ins ^ (dst << 5)) & 0x000003e0))
|
||||
*as->mcp = ins ^ (swp << 5); /* Swap N in load/store. */
|
||||
if (!(ins & 0x00400000) && !((ins ^ dst) & 0x0000001f))
|
||||
*as->mcp = ins ^ swp; /* Swap D in store. */
|
||||
}
|
||||
}
|
||||
emit_dm(as, A64I_MOVx, dst, src);
|
||||
}
|
||||
|
||||
/* Generic load of register with base and (small) offset address. */
|
||||
static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r >= RID_MAX_GPR)
|
||||
emit_lso(as, irt_isnum(ir->t) ? A64I_LDRd : A64I_LDRs, (r & 31), base, ofs);
|
||||
else
|
||||
emit_lso(as, irt_is64(ir->t) ? A64I_LDRx : A64I_LDRw, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Generic store of register with base and (small) offset address. */
|
||||
static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r >= RID_MAX_GPR)
|
||||
emit_lso(as, irt_isnum(ir->t) ? A64I_STRd : A64I_STRs, (r & 31), base, ofs);
|
||||
else
|
||||
emit_lso(as, irt_is64(ir->t) ? A64I_STRx : A64I_STRw, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Emit an arithmetic operation with a constant operand. */
|
||||
static void emit_opk(ASMState *as, A64Ins ai, Reg dest, Reg src,
|
||||
int32_t i, RegSet allow)
|
||||
{
|
||||
uint32_t k = emit_isk12(i);
|
||||
if (k)
|
||||
emit_dn(as, ai^k, dest, src);
|
||||
else
|
||||
emit_dnm(as, ai, dest, src, ra_allock(as, i, allow));
|
||||
}
|
||||
|
||||
/* Add offset to pointer. */
|
||||
static void emit_addptr(ASMState *as, Reg r, int32_t ofs)
|
||||
{
|
||||
if (ofs)
|
||||
emit_opk(as, ofs < 0 ? A64I_SUBx : A64I_ADDx, r, r,
|
||||
ofs < 0 ? -ofs : ofs, rset_exclude(RSET_GPR, r));
|
||||
}
|
||||
|
||||
#define emit_spsub(as, ofs) emit_addptr(as, RID_SP, -(ofs))
|
||||
|
||||
293
include/lua/lj_emit_mips.h
Normal file
293
include/lua/lj_emit_mips.h
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
** MIPS instruction emitter.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#if LJ_64
|
||||
static intptr_t get_k64val(IRIns *ir)
|
||||
{
|
||||
if (ir->o == IR_KINT64) {
|
||||
return (intptr_t)ir_kint64(ir)->u64;
|
||||
} else if (ir->o == IR_KGC) {
|
||||
return (intptr_t)ir_kgc(ir);
|
||||
} else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) {
|
||||
return (intptr_t)ir_kptr(ir);
|
||||
} else {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KNULL);
|
||||
return ir->i; /* Sign-extended. */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LJ_64
|
||||
#define get_kval(ir) get_k64val(ir)
|
||||
#else
|
||||
#define get_kval(ir) ((ir)->i)
|
||||
#endif
|
||||
|
||||
/* -- Emit basic instructions --------------------------------------------- */
|
||||
|
||||
static void emit_dst(ASMState *as, MIPSIns mi, Reg rd, Reg rs, Reg rt)
|
||||
{
|
||||
*--as->mcp = mi | MIPSF_D(rd) | MIPSF_S(rs) | MIPSF_T(rt);
|
||||
}
|
||||
|
||||
static void emit_dta(ASMState *as, MIPSIns mi, Reg rd, Reg rt, uint32_t a)
|
||||
{
|
||||
*--as->mcp = mi | MIPSF_D(rd) | MIPSF_T(rt) | MIPSF_A(a);
|
||||
}
|
||||
|
||||
#define emit_ds(as, mi, rd, rs) emit_dst(as, (mi), (rd), (rs), 0)
|
||||
#define emit_tg(as, mi, rt, rg) emit_dst(as, (mi), (rg)&31, 0, (rt))
|
||||
|
||||
static void emit_tsi(ASMState *as, MIPSIns mi, Reg rt, Reg rs, int32_t i)
|
||||
{
|
||||
*--as->mcp = mi | MIPSF_T(rt) | MIPSF_S(rs) | (i & 0xffff);
|
||||
}
|
||||
|
||||
#define emit_ti(as, mi, rt, i) emit_tsi(as, (mi), (rt), 0, (i))
|
||||
#define emit_hsi(as, mi, rh, rs, i) emit_tsi(as, (mi), (rh) & 31, (rs), (i))
|
||||
|
||||
static void emit_fgh(ASMState *as, MIPSIns mi, Reg rf, Reg rg, Reg rh)
|
||||
{
|
||||
*--as->mcp = mi | MIPSF_F(rf&31) | MIPSF_G(rg&31) | MIPSF_H(rh&31);
|
||||
}
|
||||
|
||||
#define emit_fg(as, mi, rf, rg) emit_fgh(as, (mi), (rf), (rg), 0)
|
||||
|
||||
static void emit_rotr(ASMState *as, Reg dest, Reg src, Reg tmp, uint32_t shift)
|
||||
{
|
||||
if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) {
|
||||
emit_dta(as, MIPSI_ROTR, dest, src, shift);
|
||||
} else {
|
||||
emit_dst(as, MIPSI_OR, dest, dest, tmp);
|
||||
emit_dta(as, MIPSI_SLL, dest, src, (-shift)&31);
|
||||
emit_dta(as, MIPSI_SRL, tmp, src, shift);
|
||||
}
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
static void emit_tsml(ASMState *as, MIPSIns mi, Reg rt, Reg rs, uint32_t msb,
|
||||
uint32_t lsb)
|
||||
{
|
||||
*--as->mcp = mi | MIPSF_T(rt) | MIPSF_S(rs) | MIPSF_M(msb) | MIPSF_L(lsb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Emit loads/stores --------------------------------------------------- */
|
||||
|
||||
/* Prefer rematerialization of BASE/L from global_State over spills. */
|
||||
#define emit_canremat(ref) ((ref) <= REF_BASE)
|
||||
|
||||
/* Try to find a one step delta relative to another constant. */
|
||||
static int emit_kdelta1(ASMState *as, Reg t, intptr_t i)
|
||||
{
|
||||
RegSet work = ~as->freeset & RSET_GPR;
|
||||
while (work) {
|
||||
Reg r = rset_picktop(work);
|
||||
IRRef ref = regcost_ref(as->cost[r]);
|
||||
lua_assert(r != t);
|
||||
if (ref < ASMREF_L) {
|
||||
intptr_t delta = (intptr_t)((uintptr_t)i -
|
||||
(uintptr_t)(ra_iskref(ref) ? ra_krefk(as, ref) : get_kval(IR(ref))));
|
||||
if (checki16(delta)) {
|
||||
emit_tsi(as, MIPSI_AADDIU, t, r, delta);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
}
|
||||
return 0; /* Failed. */
|
||||
}
|
||||
|
||||
/* Load a 32 bit constant into a GPR. */
|
||||
static void emit_loadi(ASMState *as, Reg r, int32_t i)
|
||||
{
|
||||
if (checki16(i)) {
|
||||
emit_ti(as, MIPSI_LI, r, i);
|
||||
} else {
|
||||
if ((i & 0xffff)) {
|
||||
intptr_t jgl = (intptr_t)(void *)J2G(as->J);
|
||||
if ((uintptr_t)(i-jgl) < 65536) {
|
||||
emit_tsi(as, MIPSI_ADDIU, r, RID_JGL, i-jgl-32768);
|
||||
return;
|
||||
} else if (emit_kdelta1(as, r, i)) {
|
||||
return;
|
||||
} else if ((i >> 16) == 0) {
|
||||
emit_tsi(as, MIPSI_ORI, r, RID_ZERO, i);
|
||||
return;
|
||||
}
|
||||
emit_tsi(as, MIPSI_ORI, r, r, i);
|
||||
}
|
||||
emit_ti(as, MIPSI_LUI, r, (i >> 16));
|
||||
}
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
/* Load a 64 bit constant into a GPR. */
|
||||
static void emit_loadu64(ASMState *as, Reg r, uint64_t u64)
|
||||
{
|
||||
if (checki32((int64_t)u64)) {
|
||||
emit_loadi(as, r, (int32_t)u64);
|
||||
} else {
|
||||
uint64_t delta = u64 - (uint64_t)(void *)J2G(as->J);
|
||||
if (delta < 65536) {
|
||||
emit_tsi(as, MIPSI_DADDIU, r, RID_JGL, (int32_t)(delta-32768));
|
||||
} else if (emit_kdelta1(as, r, (intptr_t)u64)) {
|
||||
return;
|
||||
} else {
|
||||
if ((u64 & 0xffff)) {
|
||||
emit_tsi(as, MIPSI_ORI, r, r, u64 & 0xffff);
|
||||
}
|
||||
if (((u64 >> 16) & 0xffff)) {
|
||||
emit_dta(as, MIPSI_DSLL, r, r, 16);
|
||||
emit_tsi(as, MIPSI_ORI, r, r, (u64 >> 16) & 0xffff);
|
||||
emit_dta(as, MIPSI_DSLL, r, r, 16);
|
||||
} else {
|
||||
emit_dta(as, MIPSI_DSLL32, r, r, 0);
|
||||
}
|
||||
emit_loadi(as, r, (int32_t)(u64 >> 32));
|
||||
}
|
||||
/* TODO: There are probably more optimization opportunities. */
|
||||
}
|
||||
}
|
||||
|
||||
#define emit_loada(as, r, addr) emit_loadu64(as, (r), u64ptr((addr)))
|
||||
#else
|
||||
#define emit_loada(as, r, addr) emit_loadi(as, (r), i32ptr((addr)))
|
||||
#endif
|
||||
|
||||
static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
|
||||
static void ra_allockreg(ASMState *as, intptr_t k, Reg r);
|
||||
|
||||
/* Get/set from constant pointer. */
|
||||
static void emit_lsptr(ASMState *as, MIPSIns mi, Reg r, void *p, RegSet allow)
|
||||
{
|
||||
intptr_t jgl = (intptr_t)(J2G(as->J));
|
||||
intptr_t i = (intptr_t)(p);
|
||||
Reg base;
|
||||
if ((uint32_t)(i-jgl) < 65536) {
|
||||
i = i-jgl-32768;
|
||||
base = RID_JGL;
|
||||
} else {
|
||||
base = ra_allock(as, i-(int16_t)i, allow);
|
||||
}
|
||||
emit_tsi(as, mi, r, base, i);
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
static void emit_loadk64(ASMState *as, Reg r, IRIns *ir)
|
||||
{
|
||||
const uint64_t *k = &ir_k64(ir)->u64;
|
||||
Reg r64 = r;
|
||||
if (rset_test(RSET_FPR, r)) {
|
||||
r64 = RID_TMP;
|
||||
emit_tg(as, MIPSI_DMTC1, r64, r);
|
||||
}
|
||||
if ((uint32_t)((intptr_t)k-(intptr_t)J2G(as->J)) < 65536)
|
||||
emit_lsptr(as, MIPSI_LD, r64, (void *)k, 0);
|
||||
else
|
||||
emit_loadu64(as, r64, *k);
|
||||
}
|
||||
#else
|
||||
#define emit_loadk64(as, r, ir) \
|
||||
emit_lsptr(as, MIPSI_LDC1, ((r) & 31), (void *)&ir_knum((ir))->u64, RSET_GPR)
|
||||
#endif
|
||||
|
||||
/* Get/set global_State fields. */
|
||||
static void emit_lsglptr(ASMState *as, MIPSIns mi, Reg r, int32_t ofs)
|
||||
{
|
||||
emit_tsi(as, mi, r, RID_JGL, ofs-32768);
|
||||
}
|
||||
|
||||
#define emit_getgl(as, r, field) \
|
||||
emit_lsglptr(as, MIPSI_AL, (r), (int32_t)offsetof(global_State, field))
|
||||
#define emit_setgl(as, r, field) \
|
||||
emit_lsglptr(as, MIPSI_AS, (r), (int32_t)offsetof(global_State, field))
|
||||
|
||||
/* Trace number is determined from per-trace exit stubs. */
|
||||
#define emit_setvmstate(as, i) UNUSED(i)
|
||||
|
||||
/* -- Emit control-flow instructions -------------------------------------- */
|
||||
|
||||
/* Label for internal jumps. */
|
||||
typedef MCode *MCLabel;
|
||||
|
||||
/* Return label pointing to current PC. */
|
||||
#define emit_label(as) ((as)->mcp)
|
||||
|
||||
static void emit_branch(ASMState *as, MIPSIns mi, Reg rs, Reg rt, MCode *target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(((delta + 0x8000) >> 16) == 0);
|
||||
*--p = mi | MIPSF_S(rs) | MIPSF_T(rt) | ((uint32_t)delta & 0xffffu);
|
||||
as->mcp = p;
|
||||
}
|
||||
|
||||
static void emit_jmp(ASMState *as, MCode *target)
|
||||
{
|
||||
*--as->mcp = MIPSI_NOP;
|
||||
emit_branch(as, MIPSI_B, RID_ZERO, RID_ZERO, (target));
|
||||
}
|
||||
|
||||
static void emit_call(ASMState *as, void *target, int needcfa)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
*--p = MIPSI_NOP;
|
||||
if ((((uintptr_t)target ^ (uintptr_t)p) >> 28) == 0) {
|
||||
*--p = (((uintptr_t)target & 1) ? MIPSI_JALX : MIPSI_JAL) |
|
||||
(((uintptr_t)target >>2) & 0x03ffffffu);
|
||||
} else { /* Target out of range: need indirect call. */
|
||||
*--p = MIPSI_JALR | MIPSF_S(RID_CFUNCADDR);
|
||||
needcfa = 1;
|
||||
}
|
||||
as->mcp = p;
|
||||
if (needcfa) ra_allockreg(as, (intptr_t)target, RID_CFUNCADDR);
|
||||
}
|
||||
|
||||
/* -- Emit generic operations --------------------------------------------- */
|
||||
|
||||
#define emit_move(as, dst, src) \
|
||||
emit_ds(as, MIPSI_MOVE, (dst), (src))
|
||||
|
||||
/* Generic move between two regs. */
|
||||
static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src)
|
||||
{
|
||||
if (dst < RID_MAX_GPR)
|
||||
emit_move(as, dst, src);
|
||||
else
|
||||
emit_fg(as, irt_isnum(ir->t) ? MIPSI_MOV_D : MIPSI_MOV_S, dst, src);
|
||||
}
|
||||
|
||||
/* Generic load of register with base and (small) offset address. */
|
||||
static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r < RID_MAX_GPR)
|
||||
emit_tsi(as, irt_is64(ir->t) ? MIPSI_LD : MIPSI_LW, r, base, ofs);
|
||||
else
|
||||
emit_tsi(as, irt_isnum(ir->t) ? MIPSI_LDC1 : MIPSI_LWC1,
|
||||
(r & 31), base, ofs);
|
||||
}
|
||||
|
||||
/* Generic store of register with base and (small) offset address. */
|
||||
static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r < RID_MAX_GPR)
|
||||
emit_tsi(as, irt_is64(ir->t) ? MIPSI_SD : MIPSI_SW, r, base, ofs);
|
||||
else
|
||||
emit_tsi(as, irt_isnum(ir->t) ? MIPSI_SDC1 : MIPSI_SWC1,
|
||||
(r&31), base, ofs);
|
||||
}
|
||||
|
||||
/* Add offset to pointer. */
|
||||
static void emit_addptr(ASMState *as, Reg r, int32_t ofs)
|
||||
{
|
||||
if (ofs) {
|
||||
lua_assert(checki16(ofs));
|
||||
emit_tsi(as, MIPSI_AADDIU, r, r, ofs);
|
||||
}
|
||||
}
|
||||
|
||||
#define emit_spsub(as, ofs) emit_addptr(as, RID_SP, -(ofs))
|
||||
|
||||
238
include/lua/lj_emit_ppc.h
Normal file
238
include/lua/lj_emit_ppc.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
** PPC instruction emitter.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* -- Emit basic instructions --------------------------------------------- */
|
||||
|
||||
static void emit_tab(ASMState *as, PPCIns pi, Reg rt, Reg ra, Reg rb)
|
||||
{
|
||||
*--as->mcp = pi | PPCF_T(rt) | PPCF_A(ra) | PPCF_B(rb);
|
||||
}
|
||||
|
||||
#define emit_asb(as, pi, ra, rs, rb) emit_tab(as, (pi), (rs), (ra), (rb))
|
||||
#define emit_as(as, pi, ra, rs) emit_tab(as, (pi), (rs), (ra), 0)
|
||||
#define emit_ab(as, pi, ra, rb) emit_tab(as, (pi), 0, (ra), (rb))
|
||||
|
||||
static void emit_tai(ASMState *as, PPCIns pi, Reg rt, Reg ra, int32_t i)
|
||||
{
|
||||
*--as->mcp = pi | PPCF_T(rt) | PPCF_A(ra) | (i & 0xffff);
|
||||
}
|
||||
|
||||
#define emit_ti(as, pi, rt, i) emit_tai(as, (pi), (rt), 0, (i))
|
||||
#define emit_ai(as, pi, ra, i) emit_tai(as, (pi), 0, (ra), (i))
|
||||
#define emit_asi(as, pi, ra, rs, i) emit_tai(as, (pi), (rs), (ra), (i))
|
||||
|
||||
#define emit_fab(as, pi, rf, ra, rb) \
|
||||
emit_tab(as, (pi), (rf)&31, (ra)&31, (rb)&31)
|
||||
#define emit_fb(as, pi, rf, rb) emit_tab(as, (pi), (rf)&31, 0, (rb)&31)
|
||||
#define emit_fac(as, pi, rf, ra, rc) \
|
||||
emit_tab(as, (pi) | PPCF_C((rc) & 31), (rf)&31, (ra)&31, 0)
|
||||
#define emit_facb(as, pi, rf, ra, rc, rb) \
|
||||
emit_tab(as, (pi) | PPCF_C((rc) & 31), (rf)&31, (ra)&31, (rb)&31)
|
||||
#define emit_fai(as, pi, rf, ra, i) emit_tai(as, (pi), (rf)&31, (ra), (i))
|
||||
|
||||
static void emit_rot(ASMState *as, PPCIns pi, Reg ra, Reg rs,
|
||||
int32_t n, int32_t b, int32_t e)
|
||||
{
|
||||
*--as->mcp = pi | PPCF_T(rs) | PPCF_A(ra) | PPCF_B(n) |
|
||||
PPCF_MB(b) | PPCF_ME(e);
|
||||
}
|
||||
|
||||
static void emit_slwi(ASMState *as, Reg ra, Reg rs, int32_t n)
|
||||
{
|
||||
lua_assert(n >= 0 && n < 32);
|
||||
emit_rot(as, PPCI_RLWINM, ra, rs, n, 0, 31-n);
|
||||
}
|
||||
|
||||
static void emit_rotlwi(ASMState *as, Reg ra, Reg rs, int32_t n)
|
||||
{
|
||||
lua_assert(n >= 0 && n < 32);
|
||||
emit_rot(as, PPCI_RLWINM, ra, rs, n, 0, 31);
|
||||
}
|
||||
|
||||
/* -- Emit loads/stores --------------------------------------------------- */
|
||||
|
||||
/* Prefer rematerialization of BASE/L from global_State over spills. */
|
||||
#define emit_canremat(ref) ((ref) <= REF_BASE)
|
||||
|
||||
/* Try to find a one step delta relative to another constant. */
|
||||
static int emit_kdelta1(ASMState *as, Reg t, int32_t i)
|
||||
{
|
||||
RegSet work = ~as->freeset & RSET_GPR;
|
||||
while (work) {
|
||||
Reg r = rset_picktop(work);
|
||||
IRRef ref = regcost_ref(as->cost[r]);
|
||||
lua_assert(r != t);
|
||||
if (ref < ASMREF_L) {
|
||||
int32_t delta = i - (ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i);
|
||||
if (checki16(delta)) {
|
||||
emit_tai(as, PPCI_ADDI, t, r, delta);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
}
|
||||
return 0; /* Failed. */
|
||||
}
|
||||
|
||||
/* Load a 32 bit constant into a GPR. */
|
||||
static void emit_loadi(ASMState *as, Reg r, int32_t i)
|
||||
{
|
||||
if (checki16(i)) {
|
||||
emit_ti(as, PPCI_LI, r, i);
|
||||
} else {
|
||||
if ((i & 0xffff)) {
|
||||
int32_t jgl = i32ptr(J2G(as->J));
|
||||
if ((uint32_t)(i-jgl) < 65536) {
|
||||
emit_tai(as, PPCI_ADDI, r, RID_JGL, i-jgl-32768);
|
||||
return;
|
||||
} else if (emit_kdelta1(as, r, i)) {
|
||||
return;
|
||||
}
|
||||
emit_asi(as, PPCI_ORI, r, r, i);
|
||||
}
|
||||
emit_ti(as, PPCI_LIS, r, (i >> 16));
|
||||
}
|
||||
}
|
||||
|
||||
#define emit_loada(as, r, addr) emit_loadi(as, (r), i32ptr((addr)))
|
||||
|
||||
static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
|
||||
|
||||
/* Get/set from constant pointer. */
|
||||
static void emit_lsptr(ASMState *as, PPCIns pi, Reg r, void *p, RegSet allow)
|
||||
{
|
||||
int32_t jgl = i32ptr(J2G(as->J));
|
||||
int32_t i = i32ptr(p);
|
||||
Reg base;
|
||||
if ((uint32_t)(i-jgl) < 65536) {
|
||||
i = i-jgl-32768;
|
||||
base = RID_JGL;
|
||||
} else {
|
||||
base = ra_allock(as, i-(int16_t)i, allow);
|
||||
}
|
||||
emit_tai(as, pi, r, base, i);
|
||||
}
|
||||
|
||||
#define emit_loadk64(as, r, ir) \
|
||||
emit_lsptr(as, PPCI_LFD, ((r) & 31), (void *)&ir_knum((ir))->u64, RSET_GPR)
|
||||
|
||||
/* Get/set global_State fields. */
|
||||
static void emit_lsglptr(ASMState *as, PPCIns pi, Reg r, int32_t ofs)
|
||||
{
|
||||
emit_tai(as, pi, r, RID_JGL, ofs-32768);
|
||||
}
|
||||
|
||||
#define emit_getgl(as, r, field) \
|
||||
emit_lsglptr(as, PPCI_LWZ, (r), (int32_t)offsetof(global_State, field))
|
||||
#define emit_setgl(as, r, field) \
|
||||
emit_lsglptr(as, PPCI_STW, (r), (int32_t)offsetof(global_State, field))
|
||||
|
||||
/* Trace number is determined from per-trace exit stubs. */
|
||||
#define emit_setvmstate(as, i) UNUSED(i)
|
||||
|
||||
/* -- Emit control-flow instructions -------------------------------------- */
|
||||
|
||||
/* Label for internal jumps. */
|
||||
typedef MCode *MCLabel;
|
||||
|
||||
/* Return label pointing to current PC. */
|
||||
#define emit_label(as) ((as)->mcp)
|
||||
|
||||
static void emit_condbranch(ASMState *as, PPCIns pi, PPCCC cc, MCode *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = (char *)target - (char *)p;
|
||||
lua_assert(((delta + 0x8000) >> 16) == 0);
|
||||
pi ^= (delta & 0x8000) * (PPCF_Y/0x8000);
|
||||
*p = pi | PPCF_CC(cc) | ((uint32_t)delta & 0xffffu);
|
||||
}
|
||||
|
||||
static void emit_jmp(ASMState *as, MCode *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = (char *)target - (char *)p;
|
||||
*p = PPCI_B | (delta & 0x03fffffcu);
|
||||
}
|
||||
|
||||
static void emit_call(ASMState *as, void *target)
|
||||
{
|
||||
MCode *p = --as->mcp;
|
||||
ptrdiff_t delta = (char *)target - (char *)p;
|
||||
if ((((delta>>2) + 0x00800000) >> 24) == 0) {
|
||||
*p = PPCI_BL | (delta & 0x03fffffcu);
|
||||
} else { /* Target out of range: need indirect call. Don't use arg reg. */
|
||||
RegSet allow = RSET_GPR & ~RSET_RANGE(RID_R0, REGARG_LASTGPR+1);
|
||||
Reg r = ra_allock(as, i32ptr(target), allow);
|
||||
*p = PPCI_BCTRL;
|
||||
p[-1] = PPCI_MTCTR | PPCF_T(r);
|
||||
as->mcp = p-1;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Emit generic operations --------------------------------------------- */
|
||||
|
||||
#define emit_mr(as, dst, src) \
|
||||
emit_asb(as, PPCI_MR, (dst), (src), (src))
|
||||
|
||||
/* Generic move between two regs. */
|
||||
static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src)
|
||||
{
|
||||
UNUSED(ir);
|
||||
if (dst < RID_MAX_GPR)
|
||||
emit_mr(as, dst, src);
|
||||
else
|
||||
emit_fb(as, PPCI_FMR, dst, src);
|
||||
}
|
||||
|
||||
/* Generic load of register with base and (small) offset address. */
|
||||
static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r < RID_MAX_GPR)
|
||||
emit_tai(as, PPCI_LWZ, r, base, ofs);
|
||||
else
|
||||
emit_fai(as, irt_isnum(ir->t) ? PPCI_LFD : PPCI_LFS, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Generic store of register with base and (small) offset address. */
|
||||
static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r < RID_MAX_GPR)
|
||||
emit_tai(as, PPCI_STW, r, base, ofs);
|
||||
else
|
||||
emit_fai(as, irt_isnum(ir->t) ? PPCI_STFD : PPCI_STFS, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Emit a compare (for equality) with a constant operand. */
|
||||
static void emit_cmpi(ASMState *as, Reg r, int32_t k)
|
||||
{
|
||||
if (checki16(k)) {
|
||||
emit_ai(as, PPCI_CMPWI, r, k);
|
||||
} else if (checku16(k)) {
|
||||
emit_ai(as, PPCI_CMPLWI, r, k);
|
||||
} else {
|
||||
emit_ai(as, PPCI_CMPLWI, RID_TMP, k);
|
||||
emit_asi(as, PPCI_XORIS, RID_TMP, r, (k >> 16));
|
||||
}
|
||||
}
|
||||
|
||||
/* Add offset to pointer. */
|
||||
static void emit_addptr(ASMState *as, Reg r, int32_t ofs)
|
||||
{
|
||||
if (ofs) {
|
||||
emit_tai(as, PPCI_ADDI, r, r, ofs);
|
||||
if (!checki16(ofs))
|
||||
emit_tai(as, PPCI_ADDIS, r, r, (ofs + 32768) >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_spsub(ASMState *as, int32_t ofs)
|
||||
{
|
||||
if (ofs) {
|
||||
emit_tai(as, PPCI_STWU, RID_TMP, RID_SP, -ofs);
|
||||
emit_tai(as, PPCI_ADDI, RID_TMP, RID_SP,
|
||||
CFRAME_SIZE + (as->parent ? as->parent->spadjust : 0));
|
||||
}
|
||||
}
|
||||
|
||||
553
include/lua/lj_emit_x86.h
Normal file
553
include/lua/lj_emit_x86.h
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
** x86/x64 instruction emitter.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* -- Emit basic instructions --------------------------------------------- */
|
||||
|
||||
#define MODRM(mode, r1, r2) ((MCode)((mode)+(((r1)&7)<<3)+((r2)&7)))
|
||||
|
||||
#if LJ_64
|
||||
#define REXRB(p, rr, rb) \
|
||||
{ MCode rex = 0x40 + (((rr)>>1)&4) + (((rb)>>3)&1); \
|
||||
if (rex != 0x40) *--(p) = rex; }
|
||||
#define FORCE_REX 0x200
|
||||
#define REX_64 (FORCE_REX|0x080000)
|
||||
#define VEX_64 0x800000
|
||||
#else
|
||||
#define REXRB(p, rr, rb) ((void)0)
|
||||
#define FORCE_REX 0
|
||||
#define REX_64 0
|
||||
#define VEX_64 0
|
||||
#endif
|
||||
#if LJ_GC64
|
||||
#define REX_GC64 REX_64
|
||||
#else
|
||||
#define REX_GC64 0
|
||||
#endif
|
||||
|
||||
#define emit_i8(as, i) (*--as->mcp = (MCode)(i))
|
||||
#define emit_i32(as, i) (*(int32_t *)(as->mcp-4) = (i), as->mcp -= 4)
|
||||
#define emit_u32(as, u) (*(uint32_t *)(as->mcp-4) = (u), as->mcp -= 4)
|
||||
|
||||
#define emit_x87op(as, xo) \
|
||||
(*(uint16_t *)(as->mcp-2) = (uint16_t)(xo), as->mcp -= 2)
|
||||
|
||||
/* op */
|
||||
static LJ_AINLINE MCode *emit_op(x86Op xo, Reg rr, Reg rb, Reg rx,
|
||||
MCode *p, int delta)
|
||||
{
|
||||
int n = (int8_t)xo;
|
||||
if (n == -60) { /* VEX-encoded instruction */
|
||||
#if LJ_64
|
||||
xo ^= (((rr>>1)&4)+((rx>>2)&2)+((rb>>3)&1))<<13;
|
||||
#endif
|
||||
*(uint32_t *)(p+delta-5) = (uint32_t)xo;
|
||||
return p+delta-5;
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
if (__builtin_constant_p(xo) && n == -2)
|
||||
p[delta-2] = (MCode)(xo >> 24);
|
||||
else if (__builtin_constant_p(xo) && n == -3)
|
||||
*(uint16_t *)(p+delta-3) = (uint16_t)(xo >> 16);
|
||||
else
|
||||
#endif
|
||||
*(uint32_t *)(p+delta-5) = (uint32_t)xo;
|
||||
p += n + delta;
|
||||
#if LJ_64
|
||||
{
|
||||
uint32_t rex = 0x40 + ((rr>>1)&(4+(FORCE_REX>>1)))+((rx>>2)&2)+((rb>>3)&1);
|
||||
if (rex != 0x40) {
|
||||
rex |= (rr >> 16);
|
||||
if (n == -4) { *p = (MCode)rex; rex = (MCode)(xo >> 8); }
|
||||
else if ((xo & 0xffffff) == 0x6600fd) { *p = (MCode)rex; rex = 0x66; }
|
||||
*--p = (MCode)rex;
|
||||
}
|
||||
}
|
||||
#else
|
||||
UNUSED(rr); UNUSED(rb); UNUSED(rx);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
/* op + modrm */
|
||||
#define emit_opm(xo, mode, rr, rb, p, delta) \
|
||||
(p[(delta)-1] = MODRM((mode), (rr), (rb)), \
|
||||
emit_op((xo), (rr), (rb), 0, (p), (delta)))
|
||||
|
||||
/* op + modrm + sib */
|
||||
#define emit_opmx(xo, mode, scale, rr, rb, rx, p) \
|
||||
(p[-1] = MODRM((scale), (rx), (rb)), \
|
||||
p[-2] = MODRM((mode), (rr), RID_ESP), \
|
||||
emit_op((xo), (rr), (rb), (rx), (p), -1))
|
||||
|
||||
/* op r1, r2 */
|
||||
static void emit_rr(ASMState *as, x86Op xo, Reg r1, Reg r2)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
as->mcp = emit_opm(xo, XM_REG, r1, r2, p, 0);
|
||||
}
|
||||
|
||||
#if LJ_64 && defined(LUA_USE_ASSERT)
|
||||
/* [addr] is sign-extended in x64 and must be in lower 2G (not 4G). */
|
||||
static int32_t ptr2addr(const void *p)
|
||||
{
|
||||
lua_assert((uintptr_t)p < (uintptr_t)0x80000000);
|
||||
return i32ptr(p);
|
||||
}
|
||||
#else
|
||||
#define ptr2addr(p) (i32ptr((p)))
|
||||
#endif
|
||||
|
||||
/* op r, [base+ofs] */
|
||||
static void emit_rmro(ASMState *as, x86Op xo, Reg rr, Reg rb, int32_t ofs)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
x86Mode mode;
|
||||
if (ra_hasreg(rb)) {
|
||||
if (LJ_GC64 && rb == RID_RIP) {
|
||||
mode = XM_OFS0;
|
||||
p -= 4;
|
||||
*(int32_t *)p = ofs;
|
||||
} else if (ofs == 0 && (rb&7) != RID_EBP) {
|
||||
mode = XM_OFS0;
|
||||
} else if (checki8(ofs)) {
|
||||
*--p = (MCode)ofs;
|
||||
mode = XM_OFS8;
|
||||
} else {
|
||||
p -= 4;
|
||||
*(int32_t *)p = ofs;
|
||||
mode = XM_OFS32;
|
||||
}
|
||||
if ((rb&7) == RID_ESP)
|
||||
*--p = MODRM(XM_SCALE1, RID_ESP, RID_ESP);
|
||||
} else {
|
||||
*(int32_t *)(p-4) = ofs;
|
||||
#if LJ_64
|
||||
p[-5] = MODRM(XM_SCALE1, RID_ESP, RID_EBP);
|
||||
p -= 5;
|
||||
rb = RID_ESP;
|
||||
#else
|
||||
p -= 4;
|
||||
rb = RID_EBP;
|
||||
#endif
|
||||
mode = XM_OFS0;
|
||||
}
|
||||
as->mcp = emit_opm(xo, mode, rr, rb, p, 0);
|
||||
}
|
||||
|
||||
/* op r, [base+idx*scale+ofs] */
|
||||
static void emit_rmrxo(ASMState *as, x86Op xo, Reg rr, Reg rb, Reg rx,
|
||||
x86Mode scale, int32_t ofs)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
x86Mode mode;
|
||||
if (ofs == 0 && (rb&7) != RID_EBP) {
|
||||
mode = XM_OFS0;
|
||||
} else if (checki8(ofs)) {
|
||||
mode = XM_OFS8;
|
||||
*--p = (MCode)ofs;
|
||||
} else {
|
||||
mode = XM_OFS32;
|
||||
p -= 4;
|
||||
*(int32_t *)p = ofs;
|
||||
}
|
||||
as->mcp = emit_opmx(xo, mode, scale, rr, rb, rx, p);
|
||||
}
|
||||
|
||||
/* op r, i */
|
||||
static void emit_gri(ASMState *as, x86Group xg, Reg rb, int32_t i)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
x86Op xo;
|
||||
if (checki8(i)) {
|
||||
*--p = (MCode)i;
|
||||
xo = XG_TOXOi8(xg);
|
||||
} else {
|
||||
p -= 4;
|
||||
*(int32_t *)p = i;
|
||||
xo = XG_TOXOi(xg);
|
||||
}
|
||||
as->mcp = emit_opm(xo, XM_REG, (Reg)(xg & 7) | (rb & REX_64), rb, p, 0);
|
||||
}
|
||||
|
||||
/* op [base+ofs], i */
|
||||
static void emit_gmroi(ASMState *as, x86Group xg, Reg rb, int32_t ofs,
|
||||
int32_t i)
|
||||
{
|
||||
x86Op xo;
|
||||
if (checki8(i)) {
|
||||
emit_i8(as, i);
|
||||
xo = XG_TOXOi8(xg);
|
||||
} else {
|
||||
emit_i32(as, i);
|
||||
xo = XG_TOXOi(xg);
|
||||
}
|
||||
emit_rmro(as, xo, (Reg)(xg & 7), rb, ofs);
|
||||
}
|
||||
|
||||
#define emit_shifti(as, xg, r, i) \
|
||||
(emit_i8(as, (i)), emit_rr(as, XO_SHIFTi, (Reg)(xg), (r)))
|
||||
|
||||
/* op r, rm/mrm */
|
||||
static void emit_mrm(ASMState *as, x86Op xo, Reg rr, Reg rb)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
x86Mode mode = XM_REG;
|
||||
if (rb == RID_MRM) {
|
||||
rb = as->mrm.base;
|
||||
if (rb == RID_NONE) {
|
||||
rb = RID_EBP;
|
||||
mode = XM_OFS0;
|
||||
p -= 4;
|
||||
*(int32_t *)p = as->mrm.ofs;
|
||||
if (as->mrm.idx != RID_NONE)
|
||||
goto mrmidx;
|
||||
#if LJ_64
|
||||
*--p = MODRM(XM_SCALE1, RID_ESP, RID_EBP);
|
||||
rb = RID_ESP;
|
||||
#endif
|
||||
} else if (LJ_GC64 && rb == RID_RIP) {
|
||||
lua_assert(as->mrm.idx == RID_NONE);
|
||||
mode = XM_OFS0;
|
||||
p -= 4;
|
||||
*(int32_t *)p = as->mrm.ofs;
|
||||
} else {
|
||||
if (as->mrm.ofs == 0 && (rb&7) != RID_EBP) {
|
||||
mode = XM_OFS0;
|
||||
} else if (checki8(as->mrm.ofs)) {
|
||||
*--p = (MCode)as->mrm.ofs;
|
||||
mode = XM_OFS8;
|
||||
} else {
|
||||
p -= 4;
|
||||
*(int32_t *)p = as->mrm.ofs;
|
||||
mode = XM_OFS32;
|
||||
}
|
||||
if (as->mrm.idx != RID_NONE) {
|
||||
mrmidx:
|
||||
as->mcp = emit_opmx(xo, mode, as->mrm.scale, rr, rb, as->mrm.idx, p);
|
||||
return;
|
||||
}
|
||||
if ((rb&7) == RID_ESP)
|
||||
*--p = MODRM(XM_SCALE1, RID_ESP, RID_ESP);
|
||||
}
|
||||
}
|
||||
as->mcp = emit_opm(xo, mode, rr, rb, p, 0);
|
||||
}
|
||||
|
||||
/* op rm/mrm, i */
|
||||
static void emit_gmrmi(ASMState *as, x86Group xg, Reg rb, int32_t i)
|
||||
{
|
||||
x86Op xo;
|
||||
if (checki8(i)) {
|
||||
emit_i8(as, i);
|
||||
xo = XG_TOXOi8(xg);
|
||||
} else {
|
||||
emit_i32(as, i);
|
||||
xo = XG_TOXOi(xg);
|
||||
}
|
||||
emit_mrm(as, xo, (Reg)(xg & 7) | (rb & REX_64), (rb & ~REX_64));
|
||||
}
|
||||
|
||||
/* -- Emit loads/stores --------------------------------------------------- */
|
||||
|
||||
/* mov [base+ofs], i */
|
||||
static void emit_movmroi(ASMState *as, Reg base, int32_t ofs, int32_t i)
|
||||
{
|
||||
emit_i32(as, i);
|
||||
emit_rmro(as, XO_MOVmi, 0, base, ofs);
|
||||
}
|
||||
|
||||
/* mov [base+ofs], r */
|
||||
#define emit_movtomro(as, r, base, ofs) \
|
||||
emit_rmro(as, XO_MOVto, (r), (base), (ofs))
|
||||
|
||||
/* Get/set global_State fields. */
|
||||
#define emit_opgl(as, xo, r, field) \
|
||||
emit_rma(as, (xo), (r), (void *)&J2G(as->J)->field)
|
||||
#define emit_getgl(as, r, field) emit_opgl(as, XO_MOV, (r)|REX_GC64, field)
|
||||
#define emit_setgl(as, r, field) emit_opgl(as, XO_MOVto, (r)|REX_GC64, field)
|
||||
|
||||
#define emit_setvmstate(as, i) \
|
||||
(emit_i32(as, i), emit_opgl(as, XO_MOVmi, 0, vmstate))
|
||||
|
||||
/* mov r, i / xor r, r */
|
||||
static void emit_loadi(ASMState *as, Reg r, int32_t i)
|
||||
{
|
||||
/* XOR r,r is shorter, but modifies the flags. This is bad for HIOP. */
|
||||
if (i == 0 && !(LJ_32 && (IR(as->curins)->o == IR_HIOP ||
|
||||
(as->curins+1 < as->T->nins &&
|
||||
IR(as->curins+1)->o == IR_HIOP)))) {
|
||||
emit_rr(as, XO_ARITH(XOg_XOR), r, r);
|
||||
} else {
|
||||
MCode *p = as->mcp;
|
||||
*(int32_t *)(p-4) = i;
|
||||
p[-5] = (MCode)(XI_MOVri+(r&7));
|
||||
p -= 5;
|
||||
REXRB(p, 0, r);
|
||||
as->mcp = p;
|
||||
}
|
||||
}
|
||||
|
||||
#if LJ_GC64
|
||||
#define dispofs(as, k) \
|
||||
((intptr_t)((uintptr_t)(k) - (uintptr_t)J2GG(as->J)->dispatch))
|
||||
#define mcpofs(as, k) \
|
||||
((intptr_t)((uintptr_t)(k) - (uintptr_t)as->mcp))
|
||||
#define mctopofs(as, k) \
|
||||
((intptr_t)((uintptr_t)(k) - (uintptr_t)as->mctop))
|
||||
/* mov r, addr */
|
||||
#define emit_loada(as, r, addr) \
|
||||
emit_loadu64(as, (r), (uintptr_t)(addr))
|
||||
#else
|
||||
/* mov r, addr */
|
||||
#define emit_loada(as, r, addr) \
|
||||
emit_loadi(as, (r), ptr2addr((addr)))
|
||||
#endif
|
||||
|
||||
#if LJ_64
|
||||
/* mov r, imm64 or shorter 32 bit extended load. */
|
||||
static void emit_loadu64(ASMState *as, Reg r, uint64_t u64)
|
||||
{
|
||||
if (checku32(u64)) { /* 32 bit load clears upper 32 bits. */
|
||||
emit_loadi(as, r, (int32_t)u64);
|
||||
} else if (checki32((int64_t)u64)) { /* Sign-extended 32 bit load. */
|
||||
MCode *p = as->mcp;
|
||||
*(int32_t *)(p-4) = (int32_t)u64;
|
||||
as->mcp = emit_opm(XO_MOVmi, XM_REG, REX_64, r, p, -4);
|
||||
#if LJ_GC64
|
||||
} else if (checki32(dispofs(as, u64))) {
|
||||
emit_rmro(as, XO_LEA, r|REX_64, RID_DISPATCH, (int32_t)dispofs(as, u64));
|
||||
} else if (checki32(mcpofs(as, u64)) && checki32(mctopofs(as, u64))) {
|
||||
/* Since as->realign assumes the code size doesn't change, check
|
||||
** RIP-relative addressing reachability for both as->mcp and as->mctop.
|
||||
*/
|
||||
emit_rmro(as, XO_LEA, r|REX_64, RID_RIP, (int32_t)mcpofs(as, u64));
|
||||
#endif
|
||||
} else { /* Full-size 64 bit load. */
|
||||
MCode *p = as->mcp;
|
||||
*(uint64_t *)(p-8) = u64;
|
||||
p[-9] = (MCode)(XI_MOVri+(r&7));
|
||||
p[-10] = 0x48 + ((r>>3)&1);
|
||||
p -= 10;
|
||||
as->mcp = p;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* op r, [addr] */
|
||||
static void emit_rma(ASMState *as, x86Op xo, Reg rr, const void *addr)
|
||||
{
|
||||
#if LJ_GC64
|
||||
if (checki32(dispofs(as, addr))) {
|
||||
emit_rmro(as, xo, rr, RID_DISPATCH, (int32_t)dispofs(as, addr));
|
||||
} else if (checki32(mcpofs(as, addr)) && checki32(mctopofs(as, addr))) {
|
||||
emit_rmro(as, xo, rr, RID_RIP, (int32_t)mcpofs(as, addr));
|
||||
} else if (!checki32((intptr_t)addr) && (xo == XO_MOV || xo == XO_MOVSD)) {
|
||||
emit_rmro(as, xo, rr, rr, 0);
|
||||
emit_loadu64(as, rr, (uintptr_t)addr);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
*(int32_t *)(p-4) = ptr2addr(addr);
|
||||
#if LJ_64
|
||||
p[-5] = MODRM(XM_SCALE1, RID_ESP, RID_EBP);
|
||||
as->mcp = emit_opm(xo, XM_OFS0, rr, RID_ESP, p, -5);
|
||||
#else
|
||||
as->mcp = emit_opm(xo, XM_OFS0, rr, RID_EBP, p, -4);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Load 64 bit IR constant into register. */
|
||||
static void emit_loadk64(ASMState *as, Reg r, IRIns *ir)
|
||||
{
|
||||
Reg r64;
|
||||
x86Op xo;
|
||||
const uint64_t *k = &ir_k64(ir)->u64;
|
||||
if (rset_test(RSET_FPR, r)) {
|
||||
r64 = r;
|
||||
xo = XO_MOVSD;
|
||||
} else {
|
||||
r64 = r | REX_64;
|
||||
xo = XO_MOV;
|
||||
}
|
||||
if (*k == 0) {
|
||||
emit_rr(as, rset_test(RSET_FPR, r) ? XO_XORPS : XO_ARITH(XOg_XOR), r, r);
|
||||
#if LJ_GC64
|
||||
} else if (checki32((intptr_t)k) || checki32(dispofs(as, k)) ||
|
||||
(checki32(mcpofs(as, k)) && checki32(mctopofs(as, k)))) {
|
||||
emit_rma(as, xo, r64, k);
|
||||
} else {
|
||||
if (ir->i) {
|
||||
lua_assert(*k == *(uint64_t*)(as->mctop - ir->i));
|
||||
} else if (as->curins <= as->stopins && rset_test(RSET_GPR, r)) {
|
||||
emit_loadu64(as, r, *k);
|
||||
return;
|
||||
} else {
|
||||
/* If all else fails, add the FP constant at the MCode area bottom. */
|
||||
while ((uintptr_t)as->mcbot & 7) *as->mcbot++ = XI_INT3;
|
||||
*(uint64_t *)as->mcbot = *k;
|
||||
ir->i = (int32_t)(as->mctop - as->mcbot);
|
||||
as->mcbot += 8;
|
||||
as->mclim = as->mcbot + MCLIM_REDZONE;
|
||||
lj_mcode_commitbot(as->J, as->mcbot);
|
||||
}
|
||||
emit_rmro(as, xo, r64, RID_RIP, (int32_t)mcpofs(as, as->mctop - ir->i));
|
||||
#else
|
||||
} else {
|
||||
emit_rma(as, xo, r64, k);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Emit control-flow instructions -------------------------------------- */
|
||||
|
||||
/* Label for short jumps. */
|
||||
typedef MCode *MCLabel;
|
||||
|
||||
#if LJ_32 && LJ_HASFFI
|
||||
/* jmp short target */
|
||||
static void emit_sjmp(ASMState *as, MCLabel target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(delta == (int8_t)delta);
|
||||
p[-1] = (MCode)(int8_t)delta;
|
||||
p[-2] = XI_JMPs;
|
||||
as->mcp = p - 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* jcc short target */
|
||||
static void emit_sjcc(ASMState *as, int cc, MCLabel target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(delta == (int8_t)delta);
|
||||
p[-1] = (MCode)(int8_t)delta;
|
||||
p[-2] = (MCode)(XI_JCCs+(cc&15));
|
||||
as->mcp = p - 2;
|
||||
}
|
||||
|
||||
/* jcc short (pending target) */
|
||||
static MCLabel emit_sjcc_label(ASMState *as, int cc)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
p[-1] = 0;
|
||||
p[-2] = (MCode)(XI_JCCs+(cc&15));
|
||||
as->mcp = p - 2;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Fixup jcc short target. */
|
||||
static void emit_sfixup(ASMState *as, MCLabel source)
|
||||
{
|
||||
source[-1] = (MCode)(as->mcp-source);
|
||||
}
|
||||
|
||||
/* Return label pointing to current PC. */
|
||||
#define emit_label(as) ((as)->mcp)
|
||||
|
||||
/* Compute relative 32 bit offset for jump and call instructions. */
|
||||
static LJ_AINLINE int32_t jmprel(MCode *p, MCode *target)
|
||||
{
|
||||
ptrdiff_t delta = target - p;
|
||||
lua_assert(delta == (int32_t)delta);
|
||||
return (int32_t)delta;
|
||||
}
|
||||
|
||||
/* jcc target */
|
||||
static void emit_jcc(ASMState *as, int cc, MCode *target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
*(int32_t *)(p-4) = jmprel(p, target);
|
||||
p[-5] = (MCode)(XI_JCCn+(cc&15));
|
||||
p[-6] = 0x0f;
|
||||
as->mcp = p - 6;
|
||||
}
|
||||
|
||||
/* jmp target */
|
||||
static void emit_jmp(ASMState *as, MCode *target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
*(int32_t *)(p-4) = jmprel(p, target);
|
||||
p[-5] = XI_JMP;
|
||||
as->mcp = p - 5;
|
||||
}
|
||||
|
||||
/* call target */
|
||||
static void emit_call_(ASMState *as, MCode *target)
|
||||
{
|
||||
MCode *p = as->mcp;
|
||||
#if LJ_64
|
||||
if (target-p != (int32_t)(target-p)) {
|
||||
/* Assumes RID_RET is never an argument to calls and always clobbered. */
|
||||
emit_rr(as, XO_GROUP5, XOg_CALL, RID_RET);
|
||||
emit_loadu64(as, RID_RET, (uint64_t)target);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
*(int32_t *)(p-4) = jmprel(p, target);
|
||||
p[-5] = XI_CALL;
|
||||
as->mcp = p - 5;
|
||||
}
|
||||
|
||||
#define emit_call(as, f) emit_call_(as, (MCode *)(void *)(f))
|
||||
|
||||
/* -- Emit generic operations --------------------------------------------- */
|
||||
|
||||
/* Use 64 bit operations to handle 64 bit IR types. */
|
||||
#if LJ_64
|
||||
#define REX_64IR(ir, r) ((r) + (irt_is64((ir)->t) ? REX_64 : 0))
|
||||
#define VEX_64IR(ir, r) ((r) + (irt_is64((ir)->t) ? VEX_64 : 0))
|
||||
#else
|
||||
#define REX_64IR(ir, r) (r)
|
||||
#define VEX_64IR(ir, r) (r)
|
||||
#endif
|
||||
|
||||
/* Generic move between two regs. */
|
||||
static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src)
|
||||
{
|
||||
UNUSED(ir);
|
||||
if (dst < RID_MAX_GPR)
|
||||
emit_rr(as, XO_MOV, REX_64IR(ir, dst), src);
|
||||
else
|
||||
emit_rr(as, XO_MOVAPS, dst, src);
|
||||
}
|
||||
|
||||
/* Generic load of register with base and (small) offset address. */
|
||||
static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r < RID_MAX_GPR)
|
||||
emit_rmro(as, XO_MOV, REX_64IR(ir, r), base, ofs);
|
||||
else
|
||||
emit_rmro(as, irt_isnum(ir->t) ? XO_MOVSD : XO_MOVSS, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Generic store of register with base and (small) offset address. */
|
||||
static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs)
|
||||
{
|
||||
if (r < RID_MAX_GPR)
|
||||
emit_rmro(as, XO_MOVto, REX_64IR(ir, r), base, ofs);
|
||||
else
|
||||
emit_rmro(as, irt_isnum(ir->t) ? XO_MOVSDto : XO_MOVSSto, r, base, ofs);
|
||||
}
|
||||
|
||||
/* Add offset to pointer. */
|
||||
static void emit_addptr(ASMState *as, Reg r, int32_t ofs)
|
||||
{
|
||||
if (ofs) {
|
||||
if ((as->flags & JIT_F_LEA_AGU))
|
||||
emit_rmro(as, XO_LEA, r|REX_GC64, r, ofs);
|
||||
else
|
||||
emit_gri(as, XG_ARITHi(XOg_ADD), r|REX_GC64, ofs);
|
||||
}
|
||||
}
|
||||
|
||||
#define emit_spsub(as, ofs) emit_addptr(as, RID_ESP|REX_64, -(ofs))
|
||||
|
||||
/* Prefer rematerialization of BASE/L from global_State over spills. */
|
||||
#define emit_canremat(ref) ((ref) <= REF_BASE)
|
||||
|
||||
41
include/lua/lj_err.h
Normal file
41
include/lua/lj_err.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
** Error handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ERR_H
|
||||
#define _LJ_ERR_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
typedef enum {
|
||||
#define ERRDEF(name, msg) \
|
||||
LJ_ERR_##name, LJ_ERR_##name##_ = LJ_ERR_##name + sizeof(msg)-1,
|
||||
#include "lj_errmsg.h"
|
||||
LJ_ERR__MAX
|
||||
} ErrMsg;
|
||||
|
||||
LJ_DATA const char *lj_err_allmsg;
|
||||
#define err2msg(em) (lj_err_allmsg+(int)(em))
|
||||
|
||||
LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em);
|
||||
LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode);
|
||||
LJ_FUNC_NORET void lj_err_mem(lua_State *L);
|
||||
LJ_FUNC_NORET void lj_err_run(lua_State *L);
|
||||
LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em);
|
||||
LJ_FUNC_NORET void lj_err_lex(lua_State *L, GCstr *src, const char *tok,
|
||||
BCLine line, ErrMsg em, va_list argp);
|
||||
LJ_FUNC_NORET void lj_err_optype(lua_State *L, cTValue *o, ErrMsg opm);
|
||||
LJ_FUNC_NORET void lj_err_comp(lua_State *L, cTValue *o1, cTValue *o2);
|
||||
LJ_FUNC_NORET void lj_err_optype_call(lua_State *L, TValue *o);
|
||||
LJ_FUNC_NORET void lj_err_callermsg(lua_State *L, const char *msg);
|
||||
LJ_FUNC_NORET void lj_err_callerv(lua_State *L, ErrMsg em, ...);
|
||||
LJ_FUNC_NORET void lj_err_caller(lua_State *L, ErrMsg em);
|
||||
LJ_FUNC_NORET void lj_err_arg(lua_State *L, int narg, ErrMsg em);
|
||||
LJ_FUNC_NORET void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...);
|
||||
LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname);
|
||||
LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt);
|
||||
|
||||
#endif
|
||||
190
include/lua/lj_errmsg.h
Normal file
190
include/lua/lj_errmsg.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
** VM error messages.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* This file may be included multiple times with different ERRDEF macros. */
|
||||
|
||||
/* Basic error handling. */
|
||||
ERRDEF(ERRMEM, "not enough memory")
|
||||
ERRDEF(ERRERR, "error in error handling")
|
||||
ERRDEF(ERRCPP, "C++ exception")
|
||||
|
||||
/* Allocations. */
|
||||
ERRDEF(STROV, "string length overflow")
|
||||
ERRDEF(UDATAOV, "userdata length overflow")
|
||||
ERRDEF(STKOV, "stack overflow")
|
||||
ERRDEF(STKOVM, "stack overflow (%s)")
|
||||
ERRDEF(TABOV, "table overflow")
|
||||
|
||||
/* Table indexing. */
|
||||
ERRDEF(NANIDX, "table index is NaN")
|
||||
ERRDEF(NILIDX, "table index is nil")
|
||||
ERRDEF(NEXTIDX, "invalid key to " LUA_QL("next"))
|
||||
|
||||
/* Metamethod resolving. */
|
||||
ERRDEF(BADCALL, "attempt to call a %s value")
|
||||
ERRDEF(BADOPRT, "attempt to %s %s " LUA_QS " (a %s value)")
|
||||
ERRDEF(BADOPRV, "attempt to %s a %s value")
|
||||
ERRDEF(BADCMPT, "attempt to compare %s with %s")
|
||||
ERRDEF(BADCMPV, "attempt to compare two %s values")
|
||||
ERRDEF(GETLOOP, "loop in gettable")
|
||||
ERRDEF(SETLOOP, "loop in settable")
|
||||
ERRDEF(OPCALL, "call")
|
||||
ERRDEF(OPINDEX, "index")
|
||||
ERRDEF(OPARITH, "perform arithmetic on")
|
||||
ERRDEF(OPCAT, "concatenate")
|
||||
ERRDEF(OPLEN, "get length of")
|
||||
|
||||
/* Type checks. */
|
||||
ERRDEF(BADSELF, "calling " LUA_QS " on bad self (%s)")
|
||||
ERRDEF(BADARG, "bad argument #%d to " LUA_QS " (%s)")
|
||||
ERRDEF(BADTYPE, "%s expected, got %s")
|
||||
ERRDEF(BADVAL, "invalid value")
|
||||
ERRDEF(NOVAL, "value expected")
|
||||
ERRDEF(NOCORO, "coroutine expected")
|
||||
ERRDEF(NOTABN, "nil or table expected")
|
||||
ERRDEF(NOLFUNC, "Lua function expected")
|
||||
ERRDEF(NOFUNCL, "function or level expected")
|
||||
ERRDEF(NOSFT, "string/function/table expected")
|
||||
ERRDEF(NOPROXY, "boolean or proxy expected")
|
||||
ERRDEF(FORINIT, LUA_QL("for") " initial value must be a number")
|
||||
ERRDEF(FORLIM, LUA_QL("for") " limit must be a number")
|
||||
ERRDEF(FORSTEP, LUA_QL("for") " step must be a number")
|
||||
|
||||
/* C API checks. */
|
||||
ERRDEF(NOENV, "no calling environment")
|
||||
ERRDEF(CYIELD, "attempt to yield across C-call boundary")
|
||||
ERRDEF(BADLU, "bad light userdata pointer")
|
||||
ERRDEF(NOGCMM, "bad action while in __gc metamethod")
|
||||
#if LJ_TARGET_WINDOWS
|
||||
ERRDEF(BADFPU, "bad FPU precision (use D3DCREATE_FPU_PRESERVE with DirectX)")
|
||||
#endif
|
||||
|
||||
/* Standard library function errors. */
|
||||
ERRDEF(ASSERT, "assertion failed!")
|
||||
ERRDEF(PROTMT, "cannot change a protected metatable")
|
||||
ERRDEF(UNPACK, "too many results to unpack")
|
||||
ERRDEF(RDRSTR, "reader function must return a string")
|
||||
ERRDEF(PRTOSTR, LUA_QL("tostring") " must return a string to " LUA_QL("print"))
|
||||
ERRDEF(IDXRNG, "index out of range")
|
||||
ERRDEF(BASERNG, "base out of range")
|
||||
ERRDEF(LVLRNG, "level out of range")
|
||||
ERRDEF(INVLVL, "invalid level")
|
||||
ERRDEF(INVOPT, "invalid option")
|
||||
ERRDEF(INVOPTM, "invalid option " LUA_QS)
|
||||
ERRDEF(INVFMT, "invalid format")
|
||||
ERRDEF(SETFENV, LUA_QL("setfenv") " cannot change environment of given object")
|
||||
ERRDEF(CORUN, "cannot resume running coroutine")
|
||||
ERRDEF(CODEAD, "cannot resume dead coroutine")
|
||||
ERRDEF(COSUSP, "cannot resume non-suspended coroutine")
|
||||
ERRDEF(TABINS, "wrong number of arguments to " LUA_QL("insert"))
|
||||
ERRDEF(TABCAT, "invalid value (%s) at index %d in table for " LUA_QL("concat"))
|
||||
ERRDEF(TABSORT, "invalid order function for sorting")
|
||||
ERRDEF(IOCLFL, "attempt to use a closed file")
|
||||
ERRDEF(IOSTDCL, "standard file is closed")
|
||||
ERRDEF(OSUNIQF, "unable to generate a unique filename")
|
||||
ERRDEF(OSDATEF, "field " LUA_QS " missing in date table")
|
||||
ERRDEF(STRDUMP, "unable to dump given function")
|
||||
ERRDEF(STRSLC, "string slice too long")
|
||||
ERRDEF(STRPATB, "missing " LUA_QL("[") " after " LUA_QL("%f") " in pattern")
|
||||
ERRDEF(STRPATC, "invalid pattern capture")
|
||||
ERRDEF(STRPATE, "malformed pattern (ends with " LUA_QL("%") ")")
|
||||
ERRDEF(STRPATM, "malformed pattern (missing " LUA_QL("]") ")")
|
||||
ERRDEF(STRPATU, "unbalanced pattern")
|
||||
ERRDEF(STRPATX, "pattern too complex")
|
||||
ERRDEF(STRCAPI, "invalid capture index")
|
||||
ERRDEF(STRCAPN, "too many captures")
|
||||
ERRDEF(STRCAPU, "unfinished capture")
|
||||
ERRDEF(STRFMT, "invalid option " LUA_QS " to " LUA_QL("format"))
|
||||
ERRDEF(STRGSRV, "invalid replacement value (a %s)")
|
||||
ERRDEF(BADMODN, "name conflict for module " LUA_QS)
|
||||
#if LJ_HASJIT
|
||||
ERRDEF(JITPROT, "runtime code generation failed, restricted kernel?")
|
||||
#if LJ_TARGET_X86ORX64
|
||||
ERRDEF(NOJIT, "JIT compiler disabled, CPU does not support SSE2")
|
||||
#else
|
||||
ERRDEF(NOJIT, "JIT compiler disabled")
|
||||
#endif
|
||||
#elif defined(LJ_ARCH_NOJIT)
|
||||
ERRDEF(NOJIT, "no JIT compiler for this architecture (yet)")
|
||||
#else
|
||||
ERRDEF(NOJIT, "JIT compiler permanently disabled by build option")
|
||||
#endif
|
||||
ERRDEF(JITOPT, "unknown or malformed optimization flag " LUA_QS)
|
||||
|
||||
/* Lexer/parser errors. */
|
||||
ERRDEF(XMODE, "attempt to load chunk with wrong mode")
|
||||
ERRDEF(XNEAR, "%s near " LUA_QS)
|
||||
ERRDEF(XLINES, "chunk has too many lines")
|
||||
ERRDEF(XLEVELS, "chunk has too many syntax levels")
|
||||
ERRDEF(XNUMBER, "malformed number")
|
||||
ERRDEF(XLSTR, "unfinished long string")
|
||||
ERRDEF(XLCOM, "unfinished long comment")
|
||||
ERRDEF(XSTR, "unfinished string")
|
||||
ERRDEF(XESC, "invalid escape sequence")
|
||||
ERRDEF(XLDELIM, "invalid long string delimiter")
|
||||
ERRDEF(XTOKEN, LUA_QS " expected")
|
||||
ERRDEF(XJUMP, "control structure too long")
|
||||
ERRDEF(XSLOTS, "function or expression too complex")
|
||||
ERRDEF(XLIMC, "chunk has more than %d local variables")
|
||||
ERRDEF(XLIMM, "main function has more than %d %s")
|
||||
ERRDEF(XLIMF, "function at line %d has more than %d %s")
|
||||
ERRDEF(XMATCH, LUA_QS " expected (to close " LUA_QS " at line %d)")
|
||||
ERRDEF(XFIXUP, "function too long for return fixup")
|
||||
ERRDEF(XPARAM, "<name> or " LUA_QL("...") " expected")
|
||||
#if !LJ_52
|
||||
ERRDEF(XAMBIG, "ambiguous syntax (function call x new statement)")
|
||||
#endif
|
||||
ERRDEF(XFUNARG, "function arguments expected")
|
||||
ERRDEF(XSYMBOL, "unexpected symbol")
|
||||
ERRDEF(XDOTS, "cannot use " LUA_QL("...") " outside a vararg function")
|
||||
ERRDEF(XSYNTAX, "syntax error")
|
||||
ERRDEF(XFOR, LUA_QL("=") " or " LUA_QL("in") " expected")
|
||||
ERRDEF(XBREAK, "no loop to break")
|
||||
ERRDEF(XLUNDEF, "undefined label " LUA_QS)
|
||||
ERRDEF(XLDUP, "duplicate label " LUA_QS)
|
||||
ERRDEF(XGSCOPE, "<goto %s> jumps into the scope of local " LUA_QS)
|
||||
|
||||
/* Bytecode reader errors. */
|
||||
ERRDEF(BCFMT, "cannot load incompatible bytecode")
|
||||
ERRDEF(BCBAD, "cannot load malformed bytecode")
|
||||
|
||||
#if LJ_HASFFI
|
||||
/* FFI errors. */
|
||||
ERRDEF(FFI_INVTYPE, "invalid C type")
|
||||
ERRDEF(FFI_INVSIZE, "size of C type is unknown or too large")
|
||||
ERRDEF(FFI_BADSCL, "bad storage class")
|
||||
ERRDEF(FFI_DECLSPEC, "declaration specifier expected")
|
||||
ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS)
|
||||
ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS)
|
||||
ERRDEF(FFI_NUMPARAM, "wrong number of type parameters")
|
||||
ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS)
|
||||
ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS)
|
||||
ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS)
|
||||
ERRDEF(FFI_BADCONCAT, "attempt to concatenate " LUA_QS " and " LUA_QS)
|
||||
ERRDEF(FFI_BADARITH, "attempt to perform arithmetic on " LUA_QS " and " LUA_QS)
|
||||
ERRDEF(FFI_BADCOMP, "attempt to compare " LUA_QS " with " LUA_QS)
|
||||
ERRDEF(FFI_BADCALL, LUA_QS " is not callable")
|
||||
ERRDEF(FFI_NUMARG, "wrong number of arguments for function call")
|
||||
ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS)
|
||||
ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed")
|
||||
ERRDEF(FFI_BADIDXW, LUA_QS " cannot be indexed with " LUA_QS)
|
||||
ERRDEF(FFI_BADMM, LUA_QS " has no " LUA_QS " metamethod")
|
||||
ERRDEF(FFI_WRCONST, "attempt to write to constant location")
|
||||
ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS)
|
||||
ERRDEF(FFI_BADCBACK, "bad callback")
|
||||
#if LJ_OS_NOJIT
|
||||
ERRDEF(FFI_CBACKOV, "no support for callbacks on this OS")
|
||||
#else
|
||||
ERRDEF(FFI_CBACKOV, "too many callbacks")
|
||||
#endif
|
||||
ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields")
|
||||
ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)")
|
||||
#endif
|
||||
|
||||
#undef ERRDEF
|
||||
|
||||
/* Detecting unused error messages:
|
||||
awk -F, '/^ERRDEF/ { gsub(/ERRDEF./, ""); printf "grep -q LJ_ERR_%s *.[ch] || echo %s\n", $1, $1}' lj_errmsg.h | sh
|
||||
*/
|
||||
18
include/lua/lj_ff.h
Normal file
18
include/lua/lj_ff.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
** Fast function IDs.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_FF_H
|
||||
#define _LJ_FF_H
|
||||
|
||||
/* Fast function ID. */
|
||||
typedef enum {
|
||||
FF_LUA_ = FF_LUA, /* Lua function (must be 0). */
|
||||
FF_C_ = FF_C, /* Regular C function (must be 1). */
|
||||
#define FFDEF(name) FF_##name,
|
||||
#include "lj_ffdef.h"
|
||||
FF__MAX
|
||||
} FastFunc;
|
||||
|
||||
#endif
|
||||
210
include/lua/lj_ffdef.h
Normal file
210
include/lua/lj_ffdef.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/* This is a generated file. DO NOT EDIT! */
|
||||
|
||||
FFDEF(assert)
|
||||
FFDEF(type)
|
||||
FFDEF(next)
|
||||
FFDEF(pairs)
|
||||
FFDEF(ipairs_aux)
|
||||
FFDEF(ipairs)
|
||||
FFDEF(getmetatable)
|
||||
FFDEF(setmetatable)
|
||||
FFDEF(getfenv)
|
||||
FFDEF(setfenv)
|
||||
FFDEF(rawget)
|
||||
FFDEF(rawset)
|
||||
FFDEF(rawequal)
|
||||
FFDEF(unpack)
|
||||
FFDEF(select)
|
||||
FFDEF(tonumber)
|
||||
FFDEF(tostring)
|
||||
FFDEF(error)
|
||||
FFDEF(pcall)
|
||||
FFDEF(xpcall)
|
||||
FFDEF(loadfile)
|
||||
FFDEF(load)
|
||||
FFDEF(loadstring)
|
||||
FFDEF(dofile)
|
||||
FFDEF(gcinfo)
|
||||
FFDEF(collectgarbage)
|
||||
FFDEF(newproxy)
|
||||
FFDEF(print)
|
||||
FFDEF(coroutine_status)
|
||||
FFDEF(coroutine_running)
|
||||
FFDEF(coroutine_isyieldable)
|
||||
FFDEF(coroutine_create)
|
||||
FFDEF(coroutine_yield)
|
||||
FFDEF(coroutine_resume)
|
||||
FFDEF(coroutine_wrap_aux)
|
||||
FFDEF(coroutine_wrap)
|
||||
FFDEF(math_abs)
|
||||
FFDEF(math_floor)
|
||||
FFDEF(math_ceil)
|
||||
FFDEF(math_sqrt)
|
||||
FFDEF(math_log10)
|
||||
FFDEF(math_exp)
|
||||
FFDEF(math_sin)
|
||||
FFDEF(math_cos)
|
||||
FFDEF(math_tan)
|
||||
FFDEF(math_asin)
|
||||
FFDEF(math_acos)
|
||||
FFDEF(math_atan)
|
||||
FFDEF(math_sinh)
|
||||
FFDEF(math_cosh)
|
||||
FFDEF(math_tanh)
|
||||
FFDEF(math_frexp)
|
||||
FFDEF(math_modf)
|
||||
FFDEF(math_log)
|
||||
FFDEF(math_atan2)
|
||||
FFDEF(math_pow)
|
||||
FFDEF(math_fmod)
|
||||
FFDEF(math_ldexp)
|
||||
FFDEF(math_min)
|
||||
FFDEF(math_max)
|
||||
FFDEF(math_random)
|
||||
FFDEF(math_randomseed)
|
||||
FFDEF(bit_tobit)
|
||||
FFDEF(bit_bnot)
|
||||
FFDEF(bit_bswap)
|
||||
FFDEF(bit_lshift)
|
||||
FFDEF(bit_rshift)
|
||||
FFDEF(bit_arshift)
|
||||
FFDEF(bit_rol)
|
||||
FFDEF(bit_ror)
|
||||
FFDEF(bit_band)
|
||||
FFDEF(bit_bor)
|
||||
FFDEF(bit_bxor)
|
||||
FFDEF(bit_tohex)
|
||||
FFDEF(string_byte)
|
||||
FFDEF(string_char)
|
||||
FFDEF(string_sub)
|
||||
FFDEF(string_rep)
|
||||
FFDEF(string_reverse)
|
||||
FFDEF(string_lower)
|
||||
FFDEF(string_upper)
|
||||
FFDEF(string_dump)
|
||||
FFDEF(string_find)
|
||||
FFDEF(string_match)
|
||||
FFDEF(string_gmatch_aux)
|
||||
FFDEF(string_gmatch)
|
||||
FFDEF(string_gsub)
|
||||
FFDEF(string_format)
|
||||
FFDEF(table_maxn)
|
||||
FFDEF(table_insert)
|
||||
FFDEF(table_concat)
|
||||
FFDEF(table_sort)
|
||||
FFDEF(table_new)
|
||||
FFDEF(table_clear)
|
||||
FFDEF(io_method_close)
|
||||
FFDEF(io_method_read)
|
||||
FFDEF(io_method_write)
|
||||
FFDEF(io_method_flush)
|
||||
FFDEF(io_method_seek)
|
||||
FFDEF(io_method_setvbuf)
|
||||
FFDEF(io_method_lines)
|
||||
FFDEF(io_method___gc)
|
||||
FFDEF(io_method___tostring)
|
||||
FFDEF(io_open)
|
||||
FFDEF(io_popen)
|
||||
FFDEF(io_tmpfile)
|
||||
FFDEF(io_close)
|
||||
FFDEF(io_read)
|
||||
FFDEF(io_write)
|
||||
FFDEF(io_flush)
|
||||
FFDEF(io_input)
|
||||
FFDEF(io_output)
|
||||
FFDEF(io_lines)
|
||||
FFDEF(io_type)
|
||||
FFDEF(os_execute)
|
||||
FFDEF(os_remove)
|
||||
FFDEF(os_rename)
|
||||
FFDEF(os_tmpname)
|
||||
FFDEF(os_getenv)
|
||||
FFDEF(os_exit)
|
||||
FFDEF(os_clock)
|
||||
FFDEF(os_date)
|
||||
FFDEF(os_time)
|
||||
FFDEF(os_difftime)
|
||||
FFDEF(os_setlocale)
|
||||
FFDEF(debug_getregistry)
|
||||
FFDEF(debug_getmetatable)
|
||||
FFDEF(debug_setmetatable)
|
||||
FFDEF(debug_getfenv)
|
||||
FFDEF(debug_setfenv)
|
||||
FFDEF(debug_getinfo)
|
||||
FFDEF(debug_getlocal)
|
||||
FFDEF(debug_setlocal)
|
||||
FFDEF(debug_getupvalue)
|
||||
FFDEF(debug_setupvalue)
|
||||
FFDEF(debug_upvalueid)
|
||||
FFDEF(debug_upvaluejoin)
|
||||
FFDEF(debug_sethook)
|
||||
FFDEF(debug_gethook)
|
||||
FFDEF(debug_debug)
|
||||
FFDEF(debug_traceback)
|
||||
FFDEF(jit_on)
|
||||
FFDEF(jit_off)
|
||||
FFDEF(jit_flush)
|
||||
FFDEF(jit_status)
|
||||
FFDEF(jit_attach)
|
||||
FFDEF(jit_util_funcinfo)
|
||||
FFDEF(jit_util_funcbc)
|
||||
FFDEF(jit_util_funck)
|
||||
FFDEF(jit_util_funcuvname)
|
||||
FFDEF(jit_util_traceinfo)
|
||||
FFDEF(jit_util_traceir)
|
||||
FFDEF(jit_util_tracek)
|
||||
FFDEF(jit_util_tracesnap)
|
||||
FFDEF(jit_util_tracemc)
|
||||
FFDEF(jit_util_traceexitstub)
|
||||
FFDEF(jit_util_ircalladdr)
|
||||
FFDEF(jit_opt_start)
|
||||
FFDEF(jit_profile_start)
|
||||
FFDEF(jit_profile_stop)
|
||||
FFDEF(jit_profile_dumpstack)
|
||||
FFDEF(ffi_meta___index)
|
||||
FFDEF(ffi_meta___newindex)
|
||||
FFDEF(ffi_meta___eq)
|
||||
FFDEF(ffi_meta___len)
|
||||
FFDEF(ffi_meta___lt)
|
||||
FFDEF(ffi_meta___le)
|
||||
FFDEF(ffi_meta___concat)
|
||||
FFDEF(ffi_meta___call)
|
||||
FFDEF(ffi_meta___add)
|
||||
FFDEF(ffi_meta___sub)
|
||||
FFDEF(ffi_meta___mul)
|
||||
FFDEF(ffi_meta___div)
|
||||
FFDEF(ffi_meta___mod)
|
||||
FFDEF(ffi_meta___pow)
|
||||
FFDEF(ffi_meta___unm)
|
||||
FFDEF(ffi_meta___tostring)
|
||||
FFDEF(ffi_meta___pairs)
|
||||
FFDEF(ffi_meta___ipairs)
|
||||
FFDEF(ffi_clib___index)
|
||||
FFDEF(ffi_clib___newindex)
|
||||
FFDEF(ffi_clib___gc)
|
||||
FFDEF(ffi_callback_free)
|
||||
FFDEF(ffi_callback_set)
|
||||
FFDEF(ffi_cdef)
|
||||
FFDEF(ffi_new)
|
||||
FFDEF(ffi_cast)
|
||||
FFDEF(ffi_typeof)
|
||||
FFDEF(ffi_typeinfo)
|
||||
FFDEF(ffi_istype)
|
||||
FFDEF(ffi_sizeof)
|
||||
FFDEF(ffi_alignof)
|
||||
FFDEF(ffi_offsetof)
|
||||
FFDEF(ffi_errno)
|
||||
FFDEF(ffi_string)
|
||||
FFDEF(ffi_copy)
|
||||
FFDEF(ffi_fill)
|
||||
FFDEF(ffi_abi)
|
||||
FFDEF(ffi_metatype)
|
||||
FFDEF(ffi_gc)
|
||||
FFDEF(ffi_load)
|
||||
|
||||
#undef FFDEF
|
||||
|
||||
#ifndef FF_NUM_ASMFUNC
|
||||
#define FF_NUM_ASMFUNC 57
|
||||
#endif
|
||||
|
||||
24
include/lua/lj_ffrecord.h
Normal file
24
include/lua/lj_ffrecord.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
** Fast function call recorder.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_FFRECORD_H
|
||||
#define _LJ_FFRECORD_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_jit.h"
|
||||
|
||||
#if LJ_HASJIT
|
||||
/* Data used by handlers to record a fast function. */
|
||||
typedef struct RecordFFData {
|
||||
TValue *argv; /* Runtime argument values. */
|
||||
ptrdiff_t nres; /* Number of returned results (defaults to 1). */
|
||||
uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */
|
||||
} RecordFFData;
|
||||
|
||||
LJ_FUNC int32_t lj_ffrecord_select_mode(jit_State *J, TRef tr, TValue *tv);
|
||||
LJ_FUNC void lj_ffrecord_func(jit_State *J);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1113
include/lua/lj_folddef.h
Normal file
1113
include/lua/lj_folddef.h
Normal file
File diff suppressed because it is too large
Load Diff
297
include/lua/lj_frame.h
Normal file
297
include/lua/lj_frame.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
** Stack frames.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_FRAME_H
|
||||
#define _LJ_FRAME_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_bc.h"
|
||||
|
||||
/* -- Lua stack frame ----------------------------------------------------- */
|
||||
|
||||
/* Frame type markers in LSB of PC (4-byte aligned) or delta (8-byte aligned:
|
||||
**
|
||||
** PC 00 Lua frame
|
||||
** delta 001 C frame
|
||||
** delta 010 Continuation frame
|
||||
** delta 011 Lua vararg frame
|
||||
** delta 101 cpcall() frame
|
||||
** delta 110 ff pcall() frame
|
||||
** delta 111 ff pcall() frame with active hook
|
||||
*/
|
||||
enum {
|
||||
FRAME_LUA, FRAME_C, FRAME_CONT, FRAME_VARG,
|
||||
FRAME_LUAP, FRAME_CP, FRAME_PCALL, FRAME_PCALLH
|
||||
};
|
||||
#define FRAME_TYPE 3
|
||||
#define FRAME_P 4
|
||||
#define FRAME_TYPEP (FRAME_TYPE|FRAME_P)
|
||||
|
||||
/* Macros to access and modify Lua frames. */
|
||||
#if LJ_FR2
|
||||
/* Two-slot frame info, required for 64 bit PC/GCRef:
|
||||
**
|
||||
** base-2 base-1 | base base+1 ...
|
||||
** [func PC/delta/ft] | [slots ...]
|
||||
** ^-- frame | ^-- base ^-- top
|
||||
**
|
||||
** Continuation frames:
|
||||
**
|
||||
** base-4 base-3 base-2 base-1 | base base+1 ...
|
||||
** [cont PC ] [func PC/delta/ft] | [slots ...]
|
||||
** ^-- frame | ^-- base ^-- top
|
||||
*/
|
||||
#define frame_gc(f) (gcval((f)-1))
|
||||
#define frame_ftsz(f) ((ptrdiff_t)(f)->ftsz)
|
||||
#define frame_pc(f) ((const BCIns *)frame_ftsz(f))
|
||||
#define setframe_gc(f, p, tp) (setgcVraw((f)-1, (p), (tp)))
|
||||
#define setframe_ftsz(f, sz) ((f)->ftsz = (sz))
|
||||
#define setframe_pc(f, pc) ((f)->ftsz = (int64_t)(intptr_t)(pc))
|
||||
#else
|
||||
/* One-slot frame info, sufficient for 32 bit PC/GCRef:
|
||||
**
|
||||
** base-1 | base base+1 ...
|
||||
** lo hi |
|
||||
** [func | PC/delta/ft] | [slots ...]
|
||||
** ^-- frame | ^-- base ^-- top
|
||||
**
|
||||
** Continuation frames:
|
||||
**
|
||||
** base-2 base-1 | base base+1 ...
|
||||
** lo hi lo hi |
|
||||
** [cont | PC] [func | PC/delta/ft] | [slots ...]
|
||||
** ^-- frame | ^-- base ^-- top
|
||||
*/
|
||||
#define frame_gc(f) (gcref((f)->fr.func))
|
||||
#define frame_ftsz(f) ((ptrdiff_t)(f)->fr.tp.ftsz)
|
||||
#define frame_pc(f) (mref((f)->fr.tp.pcr, const BCIns))
|
||||
#define setframe_gc(f, p, tp) (setgcref((f)->fr.func, (p)), UNUSED(tp))
|
||||
#define setframe_ftsz(f, sz) ((f)->fr.tp.ftsz = (int32_t)(sz))
|
||||
#define setframe_pc(f, pc) (setmref((f)->fr.tp.pcr, (pc)))
|
||||
#endif
|
||||
|
||||
#define frame_type(f) (frame_ftsz(f) & FRAME_TYPE)
|
||||
#define frame_typep(f) (frame_ftsz(f) & FRAME_TYPEP)
|
||||
#define frame_islua(f) (frame_type(f) == FRAME_LUA)
|
||||
#define frame_isc(f) (frame_type(f) == FRAME_C)
|
||||
#define frame_iscont(f) (frame_typep(f) == FRAME_CONT)
|
||||
#define frame_isvarg(f) (frame_typep(f) == FRAME_VARG)
|
||||
#define frame_ispcall(f) ((frame_ftsz(f) & 6) == FRAME_PCALL)
|
||||
|
||||
#define frame_func(f) (&frame_gc(f)->fn)
|
||||
#define frame_delta(f) (frame_ftsz(f) >> 3)
|
||||
#define frame_sized(f) (frame_ftsz(f) & ~FRAME_TYPEP)
|
||||
|
||||
enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
|
||||
|
||||
#if LJ_FR2
|
||||
#define frame_contpc(f) (frame_pc((f)-2))
|
||||
#define frame_contv(f) (((f)-3)->u64)
|
||||
#else
|
||||
#define frame_contpc(f) (frame_pc((f)-1))
|
||||
#define frame_contv(f) (((f)-1)->u32.lo)
|
||||
#endif
|
||||
#if LJ_FR2
|
||||
#define frame_contf(f) ((ASMFunction)(uintptr_t)((f)-3)->u64)
|
||||
#elif LJ_64
|
||||
#define frame_contf(f) \
|
||||
((ASMFunction)(void *)((intptr_t)lj_vm_asm_begin + \
|
||||
(intptr_t)(int32_t)((f)-1)->u32.lo))
|
||||
#else
|
||||
#define frame_contf(f) ((ASMFunction)gcrefp(((f)-1)->gcr, void))
|
||||
#endif
|
||||
#define frame_iscont_fficb(f) \
|
||||
(LJ_HASFFI && frame_contv(f) == LJ_CONT_FFI_CALLBACK)
|
||||
|
||||
#define frame_prevl(f) ((f) - (1+LJ_FR2+bc_a(frame_pc(f)[-1])))
|
||||
#define frame_prevd(f) ((TValue *)((char *)(f) - frame_sized(f)))
|
||||
#define frame_prev(f) (frame_islua(f)?frame_prevl(f):frame_prevd(f))
|
||||
/* Note: this macro does not skip over FRAME_VARG. */
|
||||
|
||||
/* -- C stack frame ------------------------------------------------------- */
|
||||
|
||||
/* Macros to access and modify the C stack frame chain. */
|
||||
|
||||
/* These definitions must match with the arch-specific *.dasc files. */
|
||||
#if LJ_TARGET_X86
|
||||
#if LJ_ABI_WIN
|
||||
#define CFRAME_OFS_ERRF (19*4)
|
||||
#define CFRAME_OFS_NRES (18*4)
|
||||
#define CFRAME_OFS_PREV (17*4)
|
||||
#define CFRAME_OFS_L (16*4)
|
||||
#define CFRAME_OFS_SEH (9*4)
|
||||
#define CFRAME_OFS_PC (6*4)
|
||||
#define CFRAME_OFS_MULTRES (5*4)
|
||||
#define CFRAME_SIZE (16*4)
|
||||
#define CFRAME_SHIFT_MULTRES 0
|
||||
#else
|
||||
#define CFRAME_OFS_ERRF (15*4)
|
||||
#define CFRAME_OFS_NRES (14*4)
|
||||
#define CFRAME_OFS_PREV (13*4)
|
||||
#define CFRAME_OFS_L (12*4)
|
||||
#define CFRAME_OFS_PC (6*4)
|
||||
#define CFRAME_OFS_MULTRES (5*4)
|
||||
#define CFRAME_SIZE (12*4)
|
||||
#define CFRAME_SHIFT_MULTRES 0
|
||||
#endif
|
||||
#elif LJ_TARGET_X64
|
||||
#if LJ_ABI_WIN
|
||||
#define CFRAME_OFS_PREV (13*8)
|
||||
#if LJ_GC64
|
||||
#define CFRAME_OFS_PC (12*8)
|
||||
#define CFRAME_OFS_L (11*8)
|
||||
#define CFRAME_OFS_ERRF (21*4)
|
||||
#define CFRAME_OFS_NRES (20*4)
|
||||
#define CFRAME_OFS_MULTRES (8*4)
|
||||
#else
|
||||
#define CFRAME_OFS_PC (25*4)
|
||||
#define CFRAME_OFS_L (24*4)
|
||||
#define CFRAME_OFS_ERRF (23*4)
|
||||
#define CFRAME_OFS_NRES (22*4)
|
||||
#define CFRAME_OFS_MULTRES (21*4)
|
||||
#endif
|
||||
#define CFRAME_SIZE (10*8)
|
||||
#define CFRAME_SIZE_JIT (CFRAME_SIZE + 9*16 + 4*8)
|
||||
#define CFRAME_SHIFT_MULTRES 0
|
||||
#else
|
||||
#define CFRAME_OFS_PREV (4*8)
|
||||
#if LJ_GC64
|
||||
#define CFRAME_OFS_PC (3*8)
|
||||
#define CFRAME_OFS_L (2*8)
|
||||
#define CFRAME_OFS_ERRF (3*4)
|
||||
#define CFRAME_OFS_NRES (2*4)
|
||||
#define CFRAME_OFS_MULTRES (0*4)
|
||||
#else
|
||||
#define CFRAME_OFS_PC (7*4)
|
||||
#define CFRAME_OFS_L (6*4)
|
||||
#define CFRAME_OFS_ERRF (5*4)
|
||||
#define CFRAME_OFS_NRES (4*4)
|
||||
#define CFRAME_OFS_MULTRES (1*4)
|
||||
#endif
|
||||
#if LJ_NO_UNWIND
|
||||
#define CFRAME_SIZE (12*8)
|
||||
#else
|
||||
#define CFRAME_SIZE (10*8)
|
||||
#endif
|
||||
#define CFRAME_SIZE_JIT (CFRAME_SIZE + 16)
|
||||
#define CFRAME_SHIFT_MULTRES 0
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM
|
||||
#define CFRAME_OFS_ERRF 24
|
||||
#define CFRAME_OFS_NRES 20
|
||||
#define CFRAME_OFS_PREV 16
|
||||
#define CFRAME_OFS_L 12
|
||||
#define CFRAME_OFS_PC 8
|
||||
#define CFRAME_OFS_MULTRES 4
|
||||
#if LJ_ARCH_HASFPU
|
||||
#define CFRAME_SIZE 128
|
||||
#else
|
||||
#define CFRAME_SIZE 64
|
||||
#endif
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#elif LJ_TARGET_ARM64
|
||||
#define CFRAME_OFS_ERRF 196
|
||||
#define CFRAME_OFS_NRES 200
|
||||
#define CFRAME_OFS_PREV 160
|
||||
#define CFRAME_OFS_L 176
|
||||
#define CFRAME_OFS_PC 168
|
||||
#define CFRAME_OFS_MULTRES 192
|
||||
#define CFRAME_SIZE 208
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#elif LJ_TARGET_PPC
|
||||
#if LJ_TARGET_XBOX360
|
||||
#define CFRAME_OFS_ERRF 424
|
||||
#define CFRAME_OFS_NRES 420
|
||||
#define CFRAME_OFS_PREV 400
|
||||
#define CFRAME_OFS_L 416
|
||||
#define CFRAME_OFS_PC 412
|
||||
#define CFRAME_OFS_MULTRES 408
|
||||
#define CFRAME_SIZE 384
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#elif LJ_ARCH_PPC32ON64
|
||||
#define CFRAME_OFS_ERRF 472
|
||||
#define CFRAME_OFS_NRES 468
|
||||
#define CFRAME_OFS_PREV 448
|
||||
#define CFRAME_OFS_L 464
|
||||
#define CFRAME_OFS_PC 460
|
||||
#define CFRAME_OFS_MULTRES 456
|
||||
#define CFRAME_SIZE 400
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#else
|
||||
#define CFRAME_OFS_ERRF 48
|
||||
#define CFRAME_OFS_NRES 44
|
||||
#define CFRAME_OFS_PREV 40
|
||||
#define CFRAME_OFS_L 36
|
||||
#define CFRAME_OFS_PC 32
|
||||
#define CFRAME_OFS_MULTRES 28
|
||||
#define CFRAME_SIZE 272
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS32
|
||||
#if LJ_ARCH_HASFPU
|
||||
#define CFRAME_OFS_ERRF 124
|
||||
#define CFRAME_OFS_NRES 120
|
||||
#define CFRAME_OFS_PREV 116
|
||||
#define CFRAME_OFS_L 112
|
||||
#define CFRAME_SIZE 112
|
||||
#else
|
||||
#define CFRAME_OFS_ERRF 76
|
||||
#define CFRAME_OFS_NRES 72
|
||||
#define CFRAME_OFS_PREV 68
|
||||
#define CFRAME_OFS_L 64
|
||||
#define CFRAME_SIZE 64
|
||||
#endif
|
||||
#define CFRAME_OFS_PC 20
|
||||
#define CFRAME_OFS_MULTRES 16
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#elif LJ_TARGET_MIPS64
|
||||
#if LJ_ARCH_HASFPU
|
||||
#define CFRAME_OFS_ERRF 188
|
||||
#define CFRAME_OFS_NRES 184
|
||||
#define CFRAME_OFS_PREV 176
|
||||
#define CFRAME_OFS_L 168
|
||||
#define CFRAME_OFS_PC 160
|
||||
#define CFRAME_SIZE 192
|
||||
#else
|
||||
#define CFRAME_OFS_ERRF 124
|
||||
#define CFRAME_OFS_NRES 120
|
||||
#define CFRAME_OFS_PREV 112
|
||||
#define CFRAME_OFS_L 104
|
||||
#define CFRAME_OFS_PC 96
|
||||
#define CFRAME_SIZE 128
|
||||
#endif
|
||||
#define CFRAME_OFS_MULTRES 0
|
||||
#define CFRAME_SHIFT_MULTRES 3
|
||||
#else
|
||||
#error "Missing CFRAME_* definitions for this architecture"
|
||||
#endif
|
||||
|
||||
#ifndef CFRAME_SIZE_JIT
|
||||
#define CFRAME_SIZE_JIT CFRAME_SIZE
|
||||
#endif
|
||||
|
||||
#define CFRAME_RESUME 1
|
||||
#define CFRAME_UNWIND_FF 2 /* Only used in unwinder. */
|
||||
#define CFRAME_RAWMASK (~(intptr_t)(CFRAME_RESUME|CFRAME_UNWIND_FF))
|
||||
|
||||
#define cframe_errfunc(cf) (*(int32_t *)(((char *)(cf))+CFRAME_OFS_ERRF))
|
||||
#define cframe_nres(cf) (*(int32_t *)(((char *)(cf))+CFRAME_OFS_NRES))
|
||||
#define cframe_prev(cf) (*(void **)(((char *)(cf))+CFRAME_OFS_PREV))
|
||||
#define cframe_multres(cf) (*(uint32_t *)(((char *)(cf))+CFRAME_OFS_MULTRES))
|
||||
#define cframe_multres_n(cf) (cframe_multres((cf)) >> CFRAME_SHIFT_MULTRES)
|
||||
#define cframe_L(cf) \
|
||||
(&gcref(*(GCRef *)(((char *)(cf))+CFRAME_OFS_L))->th)
|
||||
#define cframe_pc(cf) \
|
||||
(mref(*(MRef *)(((char *)(cf))+CFRAME_OFS_PC), const BCIns))
|
||||
#define setcframe_L(cf, L) \
|
||||
(setmref(*(MRef *)(((char *)(cf))+CFRAME_OFS_L), (L)))
|
||||
#define setcframe_pc(cf, pc) \
|
||||
(setmref(*(MRef *)(((char *)(cf))+CFRAME_OFS_PC), (pc)))
|
||||
#define cframe_canyield(cf) ((intptr_t)(cf) & CFRAME_RESUME)
|
||||
#define cframe_unwind_ff(cf) ((intptr_t)(cf) & CFRAME_UNWIND_FF)
|
||||
#define cframe_raw(cf) ((void *)((intptr_t)(cf) & CFRAME_RAWMASK))
|
||||
#define cframe_Lpc(L) cframe_pc(cframe_raw(L->cframe))
|
||||
|
||||
#endif
|
||||
24
include/lua/lj_func.h
Normal file
24
include/lua/lj_func.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
** Function handling (prototypes, functions and upvalues).
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_FUNC_H
|
||||
#define _LJ_FUNC_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Prototypes. */
|
||||
LJ_FUNC void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt);
|
||||
|
||||
/* Upvalues. */
|
||||
LJ_FUNCA void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level);
|
||||
LJ_FUNC void LJ_FASTCALL lj_func_freeuv(global_State *g, GCupval *uv);
|
||||
|
||||
/* Functions (closures). */
|
||||
LJ_FUNC GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env);
|
||||
LJ_FUNC GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env);
|
||||
LJ_FUNCA GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent);
|
||||
LJ_FUNC void LJ_FASTCALL lj_func_free(global_State *g, GCfunc *c);
|
||||
|
||||
#endif
|
||||
134
include/lua/lj_gc.h
Normal file
134
include/lua/lj_gc.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
** Garbage collector.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_GC_H
|
||||
#define _LJ_GC_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Garbage collector states. Order matters. */
|
||||
enum {
|
||||
GCSpause, GCSpropagate, GCSatomic, GCSsweepstring, GCSsweep, GCSfinalize
|
||||
};
|
||||
|
||||
/* Bitmasks for marked field of GCobj. */
|
||||
#define LJ_GC_WHITE0 0x01
|
||||
#define LJ_GC_WHITE1 0x02
|
||||
#define LJ_GC_BLACK 0x04
|
||||
#define LJ_GC_FINALIZED 0x08
|
||||
#define LJ_GC_WEAKKEY 0x08
|
||||
#define LJ_GC_WEAKVAL 0x10
|
||||
#define LJ_GC_CDATA_FIN 0x10
|
||||
#define LJ_GC_FIXED 0x20
|
||||
#define LJ_GC_SFIXED 0x40
|
||||
|
||||
#define LJ_GC_WHITES (LJ_GC_WHITE0 | LJ_GC_WHITE1)
|
||||
#define LJ_GC_COLORS (LJ_GC_WHITES | LJ_GC_BLACK)
|
||||
#define LJ_GC_WEAK (LJ_GC_WEAKKEY | LJ_GC_WEAKVAL)
|
||||
|
||||
/* Macros to test and set GCobj colors. */
|
||||
#define iswhite(x) ((x)->gch.marked & LJ_GC_WHITES)
|
||||
#define isblack(x) ((x)->gch.marked & LJ_GC_BLACK)
|
||||
#define isgray(x) (!((x)->gch.marked & (LJ_GC_BLACK|LJ_GC_WHITES)))
|
||||
#define tviswhite(x) (tvisgcv(x) && iswhite(gcV(x)))
|
||||
#define otherwhite(g) (g->gc.currentwhite ^ LJ_GC_WHITES)
|
||||
#define isdead(g, v) ((v)->gch.marked & otherwhite(g) & LJ_GC_WHITES)
|
||||
|
||||
#define curwhite(g) ((g)->gc.currentwhite & LJ_GC_WHITES)
|
||||
#define newwhite(g, x) (obj2gco(x)->gch.marked = (uint8_t)curwhite(g))
|
||||
#define makewhite(g, x) \
|
||||
((x)->gch.marked = ((x)->gch.marked & (uint8_t)~LJ_GC_COLORS) | curwhite(g))
|
||||
#define flipwhite(x) ((x)->gch.marked ^= LJ_GC_WHITES)
|
||||
#define black2gray(x) ((x)->gch.marked &= (uint8_t)~LJ_GC_BLACK)
|
||||
#define fixstring(s) ((s)->marked |= LJ_GC_FIXED)
|
||||
#define markfinalized(x) ((x)->gch.marked |= LJ_GC_FINALIZED)
|
||||
|
||||
/* Collector. */
|
||||
LJ_FUNC size_t lj_gc_separateudata(global_State *g, int all);
|
||||
LJ_FUNC void lj_gc_finalize_udata(lua_State *L);
|
||||
#if LJ_HASFFI
|
||||
LJ_FUNC void lj_gc_finalize_cdata(lua_State *L);
|
||||
#else
|
||||
#define lj_gc_finalize_cdata(L) UNUSED(L)
|
||||
#endif
|
||||
LJ_FUNC void lj_gc_freeall(global_State *g);
|
||||
LJ_FUNCA int LJ_FASTCALL lj_gc_step(lua_State *L);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC int LJ_FASTCALL lj_gc_step_jit(global_State *g, MSize steps);
|
||||
#endif
|
||||
LJ_FUNC void lj_gc_fullgc(lua_State *L);
|
||||
|
||||
/* GC check: drive collector forward if the GC threshold has been reached. */
|
||||
#define lj_gc_check(L) \
|
||||
{ if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \
|
||||
lj_gc_step(L); }
|
||||
#define lj_gc_check_fixtop(L) \
|
||||
{ if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \
|
||||
lj_gc_step_fixtop(L); }
|
||||
|
||||
/* Write barriers. */
|
||||
LJ_FUNC void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv);
|
||||
LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC void lj_gc_barriertrace(global_State *g, uint32_t traceno);
|
||||
#endif
|
||||
|
||||
/* Move the GC propagation frontier back for tables (make it gray again). */
|
||||
static LJ_AINLINE void lj_gc_barrierback(global_State *g, GCtab *t)
|
||||
{
|
||||
GCobj *o = obj2gco(t);
|
||||
lua_assert(isblack(o) && !isdead(g, o));
|
||||
lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause);
|
||||
black2gray(o);
|
||||
setgcrefr(t->gclist, g->gc.grayagain);
|
||||
setgcref(g->gc.grayagain, o);
|
||||
}
|
||||
|
||||
/* Barrier for stores to table objects. TValue and GCobj variant. */
|
||||
#define lj_gc_anybarriert(L, t) \
|
||||
{ if (LJ_UNLIKELY(isblack(obj2gco(t)))) lj_gc_barrierback(G(L), (t)); }
|
||||
#define lj_gc_barriert(L, t, tv) \
|
||||
{ if (tviswhite(tv) && isblack(obj2gco(t))) \
|
||||
lj_gc_barrierback(G(L), (t)); }
|
||||
#define lj_gc_objbarriert(L, t, o) \
|
||||
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) \
|
||||
lj_gc_barrierback(G(L), (t)); }
|
||||
|
||||
/* Barrier for stores to any other object. TValue and GCobj variant. */
|
||||
#define lj_gc_barrier(L, p, tv) \
|
||||
{ if (tviswhite(tv) && isblack(obj2gco(p))) \
|
||||
lj_gc_barrierf(G(L), obj2gco(p), gcV(tv)); }
|
||||
#define lj_gc_objbarrier(L, p, o) \
|
||||
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
|
||||
lj_gc_barrierf(G(L), obj2gco(p), obj2gco(o)); }
|
||||
|
||||
/* Allocator. */
|
||||
LJ_FUNC void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz);
|
||||
LJ_FUNC void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size);
|
||||
LJ_FUNC void *lj_mem_grow(lua_State *L, void *p,
|
||||
MSize *szp, MSize lim, MSize esz);
|
||||
|
||||
#define lj_mem_new(L, s) lj_mem_realloc(L, NULL, 0, (s))
|
||||
|
||||
static LJ_AINLINE void lj_mem_free(global_State *g, void *p, size_t osize)
|
||||
{
|
||||
g->gc.total -= (GCSize)osize;
|
||||
g->allocf(g->allocd, p, osize, 0);
|
||||
}
|
||||
|
||||
#define lj_mem_newvec(L, n, t) ((t *)lj_mem_new(L, (GCSize)((n)*sizeof(t))))
|
||||
#define lj_mem_reallocvec(L, p, on, n, t) \
|
||||
((p) = (t *)lj_mem_realloc(L, p, (on)*sizeof(t), (GCSize)((n)*sizeof(t))))
|
||||
#define lj_mem_growvec(L, p, n, m, t) \
|
||||
((p) = (t *)lj_mem_grow(L, (p), &(n), (m), (MSize)sizeof(t)))
|
||||
#define lj_mem_freevec(g, p, n, t) lj_mem_free(g, (p), (n)*sizeof(t))
|
||||
|
||||
#define lj_mem_newobj(L, t) ((t *)lj_mem_newgco(L, sizeof(t)))
|
||||
#define lj_mem_newt(L, s, t) ((t *)lj_mem_new(L, (s)))
|
||||
#define lj_mem_freet(g, p) lj_mem_free(g, (p), sizeof(*(p)))
|
||||
|
||||
#endif
|
||||
22
include/lua/lj_gdbjit.h
Normal file
22
include/lua/lj_gdbjit.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
** Client for the GDB JIT API.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_GDBJIT_H
|
||||
#define _LJ_GDBJIT_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_jit.h"
|
||||
|
||||
#if LJ_HASJIT && defined(LUAJIT_USE_GDBJIT)
|
||||
|
||||
LJ_FUNC void lj_gdbjit_addtrace(jit_State *J, GCtrace *T);
|
||||
LJ_FUNC void lj_gdbjit_deltrace(jit_State *J, GCtrace *T);
|
||||
|
||||
#else
|
||||
#define lj_gdbjit_addtrace(J, T) UNUSED(T)
|
||||
#define lj_gdbjit_deltrace(J, T) UNUSED(T)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
588
include/lua/lj_ir.h
Normal file
588
include/lua/lj_ir.h
Normal file
@@ -0,0 +1,588 @@
|
||||
/*
|
||||
** SSA IR (Intermediate Representation) format.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_IR_H
|
||||
#define _LJ_IR_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* -- IR instructions ----------------------------------------------------- */
|
||||
|
||||
/* IR instruction definition. Order matters, see below. ORDER IR */
|
||||
#define IRDEF(_) \
|
||||
/* Guarded assertions. */ \
|
||||
/* Must be properly aligned to flip opposites (^1) and (un)ordered (^4). */ \
|
||||
_(LT, N , ref, ref) \
|
||||
_(GE, N , ref, ref) \
|
||||
_(LE, N , ref, ref) \
|
||||
_(GT, N , ref, ref) \
|
||||
\
|
||||
_(ULT, N , ref, ref) \
|
||||
_(UGE, N , ref, ref) \
|
||||
_(ULE, N , ref, ref) \
|
||||
_(UGT, N , ref, ref) \
|
||||
\
|
||||
_(EQ, C , ref, ref) \
|
||||
_(NE, C , ref, ref) \
|
||||
\
|
||||
_(ABC, N , ref, ref) \
|
||||
_(RETF, S , ref, ref) \
|
||||
\
|
||||
/* Miscellaneous ops. */ \
|
||||
_(NOP, N , ___, ___) \
|
||||
_(BASE, N , lit, lit) \
|
||||
_(PVAL, N , lit, ___) \
|
||||
_(GCSTEP, S , ___, ___) \
|
||||
_(HIOP, S , ref, ref) \
|
||||
_(LOOP, S , ___, ___) \
|
||||
_(USE, S , ref, ___) \
|
||||
_(PHI, S , ref, ref) \
|
||||
_(RENAME, S , ref, lit) \
|
||||
_(PROF, S , ___, ___) \
|
||||
\
|
||||
/* Constants. */ \
|
||||
_(KPRI, N , ___, ___) \
|
||||
_(KINT, N , cst, ___) \
|
||||
_(KGC, N , cst, ___) \
|
||||
_(KPTR, N , cst, ___) \
|
||||
_(KKPTR, N , cst, ___) \
|
||||
_(KNULL, N , cst, ___) \
|
||||
_(KNUM, N , cst, ___) \
|
||||
_(KINT64, N , cst, ___) \
|
||||
_(KSLOT, N , ref, lit) \
|
||||
\
|
||||
/* Bit ops. */ \
|
||||
_(BNOT, N , ref, ___) \
|
||||
_(BSWAP, N , ref, ___) \
|
||||
_(BAND, C , ref, ref) \
|
||||
_(BOR, C , ref, ref) \
|
||||
_(BXOR, C , ref, ref) \
|
||||
_(BSHL, N , ref, ref) \
|
||||
_(BSHR, N , ref, ref) \
|
||||
_(BSAR, N , ref, ref) \
|
||||
_(BROL, N , ref, ref) \
|
||||
_(BROR, N , ref, ref) \
|
||||
\
|
||||
/* Arithmetic ops. ORDER ARITH */ \
|
||||
_(ADD, C , ref, ref) \
|
||||
_(SUB, N , ref, ref) \
|
||||
_(MUL, C , ref, ref) \
|
||||
_(DIV, N , ref, ref) \
|
||||
_(MOD, N , ref, ref) \
|
||||
_(POW, N , ref, ref) \
|
||||
_(NEG, N , ref, ref) \
|
||||
\
|
||||
_(ABS, N , ref, ref) \
|
||||
_(ATAN2, N , ref, ref) \
|
||||
_(LDEXP, N , ref, ref) \
|
||||
_(MIN, C , ref, ref) \
|
||||
_(MAX, C , ref, ref) \
|
||||
_(FPMATH, N , ref, lit) \
|
||||
\
|
||||
/* Overflow-checking arithmetic ops. */ \
|
||||
_(ADDOV, CW, ref, ref) \
|
||||
_(SUBOV, NW, ref, ref) \
|
||||
_(MULOV, CW, ref, ref) \
|
||||
\
|
||||
/* Memory ops. A = array, H = hash, U = upvalue, F = field, S = stack. */ \
|
||||
\
|
||||
/* Memory references. */ \
|
||||
_(AREF, R , ref, ref) \
|
||||
_(HREFK, R , ref, ref) \
|
||||
_(HREF, L , ref, ref) \
|
||||
_(NEWREF, S , ref, ref) \
|
||||
_(UREFO, LW, ref, lit) \
|
||||
_(UREFC, LW, ref, lit) \
|
||||
_(FREF, R , ref, lit) \
|
||||
_(STRREF, N , ref, ref) \
|
||||
_(LREF, L , ___, ___) \
|
||||
\
|
||||
/* Loads and Stores. These must be in the same order. */ \
|
||||
_(ALOAD, L , ref, ___) \
|
||||
_(HLOAD, L , ref, ___) \
|
||||
_(ULOAD, L , ref, ___) \
|
||||
_(FLOAD, L , ref, lit) \
|
||||
_(XLOAD, L , ref, lit) \
|
||||
_(SLOAD, L , lit, lit) \
|
||||
_(VLOAD, L , ref, ___) \
|
||||
\
|
||||
_(ASTORE, S , ref, ref) \
|
||||
_(HSTORE, S , ref, ref) \
|
||||
_(USTORE, S , ref, ref) \
|
||||
_(FSTORE, S , ref, ref) \
|
||||
_(XSTORE, S , ref, ref) \
|
||||
\
|
||||
/* Allocations. */ \
|
||||
_(SNEW, N , ref, ref) /* CSE is ok, not marked as A. */ \
|
||||
_(XSNEW, A , ref, ref) \
|
||||
_(TNEW, AW, lit, lit) \
|
||||
_(TDUP, AW, ref, ___) \
|
||||
_(CNEW, AW, ref, ref) \
|
||||
_(CNEWI, NW, ref, ref) /* CSE is ok, not marked as A. */ \
|
||||
\
|
||||
/* Buffer operations. */ \
|
||||
_(BUFHDR, L , ref, lit) \
|
||||
_(BUFPUT, L , ref, ref) \
|
||||
_(BUFSTR, A , ref, ref) \
|
||||
\
|
||||
/* Barriers. */ \
|
||||
_(TBAR, S , ref, ___) \
|
||||
_(OBAR, S , ref, ref) \
|
||||
_(XBAR, S , ___, ___) \
|
||||
\
|
||||
/* Type conversions. */ \
|
||||
_(CONV, NW, ref, lit) \
|
||||
_(TOBIT, N , ref, ref) \
|
||||
_(TOSTR, N , ref, lit) \
|
||||
_(STRTO, N , ref, ___) \
|
||||
\
|
||||
/* Calls. */ \
|
||||
_(CALLN, N , ref, lit) \
|
||||
_(CALLA, A , ref, lit) \
|
||||
_(CALLL, L , ref, lit) \
|
||||
_(CALLS, S , ref, lit) \
|
||||
_(CALLXS, S , ref, ref) \
|
||||
_(CARG, N , ref, ref) \
|
||||
\
|
||||
/* End of list. */
|
||||
|
||||
/* IR opcodes (max. 256). */
|
||||
typedef enum {
|
||||
#define IRENUM(name, m, m1, m2) IR_##name,
|
||||
IRDEF(IRENUM)
|
||||
#undef IRENUM
|
||||
IR__MAX
|
||||
} IROp;
|
||||
|
||||
/* Stored opcode. */
|
||||
typedef uint8_t IROp1;
|
||||
|
||||
LJ_STATIC_ASSERT(((int)IR_EQ^1) == (int)IR_NE);
|
||||
LJ_STATIC_ASSERT(((int)IR_LT^1) == (int)IR_GE);
|
||||
LJ_STATIC_ASSERT(((int)IR_LE^1) == (int)IR_GT);
|
||||
LJ_STATIC_ASSERT(((int)IR_LT^3) == (int)IR_GT);
|
||||
LJ_STATIC_ASSERT(((int)IR_LT^4) == (int)IR_ULT);
|
||||
|
||||
/* Delta between xLOAD and xSTORE. */
|
||||
#define IRDELTA_L2S ((int)IR_ASTORE - (int)IR_ALOAD)
|
||||
|
||||
LJ_STATIC_ASSERT((int)IR_HLOAD + IRDELTA_L2S == (int)IR_HSTORE);
|
||||
LJ_STATIC_ASSERT((int)IR_ULOAD + IRDELTA_L2S == (int)IR_USTORE);
|
||||
LJ_STATIC_ASSERT((int)IR_FLOAD + IRDELTA_L2S == (int)IR_FSTORE);
|
||||
LJ_STATIC_ASSERT((int)IR_XLOAD + IRDELTA_L2S == (int)IR_XSTORE);
|
||||
|
||||
/* -- Named IR literals --------------------------------------------------- */
|
||||
|
||||
/* FPMATH sub-functions. ORDER FPM. */
|
||||
#define IRFPMDEF(_) \
|
||||
_(FLOOR) _(CEIL) _(TRUNC) /* Must be first and in this order. */ \
|
||||
_(SQRT) _(EXP) _(EXP2) _(LOG) _(LOG2) _(LOG10) \
|
||||
_(SIN) _(COS) _(TAN) \
|
||||
_(OTHER)
|
||||
|
||||
typedef enum {
|
||||
#define FPMENUM(name) IRFPM_##name,
|
||||
IRFPMDEF(FPMENUM)
|
||||
#undef FPMENUM
|
||||
IRFPM__MAX
|
||||
} IRFPMathOp;
|
||||
|
||||
/* FLOAD fields. */
|
||||
#define IRFLDEF(_) \
|
||||
_(STR_LEN, offsetof(GCstr, len)) \
|
||||
_(FUNC_ENV, offsetof(GCfunc, l.env)) \
|
||||
_(FUNC_PC, offsetof(GCfunc, l.pc)) \
|
||||
_(FUNC_FFID, offsetof(GCfunc, l.ffid)) \
|
||||
_(THREAD_ENV, offsetof(lua_State, env)) \
|
||||
_(TAB_META, offsetof(GCtab, metatable)) \
|
||||
_(TAB_ARRAY, offsetof(GCtab, array)) \
|
||||
_(TAB_NODE, offsetof(GCtab, node)) \
|
||||
_(TAB_ASIZE, offsetof(GCtab, asize)) \
|
||||
_(TAB_HMASK, offsetof(GCtab, hmask)) \
|
||||
_(TAB_NOMM, offsetof(GCtab, nomm)) \
|
||||
_(UDATA_META, offsetof(GCudata, metatable)) \
|
||||
_(UDATA_UDTYPE, offsetof(GCudata, udtype)) \
|
||||
_(UDATA_FILE, sizeof(GCudata)) \
|
||||
_(CDATA_CTYPEID, offsetof(GCcdata, ctypeid)) \
|
||||
_(CDATA_PTR, sizeof(GCcdata)) \
|
||||
_(CDATA_INT, sizeof(GCcdata)) \
|
||||
_(CDATA_INT64, sizeof(GCcdata)) \
|
||||
_(CDATA_INT64_4, sizeof(GCcdata) + 4)
|
||||
|
||||
typedef enum {
|
||||
#define FLENUM(name, ofs) IRFL_##name,
|
||||
IRFLDEF(FLENUM)
|
||||
#undef FLENUM
|
||||
IRFL__MAX
|
||||
} IRFieldID;
|
||||
|
||||
/* SLOAD mode bits, stored in op2. */
|
||||
#define IRSLOAD_PARENT 0x01 /* Coalesce with parent trace. */
|
||||
#define IRSLOAD_FRAME 0x02 /* Load 32 bits of ftsz. */
|
||||
#define IRSLOAD_TYPECHECK 0x04 /* Needs type check. */
|
||||
#define IRSLOAD_CONVERT 0x08 /* Number to integer conversion. */
|
||||
#define IRSLOAD_READONLY 0x10 /* Read-only, omit slot store. */
|
||||
#define IRSLOAD_INHERIT 0x20 /* Inherited by exits/side traces. */
|
||||
|
||||
/* XLOAD mode, stored in op2. */
|
||||
#define IRXLOAD_READONLY 1 /* Load from read-only data. */
|
||||
#define IRXLOAD_VOLATILE 2 /* Load from volatile data. */
|
||||
#define IRXLOAD_UNALIGNED 4 /* Unaligned load. */
|
||||
|
||||
/* BUFHDR mode, stored in op2. */
|
||||
#define IRBUFHDR_RESET 0 /* Reset buffer. */
|
||||
#define IRBUFHDR_APPEND 1 /* Append to buffer. */
|
||||
|
||||
/* CONV mode, stored in op2. */
|
||||
#define IRCONV_SRCMASK 0x001f /* Source IRType. */
|
||||
#define IRCONV_DSTMASK 0x03e0 /* Dest. IRType (also in ir->t). */
|
||||
#define IRCONV_DSH 5
|
||||
#define IRCONV_NUM_INT ((IRT_NUM<<IRCONV_DSH)|IRT_INT)
|
||||
#define IRCONV_INT_NUM ((IRT_INT<<IRCONV_DSH)|IRT_NUM)
|
||||
#define IRCONV_SEXT 0x0800 /* Sign-extend integer to integer. */
|
||||
#define IRCONV_MODEMASK 0x0fff
|
||||
#define IRCONV_CONVMASK 0xf000
|
||||
#define IRCONV_CSH 12
|
||||
/* Number to integer conversion mode. Ordered by strength of the checks. */
|
||||
#define IRCONV_TOBIT (0<<IRCONV_CSH) /* None. Cache only: TOBIT conv. */
|
||||
#define IRCONV_ANY (1<<IRCONV_CSH) /* Any FP number is ok. */
|
||||
#define IRCONV_INDEX (2<<IRCONV_CSH) /* Check + special backprop rules. */
|
||||
#define IRCONV_CHECK (3<<IRCONV_CSH) /* Number checked for integerness. */
|
||||
|
||||
/* TOSTR mode, stored in op2. */
|
||||
#define IRTOSTR_INT 0 /* Convert integer to string. */
|
||||
#define IRTOSTR_NUM 1 /* Convert number to string. */
|
||||
#define IRTOSTR_CHAR 2 /* Convert char value to string. */
|
||||
|
||||
/* -- IR operands --------------------------------------------------------- */
|
||||
|
||||
/* IR operand mode (2 bit). */
|
||||
typedef enum {
|
||||
IRMref, /* IR reference. */
|
||||
IRMlit, /* 16 bit unsigned literal. */
|
||||
IRMcst, /* Constant literal: i, gcr or ptr. */
|
||||
IRMnone /* Unused operand. */
|
||||
} IRMode;
|
||||
#define IRM___ IRMnone
|
||||
|
||||
/* Mode bits: Commutative, {Normal/Ref, Alloc, Load, Store}, Non-weak guard. */
|
||||
#define IRM_C 0x10
|
||||
|
||||
#define IRM_N 0x00
|
||||
#define IRM_R IRM_N
|
||||
#define IRM_A 0x20
|
||||
#define IRM_L 0x40
|
||||
#define IRM_S 0x60
|
||||
|
||||
#define IRM_W 0x80
|
||||
|
||||
#define IRM_NW (IRM_N|IRM_W)
|
||||
#define IRM_CW (IRM_C|IRM_W)
|
||||
#define IRM_AW (IRM_A|IRM_W)
|
||||
#define IRM_LW (IRM_L|IRM_W)
|
||||
|
||||
#define irm_op1(m) ((IRMode)((m)&3))
|
||||
#define irm_op2(m) ((IRMode)(((m)>>2)&3))
|
||||
#define irm_iscomm(m) ((m) & IRM_C)
|
||||
#define irm_kind(m) ((m) & IRM_S)
|
||||
|
||||
#define IRMODE(name, m, m1, m2) (((IRM##m1)|((IRM##m2)<<2)|(IRM_##m))^IRM_W),
|
||||
|
||||
LJ_DATA const uint8_t lj_ir_mode[IR__MAX+1];
|
||||
|
||||
/* -- IR instruction types ------------------------------------------------ */
|
||||
|
||||
#define IRTSIZE_PGC (LJ_GC64 ? 8 : 4)
|
||||
|
||||
/* Map of itypes to non-negative numbers and their sizes. ORDER LJ_T.
|
||||
** LJ_TUPVAL/LJ_TTRACE never appear in a TValue. Use these itypes for
|
||||
** IRT_P32 and IRT_P64, which never escape the IR.
|
||||
** The various integers are only used in the IR and can only escape to
|
||||
** a TValue after implicit or explicit conversion. Their types must be
|
||||
** contiguous and next to IRT_NUM (see the typerange macros below).
|
||||
*/
|
||||
#define IRTDEF(_) \
|
||||
_(NIL, 4) _(FALSE, 4) _(TRUE, 4) _(LIGHTUD, LJ_64 ? 8 : 4) \
|
||||
_(STR, IRTSIZE_PGC) _(P32, 4) _(THREAD, IRTSIZE_PGC) _(PROTO, IRTSIZE_PGC) \
|
||||
_(FUNC, IRTSIZE_PGC) _(P64, 8) _(CDATA, IRTSIZE_PGC) _(TAB, IRTSIZE_PGC) \
|
||||
_(UDATA, IRTSIZE_PGC) \
|
||||
_(FLOAT, 4) _(NUM, 8) _(I8, 1) _(U8, 1) _(I16, 2) _(U16, 2) \
|
||||
_(INT, 4) _(U32, 4) _(I64, 8) _(U64, 8) \
|
||||
_(SOFTFP, 4) /* There is room for 8 more types. */
|
||||
|
||||
/* IR result type and flags (8 bit). */
|
||||
typedef enum {
|
||||
#define IRTENUM(name, size) IRT_##name,
|
||||
IRTDEF(IRTENUM)
|
||||
#undef IRTENUM
|
||||
IRT__MAX,
|
||||
|
||||
/* Native pointer type and the corresponding integer type. */
|
||||
IRT_PTR = LJ_64 ? IRT_P64 : IRT_P32,
|
||||
IRT_PGC = LJ_GC64 ? IRT_P64 : IRT_P32,
|
||||
IRT_IGC = LJ_GC64 ? IRT_I64 : IRT_INT,
|
||||
IRT_INTP = LJ_64 ? IRT_I64 : IRT_INT,
|
||||
IRT_UINTP = LJ_64 ? IRT_U64 : IRT_U32,
|
||||
|
||||
/* Additional flags. */
|
||||
IRT_MARK = 0x20, /* Marker for misc. purposes. */
|
||||
IRT_ISPHI = 0x40, /* Instruction is left or right PHI operand. */
|
||||
IRT_GUARD = 0x80, /* Instruction is a guard. */
|
||||
|
||||
/* Masks. */
|
||||
IRT_TYPE = 0x1f,
|
||||
IRT_T = 0xff
|
||||
} IRType;
|
||||
|
||||
#define irtype_ispri(irt) ((uint32_t)(irt) <= IRT_TRUE)
|
||||
|
||||
/* Stored IRType. */
|
||||
typedef struct IRType1 { uint8_t irt; } IRType1;
|
||||
|
||||
#define IRT(o, t) ((uint32_t)(((o)<<8) | (t)))
|
||||
#define IRTI(o) (IRT((o), IRT_INT))
|
||||
#define IRTN(o) (IRT((o), IRT_NUM))
|
||||
#define IRTG(o, t) (IRT((o), IRT_GUARD|(t)))
|
||||
#define IRTGI(o) (IRT((o), IRT_GUARD|IRT_INT))
|
||||
|
||||
#define irt_t(t) ((IRType)(t).irt)
|
||||
#define irt_type(t) ((IRType)((t).irt & IRT_TYPE))
|
||||
#define irt_sametype(t1, t2) ((((t1).irt ^ (t2).irt) & IRT_TYPE) == 0)
|
||||
#define irt_typerange(t, first, last) \
|
||||
((uint32_t)((t).irt & IRT_TYPE) - (uint32_t)(first) <= (uint32_t)(last-first))
|
||||
|
||||
#define irt_isnil(t) (irt_type(t) == IRT_NIL)
|
||||
#define irt_ispri(t) ((uint32_t)irt_type(t) <= IRT_TRUE)
|
||||
#define irt_islightud(t) (irt_type(t) == IRT_LIGHTUD)
|
||||
#define irt_isstr(t) (irt_type(t) == IRT_STR)
|
||||
#define irt_istab(t) (irt_type(t) == IRT_TAB)
|
||||
#define irt_iscdata(t) (irt_type(t) == IRT_CDATA)
|
||||
#define irt_isfloat(t) (irt_type(t) == IRT_FLOAT)
|
||||
#define irt_isnum(t) (irt_type(t) == IRT_NUM)
|
||||
#define irt_isint(t) (irt_type(t) == IRT_INT)
|
||||
#define irt_isi8(t) (irt_type(t) == IRT_I8)
|
||||
#define irt_isu8(t) (irt_type(t) == IRT_U8)
|
||||
#define irt_isi16(t) (irt_type(t) == IRT_I16)
|
||||
#define irt_isu16(t) (irt_type(t) == IRT_U16)
|
||||
#define irt_isu32(t) (irt_type(t) == IRT_U32)
|
||||
#define irt_isi64(t) (irt_type(t) == IRT_I64)
|
||||
#define irt_isu64(t) (irt_type(t) == IRT_U64)
|
||||
|
||||
#define irt_isfp(t) (irt_isnum(t) || irt_isfloat(t))
|
||||
#define irt_isinteger(t) (irt_typerange((t), IRT_I8, IRT_INT))
|
||||
#define irt_isgcv(t) (irt_typerange((t), IRT_STR, IRT_UDATA))
|
||||
#define irt_isaddr(t) (irt_typerange((t), IRT_LIGHTUD, IRT_UDATA))
|
||||
#define irt_isint64(t) (irt_typerange((t), IRT_I64, IRT_U64))
|
||||
|
||||
#if LJ_GC64
|
||||
#define IRT_IS64 \
|
||||
((1u<<IRT_NUM)|(1u<<IRT_I64)|(1u<<IRT_U64)|(1u<<IRT_P64)|\
|
||||
(1u<<IRT_LIGHTUD)|(1u<<IRT_STR)|(1u<<IRT_THREAD)|(1u<<IRT_PROTO)|\
|
||||
(1u<<IRT_FUNC)|(1u<<IRT_CDATA)|(1u<<IRT_TAB)|(1u<<IRT_UDATA))
|
||||
#elif LJ_64
|
||||
#define IRT_IS64 \
|
||||
((1u<<IRT_NUM)|(1u<<IRT_I64)|(1u<<IRT_U64)|(1u<<IRT_P64)|(1u<<IRT_LIGHTUD))
|
||||
#else
|
||||
#define IRT_IS64 \
|
||||
((1u<<IRT_NUM)|(1u<<IRT_I64)|(1u<<IRT_U64))
|
||||
#endif
|
||||
|
||||
#define irt_is64(t) ((IRT_IS64 >> irt_type(t)) & 1)
|
||||
#define irt_is64orfp(t) (((IRT_IS64|(1u<<IRT_FLOAT))>>irt_type(t)) & 1)
|
||||
|
||||
#define irt_size(t) (lj_ir_type_size[irt_t((t))])
|
||||
|
||||
LJ_DATA const uint8_t lj_ir_type_size[];
|
||||
|
||||
static LJ_AINLINE IRType itype2irt(const TValue *tv)
|
||||
{
|
||||
if (tvisint(tv))
|
||||
return IRT_INT;
|
||||
else if (tvisnum(tv))
|
||||
return IRT_NUM;
|
||||
#if LJ_64 && !LJ_GC64
|
||||
else if (tvislightud(tv))
|
||||
return IRT_LIGHTUD;
|
||||
#endif
|
||||
else
|
||||
return (IRType)~itype(tv);
|
||||
}
|
||||
|
||||
static LJ_AINLINE uint32_t irt_toitype_(IRType t)
|
||||
{
|
||||
lua_assert(!LJ_64 || LJ_GC64 || t != IRT_LIGHTUD);
|
||||
if (LJ_DUALNUM && t > IRT_NUM) {
|
||||
return LJ_TISNUM;
|
||||
} else {
|
||||
lua_assert(t <= IRT_NUM);
|
||||
return ~(uint32_t)t;
|
||||
}
|
||||
}
|
||||
|
||||
#define irt_toitype(t) irt_toitype_(irt_type((t)))
|
||||
|
||||
#define irt_isguard(t) ((t).irt & IRT_GUARD)
|
||||
#define irt_ismarked(t) ((t).irt & IRT_MARK)
|
||||
#define irt_setmark(t) ((t).irt |= IRT_MARK)
|
||||
#define irt_clearmark(t) ((t).irt &= ~IRT_MARK)
|
||||
#define irt_isphi(t) ((t).irt & IRT_ISPHI)
|
||||
#define irt_setphi(t) ((t).irt |= IRT_ISPHI)
|
||||
#define irt_clearphi(t) ((t).irt &= ~IRT_ISPHI)
|
||||
|
||||
/* Stored combined IR opcode and type. */
|
||||
typedef uint16_t IROpT;
|
||||
|
||||
/* -- IR references ------------------------------------------------------- */
|
||||
|
||||
/* IR references. */
|
||||
typedef uint16_t IRRef1; /* One stored reference. */
|
||||
typedef uint32_t IRRef2; /* Two stored references. */
|
||||
typedef uint32_t IRRef; /* Used to pass around references. */
|
||||
|
||||
/* Fixed references. */
|
||||
enum {
|
||||
REF_BIAS = 0x8000,
|
||||
REF_TRUE = REF_BIAS-3,
|
||||
REF_FALSE = REF_BIAS-2,
|
||||
REF_NIL = REF_BIAS-1, /* \--- Constants grow downwards. */
|
||||
REF_BASE = REF_BIAS, /* /--- IR grows upwards. */
|
||||
REF_FIRST = REF_BIAS+1,
|
||||
REF_DROP = 0xffff
|
||||
};
|
||||
|
||||
/* Note: IRMlit operands must be < REF_BIAS, too!
|
||||
** This allows for fast and uniform manipulation of all operands
|
||||
** without looking up the operand mode in lj_ir_mode:
|
||||
** - CSE calculates the maximum reference of two operands.
|
||||
** This must work with mixed reference/literal operands, too.
|
||||
** - DCE marking only checks for operand >= REF_BIAS.
|
||||
** - LOOP needs to substitute reference operands.
|
||||
** Constant references and literals must not be modified.
|
||||
*/
|
||||
|
||||
#define IRREF2(lo, hi) ((IRRef2)(lo) | ((IRRef2)(hi) << 16))
|
||||
|
||||
#define irref_isk(ref) ((ref) < REF_BIAS)
|
||||
|
||||
/* Tagged IR references (32 bit).
|
||||
**
|
||||
** +-------+-------+---------------+
|
||||
** | irt | flags | ref |
|
||||
** +-------+-------+---------------+
|
||||
**
|
||||
** The tag holds a copy of the IRType and speeds up IR type checks.
|
||||
*/
|
||||
typedef uint32_t TRef;
|
||||
|
||||
#define TREF_REFMASK 0x0000ffff
|
||||
#define TREF_FRAME 0x00010000
|
||||
#define TREF_CONT 0x00020000
|
||||
|
||||
#define TREF(ref, t) ((TRef)((ref) + ((t)<<24)))
|
||||
|
||||
#define tref_ref(tr) ((IRRef1)(tr))
|
||||
#define tref_t(tr) ((IRType)((tr)>>24))
|
||||
#define tref_type(tr) ((IRType)(((tr)>>24) & IRT_TYPE))
|
||||
#define tref_typerange(tr, first, last) \
|
||||
((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)(last-first))
|
||||
|
||||
#define tref_istype(tr, t) (((tr) & (IRT_TYPE<<24)) == ((t)<<24))
|
||||
#define tref_isnil(tr) (tref_istype((tr), IRT_NIL))
|
||||
#define tref_isfalse(tr) (tref_istype((tr), IRT_FALSE))
|
||||
#define tref_istrue(tr) (tref_istype((tr), IRT_TRUE))
|
||||
#define tref_islightud(tr) (tref_istype((tr), IRT_LIGHTUD))
|
||||
#define tref_isstr(tr) (tref_istype((tr), IRT_STR))
|
||||
#define tref_isfunc(tr) (tref_istype((tr), IRT_FUNC))
|
||||
#define tref_iscdata(tr) (tref_istype((tr), IRT_CDATA))
|
||||
#define tref_istab(tr) (tref_istype((tr), IRT_TAB))
|
||||
#define tref_isudata(tr) (tref_istype((tr), IRT_UDATA))
|
||||
#define tref_isnum(tr) (tref_istype((tr), IRT_NUM))
|
||||
#define tref_isint(tr) (tref_istype((tr), IRT_INT))
|
||||
|
||||
#define tref_isbool(tr) (tref_typerange((tr), IRT_FALSE, IRT_TRUE))
|
||||
#define tref_ispri(tr) (tref_typerange((tr), IRT_NIL, IRT_TRUE))
|
||||
#define tref_istruecond(tr) (!tref_typerange((tr), IRT_NIL, IRT_FALSE))
|
||||
#define tref_isinteger(tr) (tref_typerange((tr), IRT_I8, IRT_INT))
|
||||
#define tref_isnumber(tr) (tref_typerange((tr), IRT_NUM, IRT_INT))
|
||||
#define tref_isnumber_str(tr) (tref_isnumber((tr)) || tref_isstr((tr)))
|
||||
#define tref_isgcv(tr) (tref_typerange((tr), IRT_STR, IRT_UDATA))
|
||||
|
||||
#define tref_isk(tr) (irref_isk(tref_ref((tr))))
|
||||
#define tref_isk2(tr1, tr2) (irref_isk(tref_ref((tr1) | (tr2))))
|
||||
|
||||
#define TREF_PRI(t) (TREF(REF_NIL-(t), (t)))
|
||||
#define TREF_NIL (TREF_PRI(IRT_NIL))
|
||||
#define TREF_FALSE (TREF_PRI(IRT_FALSE))
|
||||
#define TREF_TRUE (TREF_PRI(IRT_TRUE))
|
||||
|
||||
/* -- IR format ----------------------------------------------------------- */
|
||||
|
||||
/* IR instruction format (64 bit).
|
||||
**
|
||||
** 16 16 8 8 8 8
|
||||
** +-------+-------+---+---+---+---+
|
||||
** | op1 | op2 | t | o | r | s |
|
||||
** +-------+-------+---+---+---+---+
|
||||
** | op12/i/gco32 | ot | prev | (alternative fields in union)
|
||||
** +-------+-------+---+---+---+---+
|
||||
** | TValue/gco64 | (2nd IR slot for 64 bit constants)
|
||||
** +---------------+-------+-------+
|
||||
** 32 16 16
|
||||
**
|
||||
** prev is only valid prior to register allocation and then reused for r + s.
|
||||
*/
|
||||
|
||||
typedef union IRIns {
|
||||
struct {
|
||||
LJ_ENDIAN_LOHI(
|
||||
IRRef1 op1; /* IR operand 1. */
|
||||
, IRRef1 op2; /* IR operand 2. */
|
||||
)
|
||||
IROpT ot; /* IR opcode and type (overlaps t and o). */
|
||||
IRRef1 prev; /* Previous ins in same chain (overlaps r and s). */
|
||||
};
|
||||
struct {
|
||||
IRRef2 op12; /* IR operand 1 and 2 (overlaps op1 and op2). */
|
||||
LJ_ENDIAN_LOHI(
|
||||
IRType1 t; /* IR type. */
|
||||
, IROp1 o; /* IR opcode. */
|
||||
)
|
||||
LJ_ENDIAN_LOHI(
|
||||
uint8_t r; /* Register allocation (overlaps prev). */
|
||||
, uint8_t s; /* Spill slot allocation (overlaps prev). */
|
||||
)
|
||||
};
|
||||
int32_t i; /* 32 bit signed integer literal (overlaps op12). */
|
||||
GCRef gcr; /* GCobj constant (overlaps op12 or entire slot). */
|
||||
MRef ptr; /* Pointer constant (overlaps op12 or entire slot). */
|
||||
TValue tv; /* TValue constant (overlaps entire slot). */
|
||||
} IRIns;
|
||||
|
||||
#define ir_kgc(ir) check_exp((ir)->o == IR_KGC, gcref((ir)[LJ_GC64].gcr))
|
||||
#define ir_kstr(ir) (gco2str(ir_kgc((ir))))
|
||||
#define ir_ktab(ir) (gco2tab(ir_kgc((ir))))
|
||||
#define ir_kfunc(ir) (gco2func(ir_kgc((ir))))
|
||||
#define ir_kcdata(ir) (gco2cd(ir_kgc((ir))))
|
||||
#define ir_knum(ir) check_exp((ir)->o == IR_KNUM, &(ir)[1].tv)
|
||||
#define ir_kint64(ir) check_exp((ir)->o == IR_KINT64, &(ir)[1].tv)
|
||||
#define ir_k64(ir) \
|
||||
check_exp((ir)->o == IR_KNUM || (ir)->o == IR_KINT64 || \
|
||||
(LJ_GC64 && \
|
||||
((ir)->o == IR_KGC || \
|
||||
(ir)->o == IR_KPTR || (ir)->o == IR_KKPTR)), \
|
||||
&(ir)[1].tv)
|
||||
#define ir_kptr(ir) \
|
||||
check_exp((ir)->o == IR_KPTR || (ir)->o == IR_KKPTR, \
|
||||
mref((ir)[LJ_GC64].ptr, void))
|
||||
|
||||
/* A store or any other op with a non-weak guard has a side-effect. */
|
||||
static LJ_AINLINE int ir_sideeff(IRIns *ir)
|
||||
{
|
||||
return (((ir->t.irt | ~IRT_GUARD) & lj_ir_mode[ir->o]) >= IRM_S);
|
||||
}
|
||||
|
||||
LJ_STATIC_ASSERT((int)IRT_GUARD == (int)IRM_W);
|
||||
|
||||
#endif
|
||||
343
include/lua/lj_ircall.h
Normal file
343
include/lua/lj_ircall.h
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
** IR CALL* instruction definitions.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_IRCALL_H
|
||||
#define _LJ_IRCALL_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_ir.h"
|
||||
#include "lj_jit.h"
|
||||
|
||||
/* C call info for CALL* instructions. */
|
||||
typedef struct CCallInfo {
|
||||
ASMFunction func; /* Function pointer. */
|
||||
uint32_t flags; /* Number of arguments and flags. */
|
||||
} CCallInfo;
|
||||
|
||||
#define CCI_NARGS(ci) ((ci)->flags & 0xff) /* # of args. */
|
||||
#define CCI_NARGS_MAX 32 /* Max. # of args. */
|
||||
|
||||
#define CCI_OTSHIFT 16
|
||||
#define CCI_OPTYPE(ci) ((ci)->flags >> CCI_OTSHIFT) /* Get op/type. */
|
||||
#define CCI_OPSHIFT 24
|
||||
#define CCI_OP(ci) ((ci)->flags >> CCI_OPSHIFT) /* Get op. */
|
||||
|
||||
#define CCI_CALL_N (IR_CALLN << CCI_OPSHIFT)
|
||||
#define CCI_CALL_A (IR_CALLA << CCI_OPSHIFT)
|
||||
#define CCI_CALL_L (IR_CALLL << CCI_OPSHIFT)
|
||||
#define CCI_CALL_S (IR_CALLS << CCI_OPSHIFT)
|
||||
#define CCI_CALL_FN (CCI_CALL_N|CCI_CC_FASTCALL)
|
||||
#define CCI_CALL_FL (CCI_CALL_L|CCI_CC_FASTCALL)
|
||||
#define CCI_CALL_FS (CCI_CALL_S|CCI_CC_FASTCALL)
|
||||
|
||||
/* C call info flags. */
|
||||
#define CCI_L 0x0100 /* Implicit L arg. */
|
||||
#define CCI_CASTU64 0x0200 /* Cast u64 result to number. */
|
||||
#define CCI_NOFPRCLOBBER 0x0400 /* Does not clobber any FPRs. */
|
||||
#define CCI_VARARG 0x0800 /* Vararg function. */
|
||||
|
||||
#define CCI_CC_MASK 0x3000 /* Calling convention mask. */
|
||||
#define CCI_CC_SHIFT 12
|
||||
/* ORDER CC */
|
||||
#define CCI_CC_CDECL 0x0000 /* Default cdecl calling convention. */
|
||||
#define CCI_CC_THISCALL 0x1000 /* Thiscall calling convention. */
|
||||
#define CCI_CC_FASTCALL 0x2000 /* Fastcall calling convention. */
|
||||
#define CCI_CC_STDCALL 0x3000 /* Stdcall calling convention. */
|
||||
|
||||
/* Extra args for SOFTFP, SPLIT 64 bit. */
|
||||
#define CCI_XARGS_SHIFT 14
|
||||
#define CCI_XARGS(ci) (((ci)->flags >> CCI_XARGS_SHIFT) & 3)
|
||||
#define CCI_XA (1u << CCI_XARGS_SHIFT)
|
||||
|
||||
#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
|
||||
#define CCI_XNARGS(ci) (CCI_NARGS((ci)) + CCI_XARGS((ci)))
|
||||
#else
|
||||
#define CCI_XNARGS(ci) CCI_NARGS((ci))
|
||||
#endif
|
||||
|
||||
/* Helpers for conditional function definitions. */
|
||||
#define IRCALLCOND_ANY(x) x
|
||||
|
||||
#if LJ_TARGET_X86ORX64
|
||||
#define IRCALLCOND_FPMATH(x) NULL
|
||||
#else
|
||||
#define IRCALLCOND_FPMATH(x) x
|
||||
#endif
|
||||
|
||||
#if LJ_SOFTFP
|
||||
#define IRCALLCOND_SOFTFP(x) x
|
||||
#if LJ_HASFFI
|
||||
#define IRCALLCOND_SOFTFP_FFI(x) x
|
||||
#else
|
||||
#define IRCALLCOND_SOFTFP_FFI(x) NULL
|
||||
#endif
|
||||
#else
|
||||
#define IRCALLCOND_SOFTFP(x) NULL
|
||||
#define IRCALLCOND_SOFTFP_FFI(x) NULL
|
||||
#endif
|
||||
|
||||
#if LJ_SOFTFP && LJ_TARGET_MIPS32
|
||||
#define IRCALLCOND_SOFTFP_MIPS(x) x
|
||||
#else
|
||||
#define IRCALLCOND_SOFTFP_MIPS(x) NULL
|
||||
#endif
|
||||
|
||||
#define LJ_NEED_FP64 (LJ_TARGET_ARM || LJ_TARGET_PPC || LJ_TARGET_MIPS32)
|
||||
|
||||
#if LJ_HASFFI && (LJ_SOFTFP || LJ_NEED_FP64)
|
||||
#define IRCALLCOND_FP64_FFI(x) x
|
||||
#else
|
||||
#define IRCALLCOND_FP64_FFI(x) NULL
|
||||
#endif
|
||||
|
||||
#if LJ_HASFFI
|
||||
#define IRCALLCOND_FFI(x) x
|
||||
#if LJ_32
|
||||
#define IRCALLCOND_FFI32(x) x
|
||||
#else
|
||||
#define IRCALLCOND_FFI32(x) NULL
|
||||
#endif
|
||||
#else
|
||||
#define IRCALLCOND_FFI(x) NULL
|
||||
#define IRCALLCOND_FFI32(x) NULL
|
||||
#endif
|
||||
|
||||
#if LJ_SOFTFP
|
||||
#define XA_FP CCI_XA
|
||||
#define XA2_FP (CCI_XA+CCI_XA)
|
||||
#else
|
||||
#define XA_FP 0
|
||||
#define XA2_FP 0
|
||||
#endif
|
||||
|
||||
#if LJ_32
|
||||
#define XA_64 CCI_XA
|
||||
#define XA2_64 (CCI_XA+CCI_XA)
|
||||
#else
|
||||
#define XA_64 0
|
||||
#define XA2_64 0
|
||||
#endif
|
||||
|
||||
/* Function definitions for CALL* instructions. */
|
||||
#define IRCALLDEF(_) \
|
||||
_(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \
|
||||
_(ANY, lj_str_find, 4, N, PGC, 0) \
|
||||
_(ANY, lj_str_new, 3, S, STR, CCI_L) \
|
||||
_(ANY, lj_strscan_num, 2, FN, INT, 0) \
|
||||
_(ANY, lj_strfmt_int, 2, FN, STR, CCI_L) \
|
||||
_(ANY, lj_strfmt_num, 2, FN, STR, CCI_L) \
|
||||
_(ANY, lj_strfmt_char, 2, FN, STR, CCI_L) \
|
||||
_(ANY, lj_strfmt_putint, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_strfmt_putnum, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_strfmt_putquoted, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_strfmt_putfxint, 3, L, PGC, XA_64) \
|
||||
_(ANY, lj_strfmt_putfnum_int, 3, L, PGC, XA_FP) \
|
||||
_(ANY, lj_strfmt_putfnum_uint, 3, L, PGC, XA_FP) \
|
||||
_(ANY, lj_strfmt_putfnum, 3, L, PGC, XA_FP) \
|
||||
_(ANY, lj_strfmt_putfstr, 3, L, PGC, 0) \
|
||||
_(ANY, lj_strfmt_putfchar, 3, L, PGC, 0) \
|
||||
_(ANY, lj_buf_putmem, 3, S, PGC, 0) \
|
||||
_(ANY, lj_buf_putstr, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_buf_putchar, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_buf_putstr_reverse, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_buf_putstr_lower, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_buf_putstr_upper, 2, FL, PGC, 0) \
|
||||
_(ANY, lj_buf_putstr_rep, 3, L, PGC, 0) \
|
||||
_(ANY, lj_buf_puttab, 5, L, PGC, 0) \
|
||||
_(ANY, lj_buf_tostr, 1, FL, STR, 0) \
|
||||
_(ANY, lj_tab_new_ah, 3, A, TAB, CCI_L) \
|
||||
_(ANY, lj_tab_new1, 2, FS, TAB, CCI_L) \
|
||||
_(ANY, lj_tab_dup, 2, FS, TAB, CCI_L) \
|
||||
_(ANY, lj_tab_clear, 1, FS, NIL, 0) \
|
||||
_(ANY, lj_tab_newkey, 3, S, PGC, CCI_L) \
|
||||
_(ANY, lj_tab_len, 1, FL, INT, 0) \
|
||||
_(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \
|
||||
_(ANY, lj_gc_barrieruv, 2, FS, NIL, 0) \
|
||||
_(ANY, lj_mem_newgco, 2, FS, PGC, CCI_L) \
|
||||
_(ANY, lj_math_random_step, 1, FS, NUM, CCI_CASTU64) \
|
||||
_(ANY, lj_vm_modi, 2, FN, INT, 0) \
|
||||
_(ANY, sinh, 1, N, NUM, XA_FP) \
|
||||
_(ANY, cosh, 1, N, NUM, XA_FP) \
|
||||
_(ANY, tanh, 1, N, NUM, XA_FP) \
|
||||
_(ANY, fputc, 2, S, INT, 0) \
|
||||
_(ANY, fwrite, 4, S, INT, 0) \
|
||||
_(ANY, fflush, 1, S, INT, 0) \
|
||||
/* ORDER FPM */ \
|
||||
_(FPMATH, lj_vm_floor, 1, N, NUM, XA_FP) \
|
||||
_(FPMATH, lj_vm_ceil, 1, N, NUM, XA_FP) \
|
||||
_(FPMATH, lj_vm_trunc, 1, N, NUM, XA_FP) \
|
||||
_(FPMATH, sqrt, 1, N, NUM, XA_FP) \
|
||||
_(ANY, exp, 1, N, NUM, XA_FP) \
|
||||
_(ANY, lj_vm_exp2, 1, N, NUM, XA_FP) \
|
||||
_(ANY, log, 1, N, NUM, XA_FP) \
|
||||
_(ANY, lj_vm_log2, 1, N, NUM, XA_FP) \
|
||||
_(ANY, log10, 1, N, NUM, XA_FP) \
|
||||
_(ANY, sin, 1, N, NUM, XA_FP) \
|
||||
_(ANY, cos, 1, N, NUM, XA_FP) \
|
||||
_(ANY, tan, 1, N, NUM, XA_FP) \
|
||||
_(ANY, lj_vm_powi, 2, N, NUM, XA_FP) \
|
||||
_(ANY, pow, 2, N, NUM, XA2_FP) \
|
||||
_(ANY, atan2, 2, N, NUM, XA2_FP) \
|
||||
_(ANY, ldexp, 2, N, NUM, XA_FP) \
|
||||
_(SOFTFP, lj_vm_tobit, 2, N, INT, 0) \
|
||||
_(SOFTFP, softfp_add, 4, N, NUM, 0) \
|
||||
_(SOFTFP, softfp_sub, 4, N, NUM, 0) \
|
||||
_(SOFTFP, softfp_mul, 4, N, NUM, 0) \
|
||||
_(SOFTFP, softfp_div, 4, N, NUM, 0) \
|
||||
_(SOFTFP, softfp_cmp, 4, N, NIL, 0) \
|
||||
_(SOFTFP, softfp_i2d, 1, N, NUM, 0) \
|
||||
_(SOFTFP, softfp_d2i, 2, N, INT, 0) \
|
||||
_(SOFTFP_MIPS, lj_vm_sfmin, 4, N, NUM, 0) \
|
||||
_(SOFTFP_MIPS, lj_vm_sfmax, 4, N, NUM, 0) \
|
||||
_(SOFTFP_FFI, softfp_ui2d, 1, N, NUM, 0) \
|
||||
_(SOFTFP_FFI, softfp_f2d, 1, N, NUM, 0) \
|
||||
_(SOFTFP_FFI, softfp_d2ui, 2, N, INT, 0) \
|
||||
_(SOFTFP_FFI, softfp_d2f, 2, N, FLOAT, 0) \
|
||||
_(SOFTFP_FFI, softfp_i2f, 1, N, FLOAT, 0) \
|
||||
_(SOFTFP_FFI, softfp_ui2f, 1, N, FLOAT, 0) \
|
||||
_(SOFTFP_FFI, softfp_f2i, 1, N, INT, 0) \
|
||||
_(SOFTFP_FFI, softfp_f2ui, 1, N, INT, 0) \
|
||||
_(FP64_FFI, fp64_l2d, 1, N, NUM, XA_64) \
|
||||
_(FP64_FFI, fp64_ul2d, 1, N, NUM, XA_64) \
|
||||
_(FP64_FFI, fp64_l2f, 1, N, FLOAT, XA_64) \
|
||||
_(FP64_FFI, fp64_ul2f, 1, N, FLOAT, XA_64) \
|
||||
_(FP64_FFI, fp64_d2l, 1, N, I64, XA_FP) \
|
||||
_(FP64_FFI, fp64_d2ul, 1, N, U64, XA_FP) \
|
||||
_(FP64_FFI, fp64_f2l, 1, N, I64, 0) \
|
||||
_(FP64_FFI, fp64_f2ul, 1, N, U64, 0) \
|
||||
_(FFI, lj_carith_divi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI, lj_carith_divu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI, lj_carith_modi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI, lj_carith_modu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI, lj_carith_powi64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI, lj_carith_powu64, 2, N, U64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI, lj_cdata_newv, 4, S, CDATA, CCI_L) \
|
||||
_(FFI, lj_cdata_setfin, 4, S, NIL, CCI_L) \
|
||||
_(FFI, strlen, 1, L, INTP, 0) \
|
||||
_(FFI, memcpy, 3, S, PTR, 0) \
|
||||
_(FFI, memset, 3, S, PTR, 0) \
|
||||
_(FFI, lj_vm_errno, 0, S, INT, CCI_NOFPRCLOBBER) \
|
||||
_(FFI32, lj_carith_mul64, 2, N, I64, XA2_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI32, lj_carith_shl64, 2, N, U64, XA_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI32, lj_carith_shr64, 2, N, U64, XA_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI32, lj_carith_sar64, 2, N, U64, XA_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI32, lj_carith_rol64, 2, N, U64, XA_64|CCI_NOFPRCLOBBER) \
|
||||
_(FFI32, lj_carith_ror64, 2, N, U64, XA_64|CCI_NOFPRCLOBBER) \
|
||||
\
|
||||
/* End of list. */
|
||||
|
||||
typedef enum {
|
||||
#define IRCALLENUM(cond, name, nargs, kind, type, flags) IRCALL_##name,
|
||||
IRCALLDEF(IRCALLENUM)
|
||||
#undef IRCALLENUM
|
||||
IRCALL__MAX
|
||||
} IRCallID;
|
||||
|
||||
LJ_FUNC TRef lj_ir_call(jit_State *J, IRCallID id, ...);
|
||||
|
||||
LJ_DATA const CCallInfo lj_ir_callinfo[IRCALL__MAX+1];
|
||||
|
||||
/* Soft-float declarations. */
|
||||
#if LJ_SOFTFP
|
||||
#if LJ_TARGET_ARM
|
||||
#define softfp_add __aeabi_dadd
|
||||
#define softfp_sub __aeabi_dsub
|
||||
#define softfp_mul __aeabi_dmul
|
||||
#define softfp_div __aeabi_ddiv
|
||||
#define softfp_cmp __aeabi_cdcmple
|
||||
#define softfp_i2d __aeabi_i2d
|
||||
#define softfp_d2i __aeabi_d2iz
|
||||
#define softfp_ui2d __aeabi_ui2d
|
||||
#define softfp_f2d __aeabi_f2d
|
||||
#define softfp_d2ui __aeabi_d2uiz
|
||||
#define softfp_d2f __aeabi_d2f
|
||||
#define softfp_i2f __aeabi_i2f
|
||||
#define softfp_ui2f __aeabi_ui2f
|
||||
#define softfp_f2i __aeabi_f2iz
|
||||
#define softfp_f2ui __aeabi_f2uiz
|
||||
#define fp64_l2d __aeabi_l2d
|
||||
#define fp64_ul2d __aeabi_ul2d
|
||||
#define fp64_l2f __aeabi_l2f
|
||||
#define fp64_ul2f __aeabi_ul2f
|
||||
#if LJ_TARGET_IOS
|
||||
#define fp64_d2l __fixdfdi
|
||||
#define fp64_d2ul __fixunsdfdi
|
||||
#define fp64_f2l __fixsfdi
|
||||
#define fp64_f2ul __fixunssfdi
|
||||
#else
|
||||
#define fp64_d2l __aeabi_d2lz
|
||||
#define fp64_d2ul __aeabi_d2ulz
|
||||
#define fp64_f2l __aeabi_f2lz
|
||||
#define fp64_f2ul __aeabi_f2ulz
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS
|
||||
#define softfp_add __adddf3
|
||||
#define softfp_sub __subdf3
|
||||
#define softfp_mul __muldf3
|
||||
#define softfp_div __divdf3
|
||||
#define softfp_cmp __ledf2
|
||||
#define softfp_i2d __floatsidf
|
||||
#define softfp_d2i __fixdfsi
|
||||
#define softfp_ui2d __floatunsidf
|
||||
#define softfp_f2d __extendsfdf2
|
||||
#define softfp_d2ui __fixunsdfsi
|
||||
#define softfp_d2f __truncdfsf2
|
||||
#define softfp_i2f __floatsisf
|
||||
#define softfp_ui2f __floatunsisf
|
||||
#define softfp_f2i __fixsfsi
|
||||
#define softfp_f2ui __fixunssfsi
|
||||
#else
|
||||
#error "Missing soft-float definitions for target architecture"
|
||||
#endif
|
||||
extern double softfp_add(double a, double b);
|
||||
extern double softfp_sub(double a, double b);
|
||||
extern double softfp_mul(double a, double b);
|
||||
extern double softfp_div(double a, double b);
|
||||
extern void softfp_cmp(double a, double b);
|
||||
extern double softfp_i2d(int32_t a);
|
||||
extern int32_t softfp_d2i(double a);
|
||||
#if LJ_HASFFI
|
||||
extern double softfp_ui2d(uint32_t a);
|
||||
extern double softfp_f2d(float a);
|
||||
extern uint32_t softfp_d2ui(double a);
|
||||
extern float softfp_d2f(double a);
|
||||
extern float softfp_i2f(int32_t a);
|
||||
extern float softfp_ui2f(uint32_t a);
|
||||
extern int32_t softfp_f2i(float a);
|
||||
extern uint32_t softfp_f2ui(float a);
|
||||
#endif
|
||||
#if LJ_TARGET_MIPS
|
||||
extern double lj_vm_sfmin(double a, double b);
|
||||
extern double lj_vm_sfmax(double a, double b);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LJ_HASFFI && LJ_NEED_FP64 && !(LJ_TARGET_ARM && LJ_SOFTFP)
|
||||
#ifdef __GNUC__
|
||||
#define fp64_l2d __floatdidf
|
||||
#define fp64_ul2d __floatundidf
|
||||
#define fp64_l2f __floatdisf
|
||||
#define fp64_ul2f __floatundisf
|
||||
#define fp64_d2l __fixdfdi
|
||||
#define fp64_d2ul __fixunsdfdi
|
||||
#define fp64_f2l __fixsfdi
|
||||
#define fp64_f2ul __fixunssfdi
|
||||
#else
|
||||
#error "Missing fp64 helper definitions for this compiler"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LJ_HASFFI && (LJ_SOFTFP || LJ_NEED_FP64)
|
||||
extern double fp64_l2d(int64_t a);
|
||||
extern double fp64_ul2d(uint64_t a);
|
||||
extern float fp64_l2f(int64_t a);
|
||||
extern float fp64_ul2f(uint64_t a);
|
||||
extern int64_t fp64_d2l(double a);
|
||||
extern uint64_t fp64_d2ul(double a);
|
||||
extern int64_t fp64_f2l(float a);
|
||||
extern uint64_t fp64_f2ul(float a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
162
include/lua/lj_iropt.h
Normal file
162
include/lua/lj_iropt.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
** Common header for IR emitter and optimizations.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_IROPT_H
|
||||
#define _LJ_IROPT_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_jit.h"
|
||||
|
||||
#if LJ_HASJIT
|
||||
/* IR emitter. */
|
||||
LJ_FUNC void LJ_FASTCALL lj_ir_growtop(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_ir_emit(jit_State *J);
|
||||
|
||||
/* Save current IR in J->fold.ins, but do not emit it (yet). */
|
||||
static LJ_AINLINE void lj_ir_set_(jit_State *J, uint16_t ot, IRRef1 a, IRRef1 b)
|
||||
{
|
||||
J->fold.ins.ot = ot; J->fold.ins.op1 = a; J->fold.ins.op2 = b;
|
||||
}
|
||||
|
||||
#define lj_ir_set(J, ot, a, b) \
|
||||
lj_ir_set_(J, (uint16_t)(ot), (IRRef1)(a), (IRRef1)(b))
|
||||
|
||||
/* Get ref of next IR instruction and optionally grow IR.
|
||||
** Note: this may invalidate all IRIns*!
|
||||
*/
|
||||
static LJ_AINLINE IRRef lj_ir_nextins(jit_State *J)
|
||||
{
|
||||
IRRef ref = J->cur.nins;
|
||||
if (LJ_UNLIKELY(ref >= J->irtoplim)) lj_ir_growtop(J);
|
||||
J->cur.nins = ref + 1;
|
||||
return ref;
|
||||
}
|
||||
|
||||
LJ_FUNC TRef lj_ir_ggfload(jit_State *J, IRType t, uintptr_t ofs);
|
||||
|
||||
/* Interning of constants. */
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k);
|
||||
LJ_FUNC TRef lj_ir_k64(jit_State *J, IROp op, uint64_t u64);
|
||||
LJ_FUNC TRef lj_ir_knum_u64(jit_State *J, uint64_t u64);
|
||||
LJ_FUNC TRef lj_ir_knumint(jit_State *J, lua_Number n);
|
||||
LJ_FUNC TRef lj_ir_kint64(jit_State *J, uint64_t u64);
|
||||
LJ_FUNC TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t);
|
||||
LJ_FUNC TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr);
|
||||
LJ_FUNC TRef lj_ir_knull(jit_State *J, IRType t);
|
||||
LJ_FUNC TRef lj_ir_kslot(jit_State *J, TRef key, IRRef slot);
|
||||
LJ_FUNC TRef lj_ir_ktrace(jit_State *J);
|
||||
|
||||
#if LJ_64
|
||||
#define lj_ir_kintp(J, k) lj_ir_kint64(J, (uint64_t)(k))
|
||||
#else
|
||||
#define lj_ir_kintp(J, k) lj_ir_kint(J, (int32_t)(k))
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE TRef lj_ir_knum(jit_State *J, lua_Number n)
|
||||
{
|
||||
TValue tv;
|
||||
tv.n = n;
|
||||
return lj_ir_knum_u64(J, tv.u64);
|
||||
}
|
||||
|
||||
#define lj_ir_kstr(J, str) lj_ir_kgc(J, obj2gco((str)), IRT_STR)
|
||||
#define lj_ir_ktab(J, tab) lj_ir_kgc(J, obj2gco((tab)), IRT_TAB)
|
||||
#define lj_ir_kfunc(J, func) lj_ir_kgc(J, obj2gco((func)), IRT_FUNC)
|
||||
#define lj_ir_kptr(J, ptr) lj_ir_kptr_(J, IR_KPTR, (ptr))
|
||||
#define lj_ir_kkptr(J, ptr) lj_ir_kptr_(J, IR_KKPTR, (ptr))
|
||||
|
||||
/* Special FP constants. */
|
||||
#define lj_ir_knum_zero(J) lj_ir_knum_u64(J, U64x(00000000,00000000))
|
||||
#define lj_ir_knum_one(J) lj_ir_knum_u64(J, U64x(3ff00000,00000000))
|
||||
#define lj_ir_knum_tobit(J) lj_ir_knum_u64(J, U64x(43380000,00000000))
|
||||
|
||||
/* Special 128 bit SIMD constants. */
|
||||
#define lj_ir_ksimd(J, idx) \
|
||||
lj_ir_ggfload(J, IRT_NUM, (uintptr_t)LJ_KSIMD(J, idx) - (uintptr_t)J2GG(J))
|
||||
|
||||
/* Access to constants. */
|
||||
LJ_FUNC void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir);
|
||||
|
||||
/* Convert IR operand types. */
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_ir_tonumber(jit_State *J, TRef tr);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_ir_tonum(jit_State *J, TRef tr);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr);
|
||||
|
||||
/* Miscellaneous IR ops. */
|
||||
LJ_FUNC int lj_ir_numcmp(lua_Number a, lua_Number b, IROp op);
|
||||
LJ_FUNC int lj_ir_strcmp(GCstr *a, GCstr *b, IROp op);
|
||||
LJ_FUNC void lj_ir_rollback(jit_State *J, IRRef ref);
|
||||
|
||||
/* Emit IR instructions with on-the-fly optimizations. */
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fold(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_cse(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_cselim(jit_State *J, IRRef lim);
|
||||
|
||||
/* Special return values for the fold functions. */
|
||||
enum {
|
||||
NEXTFOLD, /* Couldn't fold, pass on. */
|
||||
RETRYFOLD, /* Retry fold with modified fins. */
|
||||
KINTFOLD, /* Return ref for int constant in fins->i. */
|
||||
FAILFOLD, /* Guard would always fail. */
|
||||
DROPFOLD, /* Guard eliminated. */
|
||||
MAX_FOLD
|
||||
};
|
||||
|
||||
#define INTFOLD(k) ((J->fold.ins.i = (k)), (TRef)KINTFOLD)
|
||||
#define INT64FOLD(k) (lj_ir_kint64(J, (k)))
|
||||
#define CONDFOLD(cond) ((TRef)FAILFOLD + (TRef)(cond))
|
||||
#define LEFTFOLD (J->fold.ins.op1)
|
||||
#define RIGHTFOLD (J->fold.ins.op2)
|
||||
#define CSEFOLD (lj_opt_cse(J))
|
||||
#define EMITFOLD (lj_ir_emit(J))
|
||||
|
||||
/* Load/store forwarding. */
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_aload(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_hload(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_uload(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_fload(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_xload(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_tab_len(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_hrefk(jit_State *J);
|
||||
LJ_FUNC int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J);
|
||||
LJ_FUNC int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim);
|
||||
LJ_FUNC int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref);
|
||||
|
||||
/* Dead-store elimination. */
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ustore(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_fstore(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_xstore(jit_State *J);
|
||||
|
||||
/* Narrowing. */
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_convert(jit_State *J);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_index(jit_State *J, TRef key);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_toint(jit_State *J, TRef tr);
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_tobit(jit_State *J, TRef tr);
|
||||
#if LJ_HASFFI
|
||||
LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_cindex(jit_State *J, TRef key);
|
||||
#endif
|
||||
LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
|
||||
TValue *vb, TValue *vc, IROp op);
|
||||
LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc);
|
||||
LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
|
||||
LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
|
||||
LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
|
||||
|
||||
/* Optimization passes. */
|
||||
LJ_FUNC void lj_opt_dce(jit_State *J);
|
||||
LJ_FUNC int lj_opt_loop(jit_State *J);
|
||||
#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
|
||||
LJ_FUNC void lj_opt_split(jit_State *J);
|
||||
#else
|
||||
#define lj_opt_split(J) UNUSED(J)
|
||||
#endif
|
||||
LJ_FUNC void lj_opt_sink(jit_State *J);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
499
include/lua/lj_jit.h
Normal file
499
include/lua/lj_jit.h
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
** Common definitions for the JIT compiler.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_JIT_H
|
||||
#define _LJ_JIT_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_ir.h"
|
||||
|
||||
/* JIT engine flags. */
|
||||
#define JIT_F_ON 0x00000001
|
||||
|
||||
/* CPU-specific JIT engine flags. */
|
||||
#if LJ_TARGET_X86ORX64
|
||||
#define JIT_F_SSE2 0x00000010
|
||||
#define JIT_F_SSE3 0x00000020
|
||||
#define JIT_F_SSE4_1 0x00000040
|
||||
#define JIT_F_PREFER_IMUL 0x00000080
|
||||
#define JIT_F_LEA_AGU 0x00000100
|
||||
#define JIT_F_BMI2 0x00000200
|
||||
|
||||
/* Names for the CPU-specific flags. Must match the order above. */
|
||||
#define JIT_F_CPU_FIRST JIT_F_SSE2
|
||||
#define JIT_F_CPUSTRING "\4SSE2\4SSE3\6SSE4.1\3AMD\4ATOM\4BMI2"
|
||||
#elif LJ_TARGET_ARM
|
||||
#define JIT_F_ARMV6_ 0x00000010
|
||||
#define JIT_F_ARMV6T2_ 0x00000020
|
||||
#define JIT_F_ARMV7 0x00000040
|
||||
#define JIT_F_VFPV2 0x00000080
|
||||
#define JIT_F_VFPV3 0x00000100
|
||||
|
||||
#define JIT_F_ARMV6 (JIT_F_ARMV6_|JIT_F_ARMV6T2_|JIT_F_ARMV7)
|
||||
#define JIT_F_ARMV6T2 (JIT_F_ARMV6T2_|JIT_F_ARMV7)
|
||||
#define JIT_F_VFP (JIT_F_VFPV2|JIT_F_VFPV3)
|
||||
|
||||
/* Names for the CPU-specific flags. Must match the order above. */
|
||||
#define JIT_F_CPU_FIRST JIT_F_ARMV6_
|
||||
#define JIT_F_CPUSTRING "\5ARMv6\7ARMv6T2\5ARMv7\5VFPv2\5VFPv3"
|
||||
#elif LJ_TARGET_PPC
|
||||
#define JIT_F_SQRT 0x00000010
|
||||
#define JIT_F_ROUND 0x00000020
|
||||
|
||||
/* Names for the CPU-specific flags. Must match the order above. */
|
||||
#define JIT_F_CPU_FIRST JIT_F_SQRT
|
||||
#define JIT_F_CPUSTRING "\4SQRT\5ROUND"
|
||||
#elif LJ_TARGET_MIPS
|
||||
#define JIT_F_MIPSXXR2 0x00000010
|
||||
|
||||
/* Names for the CPU-specific flags. Must match the order above. */
|
||||
#define JIT_F_CPU_FIRST JIT_F_MIPSXXR2
|
||||
#if LJ_TARGET_MIPS32
|
||||
#define JIT_F_CPUSTRING "\010MIPS32R2"
|
||||
#else
|
||||
#define JIT_F_CPUSTRING "\010MIPS64R2"
|
||||
#endif
|
||||
#else
|
||||
#define JIT_F_CPU_FIRST 0
|
||||
#define JIT_F_CPUSTRING ""
|
||||
#endif
|
||||
|
||||
/* Optimization flags. */
|
||||
#define JIT_F_OPT_MASK 0x0fff0000
|
||||
|
||||
#define JIT_F_OPT_FOLD 0x00010000
|
||||
#define JIT_F_OPT_CSE 0x00020000
|
||||
#define JIT_F_OPT_DCE 0x00040000
|
||||
#define JIT_F_OPT_FWD 0x00080000
|
||||
#define JIT_F_OPT_DSE 0x00100000
|
||||
#define JIT_F_OPT_NARROW 0x00200000
|
||||
#define JIT_F_OPT_LOOP 0x00400000
|
||||
#define JIT_F_OPT_ABC 0x00800000
|
||||
#define JIT_F_OPT_SINK 0x01000000
|
||||
#define JIT_F_OPT_FUSE 0x02000000
|
||||
|
||||
/* Optimizations names for -O. Must match the order above. */
|
||||
#define JIT_F_OPT_FIRST JIT_F_OPT_FOLD
|
||||
#define JIT_F_OPTSTRING \
|
||||
"\4fold\3cse\3dce\3fwd\3dse\6narrow\4loop\3abc\4sink\4fuse"
|
||||
|
||||
/* Optimization levels set a fixed combination of flags. */
|
||||
#define JIT_F_OPT_0 0
|
||||
#define JIT_F_OPT_1 (JIT_F_OPT_FOLD|JIT_F_OPT_CSE|JIT_F_OPT_DCE)
|
||||
#define JIT_F_OPT_2 (JIT_F_OPT_1|JIT_F_OPT_NARROW|JIT_F_OPT_LOOP)
|
||||
#define JIT_F_OPT_3 (JIT_F_OPT_2|\
|
||||
JIT_F_OPT_FWD|JIT_F_OPT_DSE|JIT_F_OPT_ABC|JIT_F_OPT_SINK|JIT_F_OPT_FUSE)
|
||||
#define JIT_F_OPT_DEFAULT JIT_F_OPT_3
|
||||
|
||||
#if LJ_TARGET_WINDOWS || LJ_64
|
||||
/* See: http://blogs.msdn.com/oldnewthing/archive/2003/10/08/55239.aspx */
|
||||
#define JIT_P_sizemcode_DEFAULT 64
|
||||
#else
|
||||
/* Could go as low as 4K, but the mmap() overhead would be rather high. */
|
||||
#define JIT_P_sizemcode_DEFAULT 32
|
||||
#endif
|
||||
|
||||
/* Optimization parameters and their defaults. Length is a char in octal! */
|
||||
#define JIT_PARAMDEF(_) \
|
||||
_(\010, maxtrace, 1000) /* Max. # of traces in cache. */ \
|
||||
_(\011, maxrecord, 4000) /* Max. # of recorded IR instructions. */ \
|
||||
_(\012, maxirconst, 500) /* Max. # of IR constants of a trace. */ \
|
||||
_(\007, maxside, 100) /* Max. # of side traces of a root trace. */ \
|
||||
_(\007, maxsnap, 500) /* Max. # of snapshots for a trace. */ \
|
||||
_(\011, minstitch, 0) /* Min. # of IR ins for a stitched trace. */ \
|
||||
\
|
||||
_(\007, hotloop, 56) /* # of iter. to detect a hot loop/call. */ \
|
||||
_(\007, hotexit, 10) /* # of taken exits to start a side trace. */ \
|
||||
_(\007, tryside, 4) /* # of attempts to compile a side trace. */ \
|
||||
\
|
||||
_(\012, instunroll, 4) /* Max. unroll for instable loops. */ \
|
||||
_(\012, loopunroll, 15) /* Max. unroll for loop ops in side traces. */ \
|
||||
_(\012, callunroll, 3) /* Max. unroll for recursive calls. */ \
|
||||
_(\011, recunroll, 2) /* Min. unroll for true recursion. */ \
|
||||
\
|
||||
/* Size of each machine code area (in KBytes). */ \
|
||||
_(\011, sizemcode, JIT_P_sizemcode_DEFAULT) \
|
||||
/* Max. total size of all machine code areas (in KBytes). */ \
|
||||
_(\010, maxmcode, 512) \
|
||||
/* End of list. */
|
||||
|
||||
enum {
|
||||
#define JIT_PARAMENUM(len, name, value) JIT_P_##name,
|
||||
JIT_PARAMDEF(JIT_PARAMENUM)
|
||||
#undef JIT_PARAMENUM
|
||||
JIT_P__MAX
|
||||
};
|
||||
|
||||
#define JIT_PARAMSTR(len, name, value) #len #name
|
||||
#define JIT_P_STRING JIT_PARAMDEF(JIT_PARAMSTR)
|
||||
|
||||
/* Trace compiler state. */
|
||||
typedef enum {
|
||||
LJ_TRACE_IDLE, /* Trace compiler idle. */
|
||||
LJ_TRACE_ACTIVE = 0x10,
|
||||
LJ_TRACE_RECORD, /* Bytecode recording active. */
|
||||
LJ_TRACE_START, /* New trace started. */
|
||||
LJ_TRACE_END, /* End of trace. */
|
||||
LJ_TRACE_ASM, /* Assemble trace. */
|
||||
LJ_TRACE_ERR /* Trace aborted with error. */
|
||||
} TraceState;
|
||||
|
||||
/* Post-processing action. */
|
||||
typedef enum {
|
||||
LJ_POST_NONE, /* No action. */
|
||||
LJ_POST_FIXCOMP, /* Fixup comparison and emit pending guard. */
|
||||
LJ_POST_FIXGUARD, /* Fixup and emit pending guard. */
|
||||
LJ_POST_FIXGUARDSNAP, /* Fixup and emit pending guard and snapshot. */
|
||||
LJ_POST_FIXBOOL, /* Fixup boolean result. */
|
||||
LJ_POST_FIXCONST, /* Fixup constant results. */
|
||||
LJ_POST_FFRETRY /* Suppress recording of retried fast functions. */
|
||||
} PostProc;
|
||||
|
||||
/* Machine code type. */
|
||||
#if LJ_TARGET_X86ORX64
|
||||
typedef uint8_t MCode;
|
||||
#else
|
||||
typedef uint32_t MCode;
|
||||
#endif
|
||||
|
||||
/* Stack snapshot header. */
|
||||
typedef struct SnapShot {
|
||||
uint16_t mapofs; /* Offset into snapshot map. */
|
||||
IRRef1 ref; /* First IR ref for this snapshot. */
|
||||
uint8_t nslots; /* Number of valid slots. */
|
||||
uint8_t topslot; /* Maximum frame extent. */
|
||||
uint8_t nent; /* Number of compressed entries. */
|
||||
uint8_t count; /* Count of taken exits for this snapshot. */
|
||||
} SnapShot;
|
||||
|
||||
#define SNAPCOUNT_DONE 255 /* Already compiled and linked a side trace. */
|
||||
|
||||
/* Compressed snapshot entry. */
|
||||
typedef uint32_t SnapEntry;
|
||||
|
||||
#define SNAP_FRAME 0x010000 /* Frame slot. */
|
||||
#define SNAP_CONT 0x020000 /* Continuation slot. */
|
||||
#define SNAP_NORESTORE 0x040000 /* No need to restore slot. */
|
||||
#define SNAP_SOFTFPNUM 0x080000 /* Soft-float number. */
|
||||
LJ_STATIC_ASSERT(SNAP_FRAME == TREF_FRAME);
|
||||
LJ_STATIC_ASSERT(SNAP_CONT == TREF_CONT);
|
||||
|
||||
#define SNAP(slot, flags, ref) (((SnapEntry)(slot) << 24) + (flags) + (ref))
|
||||
#define SNAP_TR(slot, tr) \
|
||||
(((SnapEntry)(slot) << 24) + ((tr) & (TREF_CONT|TREF_FRAME|TREF_REFMASK)))
|
||||
#if !LJ_FR2
|
||||
#define SNAP_MKPC(pc) ((SnapEntry)u32ptr(pc))
|
||||
#endif
|
||||
#define SNAP_MKFTSZ(ftsz) ((SnapEntry)(ftsz))
|
||||
#define snap_ref(sn) ((sn) & 0xffff)
|
||||
#define snap_slot(sn) ((BCReg)((sn) >> 24))
|
||||
#define snap_isframe(sn) ((sn) & SNAP_FRAME)
|
||||
#define snap_setref(sn, ref) (((sn) & (0xffff0000&~SNAP_NORESTORE)) | (ref))
|
||||
|
||||
static LJ_AINLINE const BCIns *snap_pc(SnapEntry *sn)
|
||||
{
|
||||
#if LJ_FR2
|
||||
uint64_t pcbase;
|
||||
memcpy(&pcbase, sn, sizeof(uint64_t));
|
||||
return (const BCIns *)(pcbase >> 8);
|
||||
#else
|
||||
return (const BCIns *)(uintptr_t)*sn;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Snapshot and exit numbers. */
|
||||
typedef uint32_t SnapNo;
|
||||
typedef uint32_t ExitNo;
|
||||
|
||||
/* Trace number. */
|
||||
typedef uint32_t TraceNo; /* Used to pass around trace numbers. */
|
||||
typedef uint16_t TraceNo1; /* Stored trace number. */
|
||||
|
||||
/* Type of link. ORDER LJ_TRLINK */
|
||||
typedef enum {
|
||||
LJ_TRLINK_NONE, /* Incomplete trace. No link, yet. */
|
||||
LJ_TRLINK_ROOT, /* Link to other root trace. */
|
||||
LJ_TRLINK_LOOP, /* Loop to same trace. */
|
||||
LJ_TRLINK_TAILREC, /* Tail-recursion. */
|
||||
LJ_TRLINK_UPREC, /* Up-recursion. */
|
||||
LJ_TRLINK_DOWNREC, /* Down-recursion. */
|
||||
LJ_TRLINK_INTERP, /* Fallback to interpreter. */
|
||||
LJ_TRLINK_RETURN, /* Return to interpreter. */
|
||||
LJ_TRLINK_STITCH /* Trace stitching. */
|
||||
} TraceLink;
|
||||
|
||||
/* Trace object. */
|
||||
typedef struct GCtrace {
|
||||
GCHeader;
|
||||
uint8_t topslot; /* Top stack slot already checked to be allocated. */
|
||||
uint8_t linktype; /* Type of link. */
|
||||
IRRef nins; /* Next IR instruction. Biased with REF_BIAS. */
|
||||
#if LJ_GC64
|
||||
uint32_t unused_gc64;
|
||||
#endif
|
||||
GCRef gclist;
|
||||
IRIns *ir; /* IR instructions/constants. Biased with REF_BIAS. */
|
||||
IRRef nk; /* Lowest IR constant. Biased with REF_BIAS. */
|
||||
uint16_t nsnap; /* Number of snapshots. */
|
||||
uint16_t nsnapmap; /* Number of snapshot map elements. */
|
||||
SnapShot *snap; /* Snapshot array. */
|
||||
SnapEntry *snapmap; /* Snapshot map. */
|
||||
GCRef startpt; /* Starting prototype. */
|
||||
MRef startpc; /* Bytecode PC of starting instruction. */
|
||||
BCIns startins; /* Original bytecode of starting instruction. */
|
||||
MSize szmcode; /* Size of machine code. */
|
||||
MCode *mcode; /* Start of machine code. */
|
||||
MSize mcloop; /* Offset of loop start in machine code. */
|
||||
uint16_t nchild; /* Number of child traces (root trace only). */
|
||||
uint16_t spadjust; /* Stack pointer adjustment (offset in bytes). */
|
||||
TraceNo1 traceno; /* Trace number. */
|
||||
TraceNo1 link; /* Linked trace (or self for loops). */
|
||||
TraceNo1 root; /* Root trace of side trace (or 0 for root traces). */
|
||||
TraceNo1 nextroot; /* Next root trace for same prototype. */
|
||||
TraceNo1 nextside; /* Next side trace of same root trace. */
|
||||
uint8_t sinktags; /* Trace has SINK tags. */
|
||||
uint8_t unused1;
|
||||
#ifdef LUAJIT_USE_GDBJIT
|
||||
void *gdbjit_entry; /* GDB JIT entry. */
|
||||
#endif
|
||||
} GCtrace;
|
||||
|
||||
#define gco2trace(o) check_exp((o)->gch.gct == ~LJ_TTRACE, (GCtrace *)(o))
|
||||
#define traceref(J, n) \
|
||||
check_exp((n)>0 && (MSize)(n)<J->sizetrace, (GCtrace *)gcref(J->trace[(n)]))
|
||||
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, gclist) == offsetof(GCtrace, gclist));
|
||||
|
||||
static LJ_AINLINE MSize snap_nextofs(GCtrace *T, SnapShot *snap)
|
||||
{
|
||||
if (snap+1 == &T->snap[T->nsnap])
|
||||
return T->nsnapmap;
|
||||
else
|
||||
return (snap+1)->mapofs;
|
||||
}
|
||||
|
||||
/* Round-robin penalty cache for bytecodes leading to aborted traces. */
|
||||
typedef struct HotPenalty {
|
||||
MRef pc; /* Starting bytecode PC. */
|
||||
uint16_t val; /* Penalty value, i.e. hotcount start. */
|
||||
uint16_t reason; /* Abort reason (really TraceErr). */
|
||||
} HotPenalty;
|
||||
|
||||
#define PENALTY_SLOTS 64 /* Penalty cache slot. Must be a power of 2. */
|
||||
#define PENALTY_MIN (36*2) /* Minimum penalty value. */
|
||||
#define PENALTY_MAX 60000 /* Maximum penalty value. */
|
||||
#define PENALTY_RNDBITS 4 /* # of random bits to add to penalty value. */
|
||||
|
||||
/* Round-robin backpropagation cache for narrowing conversions. */
|
||||
typedef struct BPropEntry {
|
||||
IRRef1 key; /* Key: original reference. */
|
||||
IRRef1 val; /* Value: reference after conversion. */
|
||||
IRRef mode; /* Mode for this entry (currently IRCONV_*). */
|
||||
} BPropEntry;
|
||||
|
||||
/* Number of slots for the backpropagation cache. Must be a power of 2. */
|
||||
#define BPROP_SLOTS 16
|
||||
|
||||
/* Scalar evolution analysis cache. */
|
||||
typedef struct ScEvEntry {
|
||||
MRef pc; /* Bytecode PC of FORI. */
|
||||
IRRef1 idx; /* Index reference. */
|
||||
IRRef1 start; /* Constant start reference. */
|
||||
IRRef1 stop; /* Constant stop reference. */
|
||||
IRRef1 step; /* Constant step reference. */
|
||||
IRType1 t; /* Scalar type. */
|
||||
uint8_t dir; /* Direction. 1: +, 0: -. */
|
||||
} ScEvEntry;
|
||||
|
||||
/* Reverse bytecode map (IRRef -> PC). Only for selected instructions. */
|
||||
typedef struct RBCHashEntry {
|
||||
MRef pc; /* Bytecode PC. */
|
||||
GCRef pt; /* Prototype. */
|
||||
IRRef ref; /* IR reference. */
|
||||
} RBCHashEntry;
|
||||
|
||||
/* Number of slots in the reverse bytecode hash table. Must be a power of 2. */
|
||||
#define RBCHASH_SLOTS 8
|
||||
|
||||
/* 128 bit SIMD constants. */
|
||||
enum {
|
||||
LJ_KSIMD_ABS,
|
||||
LJ_KSIMD_NEG,
|
||||
LJ_KSIMD__MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
#if LJ_TARGET_X86ORX64
|
||||
LJ_K64_TOBIT, /* 2^52 + 2^51 */
|
||||
LJ_K64_2P64, /* 2^64 */
|
||||
LJ_K64_M2P64, /* -2^64 */
|
||||
#if LJ_32
|
||||
LJ_K64_M2P64_31, /* -2^64 or -2^31 */
|
||||
#else
|
||||
LJ_K64_M2P64_31 = LJ_K64_M2P64,
|
||||
#endif
|
||||
#endif
|
||||
#if LJ_TARGET_MIPS
|
||||
LJ_K64_2P31, /* 2^31 */
|
||||
#if LJ_64
|
||||
LJ_K64_2P63, /* 2^63 */
|
||||
LJ_K64_M2P64, /* -2^64 */
|
||||
#endif
|
||||
#endif
|
||||
LJ_K64__MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
#if LJ_TARGET_X86ORX64
|
||||
LJ_K32_M2P64_31, /* -2^64 or -2^31 */
|
||||
#endif
|
||||
#if LJ_TARGET_PPC
|
||||
LJ_K32_2P52_2P31, /* 2^52 + 2^31 */
|
||||
LJ_K32_2P52, /* 2^52 */
|
||||
#endif
|
||||
#if LJ_TARGET_PPC || LJ_TARGET_MIPS
|
||||
LJ_K32_2P31, /* 2^31 */
|
||||
#endif
|
||||
#if LJ_TARGET_MIPS64
|
||||
LJ_K32_2P63, /* 2^63 */
|
||||
LJ_K32_M2P64, /* -2^64 */
|
||||
#endif
|
||||
LJ_K32__MAX
|
||||
};
|
||||
|
||||
/* Get 16 byte aligned pointer to SIMD constant. */
|
||||
#define LJ_KSIMD(J, n) \
|
||||
((TValue *)(((intptr_t)&J->ksimd[2*(n)] + 15) & ~(intptr_t)15))
|
||||
|
||||
/* Set/reset flag to activate the SPLIT pass for the current trace. */
|
||||
#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
|
||||
#define lj_needsplit(J) (J->needsplit = 1)
|
||||
#define lj_resetsplit(J) (J->needsplit = 0)
|
||||
#else
|
||||
#define lj_needsplit(J) UNUSED(J)
|
||||
#define lj_resetsplit(J) UNUSED(J)
|
||||
#endif
|
||||
|
||||
/* Fold state is used to fold instructions on-the-fly. */
|
||||
typedef struct FoldState {
|
||||
IRIns ins; /* Currently emitted instruction. */
|
||||
IRIns left[2]; /* Instruction referenced by left operand. */
|
||||
IRIns right[2]; /* Instruction referenced by right operand. */
|
||||
} FoldState;
|
||||
|
||||
/* JIT compiler state. */
|
||||
typedef struct jit_State {
|
||||
GCtrace cur; /* Current trace. */
|
||||
GCtrace *curfinal; /* Final address of current trace (set during asm). */
|
||||
|
||||
lua_State *L; /* Current Lua state. */
|
||||
const BCIns *pc; /* Current PC. */
|
||||
GCfunc *fn; /* Current function. */
|
||||
GCproto *pt; /* Current prototype. */
|
||||
TRef *base; /* Current frame base, points into J->slots. */
|
||||
|
||||
uint32_t flags; /* JIT engine flags. */
|
||||
BCReg maxslot; /* Relative to baseslot. */
|
||||
BCReg baseslot; /* Current frame base, offset into J->slots. */
|
||||
|
||||
uint8_t mergesnap; /* Allowed to merge with next snapshot. */
|
||||
uint8_t needsnap; /* Need snapshot before recording next bytecode. */
|
||||
IRType1 guardemit; /* Accumulated IRT_GUARD for emitted instructions. */
|
||||
uint8_t bcskip; /* Number of bytecode instructions to skip. */
|
||||
|
||||
FoldState fold; /* Fold state. */
|
||||
|
||||
const BCIns *bc_min; /* Start of allowed bytecode range for root trace. */
|
||||
MSize bc_extent; /* Extent of the range. */
|
||||
|
||||
TraceState state; /* Trace compiler state. */
|
||||
|
||||
int32_t instunroll; /* Unroll counter for instable loops. */
|
||||
int32_t loopunroll; /* Unroll counter for loop ops in side traces. */
|
||||
int32_t tailcalled; /* Number of successive tailcalls. */
|
||||
int32_t framedepth; /* Current frame depth. */
|
||||
int32_t retdepth; /* Return frame depth (count of RETF). */
|
||||
|
||||
TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */
|
||||
TValue k64[LJ_K64__MAX]; /* Common 8 byte constants used by backends. */
|
||||
uint32_t k32[LJ_K32__MAX]; /* Ditto for 4 byte constants. */
|
||||
|
||||
IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */
|
||||
IRRef irtoplim; /* Upper limit of instuction buffer (biased). */
|
||||
IRRef irbotlim; /* Lower limit of instuction buffer (biased). */
|
||||
IRRef loopref; /* Last loop reference or ref of final LOOP (or 0). */
|
||||
|
||||
MSize sizesnap; /* Size of temp. snapshot buffer. */
|
||||
SnapShot *snapbuf; /* Temp. snapshot buffer. */
|
||||
SnapEntry *snapmapbuf; /* Temp. snapshot map buffer. */
|
||||
MSize sizesnapmap; /* Size of temp. snapshot map buffer. */
|
||||
|
||||
PostProc postproc; /* Required post-processing after execution. */
|
||||
#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
|
||||
uint8_t needsplit; /* Need SPLIT pass. */
|
||||
#endif
|
||||
uint8_t retryrec; /* Retry recording. */
|
||||
|
||||
GCRef *trace; /* Array of traces. */
|
||||
TraceNo freetrace; /* Start of scan for next free trace. */
|
||||
MSize sizetrace; /* Size of trace array. */
|
||||
IRRef1 ktrace; /* Reference to KGC with GCtrace. */
|
||||
|
||||
IRRef1 chain[IR__MAX]; /* IR instruction skip-list chain anchors. */
|
||||
TRef slot[LJ_MAX_JSLOTS+LJ_STACK_EXTRA]; /* Stack slot map. */
|
||||
|
||||
int32_t param[JIT_P__MAX]; /* JIT engine parameters. */
|
||||
|
||||
MCode *exitstubgroup[LJ_MAX_EXITSTUBGR]; /* Exit stub group addresses. */
|
||||
|
||||
HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */
|
||||
uint32_t penaltyslot; /* Round-robin index into penalty slots. */
|
||||
uint32_t prngstate; /* PRNG state. */
|
||||
|
||||
#ifdef LUAJIT_ENABLE_TABLE_BUMP
|
||||
RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */
|
||||
#endif
|
||||
|
||||
BPropEntry bpropcache[BPROP_SLOTS]; /* Backpropagation cache slots. */
|
||||
uint32_t bpropslot; /* Round-robin index into bpropcache slots. */
|
||||
|
||||
ScEvEntry scev; /* Scalar evolution analysis cache slots. */
|
||||
|
||||
const BCIns *startpc; /* Bytecode PC of starting instruction. */
|
||||
TraceNo parent; /* Parent of current side trace (0 for root traces). */
|
||||
ExitNo exitno; /* Exit number in parent of current side trace. */
|
||||
|
||||
BCIns *patchpc; /* PC for pending re-patch. */
|
||||
BCIns patchins; /* Instruction for pending re-patch. */
|
||||
|
||||
int mcprot; /* Protection of current mcode area. */
|
||||
MCode *mcarea; /* Base of current mcode area. */
|
||||
MCode *mctop; /* Top of current mcode area. */
|
||||
MCode *mcbot; /* Bottom of current mcode area. */
|
||||
size_t szmcarea; /* Size of current mcode area. */
|
||||
size_t szallmcarea; /* Total size of all allocated mcode areas. */
|
||||
|
||||
TValue errinfo; /* Additional info element for trace errors. */
|
||||
|
||||
#if LJ_HASPROFILE
|
||||
GCproto *prev_pt; /* Previous prototype. */
|
||||
BCLine prev_line; /* Previous line. */
|
||||
int prof_mode; /* Profiling mode: 0, 'f', 'l'. */
|
||||
#endif
|
||||
}
|
||||
#if LJ_TARGET_ARM
|
||||
LJ_ALIGN(16) /* For DISPATCH-relative addresses in assembler part. */
|
||||
#endif
|
||||
jit_State;
|
||||
|
||||
/* Trivial PRNG e.g. used for penalty randomization. */
|
||||
static LJ_AINLINE uint32_t LJ_PRNG_BITS(jit_State *J, int bits)
|
||||
{
|
||||
/* Yes, this LCG is very weak, but that doesn't matter for our use case. */
|
||||
J->prngstate = J->prngstate * 1103515245 + 12345;
|
||||
return J->prngstate >> (32-bits);
|
||||
}
|
||||
|
||||
#endif
|
||||
86
include/lua/lj_lex.h
Normal file
86
include/lua/lj_lex.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
** Lexical analyzer.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_LEX_H
|
||||
#define _LJ_LEX_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_err.h"
|
||||
|
||||
/* Lua lexer tokens. */
|
||||
#define TKDEF(_, __) \
|
||||
_(and) _(break) _(do) _(else) _(elseif) _(end) _(false) \
|
||||
_(for) _(function) _(goto) _(if) _(in) _(local) _(nil) _(not) _(or) \
|
||||
_(repeat) _(return) _(then) _(true) _(until) _(while) \
|
||||
__(concat, ..) __(dots, ...) __(eq, ==) __(ge, >=) __(le, <=) __(ne, ~=) \
|
||||
__(label, ::) __(number, <number>) __(name, <name>) __(string, <string>) \
|
||||
__(eof, <eof>)
|
||||
|
||||
enum {
|
||||
TK_OFS = 256,
|
||||
#define TKENUM1(name) TK_##name,
|
||||
#define TKENUM2(name, sym) TK_##name,
|
||||
TKDEF(TKENUM1, TKENUM2)
|
||||
#undef TKENUM1
|
||||
#undef TKENUM2
|
||||
TK_RESERVED = TK_while - TK_OFS
|
||||
};
|
||||
|
||||
typedef int LexChar; /* Lexical character. Unsigned ext. from char. */
|
||||
typedef int LexToken; /* Lexical token. */
|
||||
|
||||
/* Combined bytecode ins/line. Only used during bytecode generation. */
|
||||
typedef struct BCInsLine {
|
||||
BCIns ins; /* Bytecode instruction. */
|
||||
BCLine line; /* Line number for this bytecode. */
|
||||
} BCInsLine;
|
||||
|
||||
/* Info for local variables. Only used during bytecode generation. */
|
||||
typedef struct VarInfo {
|
||||
GCRef name; /* Local variable name or goto/label name. */
|
||||
BCPos startpc; /* First point where the local variable is active. */
|
||||
BCPos endpc; /* First point where the local variable is dead. */
|
||||
uint8_t slot; /* Variable slot. */
|
||||
uint8_t info; /* Variable/goto/label info. */
|
||||
} VarInfo;
|
||||
|
||||
/* Lua lexer state. */
|
||||
typedef struct LexState {
|
||||
struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */
|
||||
struct lua_State *L; /* Lua state. */
|
||||
TValue tokval; /* Current token value. */
|
||||
TValue lookaheadval; /* Lookahead token value. */
|
||||
const char *p; /* Current position in input buffer. */
|
||||
const char *pe; /* End of input buffer. */
|
||||
LexChar c; /* Current character. */
|
||||
LexToken tok; /* Current token. */
|
||||
LexToken lookahead; /* Lookahead token. */
|
||||
SBuf sb; /* String buffer for tokens. */
|
||||
lua_Reader rfunc; /* Reader callback. */
|
||||
void *rdata; /* Reader callback data. */
|
||||
BCLine linenumber; /* Input line counter. */
|
||||
BCLine lastline; /* Line of last token. */
|
||||
GCstr *chunkname; /* Current chunk name (interned string). */
|
||||
const char *chunkarg; /* Chunk name argument. */
|
||||
const char *mode; /* Allow loading bytecode (b) and/or source text (t). */
|
||||
VarInfo *vstack; /* Stack for names and extents of local variables. */
|
||||
MSize sizevstack; /* Size of variable stack. */
|
||||
MSize vtop; /* Top of variable stack. */
|
||||
BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */
|
||||
MSize sizebcstack; /* Size of bytecode stack. */
|
||||
uint32_t level; /* Syntactical nesting level. */
|
||||
} LexState;
|
||||
|
||||
LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls);
|
||||
LJ_FUNC void lj_lex_cleanup(lua_State *L, LexState *ls);
|
||||
LJ_FUNC void lj_lex_next(LexState *ls);
|
||||
LJ_FUNC LexToken lj_lex_lookahead(LexState *ls);
|
||||
LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken tok);
|
||||
LJ_FUNC_NORET void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...);
|
||||
LJ_FUNC void lj_lex_init(lua_State *L);
|
||||
|
||||
#endif
|
||||
115
include/lua/lj_lib.h
Normal file
115
include/lua/lj_lib.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
** Library function support.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_LIB_H
|
||||
#define _LJ_LIB_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/*
|
||||
** A fallback handler is called by the assembler VM if the fast path fails:
|
||||
**
|
||||
** - too few arguments: unrecoverable.
|
||||
** - wrong argument type: recoverable, if coercion succeeds.
|
||||
** - bad argument value: unrecoverable.
|
||||
** - stack overflow: recoverable, if stack reallocation succeeds.
|
||||
** - extra handling: recoverable.
|
||||
**
|
||||
** The unrecoverable cases throw an error with lj_err_arg(), lj_err_argtype(),
|
||||
** lj_err_caller() or lj_err_callermsg().
|
||||
** The recoverable cases return 0 or the number of results + 1.
|
||||
** The assembler VM retries the fast path only if 0 is returned.
|
||||
** This time the fallback must not be called again or it gets stuck in a loop.
|
||||
*/
|
||||
|
||||
/* Return values from fallback handler. */
|
||||
#define FFH_RETRY 0
|
||||
#define FFH_UNREACHABLE FFH_RETRY
|
||||
#define FFH_RES(n) ((n)+1)
|
||||
#define FFH_TAILCALL (-1)
|
||||
|
||||
LJ_FUNC TValue *lj_lib_checkany(lua_State *L, int narg);
|
||||
LJ_FUNC GCstr *lj_lib_checkstr(lua_State *L, int narg);
|
||||
LJ_FUNC GCstr *lj_lib_optstr(lua_State *L, int narg);
|
||||
#if LJ_DUALNUM
|
||||
LJ_FUNC void lj_lib_checknumber(lua_State *L, int narg);
|
||||
#else
|
||||
#define lj_lib_checknumber(L, narg) lj_lib_checknum((L), (narg))
|
||||
#endif
|
||||
LJ_FUNC lua_Number lj_lib_checknum(lua_State *L, int narg);
|
||||
LJ_FUNC int32_t lj_lib_checkint(lua_State *L, int narg);
|
||||
LJ_FUNC int32_t lj_lib_optint(lua_State *L, int narg, int32_t def);
|
||||
LJ_FUNC GCfunc *lj_lib_checkfunc(lua_State *L, int narg);
|
||||
LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg);
|
||||
LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg);
|
||||
LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst);
|
||||
|
||||
/* Avoid including lj_frame.h. */
|
||||
#if LJ_GC64
|
||||
#define lj_lib_upvalue(L, n) \
|
||||
(&gcval(L->base-2)->fn.c.upvalue[(n)-1])
|
||||
#elif LJ_FR2
|
||||
#define lj_lib_upvalue(L, n) \
|
||||
(&gcref((L->base-2)->gcr)->fn.c.upvalue[(n)-1])
|
||||
#else
|
||||
#define lj_lib_upvalue(L, n) \
|
||||
(&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1])
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_WINDOWS
|
||||
#define lj_lib_checkfpu(L) \
|
||||
do { setnumV(L->top++, (lua_Number)1437217655); \
|
||||
if (lua_tointeger(L, -1) != 1437217655) lj_err_caller(L, LJ_ERR_BADFPU); \
|
||||
L->top--; } while (0)
|
||||
#else
|
||||
#define lj_lib_checkfpu(L) UNUSED(L)
|
||||
#endif
|
||||
|
||||
LJ_FUNC GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n);
|
||||
#define lj_lib_pushcf(L, fn, id) (lj_lib_pushcc(L, (fn), (id), 0))
|
||||
|
||||
/* Library function declarations. Scanned by buildvm. */
|
||||
#define LJLIB_CF(name) static int lj_cf_##name(lua_State *L)
|
||||
#define LJLIB_ASM(name) static int lj_ffh_##name(lua_State *L)
|
||||
#define LJLIB_ASM_(name)
|
||||
#define LJLIB_LUA(name)
|
||||
#define LJLIB_SET(name)
|
||||
#define LJLIB_PUSH(arg)
|
||||
#define LJLIB_REC(handler)
|
||||
#define LJLIB_NOREGUV
|
||||
#define LJLIB_NOREG
|
||||
|
||||
#define LJ_LIB_REG(L, regname, name) \
|
||||
lj_lib_register(L, regname, lj_lib_init_##name, lj_lib_cf_##name)
|
||||
|
||||
LJ_FUNC void lj_lib_register(lua_State *L, const char *libname,
|
||||
const uint8_t *init, const lua_CFunction *cf);
|
||||
LJ_FUNC void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f,
|
||||
GCtab *env);
|
||||
LJ_FUNC int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id,
|
||||
const char *name);
|
||||
|
||||
/* Library init data tags. */
|
||||
#define LIBINIT_LENMASK 0x3f
|
||||
#define LIBINIT_TAGMASK 0xc0
|
||||
#define LIBINIT_CF 0x00
|
||||
#define LIBINIT_ASM 0x40
|
||||
#define LIBINIT_ASM_ 0x80
|
||||
#define LIBINIT_STRING 0xc0
|
||||
#define LIBINIT_MAXSTR 0x38
|
||||
#define LIBINIT_LUA 0xf9
|
||||
#define LIBINIT_SET 0xfa
|
||||
#define LIBINIT_NUMBER 0xfb
|
||||
#define LIBINIT_COPY 0xfc
|
||||
#define LIBINIT_LASTCL 0xfd
|
||||
#define LIBINIT_FFID 0xfe
|
||||
#define LIBINIT_END 0xff
|
||||
|
||||
/* Exported library functions. */
|
||||
|
||||
typedef struct RandomState RandomState;
|
||||
LJ_FUNC uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs);
|
||||
|
||||
#endif
|
||||
420
include/lua/lj_libdef.h
Normal file
420
include/lua/lj_libdef.h
Normal file
@@ -0,0 +1,420 @@
|
||||
/* This is a generated file. DO NOT EDIT! */
|
||||
|
||||
#ifdef LJLIB_MODULE_base
|
||||
#undef LJLIB_MODULE_base
|
||||
static const lua_CFunction lj_lib_cf_base[] = {
|
||||
lj_ffh_assert,
|
||||
lj_ffh_next,
|
||||
lj_ffh_pairs,
|
||||
lj_ffh_ipairs_aux,
|
||||
lj_ffh_ipairs,
|
||||
lj_ffh_setmetatable,
|
||||
lj_cf_getfenv,
|
||||
lj_cf_setfenv,
|
||||
lj_ffh_rawget,
|
||||
lj_cf_rawset,
|
||||
lj_cf_rawequal,
|
||||
lj_cf_unpack,
|
||||
lj_cf_select,
|
||||
lj_ffh_tonumber,
|
||||
lj_ffh_tostring,
|
||||
lj_cf_error,
|
||||
lj_ffh_pcall,
|
||||
lj_cf_loadfile,
|
||||
lj_cf_load,
|
||||
lj_cf_loadstring,
|
||||
lj_cf_dofile,
|
||||
lj_cf_gcinfo,
|
||||
lj_cf_collectgarbage,
|
||||
lj_cf_newproxy,
|
||||
lj_cf_print
|
||||
};
|
||||
static const uint8_t lj_lib_init_base[] = {
|
||||
2,0,28,70,97,115,115,101,114,116,195,110,105,108,199,98,111,111,108,101,97,
|
||||
110,252,1,200,117,115,101,114,100,97,116,97,198,115,116,114,105,110,103,197,
|
||||
117,112,118,97,108,198,116,104,114,101,97,100,197,112,114,111,116,111,200,102,
|
||||
117,110,99,116,105,111,110,197,116,114,97,99,101,197,99,100,97,116,97,197,116,
|
||||
97,98,108,101,252,9,198,110,117,109,98,101,114,132,116,121,112,101,68,110,101,
|
||||
120,116,253,69,112,97,105,114,115,64,253,70,105,112,97,105,114,115,140,103,
|
||||
101,116,109,101,116,97,116,97,98,108,101,76,115,101,116,109,101,116,97,116,
|
||||
97,98,108,101,7,103,101,116,102,101,110,118,7,115,101,116,102,101,110,118,70,
|
||||
114,97,119,103,101,116,6,114,97,119,115,101,116,8,114,97,119,101,113,117,97,
|
||||
108,6,117,110,112,97,99,107,6,115,101,108,101,99,116,72,116,111,110,117,109,
|
||||
98,101,114,72,116,111,115,116,114,105,110,103,5,101,114,114,111,114,69,112,
|
||||
99,97,108,108,134,120,112,99,97,108,108,8,108,111,97,100,102,105,108,101,4,
|
||||
108,111,97,100,10,108,111,97,100,115,116,114,105,110,103,6,100,111,102,105,
|
||||
108,101,6,103,99,105,110,102,111,14,99,111,108,108,101,99,116,103,97,114,98,
|
||||
97,103,101,252,2,8,110,101,119,112,114,111,120,121,200,116,111,115,116,114,
|
||||
105,110,103,5,112,114,105,110,116,252,3,200,95,86,69,82,83,73,79,78,250,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_coroutine
|
||||
#undef LJLIB_MODULE_coroutine
|
||||
static const lua_CFunction lj_lib_cf_coroutine[] = {
|
||||
lj_cf_coroutine_status,
|
||||
lj_cf_coroutine_running,
|
||||
lj_cf_coroutine_isyieldable,
|
||||
lj_cf_coroutine_create,
|
||||
lj_ffh_coroutine_yield,
|
||||
lj_ffh_coroutine_resume,
|
||||
lj_cf_coroutine_wrap
|
||||
};
|
||||
static const uint8_t lj_lib_init_coroutine[] = {
|
||||
30,13,7,6,115,116,97,116,117,115,7,114,117,110,110,105,110,103,11,105,115,121,
|
||||
105,101,108,100,97,98,108,101,6,99,114,101,97,116,101,69,121,105,101,108,100,
|
||||
70,114,101,115,117,109,101,254,4,119,114,97,112,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_math
|
||||
#undef LJLIB_MODULE_math
|
||||
static const lua_CFunction lj_lib_cf_math[] = {
|
||||
lj_ffh_math_abs,
|
||||
lj_ffh_math_sqrt,
|
||||
lj_ffh_math_log,
|
||||
lj_ffh_math_atan2,
|
||||
lj_ffh_math_ldexp,
|
||||
lj_ffh_math_min,
|
||||
lj_cf_math_random,
|
||||
lj_cf_math_randomseed
|
||||
};
|
||||
static const uint8_t lj_lib_init_math[] = {
|
||||
38,16,30,67,97,98,115,133,102,108,111,111,114,132,99,101,105,108,68,115,113,
|
||||
114,116,133,108,111,103,49,48,131,101,120,112,131,115,105,110,131,99,111,115,
|
||||
131,116,97,110,132,97,115,105,110,132,97,99,111,115,132,97,116,97,110,132,115,
|
||||
105,110,104,132,99,111,115,104,132,116,97,110,104,133,102,114,101,120,112,132,
|
||||
109,111,100,102,67,108,111,103,249,3,100,101,103,0,1,2,0,0,1,2,24,1,0,0,76,
|
||||
1,2,0,241,135,158,166,3,220,203,178,130,4,249,3,114,97,100,0,1,2,0,0,1,2,24,
|
||||
1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,69,97,116,97,110,50,131,
|
||||
112,111,119,132,102,109,111,100,69,108,100,101,120,112,67,109,105,110,131,109,
|
||||
97,120,251,24,45,68,84,251,33,9,64,194,112,105,250,251,0,0,0,0,0,0,240,127,
|
||||
196,104,117,103,101,250,252,2,6,114,97,110,100,111,109,252,2,10,114,97,110,
|
||||
100,111,109,115,101,101,100,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_bit
|
||||
#undef LJLIB_MODULE_bit
|
||||
static const lua_CFunction lj_lib_cf_bit[] = {
|
||||
lj_ffh_bit_tobit,
|
||||
lj_ffh_bit_bnot,
|
||||
lj_ffh_bit_bswap,
|
||||
lj_ffh_bit_lshift,
|
||||
lj_ffh_bit_band,
|
||||
lj_cf_bit_tohex
|
||||
};
|
||||
static const uint8_t lj_lib_init_bit[] = {
|
||||
64,40,12,69,116,111,98,105,116,68,98,110,111,116,69,98,115,119,97,112,70,108,
|
||||
115,104,105,102,116,134,114,115,104,105,102,116,135,97,114,115,104,105,102,
|
||||
116,131,114,111,108,131,114,111,114,68,98,97,110,100,131,98,111,114,132,98,
|
||||
120,111,114,5,116,111,104,101,120,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_string
|
||||
#undef LJLIB_MODULE_string
|
||||
static const lua_CFunction lj_lib_cf_string[] = {
|
||||
lj_ffh_string_byte,
|
||||
lj_ffh_string_char,
|
||||
lj_ffh_string_sub,
|
||||
lj_cf_string_rep,
|
||||
lj_ffh_string_reverse,
|
||||
lj_cf_string_dump,
|
||||
lj_cf_string_find,
|
||||
lj_cf_string_match,
|
||||
lj_cf_string_gmatch,
|
||||
lj_cf_string_gsub,
|
||||
lj_cf_string_format
|
||||
};
|
||||
static const uint8_t lj_lib_init_string[] = {
|
||||
76,51,14,249,3,108,101,110,0,1,2,0,0,0,3,16,0,5,0,21,1,0,0,76,1,2,0,68,98,121,
|
||||
116,101,68,99,104,97,114,67,115,117,98,3,114,101,112,71,114,101,118,101,114,
|
||||
115,101,133,108,111,119,101,114,133,117,112,112,101,114,4,100,117,109,112,4,
|
||||
102,105,110,100,5,109,97,116,99,104,254,6,103,109,97,116,99,104,4,103,115,117,
|
||||
98,6,102,111,114,109,97,116,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_table
|
||||
#undef LJLIB_MODULE_table
|
||||
static const lua_CFunction lj_lib_cf_table[] = {
|
||||
lj_cf_table_maxn,
|
||||
lj_cf_table_insert,
|
||||
lj_cf_table_concat,
|
||||
lj_cf_table_sort
|
||||
};
|
||||
static const uint8_t lj_lib_init_table[] = {
|
||||
90,57,9,249,8,102,111,114,101,97,99,104,105,0,2,9,0,0,0,15,16,0,12,0,16,1,9,
|
||||
0,41,2,1,0,21,3,0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,7,5,0,59,8,5,0,66,6,3,2,
|
||||
10,6,0,0,88,7,1,128,76,6,2,0,79,2,248,127,75,0,1,0,249,7,102,111,114,101,97,
|
||||
99,104,0,2,10,0,0,0,16,16,0,12,0,16,1,9,0,43,2,0,0,18,3,0,0,41,4,0,0,88,5,7,
|
||||
128,18,7,1,0,18,8,5,0,18,9,6,0,66,7,3,2,10,7,0,0,88,8,1,128,76,7,2,0,70,5,3,
|
||||
3,82,5,247,127,75,0,1,0,249,4,103,101,116,110,0,1,2,0,0,0,3,16,0,12,0,21,1,
|
||||
0,0,76,1,2,0,4,109,97,120,110,6,105,110,115,101,114,116,249,6,114,101,109,111,
|
||||
118,101,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128,8,2,0,0,88,3,
|
||||
23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,17,1,15,0,41,3,1,0,3,
|
||||
3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,0,41,6,1,0,77,
|
||||
4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,2,0,76,3,2,0,
|
||||
75,0,1,0,0,2,249,4,109,111,118,101,0,5,12,0,0,0,35,16,0,12,0,17,1,15,0,17,2,
|
||||
15,0,17,3,15,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,
|
||||
5,1,3,0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,
|
||||
7,2,0,41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,
|
||||
8,128,18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,
|
||||
4,79,6,252,127,76,4,2,0,6,99,111,110,99,97,116,4,115,111,114,116,254,254,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_io_method
|
||||
#undef LJLIB_MODULE_io_method
|
||||
static const lua_CFunction lj_lib_cf_io_method[] = {
|
||||
lj_cf_io_method_close,
|
||||
lj_cf_io_method_read,
|
||||
lj_cf_io_method_write,
|
||||
lj_cf_io_method_flush,
|
||||
lj_cf_io_method_seek,
|
||||
lj_cf_io_method_setvbuf,
|
||||
lj_cf_io_method_lines,
|
||||
lj_cf_io_method___gc,
|
||||
lj_cf_io_method___tostring
|
||||
};
|
||||
static const uint8_t lj_lib_init_io_method[] = {
|
||||
96,57,10,5,99,108,111,115,101,4,114,101,97,100,5,119,114,105,116,101,5,102,
|
||||
108,117,115,104,4,115,101,101,107,7,115,101,116,118,98,117,102,5,108,105,110,
|
||||
101,115,4,95,95,103,99,10,95,95,116,111,115,116,114,105,110,103,252,1,199,95,
|
||||
95,105,110,100,101,120,250,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_io
|
||||
#undef LJLIB_MODULE_io
|
||||
static const lua_CFunction lj_lib_cf_io[] = {
|
||||
lj_cf_io_open,
|
||||
lj_cf_io_popen,
|
||||
lj_cf_io_tmpfile,
|
||||
lj_cf_io_close,
|
||||
lj_cf_io_read,
|
||||
lj_cf_io_write,
|
||||
lj_cf_io_flush,
|
||||
lj_cf_io_input,
|
||||
lj_cf_io_output,
|
||||
lj_cf_io_lines,
|
||||
lj_cf_io_type
|
||||
};
|
||||
static const uint8_t lj_lib_init_io[] = {
|
||||
105,57,12,252,2,192,250,4,111,112,101,110,5,112,111,112,101,110,7,116,109,112,
|
||||
102,105,108,101,5,99,108,111,115,101,4,114,101,97,100,5,119,114,105,116,101,
|
||||
5,102,108,117,115,104,5,105,110,112,117,116,6,111,117,116,112,117,116,5,108,
|
||||
105,110,101,115,4,116,121,112,101,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_os
|
||||
#undef LJLIB_MODULE_os
|
||||
static const lua_CFunction lj_lib_cf_os[] = {
|
||||
lj_cf_os_execute,
|
||||
lj_cf_os_remove,
|
||||
lj_cf_os_rename,
|
||||
lj_cf_os_tmpname,
|
||||
lj_cf_os_getenv,
|
||||
lj_cf_os_exit,
|
||||
lj_cf_os_clock,
|
||||
lj_cf_os_date,
|
||||
lj_cf_os_time,
|
||||
lj_cf_os_difftime,
|
||||
lj_cf_os_setlocale
|
||||
};
|
||||
static const uint8_t lj_lib_init_os[] = {
|
||||
116,57,11,7,101,120,101,99,117,116,101,6,114,101,109,111,118,101,6,114,101,
|
||||
110,97,109,101,7,116,109,112,110,97,109,101,6,103,101,116,101,110,118,4,101,
|
||||
120,105,116,5,99,108,111,99,107,4,100,97,116,101,4,116,105,109,101,8,100,105,
|
||||
102,102,116,105,109,101,9,115,101,116,108,111,99,97,108,101,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_debug
|
||||
#undef LJLIB_MODULE_debug
|
||||
static const lua_CFunction lj_lib_cf_debug[] = {
|
||||
lj_cf_debug_getregistry,
|
||||
lj_cf_debug_getmetatable,
|
||||
lj_cf_debug_setmetatable,
|
||||
lj_cf_debug_getfenv,
|
||||
lj_cf_debug_setfenv,
|
||||
lj_cf_debug_getinfo,
|
||||
lj_cf_debug_getlocal,
|
||||
lj_cf_debug_setlocal,
|
||||
lj_cf_debug_getupvalue,
|
||||
lj_cf_debug_setupvalue,
|
||||
lj_cf_debug_upvalueid,
|
||||
lj_cf_debug_upvaluejoin,
|
||||
lj_cf_debug_sethook,
|
||||
lj_cf_debug_gethook,
|
||||
lj_cf_debug_debug,
|
||||
lj_cf_debug_traceback
|
||||
};
|
||||
static const uint8_t lj_lib_init_debug[] = {
|
||||
127,57,16,11,103,101,116,114,101,103,105,115,116,114,121,12,103,101,116,109,
|
||||
101,116,97,116,97,98,108,101,12,115,101,116,109,101,116,97,116,97,98,108,101,
|
||||
7,103,101,116,102,101,110,118,7,115,101,116,102,101,110,118,7,103,101,116,105,
|
||||
110,102,111,8,103,101,116,108,111,99,97,108,8,115,101,116,108,111,99,97,108,
|
||||
10,103,101,116,117,112,118,97,108,117,101,10,115,101,116,117,112,118,97,108,
|
||||
117,101,9,117,112,118,97,108,117,101,105,100,11,117,112,118,97,108,117,101,
|
||||
106,111,105,110,7,115,101,116,104,111,111,107,7,103,101,116,104,111,111,107,
|
||||
5,100,101,98,117,103,9,116,114,97,99,101,98,97,99,107,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_jit
|
||||
#undef LJLIB_MODULE_jit
|
||||
static const lua_CFunction lj_lib_cf_jit[] = {
|
||||
lj_cf_jit_on,
|
||||
lj_cf_jit_off,
|
||||
lj_cf_jit_flush,
|
||||
lj_cf_jit_status,
|
||||
lj_cf_jit_attach
|
||||
};
|
||||
static const uint8_t lj_lib_init_jit[] = {
|
||||
143,57,9,2,111,110,3,111,102,102,5,102,108,117,115,104,6,115,116,97,116,117,
|
||||
115,6,97,116,116,97,99,104,252,5,194,111,115,250,252,4,196,97,114,99,104,250,
|
||||
252,3,203,118,101,114,115,105,111,110,95,110,117,109,250,252,2,199,118,101,
|
||||
114,115,105,111,110,250,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_jit_util
|
||||
#undef LJLIB_MODULE_jit_util
|
||||
static const lua_CFunction lj_lib_cf_jit_util[] = {
|
||||
lj_cf_jit_util_funcinfo,
|
||||
lj_cf_jit_util_funcbc,
|
||||
lj_cf_jit_util_funck,
|
||||
lj_cf_jit_util_funcuvname,
|
||||
lj_cf_jit_util_traceinfo,
|
||||
lj_cf_jit_util_traceir,
|
||||
lj_cf_jit_util_tracek,
|
||||
lj_cf_jit_util_tracesnap,
|
||||
lj_cf_jit_util_tracemc,
|
||||
lj_cf_jit_util_traceexitstub,
|
||||
lj_cf_jit_util_ircalladdr
|
||||
};
|
||||
static const uint8_t lj_lib_init_jit_util[] = {
|
||||
148,57,11,8,102,117,110,99,105,110,102,111,6,102,117,110,99,98,99,5,102,117,
|
||||
110,99,107,10,102,117,110,99,117,118,110,97,109,101,9,116,114,97,99,101,105,
|
||||
110,102,111,7,116,114,97,99,101,105,114,6,116,114,97,99,101,107,9,116,114,97,
|
||||
99,101,115,110,97,112,7,116,114,97,99,101,109,99,13,116,114,97,99,101,101,120,
|
||||
105,116,115,116,117,98,10,105,114,99,97,108,108,97,100,100,114,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_jit_opt
|
||||
#undef LJLIB_MODULE_jit_opt
|
||||
static const lua_CFunction lj_lib_cf_jit_opt[] = {
|
||||
lj_cf_jit_opt_start
|
||||
};
|
||||
static const uint8_t lj_lib_init_jit_opt[] = {
|
||||
159,57,1,5,115,116,97,114,116,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_jit_profile
|
||||
#undef LJLIB_MODULE_jit_profile
|
||||
static const lua_CFunction lj_lib_cf_jit_profile[] = {
|
||||
lj_cf_jit_profile_start,
|
||||
lj_cf_jit_profile_stop,
|
||||
lj_cf_jit_profile_dumpstack
|
||||
};
|
||||
static const uint8_t lj_lib_init_jit_profile[] = {
|
||||
160,57,3,5,115,116,97,114,116,4,115,116,111,112,9,100,117,109,112,115,116,97,
|
||||
99,107,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_ffi_meta
|
||||
#undef LJLIB_MODULE_ffi_meta
|
||||
static const lua_CFunction lj_lib_cf_ffi_meta[] = {
|
||||
lj_cf_ffi_meta___index,
|
||||
lj_cf_ffi_meta___newindex,
|
||||
lj_cf_ffi_meta___eq,
|
||||
lj_cf_ffi_meta___len,
|
||||
lj_cf_ffi_meta___lt,
|
||||
lj_cf_ffi_meta___le,
|
||||
lj_cf_ffi_meta___concat,
|
||||
lj_cf_ffi_meta___call,
|
||||
lj_cf_ffi_meta___add,
|
||||
lj_cf_ffi_meta___sub,
|
||||
lj_cf_ffi_meta___mul,
|
||||
lj_cf_ffi_meta___div,
|
||||
lj_cf_ffi_meta___mod,
|
||||
lj_cf_ffi_meta___pow,
|
||||
lj_cf_ffi_meta___unm,
|
||||
lj_cf_ffi_meta___tostring,
|
||||
lj_cf_ffi_meta___pairs,
|
||||
lj_cf_ffi_meta___ipairs
|
||||
};
|
||||
static const uint8_t lj_lib_init_ffi_meta[] = {
|
||||
163,57,19,7,95,95,105,110,100,101,120,10,95,95,110,101,119,105,110,100,101,
|
||||
120,4,95,95,101,113,5,95,95,108,101,110,4,95,95,108,116,4,95,95,108,101,8,95,
|
||||
95,99,111,110,99,97,116,6,95,95,99,97,108,108,5,95,95,97,100,100,5,95,95,115,
|
||||
117,98,5,95,95,109,117,108,5,95,95,100,105,118,5,95,95,109,111,100,5,95,95,
|
||||
112,111,119,5,95,95,117,110,109,10,95,95,116,111,115,116,114,105,110,103,7,
|
||||
95,95,112,97,105,114,115,8,95,95,105,112,97,105,114,115,195,102,102,105,203,
|
||||
95,95,109,101,116,97,116,97,98,108,101,250,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_ffi_clib
|
||||
#undef LJLIB_MODULE_ffi_clib
|
||||
static const lua_CFunction lj_lib_cf_ffi_clib[] = {
|
||||
lj_cf_ffi_clib___index,
|
||||
lj_cf_ffi_clib___newindex,
|
||||
lj_cf_ffi_clib___gc
|
||||
};
|
||||
static const uint8_t lj_lib_init_ffi_clib[] = {
|
||||
181,57,3,7,95,95,105,110,100,101,120,10,95,95,110,101,119,105,110,100,101,120,
|
||||
4,95,95,103,99,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_ffi_callback
|
||||
#undef LJLIB_MODULE_ffi_callback
|
||||
static const lua_CFunction lj_lib_cf_ffi_callback[] = {
|
||||
lj_cf_ffi_callback_free,
|
||||
lj_cf_ffi_callback_set
|
||||
};
|
||||
static const uint8_t lj_lib_init_ffi_callback[] = {
|
||||
184,57,3,4,102,114,101,101,3,115,101,116,252,1,199,95,95,105,110,100,101,120,
|
||||
250,255
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LJLIB_MODULE_ffi
|
||||
#undef LJLIB_MODULE_ffi
|
||||
static const lua_CFunction lj_lib_cf_ffi[] = {
|
||||
lj_cf_ffi_cdef,
|
||||
lj_cf_ffi_new,
|
||||
lj_cf_ffi_cast,
|
||||
lj_cf_ffi_typeof,
|
||||
lj_cf_ffi_typeinfo,
|
||||
lj_cf_ffi_istype,
|
||||
lj_cf_ffi_sizeof,
|
||||
lj_cf_ffi_alignof,
|
||||
lj_cf_ffi_offsetof,
|
||||
lj_cf_ffi_errno,
|
||||
lj_cf_ffi_string,
|
||||
lj_cf_ffi_copy,
|
||||
lj_cf_ffi_fill,
|
||||
lj_cf_ffi_abi,
|
||||
lj_cf_ffi_metatype,
|
||||
lj_cf_ffi_gc,
|
||||
lj_cf_ffi_load
|
||||
};
|
||||
static const uint8_t lj_lib_init_ffi[] = {
|
||||
186,57,23,4,99,100,101,102,3,110,101,119,4,99,97,115,116,6,116,121,112,101,
|
||||
111,102,8,116,121,112,101,105,110,102,111,6,105,115,116,121,112,101,6,115,105,
|
||||
122,101,111,102,7,97,108,105,103,110,111,102,8,111,102,102,115,101,116,111,
|
||||
102,5,101,114,114,110,111,6,115,116,114,105,110,103,4,99,111,112,121,4,102,
|
||||
105,108,108,3,97,98,105,252,8,192,250,8,109,101,116,97,116,121,112,101,252,
|
||||
7,192,250,2,103,99,252,5,192,250,4,108,111,97,100,252,4,193,67,250,252,3,194,
|
||||
111,115,250,252,2,196,97,114,99,104,250,255
|
||||
};
|
||||
#endif
|
||||
|
||||
30
include/lua/lj_mcode.h
Normal file
30
include/lua/lj_mcode.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
** Machine code management.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_MCODE_H
|
||||
#define _LJ_MCODE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
#if LJ_HASJIT || LJ_HASFFI
|
||||
LJ_FUNC void lj_mcode_sync(void *start, void *end);
|
||||
#endif
|
||||
|
||||
#if LJ_HASJIT
|
||||
|
||||
#include "lj_jit.h"
|
||||
|
||||
LJ_FUNC void lj_mcode_free(jit_State *J);
|
||||
LJ_FUNC MCode *lj_mcode_reserve(jit_State *J, MCode **lim);
|
||||
LJ_FUNC void lj_mcode_commit(jit_State *J, MCode *m);
|
||||
LJ_FUNC void lj_mcode_abort(jit_State *J);
|
||||
LJ_FUNC MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish);
|
||||
LJ_FUNC_NORET void lj_mcode_limiterr(jit_State *J, size_t need);
|
||||
|
||||
#define lj_mcode_commitbot(J, m) (J->mcbot = (m))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
38
include/lua/lj_meta.h
Normal file
38
include/lua/lj_meta.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
** Metamethod handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_META_H
|
||||
#define _LJ_META_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Metamethod handling */
|
||||
LJ_FUNC void lj_meta_init(lua_State *L);
|
||||
LJ_FUNC cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name);
|
||||
LJ_FUNC cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm);
|
||||
#if LJ_HASFFI
|
||||
LJ_FUNC int lj_meta_tailcall(lua_State *L, cTValue *tv);
|
||||
#endif
|
||||
|
||||
#define lj_meta_fastg(g, mt, mm) \
|
||||
((mt) == NULL ? NULL : ((mt)->nomm & (1u<<(mm))) ? NULL : \
|
||||
lj_meta_cache(mt, mm, mmname_str(g, mm)))
|
||||
#define lj_meta_fast(L, mt, mm) lj_meta_fastg(G(L), mt, mm)
|
||||
|
||||
/* C helpers for some instructions, called from assembler VM. */
|
||||
LJ_FUNCA cTValue *lj_meta_tget(lua_State *L, cTValue *o, cTValue *k);
|
||||
LJ_FUNCA TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k);
|
||||
LJ_FUNCA TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb,
|
||||
cTValue *rc, BCReg op);
|
||||
LJ_FUNCA TValue *lj_meta_cat(lua_State *L, TValue *top, int left);
|
||||
LJ_FUNCA TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o);
|
||||
LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne);
|
||||
LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins);
|
||||
LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op);
|
||||
LJ_FUNCA void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp);
|
||||
LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o);
|
||||
|
||||
#endif
|
||||
980
include/lua/lj_obj.h
Normal file
980
include/lua/lj_obj.h
Normal file
@@ -0,0 +1,980 @@
|
||||
/*
|
||||
** LuaJIT VM tags, values and objects.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_OBJ_H
|
||||
#define _LJ_OBJ_H
|
||||
|
||||
#include "lua.h"
|
||||
#include "lj_def.h"
|
||||
#include "lj_arch.h"
|
||||
|
||||
/* -- Memory references (32 bit address space) ---------------------------- */
|
||||
|
||||
/* Memory and GC object sizes. */
|
||||
typedef uint32_t MSize;
|
||||
#if LJ_GC64
|
||||
typedef uint64_t GCSize;
|
||||
#else
|
||||
typedef uint32_t GCSize;
|
||||
#endif
|
||||
|
||||
/* Memory reference */
|
||||
typedef struct MRef {
|
||||
#if LJ_GC64
|
||||
uint64_t ptr64; /* True 64 bit pointer. */
|
||||
#else
|
||||
uint32_t ptr32; /* Pseudo 32 bit pointer. */
|
||||
#endif
|
||||
} MRef;
|
||||
|
||||
#if LJ_GC64
|
||||
#define mref(r, t) ((t *)(void *)(r).ptr64)
|
||||
|
||||
#define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p))
|
||||
#define setmrefr(r, v) ((r).ptr64 = (v).ptr64)
|
||||
#else
|
||||
#define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32)
|
||||
|
||||
#define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p))
|
||||
#define setmrefr(r, v) ((r).ptr32 = (v).ptr32)
|
||||
#endif
|
||||
|
||||
/* -- GC object references (32 bit address space) ------------------------- */
|
||||
|
||||
/* GCobj reference */
|
||||
typedef struct GCRef {
|
||||
#if LJ_GC64
|
||||
uint64_t gcptr64; /* True 64 bit pointer. */
|
||||
#else
|
||||
uint32_t gcptr32; /* Pseudo 32 bit pointer. */
|
||||
#endif
|
||||
} GCRef;
|
||||
|
||||
/* Common GC header for all collectable objects. */
|
||||
#define GCHeader GCRef nextgc; uint8_t marked; uint8_t gct
|
||||
/* This occupies 6 bytes, so use the next 2 bytes for non-32 bit fields. */
|
||||
|
||||
#if LJ_GC64
|
||||
#define gcref(r) ((GCobj *)(r).gcptr64)
|
||||
#define gcrefp(r, t) ((t *)(void *)(r).gcptr64)
|
||||
#define gcrefu(r) ((r).gcptr64)
|
||||
#define gcrefeq(r1, r2) ((r1).gcptr64 == (r2).gcptr64)
|
||||
|
||||
#define setgcref(r, gc) ((r).gcptr64 = (uint64_t)&(gc)->gch)
|
||||
#define setgcreft(r, gc, it) \
|
||||
(r).gcptr64 = (uint64_t)&(gc)->gch | (((uint64_t)(it)) << 47)
|
||||
#define setgcrefp(r, p) ((r).gcptr64 = (uint64_t)(p))
|
||||
#define setgcrefnull(r) ((r).gcptr64 = 0)
|
||||
#define setgcrefr(r, v) ((r).gcptr64 = (v).gcptr64)
|
||||
#else
|
||||
#define gcref(r) ((GCobj *)(uintptr_t)(r).gcptr32)
|
||||
#define gcrefp(r, t) ((t *)(void *)(uintptr_t)(r).gcptr32)
|
||||
#define gcrefu(r) ((r).gcptr32)
|
||||
#define gcrefeq(r1, r2) ((r1).gcptr32 == (r2).gcptr32)
|
||||
|
||||
#define setgcref(r, gc) ((r).gcptr32 = (uint32_t)(uintptr_t)&(gc)->gch)
|
||||
#define setgcrefp(r, p) ((r).gcptr32 = (uint32_t)(uintptr_t)(p))
|
||||
#define setgcrefnull(r) ((r).gcptr32 = 0)
|
||||
#define setgcrefr(r, v) ((r).gcptr32 = (v).gcptr32)
|
||||
#endif
|
||||
|
||||
#define gcnext(gc) (gcref((gc)->gch.nextgc))
|
||||
|
||||
/* IMPORTANT NOTE:
|
||||
**
|
||||
** All uses of the setgcref* macros MUST be accompanied with a write barrier.
|
||||
**
|
||||
** This is to ensure the integrity of the incremental GC. The invariant
|
||||
** to preserve is that a black object never points to a white object.
|
||||
** I.e. never store a white object into a field of a black object.
|
||||
**
|
||||
** It's ok to LEAVE OUT the write barrier ONLY in the following cases:
|
||||
** - The source is not a GC object (NULL).
|
||||
** - The target is a GC root. I.e. everything in global_State.
|
||||
** - The target is a lua_State field (threads are never black).
|
||||
** - The target is a stack slot, see setgcV et al.
|
||||
** - The target is an open upvalue, i.e. pointing to a stack slot.
|
||||
** - The target is a newly created object (i.e. marked white). But make
|
||||
** sure nothing invokes the GC inbetween.
|
||||
** - The target and the source are the same object (self-reference).
|
||||
** - The target already contains the object (e.g. moving elements around).
|
||||
**
|
||||
** The most common case is a store to a stack slot. All other cases where
|
||||
** a barrier has been omitted are annotated with a NOBARRIER comment.
|
||||
**
|
||||
** The same logic applies for stores to table slots (array part or hash
|
||||
** part). ALL uses of lj_tab_set* require a barrier for the stored value
|
||||
** *and* the stored key, based on the above rules. In practice this means
|
||||
** a barrier is needed if *either* of the key or value are a GC object.
|
||||
**
|
||||
** It's ok to LEAVE OUT the write barrier in the following special cases:
|
||||
** - The stored value is nil. The key doesn't matter because it's either
|
||||
** not resurrected or lj_tab_newkey() will take care of the key barrier.
|
||||
** - The key doesn't matter if the *previously* stored value is guaranteed
|
||||
** to be non-nil (because the key is kept alive in the table).
|
||||
** - The key doesn't matter if it's guaranteed not to be part of the table,
|
||||
** since lj_tab_newkey() takes care of the key barrier. This applies
|
||||
** trivially to new tables, but watch out for resurrected keys. Storing
|
||||
** a nil value leaves the key in the table!
|
||||
**
|
||||
** In case of doubt use lj_gc_anybarriert() as it's rather cheap. It's used
|
||||
** by the interpreter for all table stores.
|
||||
**
|
||||
** Note: In contrast to Lua's GC, LuaJIT's GC does *not* specially mark
|
||||
** dead keys in tables. The reference is left in, but it's guaranteed to
|
||||
** be never dereferenced as long as the value is nil. It's ok if the key is
|
||||
** freed or if any object subsequently gets the same address.
|
||||
**
|
||||
** Not destroying dead keys helps to keep key hash slots stable. This avoids
|
||||
** specialization back-off for HREFK when a value flips between nil and
|
||||
** non-nil and the GC gets in the way. It also allows safely hoisting
|
||||
** HREF/HREFK across GC steps. Dead keys are only removed if a table is
|
||||
** resized (i.e. by NEWREF) and xREF must not be CSEd across a resize.
|
||||
**
|
||||
** The trade-off is that a write barrier for tables must take the key into
|
||||
** account, too. Implicitly resurrecting the key by storing a non-nil value
|
||||
** may invalidate the incremental GC invariant.
|
||||
*/
|
||||
|
||||
/* -- Common type definitions --------------------------------------------- */
|
||||
|
||||
/* Types for handling bytecodes. Need this here, details in lj_bc.h. */
|
||||
typedef uint32_t BCIns; /* Bytecode instruction. */
|
||||
typedef uint32_t BCPos; /* Bytecode position. */
|
||||
typedef uint32_t BCReg; /* Bytecode register. */
|
||||
typedef int32_t BCLine; /* Bytecode line number. */
|
||||
|
||||
/* Internal assembler functions. Never call these directly from C. */
|
||||
typedef void (*ASMFunction)(void);
|
||||
|
||||
/* Resizable string buffer. Need this here, details in lj_buf.h. */
|
||||
typedef struct SBuf {
|
||||
MRef p; /* String buffer pointer. */
|
||||
MRef e; /* String buffer end pointer. */
|
||||
MRef b; /* String buffer base. */
|
||||
MRef L; /* lua_State, used for buffer resizing. */
|
||||
} SBuf;
|
||||
|
||||
/* -- Tags and values ----------------------------------------------------- */
|
||||
|
||||
/* Frame link. */
|
||||
typedef union {
|
||||
int32_t ftsz; /* Frame type and size of previous frame. */
|
||||
MRef pcr; /* Or PC for Lua frames. */
|
||||
} FrameLink;
|
||||
|
||||
/* Tagged value. */
|
||||
typedef LJ_ALIGN(8) union TValue {
|
||||
uint64_t u64; /* 64 bit pattern overlaps number. */
|
||||
lua_Number n; /* Number object overlaps split tag/value object. */
|
||||
#if LJ_GC64
|
||||
GCRef gcr; /* GCobj reference with tag. */
|
||||
int64_t it64;
|
||||
struct {
|
||||
LJ_ENDIAN_LOHI(
|
||||
int32_t i; /* Integer value. */
|
||||
, uint32_t it; /* Internal object tag. Must overlap MSW of number. */
|
||||
)
|
||||
};
|
||||
#else
|
||||
struct {
|
||||
LJ_ENDIAN_LOHI(
|
||||
union {
|
||||
GCRef gcr; /* GCobj reference (if any). */
|
||||
int32_t i; /* Integer value. */
|
||||
};
|
||||
, uint32_t it; /* Internal object tag. Must overlap MSW of number. */
|
||||
)
|
||||
};
|
||||
#endif
|
||||
#if LJ_FR2
|
||||
int64_t ftsz; /* Frame type and size of previous frame, or PC. */
|
||||
#else
|
||||
struct {
|
||||
LJ_ENDIAN_LOHI(
|
||||
GCRef func; /* Function for next frame (or dummy L). */
|
||||
, FrameLink tp; /* Link to previous frame. */
|
||||
)
|
||||
} fr;
|
||||
#endif
|
||||
struct {
|
||||
LJ_ENDIAN_LOHI(
|
||||
uint32_t lo; /* Lower 32 bits of number. */
|
||||
, uint32_t hi; /* Upper 32 bits of number. */
|
||||
)
|
||||
} u32;
|
||||
} TValue;
|
||||
|
||||
typedef const TValue cTValue;
|
||||
|
||||
#define tvref(r) (mref(r, TValue))
|
||||
|
||||
/* More external and GCobj tags for internal objects. */
|
||||
#define LAST_TT LUA_TTHREAD
|
||||
#define LUA_TPROTO (LAST_TT+1)
|
||||
#define LUA_TCDATA (LAST_TT+2)
|
||||
|
||||
/* Internal object tags.
|
||||
**
|
||||
** Format for 32 bit GC references (!LJ_GC64):
|
||||
**
|
||||
** Internal tags overlap the MSW of a number object (must be a double).
|
||||
** Interpreted as a double these are special NaNs. The FPU only generates
|
||||
** one type of NaN (0xfff8_0000_0000_0000). So MSWs > 0xfff80000 are available
|
||||
** for use as internal tags. Small negative numbers are used to shorten the
|
||||
** encoding of type comparisons (reg/mem against sign-ext. 8 bit immediate).
|
||||
**
|
||||
** ---MSW---.---LSW---
|
||||
** primitive types | itype | |
|
||||
** lightuserdata | itype | void * | (32 bit platforms)
|
||||
** lightuserdata |ffff| void * | (64 bit platforms, 47 bit pointers)
|
||||
** GC objects | itype | GCRef |
|
||||
** int (LJ_DUALNUM)| itype | int |
|
||||
** number -------double------
|
||||
**
|
||||
** Format for 64 bit GC references (LJ_GC64):
|
||||
**
|
||||
** The upper 13 bits must be 1 (0xfff8...) for a special NaN. The next
|
||||
** 4 bits hold the internal tag. The lowest 47 bits either hold a pointer,
|
||||
** a zero-extended 32 bit integer or all bits set to 1 for primitive types.
|
||||
**
|
||||
** ------MSW------.------LSW------
|
||||
** primitive types |1..1|itype|1..................1|
|
||||
** GC objects/lightud |1..1|itype|-------GCRef--------|
|
||||
** int (LJ_DUALNUM) |1..1|itype|0..0|-----int-------|
|
||||
** number ------------double-------------
|
||||
**
|
||||
** ORDER LJ_T
|
||||
** Primitive types nil/false/true must be first, lightuserdata next.
|
||||
** GC objects are at the end, table/userdata must be lowest.
|
||||
** Also check lj_ir.h for similar ordering constraints.
|
||||
*/
|
||||
#define LJ_TNIL (~0u)
|
||||
#define LJ_TFALSE (~1u)
|
||||
#define LJ_TTRUE (~2u)
|
||||
#define LJ_TLIGHTUD (~3u)
|
||||
#define LJ_TSTR (~4u)
|
||||
#define LJ_TUPVAL (~5u)
|
||||
#define LJ_TTHREAD (~6u)
|
||||
#define LJ_TPROTO (~7u)
|
||||
#define LJ_TFUNC (~8u)
|
||||
#define LJ_TTRACE (~9u)
|
||||
#define LJ_TCDATA (~10u)
|
||||
#define LJ_TTAB (~11u)
|
||||
#define LJ_TUDATA (~12u)
|
||||
/* This is just the canonical number type used in some places. */
|
||||
#define LJ_TNUMX (~13u)
|
||||
|
||||
/* Integers have itype == LJ_TISNUM doubles have itype < LJ_TISNUM */
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define LJ_TISNUM 0xfffeffffu
|
||||
#else
|
||||
#define LJ_TISNUM LJ_TNUMX
|
||||
#endif
|
||||
#define LJ_TISTRUECOND LJ_TFALSE
|
||||
#define LJ_TISPRI LJ_TTRUE
|
||||
#define LJ_TISGCV (LJ_TSTR+1)
|
||||
#define LJ_TISTABUD LJ_TTAB
|
||||
|
||||
#if LJ_GC64
|
||||
#define LJ_GCVMASK (((uint64_t)1 << 47) - 1)
|
||||
#endif
|
||||
|
||||
/* -- String object ------------------------------------------------------- */
|
||||
|
||||
/* String object header. String payload follows. */
|
||||
typedef struct GCstr {
|
||||
GCHeader;
|
||||
uint8_t reserved; /* Used by lexer for fast lookup of reserved words. */
|
||||
uint8_t unused;
|
||||
MSize hash; /* Hash of string. */
|
||||
MSize len; /* Size of string. */
|
||||
} GCstr;
|
||||
|
||||
#define strref(r) (&gcref((r))->str)
|
||||
#define strdata(s) ((const char *)((s)+1))
|
||||
#define strdatawr(s) ((char *)((s)+1))
|
||||
#define strVdata(o) strdata(strV(o))
|
||||
#define sizestring(s) (sizeof(struct GCstr)+(s)->len+1)
|
||||
|
||||
/* -- Userdata object ----------------------------------------------------- */
|
||||
|
||||
/* Userdata object. Payload follows. */
|
||||
typedef struct GCudata {
|
||||
GCHeader;
|
||||
uint8_t udtype; /* Userdata type. */
|
||||
uint8_t unused2;
|
||||
GCRef env; /* Should be at same offset in GCfunc. */
|
||||
MSize len; /* Size of payload. */
|
||||
GCRef metatable; /* Must be at same offset in GCtab. */
|
||||
uint32_t align1; /* To force 8 byte alignment of the payload. */
|
||||
} GCudata;
|
||||
|
||||
/* Userdata types. */
|
||||
enum {
|
||||
UDTYPE_USERDATA, /* Regular userdata. */
|
||||
UDTYPE_IO_FILE, /* I/O library FILE. */
|
||||
UDTYPE_FFI_CLIB, /* FFI C library namespace. */
|
||||
UDTYPE__MAX
|
||||
};
|
||||
|
||||
#define uddata(u) ((void *)((u)+1))
|
||||
#define sizeudata(u) (sizeof(struct GCudata)+(u)->len)
|
||||
|
||||
/* -- C data object ------------------------------------------------------- */
|
||||
|
||||
/* C data object. Payload follows. */
|
||||
typedef struct GCcdata {
|
||||
GCHeader;
|
||||
uint16_t ctypeid; /* C type ID. */
|
||||
} GCcdata;
|
||||
|
||||
/* Prepended to variable-sized or realigned C data objects. */
|
||||
typedef struct GCcdataVar {
|
||||
uint16_t offset; /* Offset to allocated memory (relative to GCcdata). */
|
||||
uint16_t extra; /* Extra space allocated (incl. GCcdata + GCcdatav). */
|
||||
MSize len; /* Size of payload. */
|
||||
} GCcdataVar;
|
||||
|
||||
#define cdataptr(cd) ((void *)((cd)+1))
|
||||
#define cdataisv(cd) ((cd)->marked & 0x80)
|
||||
#define cdatav(cd) ((GCcdataVar *)((char *)(cd) - sizeof(GCcdataVar)))
|
||||
#define cdatavlen(cd) check_exp(cdataisv(cd), cdatav(cd)->len)
|
||||
#define sizecdatav(cd) (cdatavlen(cd) + cdatav(cd)->extra)
|
||||
#define memcdatav(cd) ((void *)((char *)(cd) - cdatav(cd)->offset))
|
||||
|
||||
/* -- Prototype object ---------------------------------------------------- */
|
||||
|
||||
#define SCALE_NUM_GCO ((int32_t)sizeof(lua_Number)/sizeof(GCRef))
|
||||
#define round_nkgc(n) (((n) + SCALE_NUM_GCO-1) & ~(SCALE_NUM_GCO-1))
|
||||
|
||||
typedef struct GCproto {
|
||||
GCHeader;
|
||||
uint8_t numparams; /* Number of parameters. */
|
||||
uint8_t framesize; /* Fixed frame size. */
|
||||
MSize sizebc; /* Number of bytecode instructions. */
|
||||
#if LJ_GC64
|
||||
uint32_t unused_gc64;
|
||||
#endif
|
||||
GCRef gclist;
|
||||
MRef k; /* Split constant array (points to the middle). */
|
||||
MRef uv; /* Upvalue list. local slot|0x8000 or parent uv idx. */
|
||||
MSize sizekgc; /* Number of collectable constants. */
|
||||
MSize sizekn; /* Number of lua_Number constants. */
|
||||
MSize sizept; /* Total size including colocated arrays. */
|
||||
uint8_t sizeuv; /* Number of upvalues. */
|
||||
uint8_t flags; /* Miscellaneous flags (see below). */
|
||||
uint16_t trace; /* Anchor for chain of root traces. */
|
||||
/* ------ The following fields are for debugging/tracebacks only ------ */
|
||||
GCRef chunkname; /* Name of the chunk this function was defined in. */
|
||||
BCLine firstline; /* First line of the function definition. */
|
||||
BCLine numline; /* Number of lines for the function definition. */
|
||||
MRef lineinfo; /* Compressed map from bytecode ins. to source line. */
|
||||
MRef uvinfo; /* Upvalue names. */
|
||||
MRef varinfo; /* Names and compressed extents of local variables. */
|
||||
} GCproto;
|
||||
|
||||
/* Flags for prototype. */
|
||||
#define PROTO_CHILD 0x01 /* Has child prototypes. */
|
||||
#define PROTO_VARARG 0x02 /* Vararg function. */
|
||||
#define PROTO_FFI 0x04 /* Uses BC_KCDATA for FFI datatypes. */
|
||||
#define PROTO_NOJIT 0x08 /* JIT disabled for this function. */
|
||||
#define PROTO_ILOOP 0x10 /* Patched bytecode with ILOOP etc. */
|
||||
/* Only used during parsing. */
|
||||
#define PROTO_HAS_RETURN 0x20 /* Already emitted a return. */
|
||||
#define PROTO_FIXUP_RETURN 0x40 /* Need to fixup emitted returns. */
|
||||
/* Top bits used for counting created closures. */
|
||||
#define PROTO_CLCOUNT 0x20 /* Base of saturating 3 bit counter. */
|
||||
#define PROTO_CLC_BITS 3
|
||||
#define PROTO_CLC_POLY (3*PROTO_CLCOUNT) /* Polymorphic threshold. */
|
||||
|
||||
#define PROTO_UV_LOCAL 0x8000 /* Upvalue for local slot. */
|
||||
#define PROTO_UV_IMMUTABLE 0x4000 /* Immutable upvalue. */
|
||||
|
||||
#define proto_kgc(pt, idx) \
|
||||
check_exp((uintptr_t)(intptr_t)(idx) >= (uintptr_t)-(intptr_t)(pt)->sizekgc, \
|
||||
gcref(mref((pt)->k, GCRef)[(idx)]))
|
||||
#define proto_knumtv(pt, idx) \
|
||||
check_exp((uintptr_t)(idx) < (pt)->sizekn, &mref((pt)->k, TValue)[(idx)])
|
||||
#define proto_bc(pt) ((BCIns *)((char *)(pt) + sizeof(GCproto)))
|
||||
#define proto_bcpos(pt, pc) ((BCPos)((pc) - proto_bc(pt)))
|
||||
#define proto_uv(pt) (mref((pt)->uv, uint16_t))
|
||||
|
||||
#define proto_chunkname(pt) (strref((pt)->chunkname))
|
||||
#define proto_chunknamestr(pt) (strdata(proto_chunkname((pt))))
|
||||
#define proto_lineinfo(pt) (mref((pt)->lineinfo, const void))
|
||||
#define proto_uvinfo(pt) (mref((pt)->uvinfo, const uint8_t))
|
||||
#define proto_varinfo(pt) (mref((pt)->varinfo, const uint8_t))
|
||||
|
||||
/* -- Upvalue object ------------------------------------------------------ */
|
||||
|
||||
typedef struct GCupval {
|
||||
GCHeader;
|
||||
uint8_t closed; /* Set if closed (i.e. uv->v == &uv->u.value). */
|
||||
uint8_t immutable; /* Immutable value. */
|
||||
union {
|
||||
TValue tv; /* If closed: the value itself. */
|
||||
struct { /* If open: double linked list, anchored at thread. */
|
||||
GCRef prev;
|
||||
GCRef next;
|
||||
};
|
||||
};
|
||||
MRef v; /* Points to stack slot (open) or above (closed). */
|
||||
uint32_t dhash; /* Disambiguation hash: dh1 != dh2 => cannot alias. */
|
||||
} GCupval;
|
||||
|
||||
#define uvprev(uv_) (&gcref((uv_)->prev)->uv)
|
||||
#define uvnext(uv_) (&gcref((uv_)->next)->uv)
|
||||
#define uvval(uv_) (mref((uv_)->v, TValue))
|
||||
|
||||
/* -- Function object (closures) ------------------------------------------ */
|
||||
|
||||
/* Common header for functions. env should be at same offset in GCudata. */
|
||||
#define GCfuncHeader \
|
||||
GCHeader; uint8_t ffid; uint8_t nupvalues; \
|
||||
GCRef env; GCRef gclist; MRef pc
|
||||
|
||||
typedef struct GCfuncC {
|
||||
GCfuncHeader;
|
||||
lua_CFunction f; /* C function to be called. */
|
||||
TValue upvalue[1]; /* Array of upvalues (TValue). */
|
||||
} GCfuncC;
|
||||
|
||||
typedef struct GCfuncL {
|
||||
GCfuncHeader;
|
||||
GCRef uvptr[1]; /* Array of _pointers_ to upvalue objects (GCupval). */
|
||||
} GCfuncL;
|
||||
|
||||
typedef union GCfunc {
|
||||
GCfuncC c;
|
||||
GCfuncL l;
|
||||
} GCfunc;
|
||||
|
||||
#define FF_LUA 0
|
||||
#define FF_C 1
|
||||
#define isluafunc(fn) ((fn)->c.ffid == FF_LUA)
|
||||
#define iscfunc(fn) ((fn)->c.ffid == FF_C)
|
||||
#define isffunc(fn) ((fn)->c.ffid > FF_C)
|
||||
#define funcproto(fn) \
|
||||
check_exp(isluafunc(fn), (GCproto *)(mref((fn)->l.pc, char)-sizeof(GCproto)))
|
||||
#define sizeCfunc(n) (sizeof(GCfuncC)-sizeof(TValue)+sizeof(TValue)*(n))
|
||||
#define sizeLfunc(n) (sizeof(GCfuncL)-sizeof(GCRef)+sizeof(GCRef)*(n))
|
||||
|
||||
/* -- Table object -------------------------------------------------------- */
|
||||
|
||||
/* Hash node. */
|
||||
typedef struct Node {
|
||||
TValue val; /* Value object. Must be first field. */
|
||||
TValue key; /* Key object. */
|
||||
MRef next; /* Hash chain. */
|
||||
#if !LJ_GC64
|
||||
MRef freetop; /* Top of free elements (stored in t->node[0]). */
|
||||
#endif
|
||||
} Node;
|
||||
|
||||
LJ_STATIC_ASSERT(offsetof(Node, val) == 0);
|
||||
|
||||
typedef struct GCtab {
|
||||
GCHeader;
|
||||
uint8_t nomm; /* Negative cache for fast metamethods. */
|
||||
int8_t colo; /* Array colocation. */
|
||||
MRef array; /* Array part. */
|
||||
GCRef gclist;
|
||||
GCRef metatable; /* Must be at same offset in GCudata. */
|
||||
MRef node; /* Hash part. */
|
||||
uint32_t asize; /* Size of array part (keys [0, asize-1]). */
|
||||
uint32_t hmask; /* Hash part mask (size of hash part - 1). */
|
||||
#if LJ_GC64
|
||||
MRef freetop; /* Top of free elements. */
|
||||
#endif
|
||||
} GCtab;
|
||||
|
||||
#define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab))
|
||||
#define tabref(r) (&gcref((r))->tab)
|
||||
#define noderef(r) (mref((r), Node))
|
||||
#define nextnode(n) (mref((n)->next, Node))
|
||||
#if LJ_GC64
|
||||
#define getfreetop(t, n) (noderef((t)->freetop))
|
||||
#define setfreetop(t, n, v) (setmref((t)->freetop, (v)))
|
||||
#else
|
||||
#define getfreetop(t, n) (noderef((n)->freetop))
|
||||
#define setfreetop(t, n, v) (setmref((n)->freetop, (v)))
|
||||
#endif
|
||||
|
||||
/* -- State objects ------------------------------------------------------- */
|
||||
|
||||
/* VM states. */
|
||||
enum {
|
||||
LJ_VMST_INTERP, /* Interpreter. */
|
||||
LJ_VMST_C, /* C function. */
|
||||
LJ_VMST_GC, /* Garbage collector. */
|
||||
LJ_VMST_EXIT, /* Trace exit handler. */
|
||||
LJ_VMST_RECORD, /* Trace recorder. */
|
||||
LJ_VMST_OPT, /* Optimizer. */
|
||||
LJ_VMST_ASM, /* Assembler. */
|
||||
LJ_VMST__MAX
|
||||
};
|
||||
|
||||
#define setvmstate(g, st) ((g)->vmstate = ~LJ_VMST_##st)
|
||||
|
||||
/* Metamethods. ORDER MM */
|
||||
#ifdef LJ_HASFFI
|
||||
#define MMDEF_FFI(_) _(new)
|
||||
#else
|
||||
#define MMDEF_FFI(_)
|
||||
#endif
|
||||
|
||||
#if LJ_52 || LJ_HASFFI
|
||||
#define MMDEF_PAIRS(_) _(pairs) _(ipairs)
|
||||
#else
|
||||
#define MMDEF_PAIRS(_)
|
||||
#define MM_pairs 255
|
||||
#define MM_ipairs 255
|
||||
#endif
|
||||
|
||||
#define MMDEF(_) \
|
||||
_(index) _(newindex) _(gc) _(mode) _(eq) _(len) \
|
||||
/* Only the above (fast) metamethods are negative cached (max. 8). */ \
|
||||
_(lt) _(le) _(concat) _(call) \
|
||||
/* The following must be in ORDER ARITH. */ \
|
||||
_(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
|
||||
/* The following are used in the standard libraries. */ \
|
||||
_(metatable) _(tostring) MMDEF_FFI(_) MMDEF_PAIRS(_)
|
||||
|
||||
typedef enum {
|
||||
#define MMENUM(name) MM_##name,
|
||||
MMDEF(MMENUM)
|
||||
#undef MMENUM
|
||||
MM__MAX,
|
||||
MM____ = MM__MAX,
|
||||
MM_FAST = MM_len
|
||||
} MMS;
|
||||
|
||||
/* GC root IDs. */
|
||||
typedef enum {
|
||||
GCROOT_MMNAME, /* Metamethod names. */
|
||||
GCROOT_MMNAME_LAST = GCROOT_MMNAME + MM__MAX-1,
|
||||
GCROOT_BASEMT, /* Metatables for base types. */
|
||||
GCROOT_BASEMT_NUM = GCROOT_BASEMT + ~LJ_TNUMX,
|
||||
GCROOT_IO_INPUT, /* Userdata for default I/O input file. */
|
||||
GCROOT_IO_OUTPUT, /* Userdata for default I/O output file. */
|
||||
GCROOT_MAX
|
||||
} GCRootID;
|
||||
|
||||
#define basemt_it(g, it) ((g)->gcroot[GCROOT_BASEMT+~(it)])
|
||||
#define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)])
|
||||
#define mmname_str(g, mm) (strref((g)->gcroot[GCROOT_MMNAME+(mm)]))
|
||||
|
||||
typedef struct GCState {
|
||||
GCSize total; /* Memory currently allocated. */
|
||||
GCSize threshold; /* Memory threshold. */
|
||||
uint8_t currentwhite; /* Current white color. */
|
||||
uint8_t state; /* GC state. */
|
||||
uint8_t nocdatafin; /* No cdata finalizer called. */
|
||||
uint8_t unused2;
|
||||
MSize sweepstr; /* Sweep position in string table. */
|
||||
GCRef root; /* List of all collectable objects. */
|
||||
MRef sweep; /* Sweep position in root list. */
|
||||
GCRef gray; /* List of gray objects. */
|
||||
GCRef grayagain; /* List of objects for atomic traversal. */
|
||||
GCRef weak; /* List of weak tables (to be cleared). */
|
||||
GCRef mmudata; /* List of userdata (to be finalized). */
|
||||
GCSize debt; /* Debt (how much GC is behind schedule). */
|
||||
GCSize estimate; /* Estimate of memory actually in use. */
|
||||
MSize stepmul; /* Incremental GC step granularity. */
|
||||
MSize pause; /* Pause between successive GC cycles. */
|
||||
} GCState;
|
||||
|
||||
/* Global state, shared by all threads of a Lua universe. */
|
||||
typedef struct global_State {
|
||||
GCRef *strhash; /* String hash table (hash chain anchors). */
|
||||
MSize strmask; /* String hash mask (size of hash table - 1). */
|
||||
MSize strnum; /* Number of strings in hash table. */
|
||||
lua_Alloc allocf; /* Memory allocator. */
|
||||
void *allocd; /* Memory allocator data. */
|
||||
GCState gc; /* Garbage collector. */
|
||||
volatile int32_t vmstate; /* VM state or current JIT code trace number. */
|
||||
SBuf tmpbuf; /* Temporary string buffer. */
|
||||
GCstr strempty; /* Empty string. */
|
||||
uint8_t stremptyz; /* Zero terminator of empty string. */
|
||||
uint8_t hookmask; /* Hook mask. */
|
||||
uint8_t dispatchmode; /* Dispatch mode. */
|
||||
uint8_t vmevmask; /* VM event mask. */
|
||||
GCRef mainthref; /* Link to main thread. */
|
||||
TValue registrytv; /* Anchor for registry. */
|
||||
TValue tmptv, tmptv2; /* Temporary TValues. */
|
||||
Node nilnode; /* Fallback 1-element hash part (nil key and value). */
|
||||
GCupval uvhead; /* Head of double-linked list of all open upvalues. */
|
||||
int32_t hookcount; /* Instruction hook countdown. */
|
||||
int32_t hookcstart; /* Start count for instruction hook counter. */
|
||||
lua_Hook hookf; /* Hook function. */
|
||||
lua_CFunction wrapf; /* Wrapper for C function calls. */
|
||||
lua_CFunction panic; /* Called as a last resort for errors. */
|
||||
BCIns bc_cfunc_int; /* Bytecode for internal C function calls. */
|
||||
BCIns bc_cfunc_ext; /* Bytecode for external C function calls. */
|
||||
GCRef cur_L; /* Currently executing lua_State. */
|
||||
MRef jit_base; /* Current JIT code L->base or NULL. */
|
||||
MRef ctype_state; /* Pointer to C type state. */
|
||||
GCRef gcroot[GCROOT_MAX]; /* GC roots. */
|
||||
} global_State;
|
||||
|
||||
#define mainthread(g) (&gcref(g->mainthref)->th)
|
||||
#define niltv(L) \
|
||||
check_exp(tvisnil(&G(L)->nilnode.val), &G(L)->nilnode.val)
|
||||
#define niltvg(g) \
|
||||
check_exp(tvisnil(&(g)->nilnode.val), &(g)->nilnode.val)
|
||||
|
||||
/* Hook management. Hook event masks are defined in lua.h. */
|
||||
#define HOOK_EVENTMASK 0x0f
|
||||
#define HOOK_ACTIVE 0x10
|
||||
#define HOOK_ACTIVE_SHIFT 4
|
||||
#define HOOK_VMEVENT 0x20
|
||||
#define HOOK_GC 0x40
|
||||
#define HOOK_PROFILE 0x80
|
||||
#define hook_active(g) ((g)->hookmask & HOOK_ACTIVE)
|
||||
#define hook_enter(g) ((g)->hookmask |= HOOK_ACTIVE)
|
||||
#define hook_entergc(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_GC))
|
||||
#define hook_vmevent(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_VMEVENT))
|
||||
#define hook_leave(g) ((g)->hookmask &= ~HOOK_ACTIVE)
|
||||
#define hook_save(g) ((g)->hookmask & ~HOOK_EVENTMASK)
|
||||
#define hook_restore(g, h) \
|
||||
((g)->hookmask = ((g)->hookmask & HOOK_EVENTMASK) | (h))
|
||||
|
||||
/* Per-thread state object. */
|
||||
struct lua_State {
|
||||
GCHeader;
|
||||
uint8_t dummy_ffid; /* Fake FF_C for curr_funcisL() on dummy frames. */
|
||||
uint8_t status; /* Thread status. */
|
||||
MRef glref; /* Link to global state. */
|
||||
GCRef gclist; /* GC chain. */
|
||||
TValue *base; /* Base of currently executing function. */
|
||||
TValue *top; /* First free slot in the stack. */
|
||||
MRef maxstack; /* Last free slot in the stack. */
|
||||
MRef stack; /* Stack base. */
|
||||
GCRef openupval; /* List of open upvalues in the stack. */
|
||||
GCRef env; /* Thread environment (table of globals). */
|
||||
void *cframe; /* End of C stack frame chain. */
|
||||
MSize stacksize; /* True stack size (incl. LJ_STACK_EXTRA). */
|
||||
};
|
||||
|
||||
#define G(L) (mref(L->glref, global_State))
|
||||
#define registry(L) (&G(L)->registrytv)
|
||||
|
||||
/* Macros to access the currently executing (Lua) function. */
|
||||
#if LJ_GC64
|
||||
#define curr_func(L) (&gcval(L->base-2)->fn)
|
||||
#elif LJ_FR2
|
||||
#define curr_func(L) (&gcref((L->base-2)->gcr)->fn)
|
||||
#else
|
||||
#define curr_func(L) (&gcref((L->base-1)->fr.func)->fn)
|
||||
#endif
|
||||
#define curr_funcisL(L) (isluafunc(curr_func(L)))
|
||||
#define curr_proto(L) (funcproto(curr_func(L)))
|
||||
#define curr_topL(L) (L->base + curr_proto(L)->framesize)
|
||||
#define curr_top(L) (curr_funcisL(L) ? curr_topL(L) : L->top)
|
||||
|
||||
/* -- GC object definition and conversions -------------------------------- */
|
||||
|
||||
/* GC header for generic access to common fields of GC objects. */
|
||||
typedef struct GChead {
|
||||
GCHeader;
|
||||
uint8_t unused1;
|
||||
uint8_t unused2;
|
||||
GCRef env;
|
||||
GCRef gclist;
|
||||
GCRef metatable;
|
||||
} GChead;
|
||||
|
||||
/* The env field SHOULD be at the same offset for all GC objects. */
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, env) == offsetof(GCfuncL, env));
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, env) == offsetof(GCudata, env));
|
||||
|
||||
/* The metatable field MUST be at the same offset for all GC objects. */
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, metatable) == offsetof(GCtab, metatable));
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, metatable) == offsetof(GCudata, metatable));
|
||||
|
||||
/* The gclist field MUST be at the same offset for all GC objects. */
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, gclist) == offsetof(lua_State, gclist));
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, gclist) == offsetof(GCproto, gclist));
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, gclist) == offsetof(GCfuncL, gclist));
|
||||
LJ_STATIC_ASSERT(offsetof(GChead, gclist) == offsetof(GCtab, gclist));
|
||||
|
||||
typedef union GCobj {
|
||||
GChead gch;
|
||||
GCstr str;
|
||||
GCupval uv;
|
||||
lua_State th;
|
||||
GCproto pt;
|
||||
GCfunc fn;
|
||||
GCcdata cd;
|
||||
GCtab tab;
|
||||
GCudata ud;
|
||||
} GCobj;
|
||||
|
||||
/* Macros to convert a GCobj pointer into a specific value. */
|
||||
#define gco2str(o) check_exp((o)->gch.gct == ~LJ_TSTR, &(o)->str)
|
||||
#define gco2uv(o) check_exp((o)->gch.gct == ~LJ_TUPVAL, &(o)->uv)
|
||||
#define gco2th(o) check_exp((o)->gch.gct == ~LJ_TTHREAD, &(o)->th)
|
||||
#define gco2pt(o) check_exp((o)->gch.gct == ~LJ_TPROTO, &(o)->pt)
|
||||
#define gco2func(o) check_exp((o)->gch.gct == ~LJ_TFUNC, &(o)->fn)
|
||||
#define gco2cd(o) check_exp((o)->gch.gct == ~LJ_TCDATA, &(o)->cd)
|
||||
#define gco2tab(o) check_exp((o)->gch.gct == ~LJ_TTAB, &(o)->tab)
|
||||
#define gco2ud(o) check_exp((o)->gch.gct == ~LJ_TUDATA, &(o)->ud)
|
||||
|
||||
/* Macro to convert any collectable object into a GCobj pointer. */
|
||||
#define obj2gco(v) ((GCobj *)(v))
|
||||
|
||||
/* -- TValue getters/setters ---------------------------------------------- */
|
||||
|
||||
#ifdef LUA_USE_ASSERT
|
||||
#include "lj_gc.h"
|
||||
#endif
|
||||
|
||||
/* Macros to test types. */
|
||||
#if LJ_GC64
|
||||
#define itype(o) ((uint32_t)((o)->it64 >> 47))
|
||||
#define tvisnil(o) ((o)->it64 == -1)
|
||||
#else
|
||||
#define itype(o) ((o)->it)
|
||||
#define tvisnil(o) (itype(o) == LJ_TNIL)
|
||||
#endif
|
||||
#define tvisfalse(o) (itype(o) == LJ_TFALSE)
|
||||
#define tvistrue(o) (itype(o) == LJ_TTRUE)
|
||||
#define tvisbool(o) (tvisfalse(o) || tvistrue(o))
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define tvislightud(o) (((int32_t)itype(o) >> 15) == -2)
|
||||
#else
|
||||
#define tvislightud(o) (itype(o) == LJ_TLIGHTUD)
|
||||
#endif
|
||||
#define tvisstr(o) (itype(o) == LJ_TSTR)
|
||||
#define tvisfunc(o) (itype(o) == LJ_TFUNC)
|
||||
#define tvisthread(o) (itype(o) == LJ_TTHREAD)
|
||||
#define tvisproto(o) (itype(o) == LJ_TPROTO)
|
||||
#define tviscdata(o) (itype(o) == LJ_TCDATA)
|
||||
#define tvistab(o) (itype(o) == LJ_TTAB)
|
||||
#define tvisudata(o) (itype(o) == LJ_TUDATA)
|
||||
#define tvisnumber(o) (itype(o) <= LJ_TISNUM)
|
||||
#define tvisint(o) (LJ_DUALNUM && itype(o) == LJ_TISNUM)
|
||||
#define tvisnum(o) (itype(o) < LJ_TISNUM)
|
||||
|
||||
#define tvistruecond(o) (itype(o) < LJ_TISTRUECOND)
|
||||
#define tvispri(o) (itype(o) >= LJ_TISPRI)
|
||||
#define tvistabud(o) (itype(o) <= LJ_TISTABUD) /* && !tvisnum() */
|
||||
#define tvisgcv(o) ((itype(o) - LJ_TISGCV) > (LJ_TNUMX - LJ_TISGCV))
|
||||
|
||||
/* Special macros to test numbers for NaN, +0, -0, +1 and raw equality. */
|
||||
#define tvisnan(o) ((o)->n != (o)->n)
|
||||
#if LJ_64
|
||||
#define tviszero(o) (((o)->u64 << 1) == 0)
|
||||
#else
|
||||
#define tviszero(o) (((o)->u32.lo | ((o)->u32.hi << 1)) == 0)
|
||||
#endif
|
||||
#define tvispzero(o) ((o)->u64 == 0)
|
||||
#define tvismzero(o) ((o)->u64 == U64x(80000000,00000000))
|
||||
#define tvispone(o) ((o)->u64 == U64x(3ff00000,00000000))
|
||||
#define rawnumequal(o1, o2) ((o1)->u64 == (o2)->u64)
|
||||
|
||||
/* Macros to convert type ids. */
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define itypemap(o) \
|
||||
(tvisnumber(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o))
|
||||
#else
|
||||
#define itypemap(o) (tvisnumber(o) ? ~LJ_TNUMX : ~itype(o))
|
||||
#endif
|
||||
|
||||
/* Macros to get tagged values. */
|
||||
#if LJ_GC64
|
||||
#define gcval(o) ((GCobj *)(gcrefu((o)->gcr) & LJ_GCVMASK))
|
||||
#else
|
||||
#define gcval(o) (gcref((o)->gcr))
|
||||
#endif
|
||||
#define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - itype(o)))
|
||||
#if LJ_64
|
||||
#define lightudV(o) \
|
||||
check_exp(tvislightud(o), (void *)((o)->u64 & U64x(00007fff,ffffffff)))
|
||||
#else
|
||||
#define lightudV(o) check_exp(tvislightud(o), gcrefp((o)->gcr, void))
|
||||
#endif
|
||||
#define gcV(o) check_exp(tvisgcv(o), gcval(o))
|
||||
#define strV(o) check_exp(tvisstr(o), &gcval(o)->str)
|
||||
#define funcV(o) check_exp(tvisfunc(o), &gcval(o)->fn)
|
||||
#define threadV(o) check_exp(tvisthread(o), &gcval(o)->th)
|
||||
#define protoV(o) check_exp(tvisproto(o), &gcval(o)->pt)
|
||||
#define cdataV(o) check_exp(tviscdata(o), &gcval(o)->cd)
|
||||
#define tabV(o) check_exp(tvistab(o), &gcval(o)->tab)
|
||||
#define udataV(o) check_exp(tvisudata(o), &gcval(o)->ud)
|
||||
#define numV(o) check_exp(tvisnum(o), (o)->n)
|
||||
#define intV(o) check_exp(tvisint(o), (int32_t)(o)->i)
|
||||
|
||||
/* Macros to set tagged values. */
|
||||
#if LJ_GC64
|
||||
#define setitype(o, i) ((o)->it = ((i) << 15))
|
||||
#define setnilV(o) ((o)->it64 = -1)
|
||||
#define setpriV(o, x) ((o)->it64 = (int64_t)~((uint64_t)~(x)<<47))
|
||||
#define setboolV(o, x) ((o)->it64 = (int64_t)~((uint64_t)((x)+1)<<47))
|
||||
#else
|
||||
#define setitype(o, i) ((o)->it = (i))
|
||||
#define setnilV(o) ((o)->it = LJ_TNIL)
|
||||
#define setboolV(o, x) ((o)->it = LJ_TFALSE-(uint32_t)(x))
|
||||
#define setpriV(o, i) (setitype((o), (i)))
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE void setlightudV(TValue *o, void *p)
|
||||
{
|
||||
#if LJ_GC64
|
||||
o->u64 = (uint64_t)p | (((uint64_t)LJ_TLIGHTUD) << 47);
|
||||
#elif LJ_64
|
||||
o->u64 = (uint64_t)p | (((uint64_t)0xffff) << 48);
|
||||
#else
|
||||
setgcrefp(o->gcr, p); setitype(o, LJ_TLIGHTUD);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
#define checklightudptr(L, p) \
|
||||
(((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p))
|
||||
#else
|
||||
#define checklightudptr(L, p) (p)
|
||||
#endif
|
||||
|
||||
#if LJ_FR2
|
||||
#define contptr(f) ((void *)(f))
|
||||
#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)contptr(f))
|
||||
#elif LJ_64
|
||||
#define contptr(f) \
|
||||
((void *)(uintptr_t)(uint32_t)((intptr_t)(f) - (intptr_t)lj_vm_asm_begin))
|
||||
#define setcont(o, f) \
|
||||
((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin)
|
||||
#else
|
||||
#define contptr(f) ((void *)(f))
|
||||
#define setcont(o, f) setlightudV((o), contptr(f))
|
||||
#endif
|
||||
|
||||
#define tvchecklive(L, o) \
|
||||
UNUSED(L), lua_assert(!tvisgcv(o) || \
|
||||
((~itype(o) == gcval(o)->gch.gct) && !isdead(G(L), gcval(o))))
|
||||
|
||||
static LJ_AINLINE void setgcVraw(TValue *o, GCobj *v, uint32_t itype)
|
||||
{
|
||||
#if LJ_GC64
|
||||
setgcreft(o->gcr, v, itype);
|
||||
#else
|
||||
setgcref(o->gcr, v); setitype(o, itype);
|
||||
#endif
|
||||
}
|
||||
|
||||
static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it)
|
||||
{
|
||||
setgcVraw(o, v, it); tvchecklive(L, o);
|
||||
}
|
||||
|
||||
#define define_setV(name, type, tag) \
|
||||
static LJ_AINLINE void name(lua_State *L, TValue *o, type *v) \
|
||||
{ \
|
||||
setgcV(L, o, obj2gco(v), tag); \
|
||||
}
|
||||
define_setV(setstrV, GCstr, LJ_TSTR)
|
||||
define_setV(setthreadV, lua_State, LJ_TTHREAD)
|
||||
define_setV(setprotoV, GCproto, LJ_TPROTO)
|
||||
define_setV(setfuncV, GCfunc, LJ_TFUNC)
|
||||
define_setV(setcdataV, GCcdata, LJ_TCDATA)
|
||||
define_setV(settabV, GCtab, LJ_TTAB)
|
||||
define_setV(setudataV, GCudata, LJ_TUDATA)
|
||||
|
||||
#define setnumV(o, x) ((o)->n = (x))
|
||||
#define setnanV(o) ((o)->u64 = U64x(fff80000,00000000))
|
||||
#define setpinfV(o) ((o)->u64 = U64x(7ff00000,00000000))
|
||||
#define setminfV(o) ((o)->u64 = U64x(fff00000,00000000))
|
||||
|
||||
static LJ_AINLINE void setintV(TValue *o, int32_t i)
|
||||
{
|
||||
#if LJ_DUALNUM
|
||||
o->i = (uint32_t)i; setitype(o, LJ_TISNUM);
|
||||
#else
|
||||
o->n = (lua_Number)i;
|
||||
#endif
|
||||
}
|
||||
|
||||
static LJ_AINLINE void setint64V(TValue *o, int64_t i)
|
||||
{
|
||||
if (LJ_DUALNUM && LJ_LIKELY(i == (int64_t)(int32_t)i))
|
||||
setintV(o, (int32_t)i);
|
||||
else
|
||||
setnumV(o, (lua_Number)i);
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
#define setintptrV(o, i) setint64V((o), (i))
|
||||
#else
|
||||
#define setintptrV(o, i) setintV((o), (i))
|
||||
#endif
|
||||
|
||||
/* Copy tagged values. */
|
||||
static LJ_AINLINE void copyTV(lua_State *L, TValue *o1, const TValue *o2)
|
||||
{
|
||||
*o1 = *o2; tvchecklive(L, o1);
|
||||
}
|
||||
|
||||
/* -- Number to integer conversion ---------------------------------------- */
|
||||
|
||||
#if LJ_SOFTFP
|
||||
LJ_ASMF int32_t lj_vm_tobit(double x);
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE int32_t lj_num2bit(lua_Number n)
|
||||
{
|
||||
#if LJ_SOFTFP
|
||||
return lj_vm_tobit(n);
|
||||
#else
|
||||
TValue o;
|
||||
o.n = n + 6755399441055744.0; /* 2^52 + 2^51 */
|
||||
return (int32_t)o.u32.lo;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define lj_num2int(n) ((int32_t)(n))
|
||||
|
||||
static LJ_AINLINE uint64_t lj_num2u64(lua_Number n)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
if (n >= 9223372036854775808.0) /* They think it's a feature. */
|
||||
return (uint64_t)(int64_t)(n - 18446744073709551616.0);
|
||||
else
|
||||
#endif
|
||||
return (uint64_t)n;
|
||||
}
|
||||
|
||||
static LJ_AINLINE int32_t numberVint(cTValue *o)
|
||||
{
|
||||
if (LJ_LIKELY(tvisint(o)))
|
||||
return intV(o);
|
||||
else
|
||||
return lj_num2int(numV(o));
|
||||
}
|
||||
|
||||
static LJ_AINLINE lua_Number numberVnum(cTValue *o)
|
||||
{
|
||||
if (LJ_UNLIKELY(tvisint(o)))
|
||||
return (lua_Number)intV(o);
|
||||
else
|
||||
return numV(o);
|
||||
}
|
||||
|
||||
/* -- Miscellaneous object handling --------------------------------------- */
|
||||
|
||||
/* Names and maps for internal and external object tags. */
|
||||
LJ_DATA const char *const lj_obj_typename[1+LUA_TCDATA+1];
|
||||
LJ_DATA const char *const lj_obj_itypename[~LJ_TNUMX+1];
|
||||
|
||||
#define lj_typename(o) (lj_obj_itypename[itypemap(o)])
|
||||
|
||||
/* Compare two objects without calling metamethods. */
|
||||
LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2);
|
||||
LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(cTValue *o);
|
||||
|
||||
#endif
|
||||
18
include/lua/lj_parse.h
Normal file
18
include/lua/lj_parse.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
** Lua parser (source code -> bytecode).
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_PARSE_H
|
||||
#define _LJ_PARSE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_lex.h"
|
||||
|
||||
LJ_FUNC GCproto *lj_parse(LexState *ls);
|
||||
LJ_FUNC GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t l);
|
||||
#if LJ_HASFFI
|
||||
LJ_FUNC void lj_parse_keepcdata(LexState *ls, TValue *tv, GCcdata *cd);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
21
include/lua/lj_profile.h
Normal file
21
include/lua/lj_profile.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
** Low-overhead profiling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_PROFILE_H
|
||||
#define _LJ_PROFILE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
#if LJ_HASPROFILE
|
||||
|
||||
LJ_FUNC void LJ_FASTCALL lj_profile_interpreter(lua_State *L);
|
||||
#if !LJ_PROFILE_SIGPROF
|
||||
LJ_FUNC void LJ_FASTCALL lj_profile_hook_enter(global_State *g);
|
||||
LJ_FUNC void LJ_FASTCALL lj_profile_hook_leave(global_State *g);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
271
include/lua/lj_recdef.h
Normal file
271
include/lua/lj_recdef.h
Normal file
@@ -0,0 +1,271 @@
|
||||
/* This is a generated file. DO NOT EDIT! */
|
||||
|
||||
static const uint16_t recff_idmap[] = {
|
||||
0,
|
||||
0x0100,
|
||||
0x0200,
|
||||
0x0300,
|
||||
0,
|
||||
0x0400+(0),
|
||||
0x0500,
|
||||
0x0400+(1),
|
||||
0x0600,
|
||||
0x0700,
|
||||
0x0800,
|
||||
0,
|
||||
0x0900,
|
||||
0x0a00,
|
||||
0x0b00,
|
||||
0,
|
||||
0x0c00,
|
||||
0x0d00,
|
||||
0x0e00,
|
||||
0,
|
||||
0x0f00,
|
||||
0x1000,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x1100,
|
||||
0x1200+(IRFPM_FLOOR),
|
||||
0x1200+(IRFPM_CEIL),
|
||||
0x1300+(IRFPM_SQRT),
|
||||
0x1300+(IRFPM_LOG10),
|
||||
0x1300+(IRFPM_EXP),
|
||||
0x1300+(IRFPM_SIN),
|
||||
0x1300+(IRFPM_COS),
|
||||
0x1300+(IRFPM_TAN),
|
||||
0x1400+(FF_math_asin),
|
||||
0x1400+(FF_math_acos),
|
||||
0x1400+(FF_math_atan),
|
||||
0x1500+(IRCALL_sinh),
|
||||
0x1500+(IRCALL_cosh),
|
||||
0x1500+(IRCALL_tanh),
|
||||
0,
|
||||
0x1600,
|
||||
0x1700,
|
||||
0x1800,
|
||||
0x1900,
|
||||
0,
|
||||
0x1a00,
|
||||
0x1b00+(IR_MIN),
|
||||
0x1b00+(IR_MAX),
|
||||
0x1c00,
|
||||
0,
|
||||
0x1d00,
|
||||
0x1e00+(IR_BNOT),
|
||||
0x1e00+(IR_BSWAP),
|
||||
0x1f00+(IR_BSHL),
|
||||
0x1f00+(IR_BSHR),
|
||||
0x1f00+(IR_BSAR),
|
||||
0x1f00+(IR_BROL),
|
||||
0x1f00+(IR_BROR),
|
||||
0x2000+(IR_BAND),
|
||||
0x2000+(IR_BOR),
|
||||
0x2000+(IR_BXOR),
|
||||
0x2100,
|
||||
0x2200+(0),
|
||||
0x2300,
|
||||
0x2200+(1),
|
||||
0x2400,
|
||||
0x2500+(IRCALL_lj_buf_putstr_reverse),
|
||||
0x2500+(IRCALL_lj_buf_putstr_lower),
|
||||
0x2500+(IRCALL_lj_buf_putstr_upper),
|
||||
0,
|
||||
0x2600,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x2700,
|
||||
0,
|
||||
0x2800,
|
||||
0x2900,
|
||||
0,
|
||||
0x2a00,
|
||||
0x2b00,
|
||||
0,
|
||||
0,
|
||||
0x2c00+(0),
|
||||
0x2d00+(0),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x2c00+(GCROOT_IO_OUTPUT),
|
||||
0x2d00+(GCROOT_IO_OUTPUT),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x2e00,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x2f00+(0),
|
||||
0x2f00+(1),
|
||||
0x3000+(MM_eq),
|
||||
0x3000+(MM_len),
|
||||
0x3000+(MM_lt),
|
||||
0x3000+(MM_le),
|
||||
0x3000+(MM_concat),
|
||||
0x3100,
|
||||
0x3000+(MM_add),
|
||||
0x3000+(MM_sub),
|
||||
0x3000+(MM_mul),
|
||||
0x3000+(MM_div),
|
||||
0x3000+(MM_mod),
|
||||
0x3000+(MM_pow),
|
||||
0x3000+(MM_unm),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x3200+(1),
|
||||
0x3200+(0),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x3300,
|
||||
0x3300,
|
||||
0x3400,
|
||||
0,
|
||||
0x3500,
|
||||
0x3600+(FF_ffi_sizeof),
|
||||
0x3600+(FF_ffi_alignof),
|
||||
0x3600+(FF_ffi_offsetof),
|
||||
0x3700,
|
||||
0x3800,
|
||||
0x3900,
|
||||
0x3a00,
|
||||
0x3b00,
|
||||
0,
|
||||
0x3c00
|
||||
};
|
||||
|
||||
static const RecordFunc recff_func[] = {
|
||||
recff_nyi,
|
||||
recff_c,
|
||||
recff_assert,
|
||||
recff_type,
|
||||
recff_xpairs,
|
||||
recff_ipairs_aux,
|
||||
recff_getmetatable,
|
||||
recff_setmetatable,
|
||||
recff_getfenv,
|
||||
recff_rawget,
|
||||
recff_rawset,
|
||||
recff_rawequal,
|
||||
recff_select,
|
||||
recff_tonumber,
|
||||
recff_tostring,
|
||||
recff_pcall,
|
||||
recff_xpcall,
|
||||
recff_math_abs,
|
||||
recff_math_round,
|
||||
recff_math_unary,
|
||||
recff_math_atrig,
|
||||
recff_math_htrig,
|
||||
recff_math_modf,
|
||||
recff_math_log,
|
||||
recff_math_atan2,
|
||||
recff_math_pow,
|
||||
recff_math_ldexp,
|
||||
recff_math_minmax,
|
||||
recff_math_random,
|
||||
recff_bit_tobit,
|
||||
recff_bit_unary,
|
||||
recff_bit_shift,
|
||||
recff_bit_nary,
|
||||
recff_bit_tohex,
|
||||
recff_string_range,
|
||||
recff_string_char,
|
||||
recff_string_rep,
|
||||
recff_string_op,
|
||||
recff_string_find,
|
||||
recff_string_format,
|
||||
recff_table_insert,
|
||||
recff_table_concat,
|
||||
recff_table_new,
|
||||
recff_table_clear,
|
||||
recff_io_write,
|
||||
recff_io_flush,
|
||||
recff_debug_getmetatable,
|
||||
recff_cdata_index,
|
||||
recff_cdata_arith,
|
||||
recff_cdata_call,
|
||||
recff_clib_index,
|
||||
recff_ffi_new,
|
||||
recff_ffi_typeof,
|
||||
recff_ffi_istype,
|
||||
recff_ffi_xof,
|
||||
recff_ffi_errno,
|
||||
recff_ffi_string,
|
||||
recff_ffi_copy,
|
||||
recff_ffi_fill,
|
||||
recff_ffi_abi,
|
||||
recff_ffi_gc
|
||||
};
|
||||
|
||||
45
include/lua/lj_record.h
Normal file
45
include/lua/lj_record.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
** Trace recorder (bytecode -> SSA IR).
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_RECORD_H
|
||||
#define _LJ_RECORD_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_jit.h"
|
||||
|
||||
#if LJ_HASJIT
|
||||
/* Context for recording an indexed load/store. */
|
||||
typedef struct RecordIndex {
|
||||
TValue tabv; /* Runtime value of table (or indexed object). */
|
||||
TValue keyv; /* Runtime value of key. */
|
||||
TValue valv; /* Runtime value of stored value. */
|
||||
TValue mobjv; /* Runtime value of metamethod object. */
|
||||
GCtab *mtv; /* Runtime value of metatable object. */
|
||||
cTValue *oldv; /* Runtime value of previously stored value. */
|
||||
TRef tab; /* Table (or indexed object) reference. */
|
||||
TRef key; /* Key reference. */
|
||||
TRef val; /* Value reference for a store or 0 for a load. */
|
||||
TRef mt; /* Metatable reference. */
|
||||
TRef mobj; /* Metamethod object reference. */
|
||||
int idxchain; /* Index indirections left or 0 for raw lookup. */
|
||||
} RecordIndex;
|
||||
|
||||
LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b,
|
||||
cTValue *av, cTValue *bv);
|
||||
LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk);
|
||||
LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o);
|
||||
|
||||
LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs);
|
||||
LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs);
|
||||
LJ_FUNC void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults);
|
||||
|
||||
LJ_FUNC int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm);
|
||||
LJ_FUNC TRef lj_record_idx(jit_State *J, RecordIndex *ix);
|
||||
|
||||
LJ_FUNC void lj_record_ins(jit_State *J);
|
||||
LJ_FUNC void lj_record_setup(jit_State *J);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
34
include/lua/lj_snap.h
Normal file
34
include/lua/lj_snap.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
** Snapshot handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_SNAP_H
|
||||
#define _LJ_SNAP_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_jit.h"
|
||||
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC void lj_snap_add(jit_State *J);
|
||||
LJ_FUNC void lj_snap_purge(jit_State *J);
|
||||
LJ_FUNC void lj_snap_shrink(jit_State *J);
|
||||
LJ_FUNC IRIns *lj_snap_regspmap(GCtrace *T, SnapNo snapno, IRIns *ir);
|
||||
LJ_FUNC void lj_snap_replay(jit_State *J, GCtrace *T);
|
||||
LJ_FUNC const BCIns *lj_snap_restore(jit_State *J, void *exptr);
|
||||
LJ_FUNC void lj_snap_grow_buf_(jit_State *J, MSize need);
|
||||
LJ_FUNC void lj_snap_grow_map_(jit_State *J, MSize need);
|
||||
|
||||
static LJ_AINLINE void lj_snap_grow_buf(jit_State *J, MSize need)
|
||||
{
|
||||
if (LJ_UNLIKELY(need > J->sizesnap)) lj_snap_grow_buf_(J, need);
|
||||
}
|
||||
|
||||
static LJ_AINLINE void lj_snap_grow_map(jit_State *J, MSize need)
|
||||
{
|
||||
if (LJ_UNLIKELY(need > J->sizesnapmap)) lj_snap_grow_map_(J, need);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
35
include/lua/lj_state.h
Normal file
35
include/lua/lj_state.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
** State and stack handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_STATE_H
|
||||
#define _LJ_STATE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
#define incr_top(L) \
|
||||
(++L->top >= tvref(L->maxstack) && (lj_state_growstack1(L), 0))
|
||||
|
||||
#define savestack(L, p) ((char *)(p) - mref(L->stack, char))
|
||||
#define restorestack(L, n) ((TValue *)(mref(L->stack, char) + (n)))
|
||||
|
||||
LJ_FUNC void lj_state_relimitstack(lua_State *L);
|
||||
LJ_FUNC void lj_state_shrinkstack(lua_State *L, MSize used);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need);
|
||||
LJ_FUNC void LJ_FASTCALL lj_state_growstack1(lua_State *L);
|
||||
|
||||
static LJ_AINLINE void lj_state_checkstack(lua_State *L, MSize need)
|
||||
{
|
||||
if ((mref(L->maxstack, char) - (char *)L->top) <=
|
||||
(ptrdiff_t)need*(ptrdiff_t)sizeof(TValue))
|
||||
lj_state_growstack(L, need);
|
||||
}
|
||||
|
||||
LJ_FUNC lua_State *lj_state_new(lua_State *L);
|
||||
LJ_FUNC void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L);
|
||||
#if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC))
|
||||
LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
27
include/lua/lj_str.h
Normal file
27
include/lua/lj_str.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
** String handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_STR_H
|
||||
#define _LJ_STR_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* String helpers. */
|
||||
LJ_FUNC int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b);
|
||||
LJ_FUNC const char *lj_str_find(const char *s, const char *f,
|
||||
MSize slen, MSize flen);
|
||||
LJ_FUNC int lj_str_haspattern(GCstr *s);
|
||||
|
||||
/* String interning. */
|
||||
LJ_FUNC void lj_str_resize(lua_State *L, MSize newmask);
|
||||
LJ_FUNCA GCstr *lj_str_new(lua_State *L, const char *str, size_t len);
|
||||
LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s);
|
||||
|
||||
#define lj_str_newz(L, s) (lj_str_new(L, s, strlen(s)))
|
||||
#define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1))
|
||||
|
||||
#endif
|
||||
125
include/lua/lj_strfmt.h
Normal file
125
include/lua/lj_strfmt.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
** String formatting.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_STRFMT_H
|
||||
#define _LJ_STRFMT_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
typedef uint32_t SFormat; /* Format indicator. */
|
||||
|
||||
/* Format parser state. */
|
||||
typedef struct FormatState {
|
||||
const uint8_t *p; /* Current format string pointer. */
|
||||
const uint8_t *e; /* End of format string. */
|
||||
const char *str; /* Returned literal string. */
|
||||
MSize len; /* Size of literal string. */
|
||||
} FormatState;
|
||||
|
||||
/* Format types (max. 16). */
|
||||
typedef enum FormatType {
|
||||
STRFMT_EOF, STRFMT_ERR, STRFMT_LIT,
|
||||
STRFMT_INT, STRFMT_UINT, STRFMT_NUM, STRFMT_STR, STRFMT_CHAR, STRFMT_PTR
|
||||
} FormatType;
|
||||
|
||||
/* Format subtypes (bits are reused). */
|
||||
#define STRFMT_T_HEX 0x0010 /* STRFMT_UINT */
|
||||
#define STRFMT_T_OCT 0x0020 /* STRFMT_UINT */
|
||||
#define STRFMT_T_FP_A 0x0000 /* STRFMT_NUM */
|
||||
#define STRFMT_T_FP_E 0x0010 /* STRFMT_NUM */
|
||||
#define STRFMT_T_FP_F 0x0020 /* STRFMT_NUM */
|
||||
#define STRFMT_T_FP_G 0x0030 /* STRFMT_NUM */
|
||||
#define STRFMT_T_QUOTED 0x0010 /* STRFMT_STR */
|
||||
|
||||
/* Format flags. */
|
||||
#define STRFMT_F_LEFT 0x0100
|
||||
#define STRFMT_F_PLUS 0x0200
|
||||
#define STRFMT_F_ZERO 0x0400
|
||||
#define STRFMT_F_SPACE 0x0800
|
||||
#define STRFMT_F_ALT 0x1000
|
||||
#define STRFMT_F_UPPER 0x2000
|
||||
|
||||
/* Format indicator fields. */
|
||||
#define STRFMT_SH_WIDTH 16
|
||||
#define STRFMT_SH_PREC 24
|
||||
|
||||
#define STRFMT_TYPE(sf) ((FormatType)((sf) & 15))
|
||||
#define STRFMT_WIDTH(sf) (((sf) >> STRFMT_SH_WIDTH) & 255u)
|
||||
#define STRFMT_PREC(sf) ((((sf) >> STRFMT_SH_PREC) & 255u) - 1u)
|
||||
#define STRFMT_FP(sf) (((sf) >> 4) & 3)
|
||||
|
||||
/* Formats for conversion characters. */
|
||||
#define STRFMT_A (STRFMT_NUM|STRFMT_T_FP_A)
|
||||
#define STRFMT_C (STRFMT_CHAR)
|
||||
#define STRFMT_D (STRFMT_INT)
|
||||
#define STRFMT_E (STRFMT_NUM|STRFMT_T_FP_E)
|
||||
#define STRFMT_F (STRFMT_NUM|STRFMT_T_FP_F)
|
||||
#define STRFMT_G (STRFMT_NUM|STRFMT_T_FP_G)
|
||||
#define STRFMT_I STRFMT_D
|
||||
#define STRFMT_O (STRFMT_UINT|STRFMT_T_OCT)
|
||||
#define STRFMT_P (STRFMT_PTR)
|
||||
#define STRFMT_Q (STRFMT_STR|STRFMT_T_QUOTED)
|
||||
#define STRFMT_S (STRFMT_STR)
|
||||
#define STRFMT_U (STRFMT_UINT)
|
||||
#define STRFMT_X (STRFMT_UINT|STRFMT_T_HEX)
|
||||
#define STRFMT_G14 (STRFMT_G | ((14+1) << STRFMT_SH_PREC))
|
||||
|
||||
/* Maximum buffer sizes for conversions. */
|
||||
#define STRFMT_MAXBUF_XINT (1+22) /* '0' prefix + uint64_t in octal. */
|
||||
#define STRFMT_MAXBUF_INT (1+10) /* Sign + int32_t in decimal. */
|
||||
#define STRFMT_MAXBUF_NUM 32 /* Must correspond with STRFMT_G14. */
|
||||
#define STRFMT_MAXBUF_PTR (2+2*sizeof(ptrdiff_t)) /* "0x" + hex ptr. */
|
||||
|
||||
/* Format parser. */
|
||||
LJ_FUNC SFormat LJ_FASTCALL lj_strfmt_parse(FormatState *fs);
|
||||
|
||||
static LJ_AINLINE void lj_strfmt_init(FormatState *fs, const char *p, MSize len)
|
||||
{
|
||||
fs->p = (const uint8_t *)p;
|
||||
fs->e = (const uint8_t *)p + len;
|
||||
lua_assert(*fs->e == 0); /* Must be NUL-terminated (may have NULs inside). */
|
||||
}
|
||||
|
||||
/* Raw conversions. */
|
||||
LJ_FUNC char * LJ_FASTCALL lj_strfmt_wint(char *p, int32_t k);
|
||||
LJ_FUNC char * LJ_FASTCALL lj_strfmt_wptr(char *p, const void *v);
|
||||
LJ_FUNC char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v);
|
||||
LJ_FUNC const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp);
|
||||
|
||||
/* Unformatted conversions to buffer. */
|
||||
LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o);
|
||||
#endif
|
||||
LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putptr(SBuf *sb, const void *v);
|
||||
LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str);
|
||||
|
||||
/* Formatted conversions to buffer. */
|
||||
LJ_FUNC SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k);
|
||||
LJ_FUNC SBuf *lj_strfmt_putfnum_int(SBuf *sb, SFormat sf, lua_Number n);
|
||||
LJ_FUNC SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n);
|
||||
LJ_FUNC SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat, lua_Number n);
|
||||
LJ_FUNC SBuf *lj_strfmt_putfchar(SBuf *sb, SFormat, int32_t c);
|
||||
LJ_FUNC SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat, GCstr *str);
|
||||
|
||||
/* Conversions to strings. */
|
||||
LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_int(lua_State *L, int32_t k);
|
||||
LJ_FUNCA GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o);
|
||||
LJ_FUNCA GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_char(lua_State *L, int c);
|
||||
#endif
|
||||
LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_obj(lua_State *L, cTValue *o);
|
||||
|
||||
/* Internal string formatting. */
|
||||
LJ_FUNC const char *lj_strfmt_pushvf(lua_State *L, const char *fmt,
|
||||
va_list argp);
|
||||
LJ_FUNC const char *lj_strfmt_pushf(lua_State *L, const char *fmt, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif
|
||||
39
include/lua/lj_strscan.h
Normal file
39
include/lua/lj_strscan.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
** String scanning.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_STRSCAN_H
|
||||
#define _LJ_STRSCAN_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Options for accepted/returned formats. */
|
||||
#define STRSCAN_OPT_TOINT 0x01 /* Convert to int32_t, if possible. */
|
||||
#define STRSCAN_OPT_TONUM 0x02 /* Always convert to double. */
|
||||
#define STRSCAN_OPT_IMAG 0x04
|
||||
#define STRSCAN_OPT_LL 0x08
|
||||
#define STRSCAN_OPT_C 0x10
|
||||
|
||||
/* Returned format. */
|
||||
typedef enum {
|
||||
STRSCAN_ERROR,
|
||||
STRSCAN_NUM, STRSCAN_IMAG,
|
||||
STRSCAN_INT, STRSCAN_U32, STRSCAN_I64, STRSCAN_U64,
|
||||
} StrScanFmt;
|
||||
|
||||
LJ_FUNC StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt);
|
||||
LJ_FUNC int LJ_FASTCALL lj_strscan_num(GCstr *str, TValue *o);
|
||||
#if LJ_DUALNUM
|
||||
LJ_FUNC int LJ_FASTCALL lj_strscan_number(GCstr *str, TValue *o);
|
||||
#else
|
||||
#define lj_strscan_number(s, o) lj_strscan_num((s), (o))
|
||||
#endif
|
||||
|
||||
/* Check for number or convert string to number/int in-place (!). */
|
||||
static LJ_AINLINE int lj_strscan_numberobj(TValue *o)
|
||||
{
|
||||
return tvisnumber(o) || (tvisstr(o) && lj_strscan_number(strV(o), o));
|
||||
}
|
||||
|
||||
#endif
|
||||
73
include/lua/lj_tab.h
Normal file
73
include/lua/lj_tab.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
** Table handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TAB_H
|
||||
#define _LJ_TAB_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Hash constants. Tuned using a brute force search. */
|
||||
#define HASH_BIAS (-0x04c11db7)
|
||||
#define HASH_ROT1 14
|
||||
#define HASH_ROT2 5
|
||||
#define HASH_ROT3 13
|
||||
|
||||
/* Scramble the bits of numbers and pointers. */
|
||||
static LJ_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi)
|
||||
{
|
||||
#if LJ_TARGET_X86ORX64
|
||||
/* Prefer variant that compiles well for a 2-operand CPU. */
|
||||
lo ^= hi; hi = lj_rol(hi, HASH_ROT1);
|
||||
lo -= hi; hi = lj_rol(hi, HASH_ROT2);
|
||||
hi ^= lo; hi -= lj_rol(lo, HASH_ROT3);
|
||||
#else
|
||||
lo ^= hi;
|
||||
lo = lo - lj_rol(hi, HASH_ROT1);
|
||||
hi = lo ^ lj_rol(hi, HASH_ROT1 + HASH_ROT2);
|
||||
hi = hi - lj_rol(lo, HASH_ROT3);
|
||||
#endif
|
||||
return hi;
|
||||
}
|
||||
|
||||
#define hsize2hbits(s) ((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0)
|
||||
|
||||
LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits);
|
||||
LJ_FUNC GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h);
|
||||
#if LJ_HASJIT
|
||||
LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize);
|
||||
#endif
|
||||
LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt);
|
||||
LJ_FUNC void LJ_FASTCALL lj_tab_clear(GCtab *t);
|
||||
LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t);
|
||||
#if LJ_HASFFI
|
||||
LJ_FUNC void lj_tab_rehash(lua_State *L, GCtab *t);
|
||||
#endif
|
||||
LJ_FUNC void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits);
|
||||
LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize);
|
||||
|
||||
/* Caveat: all getters except lj_tab_get() can return NULL! */
|
||||
|
||||
LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key);
|
||||
LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, GCstr *key);
|
||||
LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key);
|
||||
|
||||
/* Caveat: all setters require a write barrier for the stored value. */
|
||||
|
||||
LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key);
|
||||
LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key);
|
||||
LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key);
|
||||
LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key);
|
||||
|
||||
#define inarray(t, key) ((MSize)(key) < (MSize)(t)->asize)
|
||||
#define arrayslot(t, i) (&tvref((t)->array)[(i)])
|
||||
#define lj_tab_getint(t, key) \
|
||||
(inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_getinth((t), (key)))
|
||||
#define lj_tab_setint(L, t, key) \
|
||||
(inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_setinth(L, (t), (key)))
|
||||
|
||||
LJ_FUNCA int lj_tab_next(lua_State *L, GCtab *t, TValue *key);
|
||||
LJ_FUNCA MSize LJ_FASTCALL lj_tab_len(GCtab *t);
|
||||
|
||||
#endif
|
||||
164
include/lua/lj_target.h
Normal file
164
include/lua/lj_target.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
** Definitions for target CPU.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TARGET_H
|
||||
#define _LJ_TARGET_H
|
||||
|
||||
#include "lj_def.h"
|
||||
#include "lj_arch.h"
|
||||
|
||||
/* -- Registers and spill slots ------------------------------------------- */
|
||||
|
||||
/* Register type (uint8_t in ir->r). */
|
||||
typedef uint32_t Reg;
|
||||
|
||||
/* The hi-bit is NOT set for an allocated register. This means the value
|
||||
** can be directly used without masking. The hi-bit is set for a register
|
||||
** allocation hint or for RID_INIT, RID_SINK or RID_SUNK.
|
||||
*/
|
||||
#define RID_NONE 0x80
|
||||
#define RID_MASK 0x7f
|
||||
#define RID_INIT (RID_NONE|RID_MASK)
|
||||
#define RID_SINK (RID_INIT-1)
|
||||
#define RID_SUNK (RID_INIT-2)
|
||||
|
||||
#define ra_noreg(r) ((r) & RID_NONE)
|
||||
#define ra_hasreg(r) (!((r) & RID_NONE))
|
||||
|
||||
/* The ra_hashint() macro assumes a previous test for ra_noreg(). */
|
||||
#define ra_hashint(r) ((r) < RID_SUNK)
|
||||
#define ra_gethint(r) ((Reg)((r) & RID_MASK))
|
||||
#define ra_sethint(rr, r) rr = (uint8_t)((r)|RID_NONE)
|
||||
#define ra_samehint(r1, r2) (ra_gethint((r1)^(r2)) == 0)
|
||||
|
||||
/* Spill slot 0 means no spill slot has been allocated. */
|
||||
#define SPS_NONE 0
|
||||
|
||||
#define ra_hasspill(s) ((s) != SPS_NONE)
|
||||
|
||||
/* Combined register and spill slot (uint16_t in ir->prev). */
|
||||
typedef uint32_t RegSP;
|
||||
|
||||
#define REGSP(r, s) ((r) + ((s) << 8))
|
||||
#define REGSP_HINT(r) ((r)|RID_NONE)
|
||||
#define REGSP_INIT REGSP(RID_INIT, 0)
|
||||
|
||||
#define regsp_reg(rs) ((rs) & 255)
|
||||
#define regsp_spill(rs) ((rs) >> 8)
|
||||
#define regsp_used(rs) \
|
||||
(((rs) & ~REGSP(RID_MASK, 0)) != REGSP(RID_NONE, 0))
|
||||
|
||||
/* -- Register sets ------------------------------------------------------- */
|
||||
|
||||
/* Bitset for registers. 32 registers suffice for most architectures.
|
||||
** Note that one set holds bits for both GPRs and FPRs.
|
||||
*/
|
||||
#if LJ_TARGET_PPC || LJ_TARGET_MIPS || LJ_TARGET_ARM64
|
||||
typedef uint64_t RegSet;
|
||||
#else
|
||||
typedef uint32_t RegSet;
|
||||
#endif
|
||||
|
||||
#define RID2RSET(r) (((RegSet)1) << (r))
|
||||
#define RSET_EMPTY ((RegSet)0)
|
||||
#define RSET_RANGE(lo, hi) ((RID2RSET((hi)-(lo))-1) << (lo))
|
||||
|
||||
#define rset_test(rs, r) ((int)((rs) >> (r)) & 1)
|
||||
#define rset_set(rs, r) (rs |= RID2RSET(r))
|
||||
#define rset_clear(rs, r) (rs &= ~RID2RSET(r))
|
||||
#define rset_exclude(rs, r) (rs & ~RID2RSET(r))
|
||||
#if LJ_TARGET_PPC || LJ_TARGET_MIPS || LJ_TARGET_ARM64
|
||||
#define rset_picktop(rs) ((Reg)(__builtin_clzll(rs)^63))
|
||||
#define rset_pickbot(rs) ((Reg)__builtin_ctzll(rs))
|
||||
#else
|
||||
#define rset_picktop(rs) ((Reg)lj_fls(rs))
|
||||
#define rset_pickbot(rs) ((Reg)lj_ffs(rs))
|
||||
#endif
|
||||
|
||||
/* -- Register allocation cost -------------------------------------------- */
|
||||
|
||||
/* The register allocation heuristic keeps track of the cost for allocating
|
||||
** a specific register:
|
||||
**
|
||||
** A free register (obviously) has a cost of 0 and a 1-bit in the free mask.
|
||||
**
|
||||
** An already allocated register has the (non-zero) IR reference in the lowest
|
||||
** bits and the result of a blended cost-model in the higher bits.
|
||||
**
|
||||
** The allocator first checks the free mask for a hit. Otherwise an (unrolled)
|
||||
** linear search for the minimum cost is used. The search doesn't need to
|
||||
** keep track of the position of the minimum, which makes it very fast.
|
||||
** The lowest bits of the minimum cost show the desired IR reference whose
|
||||
** register is the one to evict.
|
||||
**
|
||||
** Without the cost-model this degenerates to the standard heuristics for
|
||||
** (reverse) linear-scan register allocation. Since code generation is done
|
||||
** in reverse, a live interval extends from the last use to the first def.
|
||||
** For an SSA IR the IR reference is the first (and only) def and thus
|
||||
** trivially marks the end of the interval. The LSRA heuristics says to pick
|
||||
** the register whose live interval has the furthest extent, i.e. the lowest
|
||||
** IR reference in our case.
|
||||
**
|
||||
** A cost-model should take into account other factors, like spill-cost and
|
||||
** restore- or rematerialization-cost, which depend on the kind of instruction.
|
||||
** E.g. constants have zero spill costs, variant instructions have higher
|
||||
** costs than invariants and PHIs should preferably never be spilled.
|
||||
**
|
||||
** Here's a first cut at simple, but effective blended cost-model for R-LSRA:
|
||||
** - Due to careful design of the IR, constants already have lower IR
|
||||
** references than invariants and invariants have lower IR references
|
||||
** than variants.
|
||||
** - The cost in the upper 16 bits is the sum of the IR reference and a
|
||||
** weighted score. The score currently only takes into account whether
|
||||
** the IRT_ISPHI bit is set in the instruction type.
|
||||
** - The PHI weight is the minimum distance (in IR instructions) a PHI
|
||||
** reference has to be further apart from a non-PHI reference to be spilled.
|
||||
** - It should be a power of two (for speed) and must be between 2 and 32768.
|
||||
** Good values for the PHI weight seem to be between 40 and 150.
|
||||
** - Further study is required.
|
||||
*/
|
||||
#define REGCOST_PHI_WEIGHT 64
|
||||
|
||||
/* Cost for allocating a specific register. */
|
||||
typedef uint32_t RegCost;
|
||||
|
||||
/* Note: assumes 16 bit IRRef1. */
|
||||
#define REGCOST(cost, ref) ((RegCost)(ref) + ((RegCost)(cost) << 16))
|
||||
#define regcost_ref(rc) ((IRRef1)(rc))
|
||||
|
||||
#define REGCOST_T(t) \
|
||||
((RegCost)((t)&IRT_ISPHI) * (((RegCost)(REGCOST_PHI_WEIGHT)<<16)/IRT_ISPHI))
|
||||
#define REGCOST_REF_T(ref, t) (REGCOST((ref), (ref)) + REGCOST_T((t)))
|
||||
|
||||
/* -- Target-specific definitions ----------------------------------------- */
|
||||
|
||||
#if LJ_TARGET_X86ORX64
|
||||
#include "lj_target_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "lj_target_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "lj_target_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "lj_target_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
#include "lj_target_mips.h"
|
||||
#else
|
||||
#error "Missing include for target CPU"
|
||||
#endif
|
||||
|
||||
#ifdef EXITSTUBS_PER_GROUP
|
||||
/* Return the address of an exit stub. */
|
||||
static LJ_AINLINE char *exitstub_addr_(char **group, uint32_t exitno)
|
||||
{
|
||||
lua_assert(group[exitno / EXITSTUBS_PER_GROUP] != NULL);
|
||||
return (char *)group[exitno / EXITSTUBS_PER_GROUP] +
|
||||
EXITSTUB_SPACING*(exitno % EXITSTUBS_PER_GROUP);
|
||||
}
|
||||
/* Avoid dependence on lj_jit.h if only including lj_target.h. */
|
||||
#define exitstub_addr(J, exitno) \
|
||||
((MCode *)exitstub_addr_((char **)((J)->exitstubgroup), (exitno)))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
270
include/lua/lj_target_arm.h
Normal file
270
include/lua/lj_target_arm.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
** Definitions for ARM CPUs.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TARGET_ARM_H
|
||||
#define _LJ_TARGET_ARM_H
|
||||
|
||||
/* -- Registers IDs ------------------------------------------------------- */
|
||||
|
||||
#define GPRDEF(_) \
|
||||
_(R0) _(R1) _(R2) _(R3) _(R4) _(R5) _(R6) _(R7) \
|
||||
_(R8) _(R9) _(R10) _(R11) _(R12) _(SP) _(LR) _(PC)
|
||||
#if LJ_SOFTFP
|
||||
#define FPRDEF(_)
|
||||
#else
|
||||
#define FPRDEF(_) \
|
||||
_(D0) _(D1) _(D2) _(D3) _(D4) _(D5) _(D6) _(D7) \
|
||||
_(D8) _(D9) _(D10) _(D11) _(D12) _(D13) _(D14) _(D15)
|
||||
#endif
|
||||
#define VRIDDEF(_)
|
||||
|
||||
#define RIDENUM(name) RID_##name,
|
||||
|
||||
enum {
|
||||
GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */
|
||||
FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */
|
||||
RID_MAX,
|
||||
RID_TMP = RID_LR,
|
||||
|
||||
/* Calling conventions. */
|
||||
RID_RET = RID_R0,
|
||||
RID_RETLO = RID_R0,
|
||||
RID_RETHI = RID_R1,
|
||||
#if LJ_SOFTFP
|
||||
RID_FPRET = RID_R0,
|
||||
#else
|
||||
RID_FPRET = RID_D0,
|
||||
#endif
|
||||
|
||||
/* These definitions must match with the *.dasc file(s): */
|
||||
RID_BASE = RID_R9, /* Interpreter BASE. */
|
||||
RID_LPC = RID_R6, /* Interpreter PC. */
|
||||
RID_DISPATCH = RID_R7, /* Interpreter DISPATCH table. */
|
||||
RID_LREG = RID_R8, /* Interpreter L. */
|
||||
|
||||
/* Register ranges [min, max) and number of registers. */
|
||||
RID_MIN_GPR = RID_R0,
|
||||
RID_MAX_GPR = RID_PC+1,
|
||||
RID_MIN_FPR = RID_MAX_GPR,
|
||||
#if LJ_SOFTFP
|
||||
RID_MAX_FPR = RID_MIN_FPR,
|
||||
#else
|
||||
RID_MAX_FPR = RID_D15+1,
|
||||
#endif
|
||||
RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR,
|
||||
RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR
|
||||
};
|
||||
|
||||
#define RID_NUM_KREF RID_NUM_GPR
|
||||
#define RID_MIN_KREF RID_R0
|
||||
|
||||
/* -- Register sets ------------------------------------------------------- */
|
||||
|
||||
/* Make use of all registers, except sp, lr and pc. */
|
||||
#define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_R12+1))
|
||||
#define RSET_GPREVEN \
|
||||
(RID2RSET(RID_R0)|RID2RSET(RID_R2)|RID2RSET(RID_R4)|RID2RSET(RID_R6)| \
|
||||
RID2RSET(RID_R8)|RID2RSET(RID_R10))
|
||||
#define RSET_GPRODD \
|
||||
(RID2RSET(RID_R1)|RID2RSET(RID_R3)|RID2RSET(RID_R5)|RID2RSET(RID_R7)| \
|
||||
RID2RSET(RID_R9)|RID2RSET(RID_R11))
|
||||
#if LJ_SOFTFP
|
||||
#define RSET_FPR 0
|
||||
#else
|
||||
#define RSET_FPR (RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR))
|
||||
#endif
|
||||
#define RSET_ALL (RSET_GPR|RSET_FPR)
|
||||
#define RSET_INIT RSET_ALL
|
||||
|
||||
/* ABI-specific register sets. lr is an implicit scratch register. */
|
||||
#define RSET_SCRATCH_GPR_ (RSET_RANGE(RID_R0, RID_R3+1)|RID2RSET(RID_R12))
|
||||
#ifdef __APPLE__
|
||||
#define RSET_SCRATCH_GPR (RSET_SCRATCH_GPR_|RID2RSET(RID_R9))
|
||||
#else
|
||||
#define RSET_SCRATCH_GPR RSET_SCRATCH_GPR_
|
||||
#endif
|
||||
#if LJ_SOFTFP
|
||||
#define RSET_SCRATCH_FPR 0
|
||||
#else
|
||||
#define RSET_SCRATCH_FPR (RSET_RANGE(RID_D0, RID_D7+1))
|
||||
#endif
|
||||
#define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR)
|
||||
#define REGARG_FIRSTGPR RID_R0
|
||||
#define REGARG_LASTGPR RID_R3
|
||||
#define REGARG_NUMGPR 4
|
||||
#if LJ_ABI_SOFTFP
|
||||
#define REGARG_FIRSTFPR 0
|
||||
#define REGARG_LASTFPR 0
|
||||
#define REGARG_NUMFPR 0
|
||||
#else
|
||||
#define REGARG_FIRSTFPR RID_D0
|
||||
#define REGARG_LASTFPR RID_D7
|
||||
#define REGARG_NUMFPR 8
|
||||
#endif
|
||||
|
||||
/* -- Spill slots --------------------------------------------------------- */
|
||||
|
||||
/* Spill slots are 32 bit wide. An even/odd pair is used for FPRs.
|
||||
**
|
||||
** SPS_FIXED: Available fixed spill slots in interpreter frame.
|
||||
** This definition must match with the *.dasc file(s).
|
||||
**
|
||||
** SPS_FIRST: First spill slot for general use. Reserve min. two 32 bit slots.
|
||||
*/
|
||||
#define SPS_FIXED 2
|
||||
#define SPS_FIRST 2
|
||||
|
||||
#define SPOFS_TMP 0
|
||||
|
||||
#define sps_scale(slot) (4 * (int32_t)(slot))
|
||||
#define sps_align(slot) (((slot) - SPS_FIXED + 1) & ~1)
|
||||
|
||||
/* -- Exit state ---------------------------------------------------------- */
|
||||
|
||||
/* This definition must match with the *.dasc file(s). */
|
||||
typedef struct {
|
||||
#if !LJ_SOFTFP
|
||||
lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */
|
||||
#endif
|
||||
int32_t gpr[RID_NUM_GPR]; /* General-purpose registers. */
|
||||
int32_t spill[256]; /* Spill slots. */
|
||||
} ExitState;
|
||||
|
||||
/* PC after instruction that caused an exit. Used to find the trace number. */
|
||||
#define EXITSTATE_PCREG RID_PC
|
||||
/* Highest exit + 1 indicates stack check. */
|
||||
#define EXITSTATE_CHECKEXIT 1
|
||||
|
||||
#define EXITSTUB_SPACING 4
|
||||
#define EXITSTUBS_PER_GROUP 32
|
||||
|
||||
/* -- Instructions -------------------------------------------------------- */
|
||||
|
||||
/* Instruction fields. */
|
||||
#define ARMF_CC(ai, cc) (((ai) ^ ARMI_CCAL) | ((cc) << 28))
|
||||
#define ARMF_N(r) ((r) << 16)
|
||||
#define ARMF_D(r) ((r) << 12)
|
||||
#define ARMF_S(r) ((r) << 8)
|
||||
#define ARMF_M(r) (r)
|
||||
#define ARMF_SH(sh, n) (((sh) << 5) | ((n) << 7))
|
||||
#define ARMF_RSH(sh, r) (0x10 | ((sh) << 5) | ARMF_S(r))
|
||||
|
||||
typedef enum ARMIns {
|
||||
ARMI_CCAL = 0xe0000000,
|
||||
ARMI_S = 0x000100000,
|
||||
ARMI_K12 = 0x02000000,
|
||||
ARMI_KNEG = 0x00200000,
|
||||
ARMI_LS_W = 0x00200000,
|
||||
ARMI_LS_U = 0x00800000,
|
||||
ARMI_LS_P = 0x01000000,
|
||||
ARMI_LS_R = 0x02000000,
|
||||
ARMI_LSX_I = 0x00400000,
|
||||
|
||||
ARMI_AND = 0xe0000000,
|
||||
ARMI_EOR = 0xe0200000,
|
||||
ARMI_SUB = 0xe0400000,
|
||||
ARMI_RSB = 0xe0600000,
|
||||
ARMI_ADD = 0xe0800000,
|
||||
ARMI_ADC = 0xe0a00000,
|
||||
ARMI_SBC = 0xe0c00000,
|
||||
ARMI_RSC = 0xe0e00000,
|
||||
ARMI_TST = 0xe1100000,
|
||||
ARMI_TEQ = 0xe1300000,
|
||||
ARMI_CMP = 0xe1500000,
|
||||
ARMI_CMN = 0xe1700000,
|
||||
ARMI_ORR = 0xe1800000,
|
||||
ARMI_MOV = 0xe1a00000,
|
||||
ARMI_BIC = 0xe1c00000,
|
||||
ARMI_MVN = 0xe1e00000,
|
||||
|
||||
ARMI_NOP = 0xe1a00000,
|
||||
|
||||
ARMI_MUL = 0xe0000090,
|
||||
ARMI_SMULL = 0xe0c00090,
|
||||
|
||||
ARMI_LDR = 0xe4100000,
|
||||
ARMI_LDRB = 0xe4500000,
|
||||
ARMI_LDRH = 0xe01000b0,
|
||||
ARMI_LDRSB = 0xe01000d0,
|
||||
ARMI_LDRSH = 0xe01000f0,
|
||||
ARMI_LDRD = 0xe00000d0,
|
||||
ARMI_STR = 0xe4000000,
|
||||
ARMI_STRB = 0xe4400000,
|
||||
ARMI_STRH = 0xe00000b0,
|
||||
ARMI_STRD = 0xe00000f0,
|
||||
ARMI_PUSH = 0xe92d0000,
|
||||
|
||||
ARMI_B = 0xea000000,
|
||||
ARMI_BL = 0xeb000000,
|
||||
ARMI_BLX = 0xfa000000,
|
||||
ARMI_BLXr = 0xe12fff30,
|
||||
|
||||
/* ARMv6 */
|
||||
ARMI_REV = 0xe6bf0f30,
|
||||
ARMI_SXTB = 0xe6af0070,
|
||||
ARMI_SXTH = 0xe6bf0070,
|
||||
ARMI_UXTB = 0xe6ef0070,
|
||||
ARMI_UXTH = 0xe6ff0070,
|
||||
|
||||
/* ARMv6T2 */
|
||||
ARMI_MOVW = 0xe3000000,
|
||||
ARMI_MOVT = 0xe3400000,
|
||||
|
||||
/* VFP */
|
||||
ARMI_VMOV_D = 0xeeb00b40,
|
||||
ARMI_VMOV_S = 0xeeb00a40,
|
||||
ARMI_VMOVI_D = 0xeeb00b00,
|
||||
|
||||
ARMI_VMOV_R_S = 0xee100a10,
|
||||
ARMI_VMOV_S_R = 0xee000a10,
|
||||
ARMI_VMOV_RR_D = 0xec500b10,
|
||||
ARMI_VMOV_D_RR = 0xec400b10,
|
||||
|
||||
ARMI_VADD_D = 0xee300b00,
|
||||
ARMI_VSUB_D = 0xee300b40,
|
||||
ARMI_VMUL_D = 0xee200b00,
|
||||
ARMI_VMLA_D = 0xee000b00,
|
||||
ARMI_VMLS_D = 0xee000b40,
|
||||
ARMI_VNMLS_D = 0xee100b00,
|
||||
ARMI_VDIV_D = 0xee800b00,
|
||||
|
||||
ARMI_VABS_D = 0xeeb00bc0,
|
||||
ARMI_VNEG_D = 0xeeb10b40,
|
||||
ARMI_VSQRT_D = 0xeeb10bc0,
|
||||
|
||||
ARMI_VCMP_D = 0xeeb40b40,
|
||||
ARMI_VCMPZ_D = 0xeeb50b40,
|
||||
|
||||
ARMI_VMRS = 0xeef1fa10,
|
||||
|
||||
ARMI_VCVT_S32_F32 = 0xeebd0ac0,
|
||||
ARMI_VCVT_S32_F64 = 0xeebd0bc0,
|
||||
ARMI_VCVT_U32_F32 = 0xeebc0ac0,
|
||||
ARMI_VCVT_U32_F64 = 0xeebc0bc0,
|
||||
ARMI_VCVT_F32_S32 = 0xeeb80ac0,
|
||||
ARMI_VCVT_F64_S32 = 0xeeb80bc0,
|
||||
ARMI_VCVT_F32_U32 = 0xeeb80a40,
|
||||
ARMI_VCVT_F64_U32 = 0xeeb80b40,
|
||||
ARMI_VCVT_F32_F64 = 0xeeb70bc0,
|
||||
ARMI_VCVT_F64_F32 = 0xeeb70ac0,
|
||||
|
||||
ARMI_VLDR_S = 0xed100a00,
|
||||
ARMI_VLDR_D = 0xed100b00,
|
||||
ARMI_VSTR_S = 0xed000a00,
|
||||
ARMI_VSTR_D = 0xed000b00,
|
||||
} ARMIns;
|
||||
|
||||
typedef enum ARMShift {
|
||||
ARMSH_LSL, ARMSH_LSR, ARMSH_ASR, ARMSH_ROR
|
||||
} ARMShift;
|
||||
|
||||
/* ARM condition codes. */
|
||||
typedef enum ARMCC {
|
||||
CC_EQ, CC_NE, CC_CS, CC_CC, CC_MI, CC_PL, CC_VS, CC_VC,
|
||||
CC_HI, CC_LS, CC_GE, CC_LT, CC_GT, CC_LE, CC_AL,
|
||||
CC_HS = CC_CS, CC_LO = CC_CC
|
||||
} ARMCC;
|
||||
|
||||
#endif
|
||||
329
include/lua/lj_target_arm64.h
Normal file
329
include/lua/lj_target_arm64.h
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
** Definitions for ARM64 CPUs.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TARGET_ARM64_H
|
||||
#define _LJ_TARGET_ARM64_H
|
||||
|
||||
/* -- Registers IDs ------------------------------------------------------- */
|
||||
|
||||
#define GPRDEF(_) \
|
||||
_(X0) _(X1) _(X2) _(X3) _(X4) _(X5) _(X6) _(X7) \
|
||||
_(X8) _(X9) _(X10) _(X11) _(X12) _(X13) _(X14) _(X15) \
|
||||
_(X16) _(X17) _(X18) _(X19) _(X20) _(X21) _(X22) _(X23) \
|
||||
_(X24) _(X25) _(X26) _(X27) _(X28) _(FP) _(LR) _(SP)
|
||||
#define FPRDEF(_) \
|
||||
_(D0) _(D1) _(D2) _(D3) _(D4) _(D5) _(D6) _(D7) \
|
||||
_(D8) _(D9) _(D10) _(D11) _(D12) _(D13) _(D14) _(D15) \
|
||||
_(D16) _(D17) _(D18) _(D19) _(D20) _(D21) _(D22) _(D23) \
|
||||
_(D24) _(D25) _(D26) _(D27) _(D28) _(D29) _(D30) _(D31)
|
||||
#define VRIDDEF(_)
|
||||
|
||||
#define RIDENUM(name) RID_##name,
|
||||
|
||||
enum {
|
||||
GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */
|
||||
FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */
|
||||
RID_MAX,
|
||||
RID_TMP = RID_LR,
|
||||
RID_ZERO = RID_SP,
|
||||
|
||||
/* Calling conventions. */
|
||||
RID_RET = RID_X0,
|
||||
RID_FPRET = RID_D0,
|
||||
|
||||
/* These definitions must match with the *.dasc file(s): */
|
||||
RID_BASE = RID_X19, /* Interpreter BASE. */
|
||||
RID_LPC = RID_X21, /* Interpreter PC. */
|
||||
RID_GL = RID_X22, /* Interpreter GL. */
|
||||
RID_LREG = RID_X23, /* Interpreter L. */
|
||||
|
||||
/* Register ranges [min, max) and number of registers. */
|
||||
RID_MIN_GPR = RID_X0,
|
||||
RID_MAX_GPR = RID_SP+1,
|
||||
RID_MIN_FPR = RID_MAX_GPR,
|
||||
RID_MAX_FPR = RID_D31+1,
|
||||
RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR,
|
||||
RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR
|
||||
};
|
||||
|
||||
#define RID_NUM_KREF RID_NUM_GPR
|
||||
#define RID_MIN_KREF RID_X0
|
||||
|
||||
/* -- Register sets ------------------------------------------------------- */
|
||||
|
||||
/* Make use of all registers, except for x18, fp, lr and sp. */
|
||||
#define RSET_FIXED \
|
||||
(RID2RSET(RID_X18)|RID2RSET(RID_FP)|RID2RSET(RID_LR)|RID2RSET(RID_SP)|\
|
||||
RID2RSET(RID_GL))
|
||||
#define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED)
|
||||
#define RSET_FPR RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)
|
||||
#define RSET_ALL (RSET_GPR|RSET_FPR)
|
||||
#define RSET_INIT RSET_ALL
|
||||
|
||||
/* lr is an implicit scratch register. */
|
||||
#define RSET_SCRATCH_GPR (RSET_RANGE(RID_X0, RID_X17+1))
|
||||
#define RSET_SCRATCH_FPR \
|
||||
(RSET_RANGE(RID_D0, RID_D7+1)|RSET_RANGE(RID_D16, RID_D31+1))
|
||||
#define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR)
|
||||
#define REGARG_FIRSTGPR RID_X0
|
||||
#define REGARG_LASTGPR RID_X7
|
||||
#define REGARG_NUMGPR 8
|
||||
#define REGARG_FIRSTFPR RID_D0
|
||||
#define REGARG_LASTFPR RID_D7
|
||||
#define REGARG_NUMFPR 8
|
||||
|
||||
/* -- Spill slots --------------------------------------------------------- */
|
||||
|
||||
/* Spill slots are 32 bit wide. An even/odd pair is used for FPRs.
|
||||
**
|
||||
** SPS_FIXED: Available fixed spill slots in interpreter frame.
|
||||
** This definition must match with the vm_arm64.dasc file.
|
||||
** Pre-allocate some slots to avoid sp adjust in every root trace.
|
||||
**
|
||||
** SPS_FIRST: First spill slot for general use. Reserve min. two 32 bit slots.
|
||||
*/
|
||||
#define SPS_FIXED 4
|
||||
#define SPS_FIRST 2
|
||||
|
||||
#define SPOFS_TMP 0
|
||||
|
||||
#define sps_scale(slot) (4 * (int32_t)(slot))
|
||||
#define sps_align(slot) (((slot) - SPS_FIXED + 3) & ~3)
|
||||
|
||||
/* -- Exit state ---------------------------------------------------------- */
|
||||
|
||||
/* This definition must match with the *.dasc file(s). */
|
||||
typedef struct {
|
||||
lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */
|
||||
intptr_t gpr[RID_NUM_GPR]; /* General-purpose registers. */
|
||||
int32_t spill[256]; /* Spill slots. */
|
||||
} ExitState;
|
||||
|
||||
/* Highest exit + 1 indicates stack check. */
|
||||
#define EXITSTATE_CHECKEXIT 1
|
||||
|
||||
/* Return the address of a per-trace exit stub. */
|
||||
static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p, uint32_t exitno)
|
||||
{
|
||||
while (*p == (LJ_LE ? 0xd503201f : 0x1f2003d5)) p++; /* Skip A64I_NOP. */
|
||||
return p + 3 + exitno;
|
||||
}
|
||||
/* Avoid dependence on lj_jit.h if only including lj_target.h. */
|
||||
#define exitstub_trace_addr(T, exitno) \
|
||||
exitstub_trace_addr_((MCode *)((char *)(T)->mcode + (T)->szmcode), (exitno))
|
||||
|
||||
/* -- Instructions -------------------------------------------------------- */
|
||||
|
||||
/* ARM64 instructions are always little-endian. Swap for ARM64BE. */
|
||||
#if LJ_BE
|
||||
#define A64I_LE(x) (lj_bswap(x))
|
||||
#else
|
||||
#define A64I_LE(x) (x)
|
||||
#endif
|
||||
|
||||
/* Instruction fields. */
|
||||
#define A64F_D(r) (r)
|
||||
#define A64F_N(r) ((r) << 5)
|
||||
#define A64F_A(r) ((r) << 10)
|
||||
#define A64F_M(r) ((r) << 16)
|
||||
#define A64F_IMMS(x) ((x) << 10)
|
||||
#define A64F_IMMR(x) ((x) << 16)
|
||||
#define A64F_U16(x) ((x) << 5)
|
||||
#define A64F_U12(x) ((x) << 10)
|
||||
#define A64F_S26(x) (x)
|
||||
#define A64F_S19(x) (((uint32_t)(x) & 0x7ffffu) << 5)
|
||||
#define A64F_S14(x) ((x) << 5)
|
||||
#define A64F_S9(x) ((x) << 12)
|
||||
#define A64F_BIT(x) ((x) << 19)
|
||||
#define A64F_SH(sh, x) (((sh) << 22) | ((x) << 10))
|
||||
#define A64F_EX(ex) (A64I_EX | ((ex) << 13))
|
||||
#define A64F_EXSH(ex,x) (A64I_EX | ((ex) << 13) | ((x) << 10))
|
||||
#define A64F_FP8(x) ((x) << 13)
|
||||
#define A64F_CC(cc) ((cc) << 12)
|
||||
#define A64F_LSL16(x) (((x) / 16) << 21)
|
||||
#define A64F_BSH(sh) ((sh) << 10)
|
||||
|
||||
typedef enum A64Ins {
|
||||
A64I_S = 0x20000000,
|
||||
A64I_X = 0x80000000,
|
||||
A64I_EX = 0x00200000,
|
||||
A64I_ON = 0x00200000,
|
||||
A64I_K12 = 0x1a000000,
|
||||
A64I_K13 = 0x18000000,
|
||||
A64I_LS_U = 0x01000000,
|
||||
A64I_LS_S = 0x00800000,
|
||||
A64I_LS_R = 0x01200800,
|
||||
A64I_LS_SH = 0x00001000,
|
||||
A64I_LS_UXTWx = 0x00004000,
|
||||
A64I_LS_SXTWx = 0x0000c000,
|
||||
A64I_LS_SXTXx = 0x0000e000,
|
||||
A64I_LS_LSLx = 0x00006000,
|
||||
|
||||
A64I_ADDw = 0x0b000000,
|
||||
A64I_ADDx = 0x8b000000,
|
||||
A64I_ADDSw = 0x2b000000,
|
||||
A64I_ADDSx = 0xab000000,
|
||||
A64I_NEGw = 0x4b0003e0,
|
||||
A64I_NEGx = 0xcb0003e0,
|
||||
A64I_SUBw = 0x4b000000,
|
||||
A64I_SUBx = 0xcb000000,
|
||||
A64I_SUBSw = 0x6b000000,
|
||||
A64I_SUBSx = 0xeb000000,
|
||||
|
||||
A64I_MULw = 0x1b007c00,
|
||||
A64I_MULx = 0x9b007c00,
|
||||
A64I_SMULL = 0x9b207c00,
|
||||
|
||||
A64I_ANDw = 0x0a000000,
|
||||
A64I_ANDx = 0x8a000000,
|
||||
A64I_ANDSw = 0x6a000000,
|
||||
A64I_ANDSx = 0xea000000,
|
||||
A64I_EORw = 0x4a000000,
|
||||
A64I_EORx = 0xca000000,
|
||||
A64I_ORRw = 0x2a000000,
|
||||
A64I_ORRx = 0xaa000000,
|
||||
A64I_TSTw = 0x6a00001f,
|
||||
A64I_TSTx = 0xea00001f,
|
||||
|
||||
A64I_CMPw = 0x6b00001f,
|
||||
A64I_CMPx = 0xeb00001f,
|
||||
A64I_CMNw = 0x2b00001f,
|
||||
A64I_CMNx = 0xab00001f,
|
||||
A64I_CCMPw = 0x7a400000,
|
||||
A64I_CCMPx = 0xfa400000,
|
||||
A64I_CSELw = 0x1a800000,
|
||||
A64I_CSELx = 0x9a800000,
|
||||
|
||||
A64I_ASRw = 0x13007c00,
|
||||
A64I_ASRx = 0x9340fc00,
|
||||
A64I_LSLx = 0xd3400000,
|
||||
A64I_LSRx = 0xd340fc00,
|
||||
A64I_SHRw = 0x1ac02000,
|
||||
A64I_SHRx = 0x9ac02000, /* lsl/lsr/asr/ror x0, x0, x0 */
|
||||
A64I_REVw = 0x5ac00800,
|
||||
A64I_REVx = 0xdac00c00,
|
||||
|
||||
A64I_EXTRw = 0x13800000,
|
||||
A64I_EXTRx = 0x93c00000,
|
||||
A64I_SBFMw = 0x13000000,
|
||||
A64I_SBFMx = 0x93400000,
|
||||
A64I_SXTBw = 0x13001c00,
|
||||
A64I_SXTHw = 0x13003c00,
|
||||
A64I_SXTW = 0x93407c00,
|
||||
A64I_UBFMw = 0x53000000,
|
||||
A64I_UBFMx = 0xd3400000,
|
||||
A64I_UXTBw = 0x53001c00,
|
||||
A64I_UXTHw = 0x53003c00,
|
||||
|
||||
A64I_MOVw = 0x2a0003e0,
|
||||
A64I_MOVx = 0xaa0003e0,
|
||||
A64I_MVNw = 0x2a2003e0,
|
||||
A64I_MVNx = 0xaa2003e0,
|
||||
A64I_MOVKw = 0x72800000,
|
||||
A64I_MOVKx = 0xf2800000,
|
||||
A64I_MOVZw = 0x52800000,
|
||||
A64I_MOVZx = 0xd2800000,
|
||||
A64I_MOVNw = 0x12800000,
|
||||
A64I_MOVNx = 0x92800000,
|
||||
|
||||
A64I_LDRB = 0x39400000,
|
||||
A64I_LDRH = 0x79400000,
|
||||
A64I_LDRw = 0xb9400000,
|
||||
A64I_LDRx = 0xf9400000,
|
||||
A64I_LDRLw = 0x18000000,
|
||||
A64I_LDRLx = 0x58000000,
|
||||
A64I_STRB = 0x39000000,
|
||||
A64I_STRH = 0x79000000,
|
||||
A64I_STRw = 0xb9000000,
|
||||
A64I_STRx = 0xf9000000,
|
||||
A64I_STPw = 0x29000000,
|
||||
A64I_STPx = 0xa9000000,
|
||||
A64I_LDPw = 0x29400000,
|
||||
A64I_LDPx = 0xa9400000,
|
||||
|
||||
A64I_B = 0x14000000,
|
||||
A64I_BCC = 0x54000000,
|
||||
A64I_BL = 0x94000000,
|
||||
A64I_BR = 0xd61f0000,
|
||||
A64I_BLR = 0xd63f0000,
|
||||
A64I_TBZ = 0x36000000,
|
||||
A64I_TBNZ = 0x37000000,
|
||||
A64I_CBZ = 0x34000000,
|
||||
A64I_CBNZ = 0x35000000,
|
||||
|
||||
A64I_NOP = 0xd503201f,
|
||||
|
||||
/* FP */
|
||||
A64I_FADDd = 0x1e602800,
|
||||
A64I_FSUBd = 0x1e603800,
|
||||
A64I_FMADDd = 0x1f400000,
|
||||
A64I_FMSUBd = 0x1f408000,
|
||||
A64I_FNMADDd = 0x1f600000,
|
||||
A64I_FNMSUBd = 0x1f608000,
|
||||
A64I_FMULd = 0x1e600800,
|
||||
A64I_FDIVd = 0x1e601800,
|
||||
A64I_FNEGd = 0x1e614000,
|
||||
A64I_FABS = 0x1e60c000,
|
||||
A64I_FSQRTd = 0x1e61c000,
|
||||
A64I_LDRs = 0xbd400000,
|
||||
A64I_LDRd = 0xfd400000,
|
||||
A64I_STRs = 0xbd000000,
|
||||
A64I_STRd = 0xfd000000,
|
||||
A64I_LDPs = 0x2d400000,
|
||||
A64I_LDPd = 0x6d400000,
|
||||
A64I_STPs = 0x2d000000,
|
||||
A64I_STPd = 0x6d000000,
|
||||
A64I_FCMPd = 0x1e602000,
|
||||
A64I_FCMPZd = 0x1e602008,
|
||||
A64I_FCSELd = 0x1e600c00,
|
||||
A64I_FRINTMd = 0x1e654000,
|
||||
A64I_FRINTPd = 0x1e64c000,
|
||||
A64I_FRINTZd = 0x1e65c000,
|
||||
|
||||
A64I_FCVT_F32_F64 = 0x1e624000,
|
||||
A64I_FCVT_F64_F32 = 0x1e22c000,
|
||||
A64I_FCVT_F32_S32 = 0x1e220000,
|
||||
A64I_FCVT_F64_S32 = 0x1e620000,
|
||||
A64I_FCVT_F32_U32 = 0x1e230000,
|
||||
A64I_FCVT_F64_U32 = 0x1e630000,
|
||||
A64I_FCVT_F32_S64 = 0x9e220000,
|
||||
A64I_FCVT_F64_S64 = 0x9e620000,
|
||||
A64I_FCVT_F32_U64 = 0x9e230000,
|
||||
A64I_FCVT_F64_U64 = 0x9e630000,
|
||||
A64I_FCVT_S32_F64 = 0x1e780000,
|
||||
A64I_FCVT_S32_F32 = 0x1e380000,
|
||||
A64I_FCVT_U32_F64 = 0x1e790000,
|
||||
A64I_FCVT_U32_F32 = 0x1e390000,
|
||||
A64I_FCVT_S64_F64 = 0x9e780000,
|
||||
A64I_FCVT_S64_F32 = 0x9e380000,
|
||||
A64I_FCVT_U64_F64 = 0x9e790000,
|
||||
A64I_FCVT_U64_F32 = 0x9e390000,
|
||||
|
||||
A64I_FMOV_S = 0x1e204000,
|
||||
A64I_FMOV_D = 0x1e604000,
|
||||
A64I_FMOV_R_S = 0x1e260000,
|
||||
A64I_FMOV_S_R = 0x1e270000,
|
||||
A64I_FMOV_R_D = 0x9e660000,
|
||||
A64I_FMOV_D_R = 0x9e670000,
|
||||
A64I_FMOV_DI = 0x1e601000,
|
||||
} A64Ins;
|
||||
|
||||
typedef enum A64Shift {
|
||||
A64SH_LSL, A64SH_LSR, A64SH_ASR, A64SH_ROR
|
||||
} A64Shift;
|
||||
|
||||
typedef enum A64Extend {
|
||||
A64EX_UXTB, A64EX_UXTH, A64EX_UXTW, A64EX_UXTX,
|
||||
A64EX_SXTB, A64EX_SXTH, A64EX_SXTW, A64EX_SXTX,
|
||||
} A64Extend;
|
||||
|
||||
/* ARM condition codes. */
|
||||
typedef enum A64CC {
|
||||
CC_EQ, CC_NE, CC_CS, CC_CC, CC_MI, CC_PL, CC_VS, CC_VC,
|
||||
CC_HI, CC_LS, CC_GE, CC_LT, CC_GT, CC_LE, CC_AL,
|
||||
CC_HS = CC_CS, CC_LO = CC_CC
|
||||
} A64CC;
|
||||
|
||||
#endif
|
||||
377
include/lua/lj_target_mips.h
Normal file
377
include/lua/lj_target_mips.h
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
** Definitions for MIPS CPUs.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TARGET_MIPS_H
|
||||
#define _LJ_TARGET_MIPS_H
|
||||
|
||||
/* -- Registers IDs ------------------------------------------------------- */
|
||||
|
||||
#define GPRDEF(_) \
|
||||
_(R0) _(R1) _(R2) _(R3) _(R4) _(R5) _(R6) _(R7) \
|
||||
_(R8) _(R9) _(R10) _(R11) _(R12) _(R13) _(R14) _(R15) \
|
||||
_(R16) _(R17) _(R18) _(R19) _(R20) _(R21) _(R22) _(R23) \
|
||||
_(R24) _(R25) _(SYS1) _(SYS2) _(R28) _(SP) _(R30) _(RA)
|
||||
#if LJ_SOFTFP
|
||||
#define FPRDEF(_)
|
||||
#else
|
||||
#define FPRDEF(_) \
|
||||
_(F0) _(F1) _(F2) _(F3) _(F4) _(F5) _(F6) _(F7) \
|
||||
_(F8) _(F9) _(F10) _(F11) _(F12) _(F13) _(F14) _(F15) \
|
||||
_(F16) _(F17) _(F18) _(F19) _(F20) _(F21) _(F22) _(F23) \
|
||||
_(F24) _(F25) _(F26) _(F27) _(F28) _(F29) _(F30) _(F31)
|
||||
#endif
|
||||
#define VRIDDEF(_)
|
||||
|
||||
#define RIDENUM(name) RID_##name,
|
||||
|
||||
enum {
|
||||
GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */
|
||||
FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */
|
||||
RID_MAX,
|
||||
RID_ZERO = RID_R0,
|
||||
RID_TMP = RID_RA,
|
||||
RID_GP = RID_R28,
|
||||
|
||||
/* Calling conventions. */
|
||||
RID_RET = RID_R2,
|
||||
#if LJ_LE
|
||||
RID_RETHI = RID_R3,
|
||||
RID_RETLO = RID_R2,
|
||||
#else
|
||||
RID_RETHI = RID_R2,
|
||||
RID_RETLO = RID_R3,
|
||||
#endif
|
||||
#if LJ_SOFTFP
|
||||
RID_FPRET = RID_R2,
|
||||
#else
|
||||
RID_FPRET = RID_F0,
|
||||
#endif
|
||||
RID_CFUNCADDR = RID_R25,
|
||||
|
||||
/* These definitions must match with the *.dasc file(s): */
|
||||
RID_BASE = RID_R16, /* Interpreter BASE. */
|
||||
RID_LPC = RID_R18, /* Interpreter PC. */
|
||||
RID_DISPATCH = RID_R19, /* Interpreter DISPATCH table. */
|
||||
RID_LREG = RID_R20, /* Interpreter L. */
|
||||
RID_JGL = RID_R30, /* On-trace: global_State + 32768. */
|
||||
|
||||
/* Register ranges [min, max) and number of registers. */
|
||||
RID_MIN_GPR = RID_R0,
|
||||
RID_MAX_GPR = RID_RA+1,
|
||||
RID_MIN_FPR = RID_MAX_GPR,
|
||||
#if LJ_SOFTFP
|
||||
RID_MAX_FPR = RID_MIN_FPR,
|
||||
#else
|
||||
RID_MAX_FPR = RID_F31+1,
|
||||
#endif
|
||||
RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR,
|
||||
RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR /* Only even regs are used. */
|
||||
};
|
||||
|
||||
#define RID_NUM_KREF RID_NUM_GPR
|
||||
#define RID_MIN_KREF RID_R0
|
||||
|
||||
/* -- Register sets ------------------------------------------------------- */
|
||||
|
||||
/* Make use of all registers, except ZERO, TMP, SP, SYS1, SYS2, JGL and GP. */
|
||||
#define RSET_FIXED \
|
||||
(RID2RSET(RID_ZERO)|RID2RSET(RID_TMP)|RID2RSET(RID_SP)|\
|
||||
RID2RSET(RID_SYS1)|RID2RSET(RID_SYS2)|RID2RSET(RID_JGL)|RID2RSET(RID_GP))
|
||||
#define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED)
|
||||
#if LJ_SOFTFP
|
||||
#define RSET_FPR 0
|
||||
#else
|
||||
#if LJ_32
|
||||
#define RSET_FPR \
|
||||
(RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\
|
||||
RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\
|
||||
RID2RSET(RID_F16)|RID2RSET(RID_F18)|RID2RSET(RID_F20)|RID2RSET(RID_F22)|\
|
||||
RID2RSET(RID_F24)|RID2RSET(RID_F26)|RID2RSET(RID_F28)|RID2RSET(RID_F30))
|
||||
#else
|
||||
#define RSET_FPR RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)
|
||||
#endif
|
||||
#endif
|
||||
#define RSET_ALL (RSET_GPR|RSET_FPR)
|
||||
#define RSET_INIT RSET_ALL
|
||||
|
||||
#define RSET_SCRATCH_GPR \
|
||||
(RSET_RANGE(RID_R1, RID_R15+1)|\
|
||||
RID2RSET(RID_R24)|RID2RSET(RID_R25))
|
||||
#if LJ_SOFTFP
|
||||
#define RSET_SCRATCH_FPR 0
|
||||
#else
|
||||
#if LJ_32
|
||||
#define RSET_SCRATCH_FPR \
|
||||
(RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\
|
||||
RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\
|
||||
RID2RSET(RID_F16)|RID2RSET(RID_F18))
|
||||
#else
|
||||
#define RSET_SCRATCH_FPR RSET_RANGE(RID_F0, RID_F24)
|
||||
#endif
|
||||
#endif
|
||||
#define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR)
|
||||
#define REGARG_FIRSTGPR RID_R4
|
||||
#if LJ_32
|
||||
#define REGARG_LASTGPR RID_R7
|
||||
#define REGARG_NUMGPR 4
|
||||
#else
|
||||
#define REGARG_LASTGPR RID_R11
|
||||
#define REGARG_NUMGPR 8
|
||||
#endif
|
||||
#if LJ_ABI_SOFTFP
|
||||
#define REGARG_FIRSTFPR 0
|
||||
#define REGARG_LASTFPR 0
|
||||
#define REGARG_NUMFPR 0
|
||||
#else
|
||||
#define REGARG_FIRSTFPR RID_F12
|
||||
#if LJ_32
|
||||
#define REGARG_LASTFPR RID_F14
|
||||
#define REGARG_NUMFPR 2
|
||||
#else
|
||||
#define REGARG_LASTFPR RID_F19
|
||||
#define REGARG_NUMFPR 8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* -- Spill slots --------------------------------------------------------- */
|
||||
|
||||
/* Spill slots are 32 bit wide. An even/odd pair is used for FPRs.
|
||||
**
|
||||
** SPS_FIXED: Available fixed spill slots in interpreter frame.
|
||||
** This definition must match with the *.dasc file(s).
|
||||
**
|
||||
** SPS_FIRST: First spill slot for general use.
|
||||
*/
|
||||
#if LJ_32
|
||||
#define SPS_FIXED 5
|
||||
#else
|
||||
#define SPS_FIXED 4
|
||||
#endif
|
||||
#define SPS_FIRST 4
|
||||
|
||||
#define SPOFS_TMP 0
|
||||
|
||||
#define sps_scale(slot) (4 * (int32_t)(slot))
|
||||
#define sps_align(slot) (((slot) - SPS_FIXED + 1) & ~1)
|
||||
|
||||
/* -- Exit state ---------------------------------------------------------- */
|
||||
|
||||
/* This definition must match with the *.dasc file(s). */
|
||||
typedef struct {
|
||||
#if !LJ_SOFTFP
|
||||
lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */
|
||||
#endif
|
||||
intptr_t gpr[RID_NUM_GPR]; /* General-purpose registers. */
|
||||
int32_t spill[256]; /* Spill slots. */
|
||||
} ExitState;
|
||||
|
||||
/* Highest exit + 1 indicates stack check. */
|
||||
#define EXITSTATE_CHECKEXIT 1
|
||||
|
||||
/* Return the address of a per-trace exit stub. */
|
||||
static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p)
|
||||
{
|
||||
while (*p == 0x00000000) p++; /* Skip MIPSI_NOP. */
|
||||
return p;
|
||||
}
|
||||
/* Avoid dependence on lj_jit.h if only including lj_target.h. */
|
||||
#define exitstub_trace_addr(T, exitno) \
|
||||
exitstub_trace_addr_((MCode *)((char *)(T)->mcode + (T)->szmcode))
|
||||
|
||||
/* -- Instructions -------------------------------------------------------- */
|
||||
|
||||
/* Instruction fields. */
|
||||
#define MIPSF_S(r) ((r) << 21)
|
||||
#define MIPSF_T(r) ((r) << 16)
|
||||
#define MIPSF_D(r) ((r) << 11)
|
||||
#define MIPSF_R(r) ((r) << 21)
|
||||
#define MIPSF_H(r) ((r) << 16)
|
||||
#define MIPSF_G(r) ((r) << 11)
|
||||
#define MIPSF_F(r) ((r) << 6)
|
||||
#define MIPSF_A(n) ((n) << 6)
|
||||
#define MIPSF_M(n) ((n) << 11)
|
||||
#define MIPSF_L(n) ((n) << 6)
|
||||
|
||||
typedef enum MIPSIns {
|
||||
MIPSI_D = 0x38,
|
||||
MIPSI_DV = 0x10,
|
||||
MIPSI_D32 = 0x3c,
|
||||
/* Integer instructions. */
|
||||
MIPSI_MOVE = 0x00000025,
|
||||
MIPSI_NOP = 0x00000000,
|
||||
|
||||
MIPSI_LI = 0x24000000,
|
||||
MIPSI_LU = 0x34000000,
|
||||
MIPSI_LUI = 0x3c000000,
|
||||
|
||||
MIPSI_AND = 0x00000024,
|
||||
MIPSI_ANDI = 0x30000000,
|
||||
MIPSI_OR = 0x00000025,
|
||||
MIPSI_ORI = 0x34000000,
|
||||
MIPSI_XOR = 0x00000026,
|
||||
MIPSI_XORI = 0x38000000,
|
||||
MIPSI_NOR = 0x00000027,
|
||||
|
||||
MIPSI_SLT = 0x0000002a,
|
||||
MIPSI_SLTU = 0x0000002b,
|
||||
MIPSI_SLTI = 0x28000000,
|
||||
MIPSI_SLTIU = 0x2c000000,
|
||||
|
||||
MIPSI_ADDU = 0x00000021,
|
||||
MIPSI_ADDIU = 0x24000000,
|
||||
MIPSI_SUB = 0x00000022,
|
||||
MIPSI_SUBU = 0x00000023,
|
||||
MIPSI_MUL = 0x70000002,
|
||||
MIPSI_DIV = 0x0000001a,
|
||||
MIPSI_DIVU = 0x0000001b,
|
||||
|
||||
MIPSI_MOVZ = 0x0000000a,
|
||||
MIPSI_MOVN = 0x0000000b,
|
||||
MIPSI_MFHI = 0x00000010,
|
||||
MIPSI_MFLO = 0x00000012,
|
||||
MIPSI_MULT = 0x00000018,
|
||||
|
||||
MIPSI_SLL = 0x00000000,
|
||||
MIPSI_SRL = 0x00000002,
|
||||
MIPSI_SRA = 0x00000003,
|
||||
MIPSI_ROTR = 0x00200002, /* MIPSXXR2 */
|
||||
MIPSI_DROTR = 0x0020003a,
|
||||
MIPSI_DROTR32 = 0x0020003e,
|
||||
MIPSI_SLLV = 0x00000004,
|
||||
MIPSI_SRLV = 0x00000006,
|
||||
MIPSI_SRAV = 0x00000007,
|
||||
MIPSI_ROTRV = 0x00000046, /* MIPSXXR2 */
|
||||
MIPSI_DROTRV = 0x00000056,
|
||||
|
||||
MIPSI_SEB = 0x7c000420, /* MIPSXXR2 */
|
||||
MIPSI_SEH = 0x7c000620, /* MIPSXXR2 */
|
||||
MIPSI_WSBH = 0x7c0000a0, /* MIPSXXR2 */
|
||||
MIPSI_DSBH = 0x7c0000a4,
|
||||
|
||||
MIPSI_B = 0x10000000,
|
||||
MIPSI_J = 0x08000000,
|
||||
MIPSI_JAL = 0x0c000000,
|
||||
MIPSI_JALX = 0x74000000,
|
||||
MIPSI_JR = 0x00000008,
|
||||
MIPSI_JALR = 0x0000f809,
|
||||
|
||||
MIPSI_BEQ = 0x10000000,
|
||||
MIPSI_BNE = 0x14000000,
|
||||
MIPSI_BLEZ = 0x18000000,
|
||||
MIPSI_BGTZ = 0x1c000000,
|
||||
MIPSI_BLTZ = 0x04000000,
|
||||
MIPSI_BGEZ = 0x04010000,
|
||||
|
||||
/* Load/store instructions. */
|
||||
MIPSI_LW = 0x8c000000,
|
||||
MIPSI_LD = 0xdc000000,
|
||||
MIPSI_SW = 0xac000000,
|
||||
MIPSI_SD = 0xfc000000,
|
||||
MIPSI_LB = 0x80000000,
|
||||
MIPSI_SB = 0xa0000000,
|
||||
MIPSI_LH = 0x84000000,
|
||||
MIPSI_SH = 0xa4000000,
|
||||
MIPSI_LBU = 0x90000000,
|
||||
MIPSI_LHU = 0x94000000,
|
||||
MIPSI_LWC1 = 0xc4000000,
|
||||
MIPSI_SWC1 = 0xe4000000,
|
||||
MIPSI_LDC1 = 0xd4000000,
|
||||
MIPSI_SDC1 = 0xf4000000,
|
||||
|
||||
/* MIPS64 instructions. */
|
||||
MIPSI_DADD = 0x0000002c,
|
||||
MIPSI_DADDI = 0x60000000,
|
||||
MIPSI_DADDU = 0x0000002d,
|
||||
MIPSI_DADDIU = 0x64000000,
|
||||
MIPSI_DSUB = 0x0000002e,
|
||||
MIPSI_DSUBU = 0x0000002f,
|
||||
MIPSI_DDIV = 0x0000001e,
|
||||
MIPSI_DDIVU = 0x0000001f,
|
||||
MIPSI_DMULT = 0x0000001c,
|
||||
MIPSI_DMULTU = 0x0000001d,
|
||||
|
||||
MIPSI_DSLL = 0x00000038,
|
||||
MIPSI_DSRL = 0x0000003a,
|
||||
MIPSI_DSLLV = 0x00000014,
|
||||
MIPSI_DSRLV = 0x00000016,
|
||||
MIPSI_DSRA = 0x0000003b,
|
||||
MIPSI_DSRAV = 0x00000017,
|
||||
MIPSI_DSRA32 = 0x0000003f,
|
||||
MIPSI_DSLL32 = 0x0000003c,
|
||||
MIPSI_DSRL32 = 0x0000003e,
|
||||
MIPSI_DSHD = 0x7c000164,
|
||||
|
||||
MIPSI_AADDU = LJ_32 ? MIPSI_ADDU : MIPSI_DADDU,
|
||||
MIPSI_AADDIU = LJ_32 ? MIPSI_ADDIU : MIPSI_DADDIU,
|
||||
MIPSI_ASUBU = LJ_32 ? MIPSI_SUBU : MIPSI_DSUBU,
|
||||
MIPSI_AL = LJ_32 ? MIPSI_LW : MIPSI_LD,
|
||||
MIPSI_AS = LJ_32 ? MIPSI_SW : MIPSI_SD,
|
||||
|
||||
/* Extract/insert instructions. */
|
||||
MIPSI_DEXTM = 0x7c000001,
|
||||
MIPSI_DEXTU = 0x7c000002,
|
||||
MIPSI_DEXT = 0x7c000003,
|
||||
MIPSI_DINSM = 0x7c000005,
|
||||
MIPSI_DINSU = 0x7c000006,
|
||||
MIPSI_DINS = 0x7c000007,
|
||||
|
||||
MIPSI_RINT_D = 0x4620001a,
|
||||
MIPSI_RINT_S = 0x4600001a,
|
||||
MIPSI_RINT = 0x4400001a,
|
||||
MIPSI_FLOOR_D = 0x4620000b,
|
||||
MIPSI_CEIL_D = 0x4620000a,
|
||||
MIPSI_ROUND_D = 0x46200008,
|
||||
|
||||
/* FP instructions. */
|
||||
MIPSI_MOV_S = 0x46000006,
|
||||
MIPSI_MOV_D = 0x46200006,
|
||||
MIPSI_MOVT_D = 0x46210011,
|
||||
MIPSI_MOVF_D = 0x46200011,
|
||||
|
||||
MIPSI_ABS_D = 0x46200005,
|
||||
MIPSI_NEG_D = 0x46200007,
|
||||
|
||||
MIPSI_ADD_D = 0x46200000,
|
||||
MIPSI_SUB_D = 0x46200001,
|
||||
MIPSI_MUL_D = 0x46200002,
|
||||
MIPSI_DIV_D = 0x46200003,
|
||||
MIPSI_SQRT_D = 0x46200004,
|
||||
|
||||
MIPSI_ADD_S = 0x46000000,
|
||||
MIPSI_SUB_S = 0x46000001,
|
||||
|
||||
MIPSI_CVT_D_S = 0x46000021,
|
||||
MIPSI_CVT_W_S = 0x46000024,
|
||||
MIPSI_CVT_S_D = 0x46200020,
|
||||
MIPSI_CVT_W_D = 0x46200024,
|
||||
MIPSI_CVT_S_W = 0x46800020,
|
||||
MIPSI_CVT_D_W = 0x46800021,
|
||||
MIPSI_CVT_S_L = 0x46a00020,
|
||||
MIPSI_CVT_D_L = 0x46a00021,
|
||||
|
||||
MIPSI_TRUNC_W_S = 0x4600000d,
|
||||
MIPSI_TRUNC_W_D = 0x4620000d,
|
||||
MIPSI_TRUNC_L_S = 0x46000009,
|
||||
MIPSI_TRUNC_L_D = 0x46200009,
|
||||
MIPSI_FLOOR_W_S = 0x4600000f,
|
||||
MIPSI_FLOOR_W_D = 0x4620000f,
|
||||
|
||||
MIPSI_MFC1 = 0x44000000,
|
||||
MIPSI_MTC1 = 0x44800000,
|
||||
MIPSI_DMTC1 = 0x44a00000,
|
||||
MIPSI_DMFC1 = 0x44200000,
|
||||
|
||||
MIPSI_BC1F = 0x45000000,
|
||||
MIPSI_BC1T = 0x45010000,
|
||||
|
||||
MIPSI_C_EQ_D = 0x46200032,
|
||||
MIPSI_C_OLT_S = 0x46000034,
|
||||
MIPSI_C_OLT_D = 0x46200034,
|
||||
MIPSI_C_ULT_D = 0x46200035,
|
||||
MIPSI_C_OLE_D = 0x46200036,
|
||||
MIPSI_C_ULE_D = 0x46200037,
|
||||
} MIPSIns;
|
||||
|
||||
#endif
|
||||
280
include/lua/lj_target_ppc.h
Normal file
280
include/lua/lj_target_ppc.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
** Definitions for PPC CPUs.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TARGET_PPC_H
|
||||
#define _LJ_TARGET_PPC_H
|
||||
|
||||
/* -- Registers IDs ------------------------------------------------------- */
|
||||
|
||||
#define GPRDEF(_) \
|
||||
_(R0) _(SP) _(SYS1) _(R3) _(R4) _(R5) _(R6) _(R7) \
|
||||
_(R8) _(R9) _(R10) _(R11) _(R12) _(SYS2) _(R14) _(R15) \
|
||||
_(R16) _(R17) _(R18) _(R19) _(R20) _(R21) _(R22) _(R23) \
|
||||
_(R24) _(R25) _(R26) _(R27) _(R28) _(R29) _(R30) _(R31)
|
||||
#define FPRDEF(_) \
|
||||
_(F0) _(F1) _(F2) _(F3) _(F4) _(F5) _(F6) _(F7) \
|
||||
_(F8) _(F9) _(F10) _(F11) _(F12) _(F13) _(F14) _(F15) \
|
||||
_(F16) _(F17) _(F18) _(F19) _(F20) _(F21) _(F22) _(F23) \
|
||||
_(F24) _(F25) _(F26) _(F27) _(F28) _(F29) _(F30) _(F31)
|
||||
#define VRIDDEF(_)
|
||||
|
||||
#define RIDENUM(name) RID_##name,
|
||||
|
||||
enum {
|
||||
GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */
|
||||
FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */
|
||||
RID_MAX,
|
||||
RID_TMP = RID_R0,
|
||||
|
||||
/* Calling conventions. */
|
||||
RID_RET = RID_R3,
|
||||
RID_RETHI = RID_R3,
|
||||
RID_RETLO = RID_R4,
|
||||
RID_FPRET = RID_F1,
|
||||
|
||||
/* These definitions must match with the *.dasc file(s): */
|
||||
RID_BASE = RID_R14, /* Interpreter BASE. */
|
||||
RID_LPC = RID_R16, /* Interpreter PC. */
|
||||
RID_DISPATCH = RID_R17, /* Interpreter DISPATCH table. */
|
||||
RID_LREG = RID_R18, /* Interpreter L. */
|
||||
RID_JGL = RID_R31, /* On-trace: global_State + 32768. */
|
||||
|
||||
/* Register ranges [min, max) and number of registers. */
|
||||
RID_MIN_GPR = RID_R0,
|
||||
RID_MAX_GPR = RID_R31+1,
|
||||
RID_MIN_FPR = RID_F0,
|
||||
RID_MAX_FPR = RID_F31+1,
|
||||
RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR,
|
||||
RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR
|
||||
};
|
||||
|
||||
#define RID_NUM_KREF RID_NUM_GPR
|
||||
#define RID_MIN_KREF RID_R0
|
||||
|
||||
/* -- Register sets ------------------------------------------------------- */
|
||||
|
||||
/* Make use of all registers, except TMP, SP, SYS1, SYS2 and JGL. */
|
||||
#define RSET_FIXED \
|
||||
(RID2RSET(RID_TMP)|RID2RSET(RID_SP)|RID2RSET(RID_SYS1)|\
|
||||
RID2RSET(RID_SYS2)|RID2RSET(RID_JGL))
|
||||
#define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED)
|
||||
#define RSET_FPR RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)
|
||||
#define RSET_ALL (RSET_GPR|RSET_FPR)
|
||||
#define RSET_INIT RSET_ALL
|
||||
|
||||
#define RSET_SCRATCH_GPR (RSET_RANGE(RID_R3, RID_R12+1))
|
||||
#define RSET_SCRATCH_FPR (RSET_RANGE(RID_F0, RID_F13+1))
|
||||
#define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR)
|
||||
#define REGARG_FIRSTGPR RID_R3
|
||||
#define REGARG_LASTGPR RID_R10
|
||||
#define REGARG_NUMGPR 8
|
||||
#define REGARG_FIRSTFPR RID_F1
|
||||
#define REGARG_LASTFPR RID_F8
|
||||
#define REGARG_NUMFPR 8
|
||||
|
||||
/* -- Spill slots --------------------------------------------------------- */
|
||||
|
||||
/* Spill slots are 32 bit wide. An even/odd pair is used for FPRs.
|
||||
**
|
||||
** SPS_FIXED: Available fixed spill slots in interpreter frame.
|
||||
** This definition must match with the *.dasc file(s).
|
||||
**
|
||||
** SPS_FIRST: First spill slot for general use.
|
||||
** [sp+12] tmplo word \
|
||||
** [sp+ 8] tmphi word / tmp dword, parameter area for callee
|
||||
** [sp+ 4] tmpw, LR of callee
|
||||
** [sp+ 0] stack chain
|
||||
*/
|
||||
#define SPS_FIXED 7
|
||||
#define SPS_FIRST 4
|
||||
|
||||
/* Stack offsets for temporary slots. Used for FP<->int conversions etc. */
|
||||
#define SPOFS_TMPW 4
|
||||
#define SPOFS_TMP 8
|
||||
#define SPOFS_TMPHI 8
|
||||
#define SPOFS_TMPLO 12
|
||||
|
||||
#define sps_scale(slot) (4 * (int32_t)(slot))
|
||||
#define sps_align(slot) (((slot) - SPS_FIXED + 3) & ~3)
|
||||
|
||||
/* -- Exit state ---------------------------------------------------------- */
|
||||
|
||||
/* This definition must match with the *.dasc file(s). */
|
||||
typedef struct {
|
||||
lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */
|
||||
intptr_t gpr[RID_NUM_GPR]; /* General-purpose registers. */
|
||||
int32_t spill[256]; /* Spill slots. */
|
||||
} ExitState;
|
||||
|
||||
/* Highest exit + 1 indicates stack check. */
|
||||
#define EXITSTATE_CHECKEXIT 1
|
||||
|
||||
/* Return the address of a per-trace exit stub. */
|
||||
static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p, uint32_t exitno)
|
||||
{
|
||||
while (*p == 0x60000000) p++; /* Skip PPCI_NOP. */
|
||||
return p + 3 + exitno;
|
||||
}
|
||||
/* Avoid dependence on lj_jit.h if only including lj_target.h. */
|
||||
#define exitstub_trace_addr(T, exitno) \
|
||||
exitstub_trace_addr_((MCode *)((char *)(T)->mcode + (T)->szmcode), (exitno))
|
||||
|
||||
/* -- Instructions -------------------------------------------------------- */
|
||||
|
||||
/* Instruction fields. */
|
||||
#define PPCF_CC(cc) ((((cc) & 3) << 16) | (((cc) & 4) << 22))
|
||||
#define PPCF_T(r) ((r) << 21)
|
||||
#define PPCF_A(r) ((r) << 16)
|
||||
#define PPCF_B(r) ((r) << 11)
|
||||
#define PPCF_C(r) ((r) << 6)
|
||||
#define PPCF_MB(n) ((n) << 6)
|
||||
#define PPCF_ME(n) ((n) << 1)
|
||||
#define PPCF_Y 0x00200000
|
||||
#define PPCF_DOT 0x00000001
|
||||
|
||||
typedef enum PPCIns {
|
||||
/* Integer instructions. */
|
||||
PPCI_MR = 0x7c000378,
|
||||
PPCI_NOP = 0x60000000,
|
||||
|
||||
PPCI_LI = 0x38000000,
|
||||
PPCI_LIS = 0x3c000000,
|
||||
|
||||
PPCI_ADD = 0x7c000214,
|
||||
PPCI_ADDC = 0x7c000014,
|
||||
PPCI_ADDO = 0x7c000614,
|
||||
PPCI_ADDE = 0x7c000114,
|
||||
PPCI_ADDZE = 0x7c000194,
|
||||
PPCI_ADDME = 0x7c0001d4,
|
||||
PPCI_ADDI = 0x38000000,
|
||||
PPCI_ADDIS = 0x3c000000,
|
||||
PPCI_ADDIC = 0x30000000,
|
||||
PPCI_ADDICDOT = 0x34000000,
|
||||
|
||||
PPCI_SUBF = 0x7c000050,
|
||||
PPCI_SUBFC = 0x7c000010,
|
||||
PPCI_SUBFO = 0x7c000450,
|
||||
PPCI_SUBFE = 0x7c000110,
|
||||
PPCI_SUBFZE = 0x7c000190,
|
||||
PPCI_SUBFME = 0x7c0001d0,
|
||||
PPCI_SUBFIC = 0x20000000,
|
||||
|
||||
PPCI_NEG = 0x7c0000d0,
|
||||
|
||||
PPCI_AND = 0x7c000038,
|
||||
PPCI_ANDC = 0x7c000078,
|
||||
PPCI_NAND = 0x7c0003b8,
|
||||
PPCI_ANDIDOT = 0x70000000,
|
||||
PPCI_ANDISDOT = 0x74000000,
|
||||
|
||||
PPCI_OR = 0x7c000378,
|
||||
PPCI_NOR = 0x7c0000f8,
|
||||
PPCI_ORI = 0x60000000,
|
||||
PPCI_ORIS = 0x64000000,
|
||||
|
||||
PPCI_XOR = 0x7c000278,
|
||||
PPCI_EQV = 0x7c000238,
|
||||
PPCI_XORI = 0x68000000,
|
||||
PPCI_XORIS = 0x6c000000,
|
||||
|
||||
PPCI_CMPW = 0x7c000000,
|
||||
PPCI_CMPLW = 0x7c000040,
|
||||
PPCI_CMPWI = 0x2c000000,
|
||||
PPCI_CMPLWI = 0x28000000,
|
||||
|
||||
PPCI_MULLW = 0x7c0001d6,
|
||||
PPCI_MULLI = 0x1c000000,
|
||||
PPCI_MULLWO = 0x7c0005d6,
|
||||
|
||||
PPCI_EXTSB = 0x7c000774,
|
||||
PPCI_EXTSH = 0x7c000734,
|
||||
|
||||
PPCI_SLW = 0x7c000030,
|
||||
PPCI_SRW = 0x7c000430,
|
||||
PPCI_SRAW = 0x7c000630,
|
||||
PPCI_SRAWI = 0x7c000670,
|
||||
|
||||
PPCI_RLWNM = 0x5c000000,
|
||||
PPCI_RLWINM = 0x54000000,
|
||||
PPCI_RLWIMI = 0x50000000,
|
||||
|
||||
PPCI_B = 0x48000000,
|
||||
PPCI_BL = 0x48000001,
|
||||
PPCI_BC = 0x40800000,
|
||||
PPCI_BCL = 0x40800001,
|
||||
PPCI_BCTR = 0x4e800420,
|
||||
PPCI_BCTRL = 0x4e800421,
|
||||
|
||||
PPCI_CRANDC = 0x4c000102,
|
||||
PPCI_CRXOR = 0x4c000182,
|
||||
PPCI_CRAND = 0x4c000202,
|
||||
PPCI_CREQV = 0x4c000242,
|
||||
PPCI_CRORC = 0x4c000342,
|
||||
PPCI_CROR = 0x4c000382,
|
||||
|
||||
PPCI_MFLR = 0x7c0802a6,
|
||||
PPCI_MTCTR = 0x7c0903a6,
|
||||
|
||||
PPCI_MCRXR = 0x7c000400,
|
||||
|
||||
/* Load/store instructions. */
|
||||
PPCI_LWZ = 0x80000000,
|
||||
PPCI_LBZ = 0x88000000,
|
||||
PPCI_STW = 0x90000000,
|
||||
PPCI_STB = 0x98000000,
|
||||
PPCI_LHZ = 0xa0000000,
|
||||
PPCI_LHA = 0xa8000000,
|
||||
PPCI_STH = 0xb0000000,
|
||||
|
||||
PPCI_STWU = 0x94000000,
|
||||
|
||||
PPCI_LFS = 0xc0000000,
|
||||
PPCI_LFD = 0xc8000000,
|
||||
PPCI_STFS = 0xd0000000,
|
||||
PPCI_STFD = 0xd8000000,
|
||||
|
||||
PPCI_LWZX = 0x7c00002e,
|
||||
PPCI_LBZX = 0x7c0000ae,
|
||||
PPCI_STWX = 0x7c00012e,
|
||||
PPCI_STBX = 0x7c0001ae,
|
||||
PPCI_LHZX = 0x7c00022e,
|
||||
PPCI_LHAX = 0x7c0002ae,
|
||||
PPCI_STHX = 0x7c00032e,
|
||||
|
||||
PPCI_LWBRX = 0x7c00042c,
|
||||
PPCI_STWBRX = 0x7c00052c,
|
||||
|
||||
PPCI_LFSX = 0x7c00042e,
|
||||
PPCI_LFDX = 0x7c0004ae,
|
||||
PPCI_STFSX = 0x7c00052e,
|
||||
PPCI_STFDX = 0x7c0005ae,
|
||||
|
||||
/* FP instructions. */
|
||||
PPCI_FMR = 0xfc000090,
|
||||
PPCI_FNEG = 0xfc000050,
|
||||
PPCI_FABS = 0xfc000210,
|
||||
|
||||
PPCI_FRSP = 0xfc000018,
|
||||
PPCI_FCTIWZ = 0xfc00001e,
|
||||
|
||||
PPCI_FADD = 0xfc00002a,
|
||||
PPCI_FSUB = 0xfc000028,
|
||||
PPCI_FMUL = 0xfc000032,
|
||||
PPCI_FDIV = 0xfc000024,
|
||||
PPCI_FSQRT = 0xfc00002c,
|
||||
|
||||
PPCI_FMADD = 0xfc00003a,
|
||||
PPCI_FMSUB = 0xfc000038,
|
||||
PPCI_FNMSUB = 0xfc00003c,
|
||||
|
||||
PPCI_FCMPU = 0xfc000000,
|
||||
PPCI_FSEL = 0xfc00002e,
|
||||
} PPCIns;
|
||||
|
||||
typedef enum PPCCC {
|
||||
CC_GE, CC_LE, CC_NE, CC_NS, CC_LT, CC_GT, CC_EQ, CC_SO
|
||||
} PPCCC;
|
||||
|
||||
#endif
|
||||
362
include/lua/lj_target_x86.h
Normal file
362
include/lua/lj_target_x86.h
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
** Definitions for x86 and x64 CPUs.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TARGET_X86_H
|
||||
#define _LJ_TARGET_X86_H
|
||||
|
||||
/* -- Registers IDs ------------------------------------------------------- */
|
||||
|
||||
#if LJ_64
|
||||
#define GPRDEF(_) \
|
||||
_(EAX) _(ECX) _(EDX) _(EBX) _(ESP) _(EBP) _(ESI) _(EDI) \
|
||||
_(R8D) _(R9D) _(R10D) _(R11D) _(R12D) _(R13D) _(R14D) _(R15D)
|
||||
#define FPRDEF(_) \
|
||||
_(XMM0) _(XMM1) _(XMM2) _(XMM3) _(XMM4) _(XMM5) _(XMM6) _(XMM7) \
|
||||
_(XMM8) _(XMM9) _(XMM10) _(XMM11) _(XMM12) _(XMM13) _(XMM14) _(XMM15)
|
||||
#else
|
||||
#define GPRDEF(_) \
|
||||
_(EAX) _(ECX) _(EDX) _(EBX) _(ESP) _(EBP) _(ESI) _(EDI)
|
||||
#define FPRDEF(_) \
|
||||
_(XMM0) _(XMM1) _(XMM2) _(XMM3) _(XMM4) _(XMM5) _(XMM6) _(XMM7)
|
||||
#endif
|
||||
#define VRIDDEF(_) \
|
||||
_(MRM) _(RIP)
|
||||
|
||||
#define RIDENUM(name) RID_##name,
|
||||
|
||||
enum {
|
||||
GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */
|
||||
FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */
|
||||
RID_MAX,
|
||||
RID_MRM = RID_MAX, /* Pseudo-id for ModRM operand. */
|
||||
RID_RIP = RID_MAX+5, /* Pseudo-id for RIP (x64 only), rm bits = 5. */
|
||||
|
||||
/* Calling conventions. */
|
||||
RID_SP = RID_ESP,
|
||||
RID_RET = RID_EAX,
|
||||
#if LJ_64
|
||||
RID_FPRET = RID_XMM0,
|
||||
#else
|
||||
RID_RETLO = RID_EAX,
|
||||
RID_RETHI = RID_EDX,
|
||||
#endif
|
||||
|
||||
/* These definitions must match with the *.dasc file(s): */
|
||||
RID_BASE = RID_EDX, /* Interpreter BASE. */
|
||||
#if LJ_64 && !LJ_ABI_WIN
|
||||
RID_LPC = RID_EBX, /* Interpreter PC. */
|
||||
RID_DISPATCH = RID_R14D, /* Interpreter DISPATCH table. */
|
||||
#else
|
||||
RID_LPC = RID_ESI, /* Interpreter PC. */
|
||||
RID_DISPATCH = RID_EBX, /* Interpreter DISPATCH table. */
|
||||
#endif
|
||||
|
||||
/* Register ranges [min, max) and number of registers. */
|
||||
RID_MIN_GPR = RID_EAX,
|
||||
RID_MIN_FPR = RID_XMM0,
|
||||
RID_MAX_GPR = RID_MIN_FPR,
|
||||
RID_MAX_FPR = RID_MAX,
|
||||
RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR,
|
||||
RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR,
|
||||
};
|
||||
|
||||
/* -- Register sets ------------------------------------------------------- */
|
||||
|
||||
/* Make use of all registers, except the stack pointer (and maybe DISPATCH). */
|
||||
#define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) \
|
||||
- RID2RSET(RID_ESP) \
|
||||
- LJ_GC64*RID2RSET(RID_DISPATCH))
|
||||
#define RSET_FPR (RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR))
|
||||
#define RSET_ALL (RSET_GPR|RSET_FPR)
|
||||
#define RSET_INIT RSET_ALL
|
||||
|
||||
#if LJ_64
|
||||
/* Note: this requires the use of FORCE_REX! */
|
||||
#define RSET_GPR8 RSET_GPR
|
||||
#else
|
||||
#define RSET_GPR8 (RSET_RANGE(RID_EAX, RID_EBX+1))
|
||||
#endif
|
||||
|
||||
/* ABI-specific register sets. */
|
||||
#define RSET_ACD (RID2RSET(RID_EAX)|RID2RSET(RID_ECX)|RID2RSET(RID_EDX))
|
||||
#if LJ_64
|
||||
#if LJ_ABI_WIN
|
||||
/* Windows x64 ABI. */
|
||||
#define RSET_SCRATCH \
|
||||
(RSET_ACD|RSET_RANGE(RID_R8D, RID_R11D+1)|RSET_RANGE(RID_XMM0, RID_XMM5+1))
|
||||
#define REGARG_GPRS \
|
||||
(RID_ECX|((RID_EDX|((RID_R8D|(RID_R9D<<5))<<5))<<5))
|
||||
#define REGARG_NUMGPR 4
|
||||
#define REGARG_NUMFPR 4
|
||||
#define REGARG_FIRSTFPR RID_XMM0
|
||||
#define REGARG_LASTFPR RID_XMM3
|
||||
#define STACKARG_OFS (4*8)
|
||||
#else
|
||||
/* The rest of the civilized x64 world has a common ABI. */
|
||||
#define RSET_SCRATCH \
|
||||
(RSET_ACD|RSET_RANGE(RID_ESI, RID_R11D+1)|RSET_FPR)
|
||||
#define REGARG_GPRS \
|
||||
(RID_EDI|((RID_ESI|((RID_EDX|((RID_ECX|((RID_R8D|(RID_R9D \
|
||||
<<5))<<5))<<5))<<5))<<5))
|
||||
#define REGARG_NUMGPR 6
|
||||
#define REGARG_NUMFPR 8
|
||||
#define REGARG_FIRSTFPR RID_XMM0
|
||||
#define REGARG_LASTFPR RID_XMM7
|
||||
#define STACKARG_OFS 0
|
||||
#endif
|
||||
#else
|
||||
/* Common x86 ABI. */
|
||||
#define RSET_SCRATCH (RSET_ACD|RSET_FPR)
|
||||
#define REGARG_GPRS (RID_ECX|(RID_EDX<<5)) /* Fastcall only. */
|
||||
#define REGARG_NUMGPR 2 /* Fastcall only. */
|
||||
#define REGARG_NUMFPR 0
|
||||
#define STACKARG_OFS 0
|
||||
#endif
|
||||
|
||||
#if LJ_64
|
||||
/* Prefer the low 8 regs of each type to reduce REX prefixes. */
|
||||
#undef rset_picktop
|
||||
#define rset_picktop(rs) (lj_fls(lj_bswap(rs)) ^ 0x18)
|
||||
#endif
|
||||
|
||||
/* -- Spill slots --------------------------------------------------------- */
|
||||
|
||||
/* Spill slots are 32 bit wide. An even/odd pair is used for FPRs.
|
||||
**
|
||||
** SPS_FIXED: Available fixed spill slots in interpreter frame.
|
||||
** This definition must match with the *.dasc file(s).
|
||||
**
|
||||
** SPS_FIRST: First spill slot for general use. Reserve min. two 32 bit slots.
|
||||
*/
|
||||
#if LJ_64
|
||||
#if LJ_ABI_WIN
|
||||
#define SPS_FIXED (4*2)
|
||||
#define SPS_FIRST (4*2) /* Don't use callee register save area. */
|
||||
#else
|
||||
#if LJ_GC64
|
||||
#define SPS_FIXED 2
|
||||
#else
|
||||
#define SPS_FIXED 4
|
||||
#endif
|
||||
#define SPS_FIRST 2
|
||||
#endif
|
||||
#else
|
||||
#define SPS_FIXED 6
|
||||
#define SPS_FIRST 2
|
||||
#endif
|
||||
|
||||
#define SPOFS_TMP 0
|
||||
|
||||
#define sps_scale(slot) (4 * (int32_t)(slot))
|
||||
#define sps_align(slot) (((slot) - SPS_FIXED + 3) & ~3)
|
||||
|
||||
/* -- Exit state ---------------------------------------------------------- */
|
||||
|
||||
/* This definition must match with the *.dasc file(s). */
|
||||
typedef struct {
|
||||
lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */
|
||||
intptr_t gpr[RID_NUM_GPR]; /* General-purpose registers. */
|
||||
int32_t spill[256]; /* Spill slots. */
|
||||
} ExitState;
|
||||
|
||||
/* Limited by the range of a short fwd jump (127): (2+2)*(32-1)-2 = 122. */
|
||||
#define EXITSTUB_SPACING (2+2)
|
||||
#define EXITSTUBS_PER_GROUP 32
|
||||
|
||||
/* -- x86 ModRM operand encoding ------------------------------------------ */
|
||||
|
||||
typedef enum {
|
||||
XM_OFS0 = 0x00, XM_OFS8 = 0x40, XM_OFS32 = 0x80, XM_REG = 0xc0,
|
||||
XM_SCALE1 = 0x00, XM_SCALE2 = 0x40, XM_SCALE4 = 0x80, XM_SCALE8 = 0xc0,
|
||||
XM_MASK = 0xc0
|
||||
} x86Mode;
|
||||
|
||||
/* Structure to hold variable ModRM operand. */
|
||||
typedef struct {
|
||||
int32_t ofs; /* Offset. */
|
||||
uint8_t base; /* Base register or RID_NONE. */
|
||||
uint8_t idx; /* Index register or RID_NONE. */
|
||||
uint8_t scale; /* Index scale (XM_SCALE1 .. XM_SCALE8). */
|
||||
} x86ModRM;
|
||||
|
||||
/* -- Opcodes ------------------------------------------------------------- */
|
||||
|
||||
/* Macros to construct variable-length x86 opcodes. -(len+1) is in LSB. */
|
||||
#define XO_(o) ((uint32_t)(0x0000fe + (0x##o<<24)))
|
||||
#define XO_FPU(a,b) ((uint32_t)(0x00fd + (0x##a<<16)+(0x##b<<24)))
|
||||
#define XO_0f(o) ((uint32_t)(0x0f00fd + (0x##o<<24)))
|
||||
#define XO_66(o) ((uint32_t)(0x6600fd + (0x##o<<24)))
|
||||
#define XO_660f(o) ((uint32_t)(0x0f66fc + (0x##o<<24)))
|
||||
#define XO_f20f(o) ((uint32_t)(0x0ff2fc + (0x##o<<24)))
|
||||
#define XO_f30f(o) ((uint32_t)(0x0ff3fc + (0x##o<<24)))
|
||||
|
||||
#define XV_660f38(o) ((uint32_t)(0x79e2c4 + (0x##o<<24)))
|
||||
#define XV_f20f38(o) ((uint32_t)(0x7be2c4 + (0x##o<<24)))
|
||||
#define XV_f20f3a(o) ((uint32_t)(0x7be3c4 + (0x##o<<24)))
|
||||
#define XV_f30f38(o) ((uint32_t)(0x7ae2c4 + (0x##o<<24)))
|
||||
|
||||
/* This list of x86 opcodes is not intended to be complete. Opcodes are only
|
||||
** included when needed. Take a look at DynASM or jit.dis_x86 to see the
|
||||
** whole mess.
|
||||
*/
|
||||
typedef enum {
|
||||
/* Fixed length opcodes. XI_* prefix. */
|
||||
XI_O16 = 0x66,
|
||||
XI_NOP = 0x90,
|
||||
XI_XCHGa = 0x90,
|
||||
XI_CALL = 0xe8,
|
||||
XI_JMP = 0xe9,
|
||||
XI_JMPs = 0xeb,
|
||||
XI_PUSH = 0x50, /* Really 50+r. */
|
||||
XI_JCCs = 0x70, /* Really 7x. */
|
||||
XI_JCCn = 0x80, /* Really 0f8x. */
|
||||
XI_LEA = 0x8d,
|
||||
XI_MOVrib = 0xb0, /* Really b0+r. */
|
||||
XI_MOVri = 0xb8, /* Really b8+r. */
|
||||
XI_ARITHib = 0x80,
|
||||
XI_ARITHi = 0x81,
|
||||
XI_ARITHi8 = 0x83,
|
||||
XI_PUSHi8 = 0x6a,
|
||||
XI_TESTb = 0x84,
|
||||
XI_TEST = 0x85,
|
||||
XI_INT3 = 0xcc,
|
||||
XI_MOVmi = 0xc7,
|
||||
XI_GROUP5 = 0xff,
|
||||
|
||||
/* Note: little-endian byte-order! */
|
||||
XI_FLDZ = 0xeed9,
|
||||
XI_FLD1 = 0xe8d9,
|
||||
XI_FLDLG2 = 0xecd9,
|
||||
XI_FLDLN2 = 0xedd9,
|
||||
XI_FDUP = 0xc0d9, /* Really fld st0. */
|
||||
XI_FPOP = 0xd8dd, /* Really fstp st0. */
|
||||
XI_FPOP1 = 0xd9dd, /* Really fstp st1. */
|
||||
XI_FRNDINT = 0xfcd9,
|
||||
XI_FSIN = 0xfed9,
|
||||
XI_FCOS = 0xffd9,
|
||||
XI_FPTAN = 0xf2d9,
|
||||
XI_FPATAN = 0xf3d9,
|
||||
XI_FSCALE = 0xfdd9,
|
||||
XI_FYL2X = 0xf1d9,
|
||||
|
||||
/* VEX-encoded instructions. XV_* prefix. */
|
||||
XV_RORX = XV_f20f3a(f0),
|
||||
XV_SARX = XV_f30f38(f7),
|
||||
XV_SHLX = XV_660f38(f7),
|
||||
XV_SHRX = XV_f20f38(f7),
|
||||
|
||||
/* Variable-length opcodes. XO_* prefix. */
|
||||
XO_OR = XO_(0b),
|
||||
XO_MOV = XO_(8b),
|
||||
XO_MOVto = XO_(89),
|
||||
XO_MOVtow = XO_66(89),
|
||||
XO_MOVtob = XO_(88),
|
||||
XO_MOVmi = XO_(c7),
|
||||
XO_MOVmib = XO_(c6),
|
||||
XO_LEA = XO_(8d),
|
||||
XO_ARITHib = XO_(80),
|
||||
XO_ARITHi = XO_(81),
|
||||
XO_ARITHi8 = XO_(83),
|
||||
XO_ARITHiw8 = XO_66(83),
|
||||
XO_SHIFTi = XO_(c1),
|
||||
XO_SHIFT1 = XO_(d1),
|
||||
XO_SHIFTcl = XO_(d3),
|
||||
XO_IMUL = XO_0f(af),
|
||||
XO_IMULi = XO_(69),
|
||||
XO_IMULi8 = XO_(6b),
|
||||
XO_CMP = XO_(3b),
|
||||
XO_TESTb = XO_(84),
|
||||
XO_TEST = XO_(85),
|
||||
XO_GROUP3b = XO_(f6),
|
||||
XO_GROUP3 = XO_(f7),
|
||||
XO_GROUP5b = XO_(fe),
|
||||
XO_GROUP5 = XO_(ff),
|
||||
XO_MOVZXb = XO_0f(b6),
|
||||
XO_MOVZXw = XO_0f(b7),
|
||||
XO_MOVSXb = XO_0f(be),
|
||||
XO_MOVSXw = XO_0f(bf),
|
||||
XO_MOVSXd = XO_(63),
|
||||
XO_BSWAP = XO_0f(c8),
|
||||
XO_CMOV = XO_0f(40),
|
||||
|
||||
XO_MOVSD = XO_f20f(10),
|
||||
XO_MOVSDto = XO_f20f(11),
|
||||
XO_MOVSS = XO_f30f(10),
|
||||
XO_MOVSSto = XO_f30f(11),
|
||||
XO_MOVLPD = XO_660f(12),
|
||||
XO_MOVAPS = XO_0f(28),
|
||||
XO_XORPS = XO_0f(57),
|
||||
XO_ANDPS = XO_0f(54),
|
||||
XO_ADDSD = XO_f20f(58),
|
||||
XO_SUBSD = XO_f20f(5c),
|
||||
XO_MULSD = XO_f20f(59),
|
||||
XO_DIVSD = XO_f20f(5e),
|
||||
XO_SQRTSD = XO_f20f(51),
|
||||
XO_MINSD = XO_f20f(5d),
|
||||
XO_MAXSD = XO_f20f(5f),
|
||||
XO_ROUNDSD = 0x0b3a0ffc, /* Really 66 0f 3a 0b. See asm_fpmath. */
|
||||
XO_UCOMISD = XO_660f(2e),
|
||||
XO_CVTSI2SD = XO_f20f(2a),
|
||||
XO_CVTTSD2SI= XO_f20f(2c),
|
||||
XO_CVTSI2SS = XO_f30f(2a),
|
||||
XO_CVTTSS2SI= XO_f30f(2c),
|
||||
XO_CVTSS2SD = XO_f30f(5a),
|
||||
XO_CVTSD2SS = XO_f20f(5a),
|
||||
XO_ADDSS = XO_f30f(58),
|
||||
XO_MOVD = XO_660f(6e),
|
||||
XO_MOVDto = XO_660f(7e),
|
||||
|
||||
XO_FLDd = XO_(d9), XOg_FLDd = 0,
|
||||
XO_FLDq = XO_(dd), XOg_FLDq = 0,
|
||||
XO_FILDd = XO_(db), XOg_FILDd = 0,
|
||||
XO_FILDq = XO_(df), XOg_FILDq = 5,
|
||||
XO_FSTPd = XO_(d9), XOg_FSTPd = 3,
|
||||
XO_FSTPq = XO_(dd), XOg_FSTPq = 3,
|
||||
XO_FISTPq = XO_(df), XOg_FISTPq = 7,
|
||||
XO_FISTTPq = XO_(dd), XOg_FISTTPq = 1,
|
||||
XO_FADDq = XO_(dc), XOg_FADDq = 0,
|
||||
XO_FLDCW = XO_(d9), XOg_FLDCW = 5,
|
||||
XO_FNSTCW = XO_(d9), XOg_FNSTCW = 7
|
||||
} x86Op;
|
||||
|
||||
/* x86 opcode groups. */
|
||||
typedef uint32_t x86Group;
|
||||
|
||||
#define XG_(i8, i, g) ((x86Group)(((i8) << 16) + ((i) << 8) + (g)))
|
||||
#define XG_ARITHi(g) XG_(XI_ARITHi8, XI_ARITHi, g)
|
||||
#define XG_TOXOi(xg) ((x86Op)(0x000000fe + (((xg)<<16) & 0xff000000)))
|
||||
#define XG_TOXOi8(xg) ((x86Op)(0x000000fe + (((xg)<<8) & 0xff000000)))
|
||||
|
||||
#define XO_ARITH(a) ((x86Op)(0x030000fe + ((a)<<27)))
|
||||
#define XO_ARITHw(a) ((x86Op)(0x036600fd + ((a)<<27)))
|
||||
|
||||
typedef enum {
|
||||
XOg_ADD, XOg_OR, XOg_ADC, XOg_SBB, XOg_AND, XOg_SUB, XOg_XOR, XOg_CMP,
|
||||
XOg_X_IMUL
|
||||
} x86Arith;
|
||||
|
||||
typedef enum {
|
||||
XOg_ROL, XOg_ROR, XOg_RCL, XOg_RCR, XOg_SHL, XOg_SHR, XOg_SAL, XOg_SAR
|
||||
} x86Shift;
|
||||
|
||||
typedef enum {
|
||||
XOg_TEST, XOg_TEST_, XOg_NOT, XOg_NEG, XOg_MUL, XOg_IMUL, XOg_DIV, XOg_IDIV
|
||||
} x86Group3;
|
||||
|
||||
typedef enum {
|
||||
XOg_INC, XOg_DEC, XOg_CALL, XOg_CALLfar, XOg_JMP, XOg_JMPfar, XOg_PUSH
|
||||
} x86Group5;
|
||||
|
||||
/* x86 condition codes. */
|
||||
typedef enum {
|
||||
CC_O, CC_NO, CC_B, CC_NB, CC_E, CC_NE, CC_BE, CC_NBE,
|
||||
CC_S, CC_NS, CC_P, CC_NP, CC_L, CC_NL, CC_LE, CC_NLE,
|
||||
CC_C = CC_B, CC_NAE = CC_C, CC_NC = CC_NB, CC_AE = CC_NB,
|
||||
CC_Z = CC_E, CC_NZ = CC_NE, CC_NA = CC_BE, CC_A = CC_NBE,
|
||||
CC_PE = CC_P, CC_PO = CC_NP, CC_NGE = CC_L, CC_GE = CC_NL,
|
||||
CC_NG = CC_LE, CC_G = CC_NLE
|
||||
} x86CC;
|
||||
|
||||
#endif
|
||||
55
include/lua/lj_trace.h
Normal file
55
include/lua/lj_trace.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
** Trace management.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_TRACE_H
|
||||
#define _LJ_TRACE_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
#if LJ_HASJIT
|
||||
#include "lj_jit.h"
|
||||
#include "lj_dispatch.h"
|
||||
|
||||
/* Trace errors. */
|
||||
typedef enum {
|
||||
#define TREDEF(name, msg) LJ_TRERR_##name,
|
||||
#include "lj_traceerr.h"
|
||||
LJ_TRERR__MAX
|
||||
} TraceError;
|
||||
|
||||
LJ_FUNC_NORET void lj_trace_err(jit_State *J, TraceError e);
|
||||
LJ_FUNC_NORET void lj_trace_err_info(jit_State *J, TraceError e);
|
||||
|
||||
/* Trace management. */
|
||||
LJ_FUNC GCtrace * LJ_FASTCALL lj_trace_alloc(lua_State *L, GCtrace *T);
|
||||
LJ_FUNC void LJ_FASTCALL lj_trace_free(global_State *g, GCtrace *T);
|
||||
LJ_FUNC void lj_trace_reenableproto(GCproto *pt);
|
||||
LJ_FUNC void lj_trace_flushproto(global_State *g, GCproto *pt);
|
||||
LJ_FUNC void lj_trace_flush(jit_State *J, TraceNo traceno);
|
||||
LJ_FUNC int lj_trace_flushall(lua_State *L);
|
||||
LJ_FUNC void lj_trace_initstate(global_State *g);
|
||||
LJ_FUNC void lj_trace_freestate(global_State *g);
|
||||
|
||||
/* Event handling. */
|
||||
LJ_FUNC void lj_trace_ins(jit_State *J, const BCIns *pc);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc);
|
||||
LJ_FUNCA int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr);
|
||||
|
||||
/* Signal asynchronous abort of trace or end of trace. */
|
||||
#define lj_trace_abort(g) (G2J(g)->state &= ~LJ_TRACE_ACTIVE)
|
||||
#define lj_trace_end(J) (J->state = LJ_TRACE_END)
|
||||
|
||||
#else
|
||||
|
||||
#define lj_trace_flushall(L) (UNUSED(L), 0)
|
||||
#define lj_trace_initstate(g) UNUSED(g)
|
||||
#define lj_trace_freestate(g) UNUSED(g)
|
||||
#define lj_trace_abort(g) UNUSED(g)
|
||||
#define lj_trace_end(J) UNUSED(J)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
61
include/lua/lj_traceerr.h
Normal file
61
include/lua/lj_traceerr.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
** Trace compiler error messages.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* This file may be included multiple times with different TREDEF macros. */
|
||||
|
||||
/* Recording. */
|
||||
TREDEF(RECERR, "error thrown or hook called during recording")
|
||||
TREDEF(TRACEUV, "trace too short")
|
||||
TREDEF(TRACEOV, "trace too long")
|
||||
TREDEF(STACKOV, "trace too deep")
|
||||
TREDEF(SNAPOV, "too many snapshots")
|
||||
TREDEF(BLACKL, "blacklisted")
|
||||
TREDEF(RETRY, "retry recording")
|
||||
TREDEF(NYIBC, "NYI: bytecode %d")
|
||||
|
||||
/* Recording loop ops. */
|
||||
TREDEF(LLEAVE, "leaving loop in root trace")
|
||||
TREDEF(LINNER, "inner loop in root trace")
|
||||
TREDEF(LUNROLL, "loop unroll limit reached")
|
||||
|
||||
/* Recording calls/returns. */
|
||||
TREDEF(BADTYPE, "bad argument type")
|
||||
TREDEF(CJITOFF, "JIT compilation disabled for function")
|
||||
TREDEF(CUNROLL, "call unroll limit reached")
|
||||
TREDEF(DOWNREC, "down-recursion, restarting")
|
||||
TREDEF(NYIFFU, "NYI: unsupported variant of FastFunc %s")
|
||||
TREDEF(NYIRETL, "NYI: return to lower frame")
|
||||
|
||||
/* Recording indexed load/store. */
|
||||
TREDEF(STORENN, "store with nil or NaN key")
|
||||
TREDEF(NOMM, "missing metamethod")
|
||||
TREDEF(IDXLOOP, "looping index lookup")
|
||||
TREDEF(NYITMIX, "NYI: mixed sparse/dense table")
|
||||
|
||||
/* Recording C data operations. */
|
||||
TREDEF(NOCACHE, "symbol not in cache")
|
||||
TREDEF(NYICONV, "NYI: unsupported C type conversion")
|
||||
TREDEF(NYICALL, "NYI: unsupported C function type")
|
||||
|
||||
/* Optimizations. */
|
||||
TREDEF(GFAIL, "guard would always fail")
|
||||
TREDEF(PHIOV, "too many PHIs")
|
||||
TREDEF(TYPEINS, "persistent type instability")
|
||||
|
||||
/* Assembler. */
|
||||
TREDEF(MCODEAL, "failed to allocate mcode memory")
|
||||
TREDEF(MCODEOV, "machine code too long")
|
||||
TREDEF(MCODELM, "hit mcode limit (retrying)")
|
||||
TREDEF(SPILLOV, "too many spill slots")
|
||||
TREDEF(BADRA, "inconsistent register allocation")
|
||||
TREDEF(NYIIR, "NYI: cannot assemble IR instruction %d")
|
||||
TREDEF(NYIPHI, "NYI: PHI shuffling too complex")
|
||||
TREDEF(NYICOAL, "NYI: register coalescing too complex")
|
||||
|
||||
#undef TREDEF
|
||||
|
||||
/* Detecting unused error messages:
|
||||
awk -F, '/^TREDEF/ { gsub(/TREDEF./, ""); printf "grep -q LJ_TRERR_%s *.[ch] || echo %s\n", $1, $1}' lj_traceerr.h | sh
|
||||
*/
|
||||
14
include/lua/lj_udata.h
Normal file
14
include/lua/lj_udata.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
** Userdata handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_UDATA_H
|
||||
#define _LJ_UDATA_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
LJ_FUNC GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env);
|
||||
LJ_FUNC void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud);
|
||||
|
||||
#endif
|
||||
120
include/lua/lj_vm.h
Normal file
120
include/lua/lj_vm.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
** Assembler VM interface definitions.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_VM_H
|
||||
#define _LJ_VM_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Entry points for ASM parts of VM. */
|
||||
LJ_ASMF void lj_vm_call(lua_State *L, TValue *base, int nres1);
|
||||
LJ_ASMF int lj_vm_pcall(lua_State *L, TValue *base, int nres1, ptrdiff_t ef);
|
||||
typedef TValue *(*lua_CPFunction)(lua_State *L, lua_CFunction func, void *ud);
|
||||
LJ_ASMF int lj_vm_cpcall(lua_State *L, lua_CFunction func, void *ud,
|
||||
lua_CPFunction cp);
|
||||
LJ_ASMF int lj_vm_resume(lua_State *L, TValue *base, int nres1, ptrdiff_t ef);
|
||||
LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_c(void *cframe, int errcode);
|
||||
LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_ff(void *cframe);
|
||||
#if LJ_ABI_WIN && LJ_TARGET_X86
|
||||
LJ_ASMF_NORET void LJ_FASTCALL lj_vm_rtlunwind(void *cframe, void *excptrec,
|
||||
void *unwinder, int errcode);
|
||||
#endif
|
||||
LJ_ASMF void lj_vm_unwind_c_eh(void);
|
||||
LJ_ASMF void lj_vm_unwind_ff_eh(void);
|
||||
#if LJ_TARGET_X86ORX64
|
||||
LJ_ASMF void lj_vm_unwind_rethrow(void);
|
||||
#endif
|
||||
|
||||
/* Miscellaneous functions. */
|
||||
#if LJ_TARGET_X86ORX64
|
||||
LJ_ASMF int lj_vm_cpuid(uint32_t f, uint32_t res[4]);
|
||||
#endif
|
||||
#if LJ_TARGET_PPC
|
||||
void lj_vm_cachesync(void *start, void *end);
|
||||
#endif
|
||||
LJ_ASMF double lj_vm_foldarith(double x, double y, int op);
|
||||
#if LJ_HASJIT
|
||||
LJ_ASMF double lj_vm_foldfpm(double x, int op);
|
||||
#endif
|
||||
#if !LJ_ARCH_HASFPU
|
||||
/* Declared in lj_obj.h: LJ_ASMF int32_t lj_vm_tobit(double x); */
|
||||
#endif
|
||||
|
||||
/* Dispatch targets for recording and hooks. */
|
||||
LJ_ASMF void lj_vm_record(void);
|
||||
LJ_ASMF void lj_vm_inshook(void);
|
||||
LJ_ASMF void lj_vm_rethook(void);
|
||||
LJ_ASMF void lj_vm_callhook(void);
|
||||
LJ_ASMF void lj_vm_profhook(void);
|
||||
|
||||
/* Trace exit handling. */
|
||||
LJ_ASMF void lj_vm_exit_handler(void);
|
||||
LJ_ASMF void lj_vm_exit_interp(void);
|
||||
|
||||
/* Internal math helper functions. */
|
||||
#if LJ_TARGET_PPC || LJ_TARGET_ARM64 || (LJ_TARGET_MIPS && LJ_ABI_SOFTFP)
|
||||
#define lj_vm_floor floor
|
||||
#define lj_vm_ceil ceil
|
||||
#else
|
||||
LJ_ASMF double lj_vm_floor(double);
|
||||
LJ_ASMF double lj_vm_ceil(double);
|
||||
#if LJ_TARGET_ARM
|
||||
LJ_ASMF double lj_vm_floor_sf(double);
|
||||
LJ_ASMF double lj_vm_ceil_sf(double);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef LUAJIT_NO_LOG2
|
||||
LJ_ASMF double lj_vm_log2(double);
|
||||
#else
|
||||
#define lj_vm_log2 log2
|
||||
#endif
|
||||
#if !(defined(_LJ_DISPATCH_H) && LJ_TARGET_MIPS)
|
||||
LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t, int32_t);
|
||||
#endif
|
||||
|
||||
#if LJ_HASJIT
|
||||
#if LJ_TARGET_X86ORX64
|
||||
LJ_ASMF void lj_vm_floor_sse(void);
|
||||
LJ_ASMF void lj_vm_ceil_sse(void);
|
||||
LJ_ASMF void lj_vm_trunc_sse(void);
|
||||
LJ_ASMF void lj_vm_powi_sse(void);
|
||||
#define lj_vm_powi NULL
|
||||
#else
|
||||
LJ_ASMF double lj_vm_powi(double, int32_t);
|
||||
#endif
|
||||
#if LJ_TARGET_PPC || LJ_TARGET_ARM64
|
||||
#define lj_vm_trunc trunc
|
||||
#else
|
||||
LJ_ASMF double lj_vm_trunc(double);
|
||||
#if LJ_TARGET_ARM
|
||||
LJ_ASMF double lj_vm_trunc_sf(double);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef LUAJIT_NO_EXP2
|
||||
LJ_ASMF double lj_vm_exp2(double);
|
||||
#else
|
||||
#define lj_vm_exp2 exp2
|
||||
#endif
|
||||
#if LJ_HASFFI
|
||||
LJ_ASMF int lj_vm_errno(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Continuations for metamethods. */
|
||||
LJ_ASMF void lj_cont_cat(void); /* Continue with concatenation. */
|
||||
LJ_ASMF void lj_cont_ra(void); /* Store result in RA from instruction. */
|
||||
LJ_ASMF void lj_cont_nop(void); /* Do nothing, just continue execution. */
|
||||
LJ_ASMF void lj_cont_condt(void); /* Branch if result is true. */
|
||||
LJ_ASMF void lj_cont_condf(void); /* Branch if result is false. */
|
||||
LJ_ASMF void lj_cont_hook(void); /* Continue from hook yield. */
|
||||
LJ_ASMF void lj_cont_stitch(void); /* Trace stitching. */
|
||||
|
||||
/* Start of the ASM code. */
|
||||
LJ_ASMF char lj_vm_asm_begin[];
|
||||
|
||||
/* Bytecode offsets are relative to lj_vm_asm_begin. */
|
||||
#define makeasmfunc(ofs) ((ASMFunction)(lj_vm_asm_begin + (ofs)))
|
||||
|
||||
#endif
|
||||
59
include/lua/lj_vmevent.h
Normal file
59
include/lua/lj_vmevent.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
** VM event handling.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_VMEVENT_H
|
||||
#define _LJ_VMEVENT_H
|
||||
|
||||
#include "lj_obj.h"
|
||||
|
||||
/* Registry key for VM event handler table. */
|
||||
#define LJ_VMEVENTS_REGKEY "_VMEVENTS"
|
||||
#define LJ_VMEVENTS_HSIZE 4
|
||||
|
||||
#define VMEVENT_MASK(ev) ((uint8_t)1 << ((int)(ev) & 7))
|
||||
#define VMEVENT_HASH(ev) ((int)(ev) & ~7)
|
||||
#define VMEVENT_HASHIDX(h) ((int)(h) << 3)
|
||||
#define VMEVENT_NOCACHE 255
|
||||
|
||||
#define VMEVENT_DEF(name, hash) \
|
||||
LJ_VMEVENT_##name##_, \
|
||||
LJ_VMEVENT_##name = ((LJ_VMEVENT_##name##_) & 7)|((hash) << 3)
|
||||
|
||||
/* VM event IDs. */
|
||||
typedef enum {
|
||||
VMEVENT_DEF(BC, 0x00003883),
|
||||
VMEVENT_DEF(TRACE, 0xb2d91467),
|
||||
VMEVENT_DEF(RECORD, 0x9284bf4f),
|
||||
VMEVENT_DEF(TEXIT, 0xb29df2b0),
|
||||
LJ_VMEVENT__MAX
|
||||
} VMEvent;
|
||||
|
||||
#ifdef LUAJIT_DISABLE_VMEVENT
|
||||
#define lj_vmevent_send(L, ev, args) UNUSED(L)
|
||||
#define lj_vmevent_send_(L, ev, args, post) UNUSED(L)
|
||||
#else
|
||||
#define lj_vmevent_send(L, ev, args) \
|
||||
if (G(L)->vmevmask & VMEVENT_MASK(LJ_VMEVENT_##ev)) { \
|
||||
ptrdiff_t argbase = lj_vmevent_prepare(L, LJ_VMEVENT_##ev); \
|
||||
if (argbase) { \
|
||||
args \
|
||||
lj_vmevent_call(L, argbase); \
|
||||
} \
|
||||
}
|
||||
#define lj_vmevent_send_(L, ev, args, post) \
|
||||
if (G(L)->vmevmask & VMEVENT_MASK(LJ_VMEVENT_##ev)) { \
|
||||
ptrdiff_t argbase = lj_vmevent_prepare(L, LJ_VMEVENT_##ev); \
|
||||
if (argbase) { \
|
||||
args \
|
||||
lj_vmevent_call(L, argbase); \
|
||||
post \
|
||||
} \
|
||||
}
|
||||
|
||||
LJ_FUNC ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev);
|
||||
LJ_FUNC void lj_vmevent_call(lua_State *L, ptrdiff_t argbase);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
402
include/lua/lua.h
Normal file
402
include/lua/lua.h
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
|
||||
** Lua - An Extensible Extension Language
|
||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||
** See Copyright Notice at the end of this file
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lua_h
|
||||
#define lua_h
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include "luaconf.h"
|
||||
|
||||
|
||||
#define LUA_VERSION "Lua 5.1"
|
||||
#define LUA_RELEASE "Lua 5.1.4"
|
||||
#define LUA_VERSION_NUM 501
|
||||
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
|
||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
||||
|
||||
|
||||
/* mark for precompiled code (`<esc>Lua') */
|
||||
#define LUA_SIGNATURE "\033Lua"
|
||||
|
||||
/* option for multiple returns in `lua_pcall' and `lua_call' */
|
||||
#define LUA_MULTRET (-1)
|
||||
|
||||
|
||||
/*
|
||||
** pseudo-indices
|
||||
*/
|
||||
#define LUA_REGISTRYINDEX (-10000)
|
||||
#define LUA_ENVIRONINDEX (-10001)
|
||||
#define LUA_GLOBALSINDEX (-10002)
|
||||
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
|
||||
|
||||
|
||||
/* thread status */
|
||||
#define LUA_OK 0
|
||||
#define LUA_YIELD 1
|
||||
#define LUA_ERRRUN 2
|
||||
#define LUA_ERRSYNTAX 3
|
||||
#define LUA_ERRMEM 4
|
||||
#define LUA_ERRERR 5
|
||||
|
||||
|
||||
typedef struct lua_State lua_State;
|
||||
|
||||
typedef int (*lua_CFunction) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** functions that read/write blocks when loading/dumping Lua chunks
|
||||
*/
|
||||
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
|
||||
|
||||
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
|
||||
|
||||
|
||||
/*
|
||||
** prototype for memory-allocation functions
|
||||
*/
|
||||
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
|
||||
|
||||
/*
|
||||
** basic types
|
||||
*/
|
||||
#define LUA_TNONE (-1)
|
||||
|
||||
#define LUA_TNIL 0
|
||||
#define LUA_TBOOLEAN 1
|
||||
#define LUA_TLIGHTUSERDATA 2
|
||||
#define LUA_TNUMBER 3
|
||||
#define LUA_TSTRING 4
|
||||
#define LUA_TTABLE 5
|
||||
#define LUA_TFUNCTION 6
|
||||
#define LUA_TUSERDATA 7
|
||||
#define LUA_TTHREAD 8
|
||||
|
||||
|
||||
|
||||
/* minimum Lua stack available to a C function */
|
||||
#define LUA_MINSTACK 20
|
||||
|
||||
|
||||
/*
|
||||
** generic extra include file
|
||||
*/
|
||||
#if defined(LUA_USER_H)
|
||||
#include LUA_USER_H
|
||||
#endif
|
||||
|
||||
|
||||
/* type of numbers in Lua */
|
||||
typedef LUA_NUMBER lua_Number;
|
||||
|
||||
|
||||
/* type for integer functions */
|
||||
typedef LUA_INTEGER lua_Integer;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** state manipulation
|
||||
*/
|
||||
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
LUA_API void (lua_close) (lua_State *L);
|
||||
LUA_API lua_State *(lua_newthread) (lua_State *L);
|
||||
|
||||
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
|
||||
/*
|
||||
** basic stack manipulation
|
||||
*/
|
||||
LUA_API int (lua_gettop) (lua_State *L);
|
||||
LUA_API void (lua_settop) (lua_State *L, int idx);
|
||||
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
|
||||
LUA_API void (lua_remove) (lua_State *L, int idx);
|
||||
LUA_API void (lua_insert) (lua_State *L, int idx);
|
||||
LUA_API void (lua_replace) (lua_State *L, int idx);
|
||||
LUA_API int (lua_checkstack) (lua_State *L, int sz);
|
||||
|
||||
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
|
||||
|
||||
|
||||
/*
|
||||
** access functions (stack -> C)
|
||||
*/
|
||||
|
||||
LUA_API int (lua_isnumber) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isstring) (lua_State *L, int idx);
|
||||
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
|
||||
LUA_API int (lua_type) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_typename) (lua_State *L, int tp);
|
||||
|
||||
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
|
||||
|
||||
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
|
||||
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
|
||||
LUA_API int (lua_toboolean) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUA_API size_t (lua_objlen) (lua_State *L, int idx);
|
||||
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
|
||||
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
|
||||
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
|
||||
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** push functions (C -> stack)
|
||||
*/
|
||||
LUA_API void (lua_pushnil) (lua_State *L);
|
||||
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
|
||||
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
|
||||
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
|
||||
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
|
||||
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
|
||||
va_list argp);
|
||||
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
|
||||
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
|
||||
LUA_API void (lua_pushboolean) (lua_State *L, int b);
|
||||
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
|
||||
LUA_API int (lua_pushthread) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** get functions (Lua -> stack)
|
||||
*/
|
||||
LUA_API void (lua_gettable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawget) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
|
||||
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
|
||||
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
|
||||
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
||||
LUA_API void (lua_getfenv) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** set functions (stack -> Lua)
|
||||
*/
|
||||
LUA_API void (lua_settable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawset) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
|
||||
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
|
||||
LUA_API int (lua_setfenv) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** `load' and `call' functions (load and run Lua code)
|
||||
*/
|
||||
LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
|
||||
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
|
||||
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
|
||||
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname);
|
||||
|
||||
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
|
||||
|
||||
|
||||
/*
|
||||
** coroutine functions
|
||||
*/
|
||||
LUA_API int (lua_yield) (lua_State *L, int nresults);
|
||||
LUA_API int (lua_resume) (lua_State *L, int narg);
|
||||
LUA_API int (lua_status) (lua_State *L);
|
||||
|
||||
/*
|
||||
** garbage-collection function and options
|
||||
*/
|
||||
|
||||
#define LUA_GCSTOP 0
|
||||
#define LUA_GCRESTART 1
|
||||
#define LUA_GCCOLLECT 2
|
||||
#define LUA_GCCOUNT 3
|
||||
#define LUA_GCCOUNTB 4
|
||||
#define LUA_GCSTEP 5
|
||||
#define LUA_GCSETPAUSE 6
|
||||
#define LUA_GCSETSTEPMUL 7
|
||||
#define LUA_GCISRUNNING 9
|
||||
|
||||
LUA_API int (lua_gc) (lua_State *L, int what, int data);
|
||||
|
||||
|
||||
/*
|
||||
** miscellaneous functions
|
||||
*/
|
||||
|
||||
LUA_API int (lua_error) (lua_State *L);
|
||||
|
||||
LUA_API int (lua_next) (lua_State *L, int idx);
|
||||
|
||||
LUA_API void (lua_concat) (lua_State *L, int n);
|
||||
|
||||
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
|
||||
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define lua_pop(L,n) lua_settop(L, -(n)-1)
|
||||
|
||||
#define lua_newtable(L) lua_createtable(L, 0, 0)
|
||||
|
||||
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
|
||||
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
||||
|
||||
#define lua_strlen(L,i) lua_objlen(L, (i))
|
||||
|
||||
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
|
||||
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
|
||||
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
|
||||
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
|
||||
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
|
||||
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
|
||||
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
|
||||
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
||||
|
||||
#define lua_pushliteral(L, s) \
|
||||
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
|
||||
|
||||
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
|
||||
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
|
||||
|
||||
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** compatibility macros and functions
|
||||
*/
|
||||
|
||||
#define lua_open() luaL_newstate()
|
||||
|
||||
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
|
||||
|
||||
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
|
||||
|
||||
#define lua_Chunkreader lua_Reader
|
||||
#define lua_Chunkwriter lua_Writer
|
||||
|
||||
|
||||
/* hack */
|
||||
LUA_API void lua_setlevel (lua_State *from, lua_State *to);
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================================
|
||||
** Debug API
|
||||
** =======================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Event codes
|
||||
*/
|
||||
#define LUA_HOOKCALL 0
|
||||
#define LUA_HOOKRET 1
|
||||
#define LUA_HOOKLINE 2
|
||||
#define LUA_HOOKCOUNT 3
|
||||
#define LUA_HOOKTAILRET 4
|
||||
|
||||
|
||||
/*
|
||||
** Event masks
|
||||
*/
|
||||
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
|
||||
#define LUA_MASKRET (1 << LUA_HOOKRET)
|
||||
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
|
||||
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
|
||||
|
||||
typedef struct lua_Debug lua_Debug; /* activation record */
|
||||
|
||||
|
||||
/* Functions to be called by the debuger in specific events */
|
||||
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
|
||||
|
||||
|
||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
|
||||
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
|
||||
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
|
||||
LUA_API lua_Hook lua_gethook (lua_State *L);
|
||||
LUA_API int lua_gethookmask (lua_State *L);
|
||||
LUA_API int lua_gethookcount (lua_State *L);
|
||||
|
||||
/* From Lua 5.2. */
|
||||
LUA_API void *lua_upvalueid (lua_State *L, int idx, int n);
|
||||
LUA_API void lua_upvaluejoin (lua_State *L, int idx1, int n1, int idx2, int n2);
|
||||
LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname, const char *mode);
|
||||
LUA_API const lua_Number *lua_version (lua_State *L);
|
||||
LUA_API void lua_copy (lua_State *L, int fromidx, int toidx);
|
||||
LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum);
|
||||
LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum);
|
||||
|
||||
/* From Lua 5.3. */
|
||||
LUA_API int lua_isyieldable (lua_State *L);
|
||||
|
||||
|
||||
struct lua_Debug {
|
||||
int event;
|
||||
const char *name; /* (n) */
|
||||
const char *namewhat; /* (n) `global', `local', `field', `method' */
|
||||
const char *what; /* (S) `Lua', `C', `main', `tail' */
|
||||
const char *source; /* (S) */
|
||||
int currentline; /* (l) */
|
||||
int nups; /* (u) number of upvalues */
|
||||
int linedefined; /* (S) */
|
||||
int lastlinedefined; /* (S) */
|
||||
char short_src[LUA_IDSIZE]; /* (S) */
|
||||
/* private part */
|
||||
int i_ci; /* active function */
|
||||
};
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#endif
|
||||
9
include/lua/lua.hpp
Normal file
9
include/lua/lua.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
// C++ wrapper for LuaJIT header files.
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "luajit.h"
|
||||
}
|
||||
|
||||
152
include/lua/luaconf.h
Normal file
152
include/lua/luaconf.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
** Configuration header.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef luaconf_h
|
||||
#define luaconf_h
|
||||
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Default path for loading Lua and C modules with require(). */
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
** In Windows, any exclamation mark ('!') in the path is replaced by the
|
||||
** path of the directory of the executable file of the current process.
|
||||
*/
|
||||
#define LUA_LDIR "!\\lua\\"
|
||||
#define LUA_CDIR "!\\"
|
||||
#define LUA_PATH_DEFAULT \
|
||||
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;"
|
||||
#define LUA_CPATH_DEFAULT \
|
||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
|
||||
#else
|
||||
/*
|
||||
** Note to distribution maintainers: do NOT patch the following lines!
|
||||
** Please read ../doc/install.html#distro and pass PREFIX=/usr instead.
|
||||
*/
|
||||
#ifndef LUA_MULTILIB
|
||||
#define LUA_MULTILIB "lib"
|
||||
#endif
|
||||
#ifndef LUA_LMULTILIB
|
||||
#define LUA_LMULTILIB "lib"
|
||||
#endif
|
||||
#define LUA_LROOT "/usr/local"
|
||||
#define LUA_LUADIR "/lua/5.1/"
|
||||
#define LUA_LJDIR "/luajit-2.1.0-beta3/"
|
||||
|
||||
#ifdef LUA_ROOT
|
||||
#define LUA_JROOT LUA_ROOT
|
||||
#define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR
|
||||
#define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR
|
||||
#define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua"
|
||||
#define LUA_RCPATH ";" LUA_RCDIR "?.so"
|
||||
#else
|
||||
#define LUA_JROOT LUA_LROOT
|
||||
#define LUA_RLPATH
|
||||
#define LUA_RCPATH
|
||||
#endif
|
||||
|
||||
#define LUA_JPATH ";" LUA_JROOT "/share" LUA_LJDIR "?.lua"
|
||||
#define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR
|
||||
#define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR
|
||||
#define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua"
|
||||
#define LUA_LCPATH1 ";" LUA_LCDIR "?.so"
|
||||
#define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so"
|
||||
|
||||
#define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH
|
||||
#define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2
|
||||
#endif
|
||||
|
||||
/* Environment variable names for path overrides and initialization code. */
|
||||
#define LUA_PATH "LUA_PATH"
|
||||
#define LUA_CPATH "LUA_CPATH"
|
||||
#define LUA_INIT "LUA_INIT"
|
||||
|
||||
/* Special file system characters. */
|
||||
#if defined(_WIN32)
|
||||
#define LUA_DIRSEP "\\"
|
||||
#else
|
||||
#define LUA_DIRSEP "/"
|
||||
#endif
|
||||
#define LUA_PATHSEP ";"
|
||||
#define LUA_PATH_MARK "?"
|
||||
#define LUA_EXECDIR "!"
|
||||
#define LUA_IGMARK "-"
|
||||
#define LUA_PATH_CONFIG \
|
||||
LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \
|
||||
LUA_EXECDIR "\n" LUA_IGMARK "\n"
|
||||
|
||||
/* Quoting in error messages. */
|
||||
#define LUA_QL(x) "'" x "'"
|
||||
#define LUA_QS LUA_QL("%s")
|
||||
|
||||
/* Various tunables. */
|
||||
#define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */
|
||||
#define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */
|
||||
#define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */
|
||||
#define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */
|
||||
#define LUA_MAXCAPTURES 32 /* Max. pattern captures. */
|
||||
|
||||
/* Configuration for the frontend (the luajit executable). */
|
||||
#if defined(luajit_c)
|
||||
#define LUA_PROGNAME "luajit" /* Fallback frontend name. */
|
||||
#define LUA_PROMPT "> " /* Interactive prompt. */
|
||||
#define LUA_PROMPT2 ">> " /* Continuation prompt. */
|
||||
#define LUA_MAXINPUT 512 /* Max. input line length. */
|
||||
#endif
|
||||
|
||||
/* Note: changing the following defines breaks the Lua 5.1 ABI. */
|
||||
#define LUA_INTEGER ptrdiff_t
|
||||
#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */
|
||||
/*
|
||||
** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using
|
||||
** unreasonable amounts of stack space, but still retain ABI compatibility.
|
||||
** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it.
|
||||
*/
|
||||
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
|
||||
|
||||
/* The following defines are here only for compatibility with luaconf.h
|
||||
** from the standard Lua distribution. They must not be changed for LuaJIT.
|
||||
*/
|
||||
#define LUA_NUMBER_DOUBLE
|
||||
#define LUA_NUMBER double
|
||||
#define LUAI_UACNUMBER double
|
||||
#define LUA_NUMBER_SCAN "%lf"
|
||||
#define LUA_NUMBER_FMT "%.14g"
|
||||
#define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n))
|
||||
#define LUAI_MAXNUMBER2STR 32
|
||||
#define LUA_INTFRMLEN "l"
|
||||
#define LUA_INTFRM_T long
|
||||
|
||||
/* Linkage of public API functions. */
|
||||
#if defined(LUA_BUILD_AS_DLL)
|
||||
#if defined(LUA_CORE) || defined(LUA_LIB)
|
||||
#define LUA_API __declspec(dllexport)
|
||||
#else
|
||||
#define LUA_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define LUA_API extern
|
||||
#endif
|
||||
|
||||
#define LUALIB_API LUA_API
|
||||
|
||||
/* Support for internal assertions. */
|
||||
#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#ifdef LUA_USE_ASSERT
|
||||
#define lua_assert(x) assert(x)
|
||||
#endif
|
||||
#ifdef LUA_USE_APICHECK
|
||||
#define luai_apicheck(L, o) { (void)L; assert(o); }
|
||||
#else
|
||||
#define luai_apicheck(L, o) { (void)L; }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
79
include/lua/luajit.h
Normal file
79
include/lua/luajit.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
** LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
|
||||
**
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
*/
|
||||
|
||||
#ifndef _LUAJIT_H
|
||||
#define _LUAJIT_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#define LUAJIT_VERSION "LuaJIT 2.1.0-beta3"
|
||||
#define LUAJIT_VERSION_NUM 20100 /* Version 2.1.0 = 02.01.00. */
|
||||
#define LUAJIT_VERSION_SYM luaJIT_version_2_1_0_beta3
|
||||
#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2017 Mike Pall"
|
||||
#define LUAJIT_URL "http://luajit.org/"
|
||||
|
||||
/* Modes for luaJIT_setmode. */
|
||||
#define LUAJIT_MODE_MASK 0x00ff
|
||||
|
||||
enum {
|
||||
LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */
|
||||
LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */
|
||||
|
||||
LUAJIT_MODE_FUNC, /* Change mode for a function. */
|
||||
LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */
|
||||
LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */
|
||||
|
||||
LUAJIT_MODE_TRACE, /* Flush a compiled trace. */
|
||||
|
||||
LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */
|
||||
|
||||
LUAJIT_MODE_MAX
|
||||
};
|
||||
|
||||
/* Flags or'ed in to the mode. */
|
||||
#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */
|
||||
#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */
|
||||
#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */
|
||||
|
||||
/* LuaJIT public C API. */
|
||||
|
||||
/* Control the JIT engine. */
|
||||
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
|
||||
|
||||
/* Low-overhead profiling API. */
|
||||
typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
|
||||
int samples, int vmstate);
|
||||
LUA_API void luaJIT_profile_start(lua_State *L, const char *mode,
|
||||
luaJIT_profile_callback cb, void *data);
|
||||
LUA_API void luaJIT_profile_stop(lua_State *L);
|
||||
LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt,
|
||||
int depth, size_t *len);
|
||||
|
||||
/* Enforce (dynamic) linker error for version mismatches. Call from main. */
|
||||
LUA_API void LUAJIT_VERSION_SYM(void);
|
||||
|
||||
#endif
|
||||
43
include/lua/lualib.h
Normal file
43
include/lua/lualib.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
** Standard library header.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LUALIB_H
|
||||
#define _LUALIB_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#define LUA_FILEHANDLE "FILE*"
|
||||
|
||||
#define LUA_COLIBNAME "coroutine"
|
||||
#define LUA_MATHLIBNAME "math"
|
||||
#define LUA_STRLIBNAME "string"
|
||||
#define LUA_TABLIBNAME "table"
|
||||
#define LUA_IOLIBNAME "io"
|
||||
#define LUA_OSLIBNAME "os"
|
||||
#define LUA_LOADLIBNAME "package"
|
||||
#define LUA_DBLIBNAME "debug"
|
||||
#define LUA_BITLIBNAME "bit"
|
||||
#define LUA_JITLIBNAME "jit"
|
||||
#define LUA_FFILIBNAME "ffi"
|
||||
|
||||
LUALIB_API int luaopen_base(lua_State *L);
|
||||
LUALIB_API int luaopen_math(lua_State *L);
|
||||
LUALIB_API int luaopen_string(lua_State *L);
|
||||
LUALIB_API int luaopen_table(lua_State *L);
|
||||
LUALIB_API int luaopen_io(lua_State *L);
|
||||
LUALIB_API int luaopen_os(lua_State *L);
|
||||
LUALIB_API int luaopen_package(lua_State *L);
|
||||
LUALIB_API int luaopen_debug(lua_State *L);
|
||||
LUALIB_API int luaopen_bit(lua_State *L);
|
||||
LUALIB_API int luaopen_jit(lua_State *L);
|
||||
LUALIB_API int luaopen_ffi(lua_State *L);
|
||||
|
||||
LUALIB_API void luaL_openlibs(lua_State *L);
|
||||
|
||||
#ifndef lua_assert
|
||||
#define lua_assert(x) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 6/17/21
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <string>
|
||||
#include "BeamNG.h"
|
||||
#undef UNICODE
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
uint32_t BeamNG::GetProcessID() {
|
||||
SetLastError(0);
|
||||
PROCESSENTRY32 pe32;
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
|
||||
if(Process32First(Snapshot, &pe32)) {
|
||||
do{
|
||||
if(std::string("BeamNG.drive.x64.exe") == pe32.szExeFile)break;
|
||||
}while(Process32Next(Snapshot, &pe32));
|
||||
}
|
||||
|
||||
if(Snapshot != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(Snapshot);
|
||||
}
|
||||
|
||||
if(GetLastError() != 0)return 0;
|
||||
return pe32.th32ProcessID;
|
||||
}
|
||||
|
||||
size_t BeamNG::GetModuleBase(const char* Name) {
|
||||
return (size_t)GetModuleHandleA(Name);
|
||||
}
|
||||
@@ -4,11 +4,11 @@
|
||||
///
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "Memory/Memory.h"
|
||||
#include "Launcher.h"
|
||||
#include "Logger.h"
|
||||
#include "BeamNG.h"
|
||||
#include "Http.h"
|
||||
#include <csignal>
|
||||
#include "Http.h"
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <ShlObj.h>
|
||||
@@ -81,7 +81,7 @@ void Launcher::WindowsInit() {
|
||||
}
|
||||
|
||||
void Launcher::LaunchGame() {
|
||||
if(BeamNG::GetProcessID() != 0) {
|
||||
if(Memory::GetBeamNGPID() != 0) {
|
||||
LOG(FATAL) << "Game is already running, please close it and try again!";
|
||||
throw ShutdownException("Fatal Error");
|
||||
}
|
||||
@@ -105,7 +105,7 @@ void Launcher::LaunchGame() {
|
||||
void Launcher::WaitForGame() {
|
||||
LOG(INFO) << "Waiting for the game, please start BeamNG manually in case of steam issues";
|
||||
do{
|
||||
GamePID = BeamNG::GetProcessID();
|
||||
GamePID = Memory::GetBeamNGPID();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
}while(GamePID == 0 && !Shutdown.load());
|
||||
if(Shutdown.load())return;
|
||||
@@ -114,9 +114,10 @@ void Launcher::WaitForGame() {
|
||||
throw ShutdownException("Fatal Error");
|
||||
}
|
||||
LOG(INFO) << "Game found! PID " << GamePID;
|
||||
Memory::Inject(GamePID);
|
||||
//TODO: start IPC
|
||||
setDiscordMessage("In menus");
|
||||
//TODO: Inject then start IPC
|
||||
while(!Shutdown.load() && BeamNG::GetProcessID() != 0) {
|
||||
while(!Shutdown.load() && Memory::GetBeamNGPID() != 0) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
}
|
||||
LOG(INFO) << "Game process was lost";
|
||||
|
||||
28
src/Memory/BeamNG.cpp
Normal file
28
src/Memory/BeamNG.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#include "Memory/Patterns.h"
|
||||
#include "Memory/BeamNG.h"
|
||||
#include "Memory/Memory.h"
|
||||
|
||||
std::string GetHex(uint64_t num) {
|
||||
char buffer[30];
|
||||
sprintf(buffer, "%llx", num);
|
||||
return std::string{buffer};
|
||||
}
|
||||
|
||||
void BeamNG::EntryPoint() {
|
||||
auto GameBaseAddr = Memory::GetModuleBase("BeamNG.drive.x64.exe");
|
||||
auto DllBaseAddr = Memory::GetModuleBase("libbeamng.x64.dll");
|
||||
Memory::Print("PID : " + std::to_string(Memory::GetPID()));
|
||||
|
||||
auto res = Memory::FindByPattern("BeamNG.drive.x64.exe", Patterns::GetTickCount[0], Patterns::GetTickCount[1]);
|
||||
auto res2 = Memory::FindByPattern("BeamNG.drive.x64.exe", Patterns::open_jit[0], Patterns::open_jit[1]);
|
||||
auto res3 = Memory::FindByPattern("BeamNG.drive.x64.exe", Patterns::get_field[0], Patterns::get_field[1]);
|
||||
auto res4 = Memory::FindByPattern("BeamNG.drive.x64.exe", Patterns::push_fstring[0], Patterns::push_fstring[1]);
|
||||
auto res5 = Memory::FindByPattern("BeamNG.drive.x64.exe", Patterns::p_call[0], Patterns::p_call[1]);
|
||||
|
||||
|
||||
}
|
||||
29
src/Memory/Detours.cpp
Normal file
29
src/Memory/Detours.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "Memory/Detours.h"
|
||||
#include <windows.h>
|
||||
#include "detours/detours.h"
|
||||
|
||||
void Detours::Attach() {
|
||||
if(!Attached){
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourAttach(&targetPtr,detourFunc);
|
||||
DetourTransactionCommit();
|
||||
Attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Detours::Detach() {
|
||||
if(Attached){
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourDetach(&targetPtr,detourFunc);
|
||||
DetourTransactionCommit();
|
||||
Attached = false;
|
||||
}
|
||||
}
|
||||
131
src/Memory/Memory.cpp
Normal file
131
src/Memory/Memory.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 1/21/22
|
||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||
///
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#undef UNICODE
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <psapi.h>
|
||||
#include "Memory/Memory.h"
|
||||
#include "Memory/BeamNG.h"
|
||||
|
||||
uint32_t Memory::GetBeamNGPID() {
|
||||
SetLastError(0);
|
||||
PROCESSENTRY32 pe32;
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
|
||||
if(Process32First(Snapshot, &pe32)) {
|
||||
do{
|
||||
if(std::string("BeamNG.drive.x64.exe") == pe32.szExeFile)break;
|
||||
}while(Process32Next(Snapshot, &pe32));
|
||||
}
|
||||
|
||||
if(Snapshot != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(Snapshot);
|
||||
}
|
||||
|
||||
if(GetLastError() != 0)return 0;
|
||||
return pe32.th32ProcessID;
|
||||
}
|
||||
|
||||
uint64_t Memory::GetModuleBase(const char* Name) {
|
||||
return (uint64_t)GetModuleHandleA(Name);
|
||||
}
|
||||
|
||||
uint32_t Memory::GetPID() {
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
|
||||
uint64_t Memory::FindByPattern(const char* module, const char* Pattern, const char* Mask) {
|
||||
MODULEINFO mInfo{nullptr};
|
||||
GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(module), &mInfo, sizeof(MODULEINFO));
|
||||
auto base = uint64_t(mInfo.lpBaseOfDll);
|
||||
auto size = uint32_t(mInfo.SizeOfImage);
|
||||
auto len = strlen(Mask);
|
||||
|
||||
for(auto i = 0; i < size - len; i++) {
|
||||
bool found = true;
|
||||
for(auto j = 0; j < len && found; j++) {
|
||||
found &= Mask[j] == '?' || Pattern[j] == *(char*)(base+i+j);
|
||||
}
|
||||
if(found) {
|
||||
return base+i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void* operator new(size_t size) {
|
||||
return GlobalAlloc(GPTR, size);
|
||||
}
|
||||
|
||||
void* operator new[](size_t size) {
|
||||
return GlobalAlloc(GPTR, size);
|
||||
}
|
||||
|
||||
void operator delete(void* p) noexcept {
|
||||
GlobalFree(p);
|
||||
}
|
||||
|
||||
void operator delete[](void* p) noexcept {
|
||||
GlobalFree(p);
|
||||
}
|
||||
|
||||
typedef struct BASE_RELOCATION_ENTRY {
|
||||
USHORT Offset : 12;
|
||||
USHORT Type : 4;
|
||||
} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY;
|
||||
|
||||
void Memory::Inject(uint32_t PID) {
|
||||
PVOID imageBase = GetModuleHandle(nullptr);
|
||||
auto dosHeader = (PIMAGE_DOS_HEADER)imageBase;
|
||||
auto ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeader->e_lfanew);
|
||||
|
||||
PVOID localImage = VirtualAlloc(nullptr, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE);
|
||||
memcpy(localImage, imageBase, ntHeader->OptionalHeader.SizeOfImage);
|
||||
|
||||
HANDLE targetProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, PID);
|
||||
PVOID targetImage = VirtualAllocEx(targetProcess, nullptr, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
DWORD_PTR deltaImageBase = DWORD_PTR(targetImage) - DWORD_PTR(imageBase);
|
||||
|
||||
auto relocationTable = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)localImage + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
||||
PDWORD_PTR patchedAddress;
|
||||
while (relocationTable->SizeOfBlock > 0){
|
||||
DWORD relocationEntriesCount = (relocationTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
|
||||
auto relocationRVA = (PBASE_RELOCATION_ENTRY)(relocationTable + 1);
|
||||
for (uint32_t i = 0; i < relocationEntriesCount; i++){
|
||||
if (relocationRVA[i].Offset){
|
||||
patchedAddress = PDWORD_PTR(DWORD_PTR(localImage) + relocationTable->VirtualAddress + relocationRVA[i].Offset);
|
||||
*patchedAddress += deltaImageBase;
|
||||
}
|
||||
}
|
||||
relocationTable = PIMAGE_BASE_RELOCATION(DWORD_PTR(relocationTable) + relocationTable->SizeOfBlock);
|
||||
}
|
||||
WriteProcessMemory(targetProcess, targetImage, localImage, ntHeader->OptionalHeader.SizeOfImage, nullptr);
|
||||
CreateRemoteThread(targetProcess,nullptr,0,(LPTHREAD_START_ROUTINE)((DWORD_PTR)EntryPoint + deltaImageBase),nullptr,0,nullptr);
|
||||
CloseHandle(targetProcess);
|
||||
}
|
||||
|
||||
void Memory::Print(const std::string& msg) {
|
||||
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (stdOut != nullptr && stdOut != INVALID_HANDLE_VALUE) {
|
||||
DWORD written = 0;
|
||||
WriteConsoleA(stdOut, "[BeamMP] ", 9, &written, nullptr);
|
||||
WriteConsoleA(stdOut, msg.c_str(), DWORD(msg.size()), &written, nullptr);
|
||||
WriteConsoleA(stdOut, "\n", 1, &written, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Memory::EntryPoint() {
|
||||
AllocConsole();
|
||||
SetConsoleTitleA("BeamMP Console");
|
||||
BeamNG::EntryPoint();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user