diff options
author | MikalaiR <nikolay.romanovich@narod.ru> | 2016-02-17 16:53:59 +0000 |
---|---|---|
committer | MikalaiR <nikolay.romanovich@narod.ru> | 2016-02-17 16:53:59 +0000 |
commit | 7a8fafbb2c8a2d1175c4f92b08d1b8c30f475a4a (patch) | |
tree | c1c93b4724215879f61ee94ff9ee99a1ead49115 /plugins/MirLua/Modules/ffi/src/ffi.h | |
parent | 939e01edacc5746bc9c6501721f270751a9be10d (diff) |
MirLua: fb ffi module
git-svn-id: http://svn.miranda-ng.org/main/trunk@16294 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirLua/Modules/ffi/src/ffi.h')
-rw-r--r-- | plugins/MirLua/Modules/ffi/src/ffi.h | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/plugins/MirLua/Modules/ffi/src/ffi.h b/plugins/MirLua/Modules/ffi/src/ffi.h new file mode 100644 index 0000000000..a66f43de4c --- /dev/null +++ b/plugins/MirLua/Modules/ffi/src/ffi.h @@ -0,0 +1,455 @@ +/* vim: ts=4 sw=4 sts=4 et tw=78
+ * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved.
+ * Portions copyright (c) 2011 James R. McKaskill.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#pragma once
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#define LUA_FFI_BUILD_AS_DLL
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+# include "..\..\..\..\..\libs\liblua\src\lua.h"
+# include "..\..\..\..\..\libs\liblua\src\lauxlib.h"
+# include "..\..\..\..\..\libs\liblua\src\lualib.h"
+}
+# define EXTERN_C extern "C"
+#else
+# include "..\..\..\..\..\libs\liblua\src\lua.h"
+# include "..\..\..\..\..\libs\liblua\src\lauxlib.h"
+# include "..\..\..\..\..\libs\liblua\src\lualib.h"
+# define EXTERN_C extern
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <errno.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <sys/mman.h>
+#endif
+
+//#include <complex.h>
+//#define HAVE_COMPLEX
+#define HAVE_LONG_DOUBLE
+
+#ifndef NDEBUG
+#define DASM_CHECKS
+#endif
+
+struct jit;
+#define Dst_DECL struct jit* Dst
+#define Dst_REF (Dst->ctx)
+#define DASM_EXTERN(a,b,c,d) get_extern(a,b,c,d)
+
+#include "dynasm/dasm_proto.h"
+
+#if defined LUA_FFI_BUILD_AS_DLL
+# define EXPORT __declspec(dllexport)
+#elif defined __GNUC__
+# define EXPORT __attribute__((visibility("default")))
+#else
+# define EXPORT
+#endif
+
+EXTERN_C EXPORT int luaopen_ffi(lua_State* L);
+
+static int lua_absindex2(lua_State* L, int idx) {
+ return (LUA_REGISTRYINDEX <= idx && idx < 0)
+ ? lua_gettop(L) + idx + 1
+ : idx;
+}
+/* use our own version of lua_absindex such that lua_absindex(L, 0) == 0 */
+#define lua_absindex(L, idx) lua_absindex2(L, idx)
+
+#if LUA_VERSION_NUM == 501
+static void lua_callk(lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k)
+{
+ lua_call(L, nargs, nresults);
+}
+/*
+** set functions from list 'l' into table at top - 'nup'; each
+** function gets the 'nup' elements at the top as upvalues.
+** Returns with only the table at the stack.
+*/
+static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+ luaL_checkstack(L, nup, "too many upvalues");
+ for (; l && l->name; l++) { /* fill the table with given functions */
+ int i;
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
+ lua_setfield(L, -(nup + 2), l->name);
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+#define lua_setuservalue lua_setfenv
+#define lua_getuservalue lua_getfenv
+#define lua_rawlen lua_objlen
+static char* luaL_prepbuffsize(luaL_Buffer* B, size_t sz) {
+ if (sz > LUAL_BUFFERSIZE) {
+ luaL_error(B->L, "string too long");
+ }
+ return luaL_prepbuffer(B);
+}
+#elif LUA_VERSION_NUM == 503
+static void (lua_remove)(lua_State *L, int idx) {
+ lua_remove(L, idx);
+}
+#endif
+
+/* architectures */
+#if defined _WIN32 && defined UNDER_CE
+# define OS_CE
+#elif defined _WIN32
+# define OS_WIN
+#elif defined __APPLE__ && defined __MACH__
+# define OS_OSX
+#elif defined __linux__
+# define OS_LINUX
+#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
+# define OS_BSD
+#elif defined unix || defined __unix__ || defined __unix || defined _POSIX_VERSION || defined _XOPEN_VERSION
+# define OS_POSIX
+#endif
+
+/* architecture */
+#if defined __i386__ || defined _M_IX86
+# define ARCH_X86
+#elif defined __amd64__ || defined _M_X64
+# define ARCH_X64
+#elif defined __arm__ || defined __ARM__ || defined ARM || defined __ARM || defined __arm
+# define ARCH_ARM
+#else
+# error
+#endif
+
+
+#ifdef _WIN32
+
+# ifdef UNDER_CE
+ static void* DoLoadLibraryA(const char* name) {
+ wchar_t buf[MAX_PATH];
+ int sz = MultiByteToWideChar(CP_UTF8, 0, name, -1, buf, 512);
+ if (sz > 0) {
+ buf[sz] = 0;
+ return LoadLibraryW(buf);
+ } else {
+ return NULL;
+ }
+ }
+# define LoadLibraryA DoLoadLibraryA
+# else
+# define GetProcAddressA GetProcAddress
+# endif
+
+# define LIB_FORMAT_1 "%s.dll"
+# define AllocPage(size) VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)
+# define FreePage(data, size) VirtualFree(data, 0, MEM_RELEASE)
+# define EnableExecute(data, size) do {DWORD old; VirtualProtect(data, size, PAGE_EXECUTE, &old); FlushInstructionCache(GetCurrentProcess(), data, size);} while (0)
+# define EnableWrite(data, size) do {DWORD old; VirtualProtect(data, size, PAGE_READWRITE, &old);} while (0)
+
+#else
+#ifdef OS_OSX
+# define LIB_FORMAT_1 "%s.dylib"
+# define LIB_FORMAT_2 "lib%s.dylib"
+#else
+# define LIB_FORMAT_1 "%s.so"
+# define LIB_FORMAT_2 "lib%s.so"
+#endif
+# define LoadLibraryA(name) dlopen(name, RTLD_LAZY | RTLD_GLOBAL)
+# define GetProcAddressA(lib, name) dlsym(lib, name)
+# define AllocPage(size) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)
+# define FreePage(data, size) munmap(data, size)
+# define EnableExecute(data, size) mprotect(data, size, PROT_READ|PROT_EXEC)
+# define EnableWrite(data, size) mprotect(data, size, PROT_READ|PROT_WRITE)
+#endif
+
+#if defined ARCH_X86 || defined ARCH_X64
+#define ALLOW_MISALIGNED_ACCESS
+#endif
+
+struct token;
+
+struct parser {
+ int line;
+ const char* next;
+ const char* prev;
+ unsigned align_mask;
+};
+
+struct page {
+ size_t size;
+ size_t off;
+ size_t freed;
+};
+
+struct jit {
+ lua_State* L;
+ int32_t last_errno;
+ dasm_State* ctx;
+ size_t pagenum;
+ struct page** pages;
+ size_t align_page_size;
+ void** globals;
+ int function_extern;
+ void* lua_dll;
+ void* kernel32_dll;
+};
+
+#define ALIGN_DOWN(PTR, MASK) \
+ (((uintptr_t) (PTR)) & (~ ((uintptr_t) (MASK)) ))
+#define ALIGN_UP(PTR, MASK) \
+ (( ((uintptr_t) (PTR)) + ((uintptr_t) (MASK)) ) & (~ ((uintptr_t) (MASK)) ))
+
+/* struct cdata/struct ctype */
+
+#define PTR_ALIGN_MASK (sizeof(void*) - 1)
+#define FUNCTION_ALIGN_MASK (sizeof(void (*)()) - 1)
+#define DEFAULT_ALIGN_MASK 7
+
+#ifdef OS_OSX
+/* TODO: figure out why the alignof trick doesn't work on OS X */
+#define ALIGNED_DEFAULT 7
+#elif defined __GNUC__
+#define ALIGNED_DEFAULT (__alignof__(void* __attribute__((aligned))) - 1)
+#else
+#define ALIGNED_DEFAULT PTR_ALIGN_MASK
+#endif
+
+extern int jit_key;
+extern int ctype_mt_key;
+extern int cdata_mt_key;
+extern int cmodule_mt_key;
+extern int callback_mt_key;
+extern int constants_key;
+extern int types_key;
+extern int gc_key;
+extern int callbacks_key;
+extern int functions_key;
+extern int abi_key;
+extern int next_unnamed_key;
+extern int niluv_key;
+extern int asmname_key;
+
+int equals_upval(lua_State* L, int idx, int* key);
+void push_upval(lua_State* L, int* key);
+void set_upval(lua_State* L, int* key);
+struct jit* get_jit(lua_State* L);
+
+/* both ctype and cdata are stored as userdatas
+ *
+ * usr value is a table shared between the related subtypes which has:
+ * name -> member ctype (for structs and unions)
+ * +ves -> member ctype - in memory order (for structs)
+ * +ves -> argument ctype (for function prototypes)
+ * 0 -> return ctype (for function prototypes)
+ * light userdata -> misc
+ */
+
+enum {
+ C_CALL,
+ STD_CALL,
+ FAST_CALL,
+};
+
+enum {
+ INVALID_TYPE,
+ VOID_TYPE,
+ FLOAT_TYPE,
+ DOUBLE_TYPE,
+ LONG_DOUBLE_TYPE,
+ COMPLEX_FLOAT_TYPE,
+ COMPLEX_DOUBLE_TYPE,
+ COMPLEX_LONG_DOUBLE_TYPE,
+ BOOL_TYPE,
+ INT8_TYPE,
+ INT16_TYPE,
+ INT32_TYPE,
+ INT64_TYPE,
+ INTPTR_TYPE,
+ ENUM_TYPE,
+ UNION_TYPE,
+ STRUCT_TYPE,
+ FUNCTION_TYPE,
+ FUNCTION_PTR_TYPE,
+};
+
+#define IS_CHAR_UNSIGNED (((char) -1) > 0)
+#define IS_COMPLEX(type) ((type) == COMPLEX_FLOAT_TYPE || (type) == COMPLEX_DOUBLE_TYPE)
+
+#define POINTER_BITS 2
+#define POINTER_MAX ((1 << POINTER_BITS) - 1)
+
+#define ALIGNOF(S) ((int) ((char*) &S.v - (char*) &S - 1))
+
+/* Note: if adding a new member that is associated with a struct/union
+ * definition then it needs to be copied over in ctype.c:set_defined for when
+ * we create types based off of the declaration alone.
+ *
+ * Since this is used as a header for every ctype and cdata, and we create a
+ * ton of them on the stack, we try and minimise its size.
+ */
+struct ctype {
+ size_t base_size; /* size of the base type in bytes */
+
+ union {
+ /* valid if is_bitfield */
+ struct {
+ /* size of bitfield in bits */
+ unsigned bit_size : 7;
+ /* offset within the current byte between 0-63 */
+ unsigned bit_offset : 6;
+ };
+ /* Valid if is_array */
+ size_t array_size;
+ /* Valid for is_variable_struct or is_variable_array. If
+ * variable_size_known (only used for is_variable_struct) then this is
+ * the total increment otherwise this is the per element increment.
+ */
+ size_t variable_increment;
+ };
+ size_t offset;
+ unsigned align_mask : 4; /* as (align bytes - 1) eg 7 gives 8 byte alignment */
+ unsigned pointers : POINTER_BITS; /* number of dereferences to get to the base type including +1 for arrays */
+ unsigned const_mask : POINTER_MAX + 1; /* const pointer mask, LSB is current pointer, +1 for the whether the base type is const */
+ unsigned type : 5; /* value given by type enum above */
+ unsigned is_reference : 1;
+ unsigned is_array : 1;
+ unsigned is_defined : 1;
+ unsigned is_null : 1;
+ unsigned has_member_name : 1;
+ unsigned calling_convention : 2;
+ unsigned has_var_arg : 1;
+ unsigned is_variable_array : 1; /* set for variable array types where we don't know the variable size yet */
+ unsigned is_variable_struct : 1;
+ unsigned variable_size_known : 1; /* used for variable structs after we know the variable size */
+ unsigned is_bitfield : 1;
+ unsigned has_bitfield : 1;
+ unsigned is_jitted : 1;
+ unsigned is_packed : 1;
+ unsigned is_unsigned : 1;
+};
+
+#ifdef _MSC_VER
+__declspec(align(16))
+#endif
+struct cdata {
+ const struct ctype type
+#ifdef __GNUC__
+ __attribute__ ((aligned(16)))
+#endif
+ ;
+};
+
+typedef void (*cfunction)(void);
+
+#ifdef HAVE_COMPLEX
+typedef double complex complex_double;
+typedef float complex complex_float;
+static complex_double mk_complex_double(double real, double imag) {
+ return real + imag * 1i;
+}
+static complex_double mk_complex_float(double real, double imag) {
+ return real + imag * 1i;
+}
+#else
+typedef struct {
+ double real, imag;
+} complex_double;
+
+typedef struct {
+ float real, imag;
+} complex_float;
+
+static complex_double mk_complex_double(double real, double imag) {
+ complex_double ret = { real, imag };
+ return ret;
+}
+static complex_float mk_complex_float(double real, double imag) {
+ complex_float ret = { real, imag };
+ return ret;
+}
+static double creal(complex_double c) {
+ return c.real;
+}
+static float crealf(complex_float c) {
+ return c.real;
+}
+
+static double cimag(complex_double c) {
+ return c.imag;
+}
+static float cimagf(complex_float c) {
+ return c.imag;
+}
+#endif
+
+#define CALLBACK_FUNC_USR_IDX 1
+
+void set_defined(lua_State* L, int ct_usr, struct ctype* ct);
+struct ctype* push_ctype(lua_State* L, int ct_usr, const struct ctype* ct);
+void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct); /* called from asm */
+void push_callback(lua_State* L, cfunction luafunc, cfunction cfunc);
+void check_ctype(lua_State* L, int idx, struct ctype* ct);
+void* to_cdata(lua_State* L, int idx, struct ctype* ct);
+void* check_cdata(lua_State* L, int idx, struct ctype* ct);
+size_t ctype_size(lua_State* L, const struct ctype* ct);
+
+int parse_type(lua_State* L, struct parser* P, struct ctype* type);
+void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* type, struct token* name, struct parser* asmname);
+void push_type_name(lua_State* L, int usr, const struct ctype* ct);
+
+int push_user_mt(lua_State* L, int ct_usr, const struct ctype* ct);
+
+int ffi_cdef(lua_State* L);
+
+void push_func_ref(lua_State* L, cfunction func);
+void free_code(struct jit* jit, lua_State* L, cfunction func);
+int x86_return_size(lua_State* L, int usr, const struct ctype* ct);
+void compile_function(lua_State* L, cfunction f, int ct_usr, const struct ctype* ct);
+cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctype* ct);
+void compile_globals(struct jit* jit, lua_State* L);
+int get_extern(struct jit* jit, uint8_t* addr, int idx, int type);
+
+/* WARNING: assembly needs to be updated for prototype changes of these functions */
+int check_bool(lua_State* L, int idx);
+double check_double(lua_State* L, int idx);
+double check_complex_imag(lua_State* L, int idx);
+float check_float(lua_State* L, int idx);
+uint64_t check_uint64(lua_State* L, int idx);
+int64_t check_int64(lua_State* L, int idx);
+int32_t check_int32(lua_State* L, int idx);
+uint32_t check_uint32(lua_State* L, int idx);
+uintptr_t check_uintptr(lua_State* L, int idx);
+int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+/* these two will always push a value so that we can create structs/functions on the fly */
+void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+complex_double check_complex_double(lua_State* L, int idx);
+complex_float check_complex_float(lua_State* L, int idx);
+
+void unpack_varargs_stack(lua_State* L, int first, int last, char* to);
+void unpack_varargs_reg(lua_State* L, int first, int last, char* to);
+
+void unpack_varargs_stack_skip(lua_State* L, int first, int last, int ints_to_skip, int floats_to_skip, char* to);
+void unpack_varargs_float(lua_State* L, int first, int last, int max, char* to);
+void unpack_varargs_int(lua_State* L, int first, int last, int max, char* to);
+
+
+
|