mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Implement sys v abi on x64 partially.
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @@ -108,6 +108,7 @@ JANET_CORE_SOURCES=src/core/abstract.c \ | |||||||
| 				   src/core/debug.c \ | 				   src/core/debug.c \ | ||||||
| 				   src/core/emit.c \ | 				   src/core/emit.c \ | ||||||
| 				   src/core/ev.c \ | 				   src/core/ev.c \ | ||||||
|  | 				   src/core/ffi.c \ | ||||||
| 				   src/core/fiber.c \ | 				   src/core/fiber.c \ | ||||||
| 				   src/core/gc.c \ | 				   src/core/gc.c \ | ||||||
| 				   src/core/inttypes.c \ | 				   src/core/inttypes.c \ | ||||||
|   | |||||||
| @@ -76,6 +76,7 @@ conf.set('JANET_SIMPLE_GETLINE', get_option('simple_getline')) | |||||||
| conf.set('JANET_EV_NO_EPOLL', not get_option('epoll')) | conf.set('JANET_EV_NO_EPOLL', not get_option('epoll')) | ||||||
| conf.set('JANET_EV_NO_KQUEUE', not get_option('kqueue')) | conf.set('JANET_EV_NO_KQUEUE', not get_option('kqueue')) | ||||||
| conf.set('JANET_NO_INTERPRETER_INTERRUPT', not get_option('interpreter_interrupt')) | conf.set('JANET_NO_INTERPRETER_INTERRUPT', not get_option('interpreter_interrupt')) | ||||||
|  | conf.set('JANET_NO_FFI', not get_option('ffi')) | ||||||
| if get_option('os_name') != '' | if get_option('os_name') != '' | ||||||
|   conf.set('JANET_OS_NAME', get_option('os_name')) |   conf.set('JANET_OS_NAME', get_option('os_name')) | ||||||
| endif | endif | ||||||
| @@ -116,6 +117,7 @@ core_src = [ | |||||||
|   'src/core/debug.c', |   'src/core/debug.c', | ||||||
|   'src/core/emit.c', |   'src/core/emit.c', | ||||||
|   'src/core/ev.c', |   'src/core/ev.c', | ||||||
|  |   'src/core/ffi.c', | ||||||
|   'src/core/fiber.c', |   'src/core/fiber.c', | ||||||
|   'src/core/gc.c', |   'src/core/gc.c', | ||||||
|   'src/core/inttypes.c', |   'src/core/inttypes.c', | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ option('simple_getline', type : 'boolean', value : false) | |||||||
| option('epoll', type : 'boolean', value : false) | option('epoll', type : 'boolean', value : false) | ||||||
| option('kqueue', type : 'boolean', value : false) | option('kqueue', type : 'boolean', value : false) | ||||||
| option('interpreter_interrupt', type : 'boolean', value : false) | option('interpreter_interrupt', type : 'boolean', value : false) | ||||||
|  | option('ffi', type : 'boolean', value : true) | ||||||
|  |  | ||||||
| option('recursion_guard', type : 'integer', min : 10, max : 8000, value : 1024) | option('recursion_guard', type : 'integer', min : 10, max : 8000, value : 1024) | ||||||
| option('max_proto_depth', type : 'integer', min : 10, max : 8000, value : 200) | option('max_proto_depth', type : 'integer', min : 10, max : 8000, value : 200) | ||||||
|   | |||||||
| @@ -3938,6 +3938,7 @@ | |||||||
|      "src/core/debug.c" |      "src/core/debug.c" | ||||||
|      "src/core/emit.c" |      "src/core/emit.c" | ||||||
|      "src/core/ev.c" |      "src/core/ev.c" | ||||||
|  |      "src/core/ffi.c" | ||||||
|      "src/core/fiber.c" |      "src/core/fiber.c" | ||||||
|      "src/core/gc.c" |      "src/core/gc.c" | ||||||
|      "src/core/inttypes.c" |      "src/core/inttypes.c" | ||||||
|   | |||||||
| @@ -260,11 +260,27 @@ int32_t janet_getinteger(const Janet *argv, int32_t n) { | |||||||
| } | } | ||||||
|  |  | ||||||
| int64_t janet_getinteger64(const Janet *argv, int32_t n) { | int64_t janet_getinteger64(const Janet *argv, int32_t n) { | ||||||
|  | #ifdef JANET_INTTYPES | ||||||
|  |     return janet_unwrap_s64(argv[n]); | ||||||
|  | #else | ||||||
|     Janet x = argv[n]; |     Janet x = argv[n]; | ||||||
|     if (!janet_checkint64(x)) { |     if (!janet_checkint64(x)) { | ||||||
|         janet_panicf("bad slot #%d, expected 64 bit signed integer, got %v", n, x); |         janet_panicf("bad slot #%d, expected 64 bit signed integer, got %v", n, x); | ||||||
|     } |     } | ||||||
|     return (int64_t) janet_unwrap_number(x); |     return (int64_t) janet_unwrap_number(x); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint64_t janet_getuinteger64(const Janet *argv, int32_t n) { | ||||||
|  | #ifdef JANET_INTTYPES | ||||||
|  |     return janet_unwrap_u64(argv[n]); | ||||||
|  | #else | ||||||
|  |     Janet x = argv[n]; | ||||||
|  |     if (!janet_checkint64(x)) { | ||||||
|  |         janet_panicf("bad slot #%d, expected 64 bit unsigned integer, got %v", n, x); | ||||||
|  |     } | ||||||
|  |     return (uint64_t) janet_unwrap_number(x); | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| size_t janet_getsize(const Janet *argv, int32_t n) { | size_t janet_getsize(const Janet *argv, int32_t n) { | ||||||
|   | |||||||
| @@ -1074,6 +1074,9 @@ static void janet_load_libs(JanetTable *env) { | |||||||
| #ifdef JANET_NET | #ifdef JANET_NET | ||||||
|     janet_lib_net(env); |     janet_lib_net(env); | ||||||
| #endif | #endif | ||||||
|  | #ifdef JANET_FFI | ||||||
|  |     janet_lib_ffi(env); | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef JANET_BOOTSTRAP | #ifdef JANET_BOOTSTRAP | ||||||
|   | |||||||
							
								
								
									
										312
									
								
								src/core/ffi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/core/ffi.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | |||||||
|  | /* | ||||||
|  | * Copyright (c) 2022 Calvin Rose | ||||||
|  | * | ||||||
|  | * 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. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | #ifndef JANET_AMALG | ||||||
|  | #include "features.h" | ||||||
|  | #include <janet.h> | ||||||
|  | #include "util.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef JANET_FFI | ||||||
|  |  | ||||||
|  | static uint64_t test_function(int32_t a, int32_t b, const char *s) { | ||||||
|  |     printf("a = %d\n", a); | ||||||
|  |     printf("b = %d\n", b); | ||||||
|  |     uint64_t ret = a + b; | ||||||
|  |     printf("string: %s\n", s); | ||||||
|  |     printf("hello from test function. Returning %lu.\n", ret); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | JANET_CORE_FN(cfun_ffi_get_test_pointer, | ||||||
|  |         "(ffi/get-test-pointer)", | ||||||
|  |         "Get a test pointer to call using ffi.") { | ||||||
|  |     janet_fixarity(argc, 0); | ||||||
|  |     (void) argv; | ||||||
|  |     return janet_wrap_pointer(test_function); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |     JANET_FFI_TYPE_VOID, | ||||||
|  |     JANET_FFI_TYPE_SHORT, | ||||||
|  |     JANET_FFI_TYPE_INT, | ||||||
|  |     JANET_FFI_TYPE_LONG, | ||||||
|  |     JANET_FFI_TYPE_USHORT, | ||||||
|  |     JANET_FFI_TYPE_UINT, | ||||||
|  |     JANET_FFI_TYPE_ULONG, | ||||||
|  |     JANET_FFI_TYPE_BOOL, | ||||||
|  |     JANET_FFI_TYPE_PTR, | ||||||
|  |     JANET_FFI_TYPE_FLOAT, | ||||||
|  |     JANET_FFI_TYPE_DOUBLE, | ||||||
|  |     JANET_FFI_TYPE_INT8, | ||||||
|  |     JANET_FFI_TYPE_UINT8, | ||||||
|  |     JANET_FFI_TYPE_INT16, | ||||||
|  |     JANET_FFI_TYPE_UINT16, | ||||||
|  |     JANET_FFI_TYPE_INT32, | ||||||
|  |     JANET_FFI_TYPE_UINT32, | ||||||
|  |     JANET_FFI_TYPE_INT64, | ||||||
|  |     JANET_FFI_TYPE_UINT64, | ||||||
|  | } JanetFFIPrimType; | ||||||
|  |  | ||||||
|  | static const size_t janet_ffi_type_sizes[] = { | ||||||
|  |     0, /* JANET_FFI_TYPE_VOID */ | ||||||
|  |     sizeof(short), /* JANET_FFI_TYPE_SHORT */ | ||||||
|  |     sizeof(int), /* JANET_FFI_TYPE_INT */ | ||||||
|  |     sizeof(long), /* JANET_FFI_TYPE_LONG */ | ||||||
|  |     sizeof(unsigned short), /* JANET_FFI_TYPE_USHORT */ | ||||||
|  |     sizeof(unsigned), /* JANET_FFI_TYPE_UINT */ | ||||||
|  |     sizeof(unsigned long), /* JANET_FFI_TYPE_ULONG */ | ||||||
|  |     sizeof(char), /* JANET_FFI_TYPE_BOOL */ | ||||||
|  |     sizeof(void *), /* JANET_FFI_TYPE_PTR */ | ||||||
|  |     sizeof(float), /* JANET_FFI_TYPE_FLOAT */ | ||||||
|  |     sizeof(double), /* JANET_FFI_TYPE_DOUBLE */ | ||||||
|  |     sizeof(int8_t), /* JANET_FFI_TYPE_INT8 */ | ||||||
|  |     sizeof(uint8_t), /* JANET_FFI_TYPE_UINT8 */ | ||||||
|  |     sizeof(int16_t), /* JANET_FFI_TYPE_INT16 */ | ||||||
|  |     sizeof(uint16_t), /* JANET_FFI_TYPE_UINT16 */ | ||||||
|  |     sizeof(int32_t), /* JANET_FFI_TYPE_INT32 */ | ||||||
|  |     sizeof(uint32_t), /* JANET_FFI_TYPE_UINT32 */ | ||||||
|  |     sizeof(int64_t), /* JANET_FFI_TYPE_INT64 */ | ||||||
|  |     sizeof(uint64_t) /* JANET_FFI_TYPE_UINT64 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |     JANET_FFI_CC_SYSV_64 | ||||||
|  | } JanetFFICallingConvention; | ||||||
|  |  | ||||||
|  | #define JANET_FFI_MAX_REGS 16 | ||||||
|  | #define JANET_FFI_MAX_STACK 32 | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     uint32_t frame_size; | ||||||
|  |     uint32_t reg_count; | ||||||
|  |     uint32_t stack_count; | ||||||
|  |     uint32_t arg_count; | ||||||
|  |     JanetFFICallingConvention cc; | ||||||
|  |     JanetFFIPrimType ret_type; | ||||||
|  |     JanetFFIPrimType regs[JANET_FFI_MAX_REGS]; | ||||||
|  |     JanetFFIPrimType stack[JANET_FFI_MAX_STACK]; | ||||||
|  | } JanetFFISignature; | ||||||
|  |  | ||||||
|  | static const JanetAbstractType janet_signature_type = { | ||||||
|  |     "core/ffi-signature", | ||||||
|  |     JANET_ATEND_NAME | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static JanetFFICallingConvention decode_ffi_cc(const uint8_t *name) { | ||||||
|  |     /* TODO */ | ||||||
|  |     (void) name; | ||||||
|  |     return JANET_FFI_CC_SYSV_64; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static JanetFFIPrimType decode_ffi_prim(const uint8_t *name) { | ||||||
|  |     if (!janet_cstrcmp(name, "void")) return JANET_FFI_TYPE_VOID; | ||||||
|  |     if (!janet_cstrcmp(name, "short")) return JANET_FFI_TYPE_SHORT; | ||||||
|  |     if (!janet_cstrcmp(name, "int")) return JANET_FFI_TYPE_INT; | ||||||
|  |     if (!janet_cstrcmp(name, "long")) return JANET_FFI_TYPE_LONG; | ||||||
|  |     if (!janet_cstrcmp(name, "ushort")) return JANET_FFI_TYPE_USHORT; | ||||||
|  |     if (!janet_cstrcmp(name, "uint")) return JANET_FFI_TYPE_UINT; | ||||||
|  |     if (!janet_cstrcmp(name, "ulong")) return JANET_FFI_TYPE_ULONG; | ||||||
|  |     if (!janet_cstrcmp(name, "bool")) return JANET_FFI_TYPE_BOOL; | ||||||
|  |     if (!janet_cstrcmp(name, "ptr")) return JANET_FFI_TYPE_PTR; | ||||||
|  |     if (!janet_cstrcmp(name, "float")) return JANET_FFI_TYPE_FLOAT; | ||||||
|  |     if (!janet_cstrcmp(name, "double")) return JANET_FFI_TYPE_DOUBLE; | ||||||
|  |     if (!janet_cstrcmp(name, "int8")) return JANET_FFI_TYPE_INT8; | ||||||
|  |     if (!janet_cstrcmp(name, "uint8")) return JANET_FFI_TYPE_UINT8; | ||||||
|  |     if (!janet_cstrcmp(name, "int16")) return JANET_FFI_TYPE_INT16; | ||||||
|  |     if (!janet_cstrcmp(name, "uint16")) return JANET_FFI_TYPE_UINT16; | ||||||
|  |     if (!janet_cstrcmp(name, "int32")) return JANET_FFI_TYPE_INT32; | ||||||
|  |     if (!janet_cstrcmp(name, "uint32")) return JANET_FFI_TYPE_UINT32; | ||||||
|  |     if (!janet_cstrcmp(name, "int64")) return JANET_FFI_TYPE_INT64; | ||||||
|  |     if (!janet_cstrcmp(name, "uint64")) return JANET_FFI_TYPE_UINT64; | ||||||
|  |     janet_panicf("unknown machine type %s", name); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | JANET_CORE_FN(cfun_ffi_signature, | ||||||
|  |         "(ffi/signature calling-convention ret-type & arg-types)", | ||||||
|  |         "Create a function signature object that can be used to make calls " | ||||||
|  |         "with raw function pointers.") { | ||||||
|  |     janet_arity(argc, 2, -1); | ||||||
|  |     uint32_t frame_size = 0; | ||||||
|  |     uint32_t reg_count = 0; | ||||||
|  |     uint32_t stack_count = 0; | ||||||
|  |     JanetFFICallingConvention cc = decode_ffi_cc(janet_getkeyword(argv, 0)); | ||||||
|  |     JanetFFIPrimType ret_type = decode_ffi_prim(janet_getkeyword(argv, 1)); | ||||||
|  |     uint32_t max_regs = JANET_FFI_MAX_REGS; | ||||||
|  |     JanetFFIPrimType regs[JANET_FFI_MAX_REGS]; | ||||||
|  |     JanetFFIPrimType stack[JANET_FFI_MAX_STACK]; | ||||||
|  |     for (int i = 0; i < JANET_FFI_MAX_REGS; i++) regs[i] = JANET_FFI_TYPE_VOID; | ||||||
|  |     for (int i = 0; i < JANET_FFI_MAX_STACK; i++) stack[i] = JANET_FFI_TYPE_VOID; | ||||||
|  |     switch (cc) { | ||||||
|  |         default: | ||||||
|  |             break; | ||||||
|  |         case JANET_FFI_CC_SYSV_64: | ||||||
|  |             max_regs = 6; | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |     for (int32_t i = 2; i < argc; i++) { | ||||||
|  |         JanetFFIPrimType ptype = decode_ffi_prim(janet_getkeyword(argv, i)); | ||||||
|  |         if (reg_count < max_regs) { | ||||||
|  |             regs[reg_count++] = ptype; | ||||||
|  |         } else { | ||||||
|  |             stack[stack_count++] = ptype; | ||||||
|  |             frame_size += janet_ffi_type_sizes[ptype]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     JanetFFISignature *abst = janet_abstract(&janet_signature_type, sizeof(JanetFFISignature)); | ||||||
|  |     abst->frame_size = frame_size; | ||||||
|  |     abst->reg_count = reg_count; | ||||||
|  |     abst->stack_count = stack_count; | ||||||
|  |     abst->cc = cc; | ||||||
|  |     abst->ret_type = ret_type; | ||||||
|  |     abst->arg_count = stack_count + reg_count; | ||||||
|  |     memcpy(abst->regs, regs, sizeof(JanetFFIPrimType) * JANET_FFI_MAX_REGS); | ||||||
|  |     memcpy(abst->stack, stack, sizeof(JanetFFIPrimType) * JANET_FFI_MAX_STACK); | ||||||
|  |     return janet_wrap_abstract(abst); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void *janet_ffi_getpointer(const Janet *argv, int32_t n) { | ||||||
|  |     switch(janet_type(argv[n])) { | ||||||
|  |         default: | ||||||
|  |             janet_panicf("bad slot #%d, expected pointer convertable type, got %v", argv[n]); | ||||||
|  |         case JANET_POINTER: | ||||||
|  |         case JANET_STRING: | ||||||
|  |         case JANET_KEYWORD: | ||||||
|  |         case JANET_SYMBOL: | ||||||
|  |             return janet_unwrap_pointer(argv[n]); | ||||||
|  |         case JANET_BUFFER: | ||||||
|  |             return janet_unwrap_buffer(argv[n])->data; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | JANET_CORE_FN(cfun_ffi_call, | ||||||
|  |         "(ffi/call pointer signature & args)", | ||||||
|  |         "Call a raw pointer as a function pointer. The function signature specifies " | ||||||
|  |         "how Janet values in `args` are converted to native machine types.") { | ||||||
|  |     janet_arity(argc, 2, -1); | ||||||
|  |     void *function_pointer = janet_getpointer(argv, 0); | ||||||
|  |     JanetFFISignature *signature = janet_getabstract(argv, 1, &janet_signature_type); | ||||||
|  |     janet_fixarity(argc - 2, signature->arg_count); | ||||||
|  |  | ||||||
|  |     uint64_t regs[6]; | ||||||
|  |     for (uint32_t i = 0; i < signature->reg_count; i++) { | ||||||
|  |         switch (signature->regs[i]) { | ||||||
|  |             case JANET_FFI_TYPE_FLOAT: | ||||||
|  |             case JANET_FFI_TYPE_DOUBLE: | ||||||
|  |                 janet_panic("nyi"); | ||||||
|  |                 break; | ||||||
|  |             case JANET_FFI_TYPE_VOID: | ||||||
|  |                 regs[i] = 0; | ||||||
|  |                 continue; | ||||||
|  |             case JANET_FFI_TYPE_PTR: | ||||||
|  |                 regs[i] = (uint64_t) janet_ffi_getpointer(argv, i + 2); | ||||||
|  |                 break; | ||||||
|  |             case JANET_FFI_TYPE_BOOL: | ||||||
|  |                 regs[i] = (uint64_t) janet_getboolean(argv, i + 2); | ||||||
|  |                 break; | ||||||
|  |             case JANET_FFI_TYPE_SHORT: | ||||||
|  |             case JANET_FFI_TYPE_INT: | ||||||
|  |             case JANET_FFI_TYPE_INT8: | ||||||
|  |             case JANET_FFI_TYPE_INT16: | ||||||
|  |             case JANET_FFI_TYPE_INT32: | ||||||
|  |             case JANET_FFI_TYPE_INT64: | ||||||
|  |             case JANET_FFI_TYPE_LONG: | ||||||
|  |                 regs[i] = (uint64_t) janet_getinteger64(argv, i + 2); | ||||||
|  |                 break; | ||||||
|  |             case JANET_FFI_TYPE_USHORT: | ||||||
|  |             case JANET_FFI_TYPE_UINT: | ||||||
|  |             case JANET_FFI_TYPE_UINT8: | ||||||
|  |             case JANET_FFI_TYPE_UINT16: | ||||||
|  |             case JANET_FFI_TYPE_UINT32: | ||||||
|  |             case JANET_FFI_TYPE_UINT64: | ||||||
|  |             case JANET_FFI_TYPE_ULONG: | ||||||
|  |                 regs[i] = janet_getuinteger64(argv, i + 2); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Danger zone */ | ||||||
|  |     uint64_t ret, rethi; | ||||||
|  |     __asm__("mov %3, %%rdi\n\t" | ||||||
|  |             "mov %4, %%rsi\n\t" | ||||||
|  |             "mov %5, %%rdx\n\t" | ||||||
|  |             "mov %6, %%rcx\n\t" | ||||||
|  |             "mov %7, %%r8\n\t" | ||||||
|  |             "mov %8, %%r9\n\t" | ||||||
|  |             "call *%2\n\t" | ||||||
|  |             "mov %%rax, %0\n\t" | ||||||
|  |             "mov %%rdx, %1" | ||||||
|  |             : "=g" (ret), "=g" (rethi) | ||||||
|  |             : "g"(function_pointer), | ||||||
|  |                 "g"(regs[0]), | ||||||
|  |                 "g"(regs[1]), | ||||||
|  |                 "g"(regs[2]), | ||||||
|  |                 "g"(regs[3]), | ||||||
|  |                 "g"(regs[4]), | ||||||
|  |                 "g"(regs[5]) | ||||||
|  |             : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11");  | ||||||
|  |  | ||||||
|  |     (void) rethi; /* at some point we will support more complex return types */ | ||||||
|  |     switch (signature->ret_type) { | ||||||
|  |         case JANET_FFI_TYPE_FLOAT: | ||||||
|  |         case JANET_FFI_TYPE_DOUBLE: | ||||||
|  |             janet_panic("nyi"); | ||||||
|  |             break; | ||||||
|  |         case JANET_FFI_TYPE_VOID: | ||||||
|  |             break; | ||||||
|  |         case JANET_FFI_TYPE_PTR: | ||||||
|  |             return janet_wrap_pointer((void *) ret); | ||||||
|  |         case JANET_FFI_TYPE_BOOL: | ||||||
|  |             return janet_wrap_boolean(ret); | ||||||
|  |         case JANET_FFI_TYPE_SHORT: | ||||||
|  |         case JANET_FFI_TYPE_INT: | ||||||
|  |         case JANET_FFI_TYPE_INT8: | ||||||
|  |         case JANET_FFI_TYPE_INT16: | ||||||
|  |         case JANET_FFI_TYPE_INT32: | ||||||
|  |             return janet_wrap_integer((int32_t) ret); | ||||||
|  |         case JANET_FFI_TYPE_INT64: | ||||||
|  |         case JANET_FFI_TYPE_LONG: | ||||||
|  |             return janet_wrap_integer((int64_t) ret); | ||||||
|  |         case JANET_FFI_TYPE_USHORT: | ||||||
|  |         case JANET_FFI_TYPE_UINT: | ||||||
|  |         case JANET_FFI_TYPE_UINT8: | ||||||
|  |         case JANET_FFI_TYPE_UINT16: | ||||||
|  |         case JANET_FFI_TYPE_UINT32: | ||||||
|  |         case JANET_FFI_TYPE_UINT64: | ||||||
|  |         case JANET_FFI_TYPE_ULONG: | ||||||
|  |             return janet_wrap_number(ret); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return janet_wrap_nil(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void janet_lib_ffi(JanetTable *env) { | ||||||
|  |     JanetRegExt ffi_cfuns[] = { | ||||||
|  |         JANET_CORE_REG("ffi/get-test-pointer", cfun_ffi_get_test_pointer), | ||||||
|  |         JANET_CORE_REG("ffi/signature", cfun_ffi_signature), | ||||||
|  |         JANET_CORE_REG("ffi/call", cfun_ffi_call), | ||||||
|  |         JANET_REG_END | ||||||
|  |     }; | ||||||
|  |     janet_core_cfuns_ext(env, NULL, ffi_cfuns); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -739,6 +739,13 @@ int janet_checkint64(Janet x) { | |||||||
|     return janet_checkint64range(dval); |     return janet_checkint64range(dval); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int janet_checkuint64(Janet x) { | ||||||
|  |     if (!janet_checktype(x, JANET_NUMBER)) | ||||||
|  |         return 0; | ||||||
|  |     double dval = janet_unwrap_number(x); | ||||||
|  |     return dval >= 0 && dval <= JANET_INTMAX_DOUBLE && dval == (uint64_t) dval; | ||||||
|  | } | ||||||
|  |  | ||||||
| int janet_checksize(Janet x) { | int janet_checksize(Janet x) { | ||||||
|     if (!janet_checktype(x, JANET_NUMBER)) |     if (!janet_checktype(x, JANET_NUMBER)) | ||||||
|         return 0; |         return 0; | ||||||
|   | |||||||
| @@ -159,5 +159,8 @@ void janet_lib_ev(JanetTable *env); | |||||||
| void janet_ev_mark(void); | void janet_ev_mark(void); | ||||||
| int janet_make_pipe(JanetHandle handles[2], int mode); | int janet_make_pipe(JanetHandle handles[2], int mode); | ||||||
| #endif | #endif | ||||||
|  | #ifdef JANET_FFI | ||||||
|  | void janet_lib_ffi(JanetTable *env); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -163,6 +163,11 @@ extern "C" { | |||||||
| #define JANET_DYNAMIC_MODULES | #define JANET_DYNAMIC_MODULES | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* Enable or disable the FFI library. */ | ||||||
|  | #ifndef JANET_NO_FFI | ||||||
|  | #define JANET_FFI | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /* Enable or disable the assembler. Enabled by default. */ | /* Enable or disable the assembler. Enabled by default. */ | ||||||
| #ifndef JANET_NO_ASSEMBLER | #ifndef JANET_NO_ASSEMBLER | ||||||
| #define JANET_ASSEMBLER | #define JANET_ASSEMBLER | ||||||
| @@ -865,6 +870,7 @@ JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer); | |||||||
|  |  | ||||||
| JANET_API int janet_checkint(Janet x); | JANET_API int janet_checkint(Janet x); | ||||||
| JANET_API int janet_checkint64(Janet x); | JANET_API int janet_checkint64(Janet x); | ||||||
|  | JANET_API int janet_checkuint64(Janet x); | ||||||
| JANET_API int janet_checksize(Janet x); | JANET_API int janet_checksize(Janet x); | ||||||
| JANET_API JanetAbstract janet_checkabstract(Janet x, const JanetAbstractType *at); | JANET_API JanetAbstract janet_checkabstract(Janet x, const JanetAbstractType *at); | ||||||
| #define janet_checkintrange(x) ((x) >= INT32_MIN && (x) <= INT32_MAX && (x) == (int32_t)(x)) | #define janet_checkintrange(x) ((x) >= INT32_MIN && (x) <= INT32_MAX && (x) == (int32_t)(x)) | ||||||
| @@ -1936,6 +1942,7 @@ JANET_API void *janet_getpointer(const Janet *argv, int32_t n); | |||||||
| JANET_API int32_t janet_getnat(const Janet *argv, int32_t n); | JANET_API int32_t janet_getnat(const Janet *argv, int32_t n); | ||||||
| JANET_API int32_t janet_getinteger(const Janet *argv, int32_t n); | JANET_API int32_t janet_getinteger(const Janet *argv, int32_t n); | ||||||
| JANET_API int64_t janet_getinteger64(const Janet *argv, int32_t n); | JANET_API int64_t janet_getinteger64(const Janet *argv, int32_t n); | ||||||
|  | JANET_API uint64_t janet_getuinteger64(const Janet *argv, int32_t n); | ||||||
| JANET_API size_t janet_getsize(const Janet *argv, int32_t n); | JANET_API size_t janet_getsize(const Janet *argv, int32_t n); | ||||||
| JANET_API JanetView janet_getindexed(const Janet *argv, int32_t n); | JANET_API JanetView janet_getindexed(const Janet *argv, int32_t n); | ||||||
| JANET_API JanetByteView janet_getbytes(const Janet *argv, int32_t n); | JANET_API JanetByteView janet_getbytes(const Janet *argv, int32_t n); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose