mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Begin working on windows calling convetion.
Also remove inline assembly for making sysv64 calls. Instead, use crafted function signatures to set all needed registers.
This commit is contained in:
		
							
								
								
									
										221
									
								
								src/core/ffi.c
									
									
									
									
									
								
							
							
						
						
									
										221
									
								
								src/core/ffi.c
									
									
									
									
									
								
							| @@ -38,6 +38,9 @@ | |||||||
| #if defined(JANET_WINDOWS) && (defined(__x86_64__) || defined(_M_X64)) | #if defined(JANET_WINDOWS) && (defined(__x86_64__) || defined(_M_X64)) | ||||||
| #define JANET_FFI_WIN64_ENABLED | #define JANET_FFI_WIN64_ENABLED | ||||||
| #endif | #endif | ||||||
|  | #if (defined(__x86_64__) || defined(_M_X64)) && !defined(JANET_WINDOWS) | ||||||
|  | #define JANET_FFI_SYSV64_ENABLED | ||||||
|  | #endif | ||||||
|  |  | ||||||
| typedef struct JanetFFIType JanetFFIType; | typedef struct JanetFFIType JanetFFIType; | ||||||
| typedef struct JanetFFIStruct JanetFFIStruct; | typedef struct JanetFFIStruct JanetFFIStruct; | ||||||
| @@ -115,7 +118,9 @@ typedef enum { | |||||||
|     JANET_SYSV64_NO_CLASS, |     JANET_SYSV64_NO_CLASS, | ||||||
|     JANET_SYSV64_MEMORY, |     JANET_SYSV64_MEMORY, | ||||||
|     JANET_WIN64_REGISTER, |     JANET_WIN64_REGISTER, | ||||||
|     JANET_WIN64_STACK |     JANET_WIN64_STACK, | ||||||
|  |     JANET_WIN64_REGISTER_REF, | ||||||
|  |     JANET_WIN64_STACK_REF | ||||||
| } JanetFFIWordSpec; | } JanetFFIWordSpec; | ||||||
|  |  | ||||||
| /* Describe how each Janet argument is interpreted in terms of machine words | /* Describe how each Janet argument is interpreted in terms of machine words | ||||||
| @@ -124,6 +129,7 @@ typedef struct { | |||||||
|     JanetFFIType type; |     JanetFFIType type; | ||||||
|     JanetFFIWordSpec spec; |     JanetFFIWordSpec spec; | ||||||
|     uint32_t offset; /* point to the exact register / stack offset depending on spec. */ |     uint32_t offset; /* point to the exact register / stack offset depending on spec. */ | ||||||
|  |     uint32_t offset2; /* for reference passing apis (windows), use to allocate reference */ | ||||||
| } JanetFFIMapping; | } JanetFFIMapping; | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
| @@ -260,6 +266,21 @@ static JanetFFIPrimType decode_ffi_prim(const uint8_t *name) { | |||||||
|     janet_panicf("unknown machine type %s", name); |     janet_panicf("unknown machine type %s", name); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* A common callback function signature. To avoid runtime code generation, which is prohibited | ||||||
|  |  * on many platforms, often buggy (see libffi), and generally complicated, instead provide | ||||||
|  |  * a single (or small set of commonly used function signatures). All callbacks should | ||||||
|  |  * eventually call this. */ | ||||||
|  | void janet_ffi_trampoline(void *ctx, void *userdata) { | ||||||
|  |     if (NULL == userdata) { | ||||||
|  |         /* Userdata not set. */ | ||||||
|  |         janet_eprintf("no userdata found for janet callback"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     Janet context = janet_wrap_pointer(ctx); | ||||||
|  |     JanetFunction *fun = userdata; | ||||||
|  |     janet_call(fun, 1, &context); | ||||||
|  | } | ||||||
|  |  | ||||||
| static JanetFFIType decode_ffi_type(Janet x); | static JanetFFIType decode_ffi_type(Janet x); | ||||||
|  |  | ||||||
| static JanetFFIStruct *build_struct_type(int32_t argc, const Janet *argv) { | static JanetFFIStruct *build_struct_type(int32_t argc, const Janet *argv) { | ||||||
| @@ -481,6 +502,7 @@ static JanetFFIMapping void_mapping(void) { | |||||||
|     return m; |     return m; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef JANET_FFI_SYSV64_ENABLED | ||||||
| /* AMD64 ABI Draft 0.99.7 – November 17, 2014 – 15:08 | /* AMD64 ABI Draft 0.99.7 – November 17, 2014 – 15:08 | ||||||
|  * See section 3.2.3 Parameter Passing */ |  * See section 3.2.3 Parameter Passing */ | ||||||
| static JanetFFIWordSpec sysv64_classify(JanetFFIType type) { | static JanetFFIWordSpec sysv64_classify(JanetFFIType type) { | ||||||
| @@ -530,6 +552,7 @@ static JanetFFIWordSpec sysv64_classify(JanetFFIType type) { | |||||||
|             return JANET_SYSV64_NO_CLASS; |             return JANET_SYSV64_NO_CLASS; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| JANET_CORE_FN(cfun_ffi_signature, | JANET_CORE_FN(cfun_ffi_signature, | ||||||
|               "(native-signature calling-convention ret-type & arg-types)", |               "(native-signature calling-convention ret-type & arg-types)", | ||||||
| @@ -545,6 +568,7 @@ JANET_CORE_FN(cfun_ffi_signature, | |||||||
|     JanetFFIMapping ret = { |     JanetFFIMapping ret = { | ||||||
|         ret_type, |         ret_type, | ||||||
|         JANET_SYSV64_NO_CLASS, |         JANET_SYSV64_NO_CLASS, | ||||||
|  |         0, | ||||||
|         0 |         0 | ||||||
|     }; |     }; | ||||||
|     JanetFFIMapping mappings[JANET_FFI_MAX_ARGS]; |     JanetFFIMapping mappings[JANET_FFI_MAX_ARGS]; | ||||||
| @@ -557,26 +581,81 @@ JANET_CORE_FN(cfun_ffi_signature, | |||||||
| #ifdef JANET_FFI_WIN64_ENABLED | #ifdef JANET_FFI_WIN64_ENABLED | ||||||
|         case JANET_FFI_CC_WIN_64: { |         case JANET_FFI_CC_WIN_64: { | ||||||
|             size_t ret_size = type_size(ret.type); |             size_t ret_size = type_size(ret.type); | ||||||
|  |             size_t ref_stack_count = 0; | ||||||
|             ret.spec = JANET_WIN64_REGISTER; |             ret.spec = JANET_WIN64_REGISTER; | ||||||
|             uint32_t next_register = 0; |             uint32_t next_register = 0; | ||||||
|             if (ret_size > 8) { |             if (ret_size != 1 && ret_size != 2 && ret_size != 4 && ret_size != 8) { | ||||||
|                 ret.spec = JANET_WIN64_STACK; |                 ret.spec = JANET_WIN64_REGISTER_REF; | ||||||
|                 next_register++; |                 next_register++; | ||||||
|  |             } else if (ret.type.prim == JANET_FFI_TYPE_FLOAT || | ||||||
|  |                        ret.type.prim == JANET_FFI_TYPE_DOUBLE) { | ||||||
|  |                 variant += 16; | ||||||
|             } |             } | ||||||
|             for (uint32_t i = 0; i < arg_count; i++) { |             for (uint32_t i = 0; i < arg_count; i++) { | ||||||
|                 mappings[i].type = decode_ffi_type(argv[i + 2]); |                 mappings[i].type = decode_ffi_type(argv[i + 2]); | ||||||
|                 mappings[i].offset = 0; |                 size_t el_size = type_size(mappings[i].type); | ||||||
|                 mappings[i].spec = JANET_WIN64_REGISTER; |                 int is_register_sized = (el_size == 1 || el_size == 2 || el_size == 4 || el_size == 8); | ||||||
|  |                 if (next_register < 4) { | ||||||
|  |                     mappings[i].offset = next_register++; | ||||||
|  |                     if (is_register_sized) { | ||||||
|  |                         mappings[i].spec = JANET_WIN64_REGISTER; | ||||||
|  |  | ||||||
|  |                         /* Select variant based on position of floating point arguments */ | ||||||
|  |                         if (mappings[i].type.prim == JANET_FFI_TYPE_FLOAT || | ||||||
|  |                                 mappings[i].type.prim == JANET_FFI_TYPE_DOUBLE) { | ||||||
|  |                             variant += 1 << next_register; | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         mappings[i].spec = JANET_WIN64_REGISTER_REF; | ||||||
|  |                         mappings[i].offset2 = ref_stack_count; | ||||||
|  |                         ref_stack_count += (el_size + 15) / 16; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     if (is_register_sized) { | ||||||
|  |                         mappings[i].spec = JANET_WIN64_STACK; | ||||||
|  |                         mappings[i].offset = stack_count; | ||||||
|  |                         stack_count++; | ||||||
|  |                     } else { | ||||||
|  |                         mappings[i].spec = JANET_WIN64_STACK_REF; | ||||||
|  |                         mappings[i].offset = stack_count; | ||||||
|  |                         stack_count++; | ||||||
|  |                         mappings[i].offset2 = ref_stack_count; | ||||||
|  |                         ref_stack_count += (el_size + 15) / 16; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             /* Take into account reference arguments and align to 16 bytes just in case */ | ||||||
|  |             stack_count += 2 * ref_stack_count; | ||||||
|  |             if (stack_count & 1) { | ||||||
|  |                 stack_count++; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             /* Invert stack | ||||||
|  |              * Offsets are in units of 8-bytes */ | ||||||
|  |             for (uint32_t i = 0; i < arg_count; i++) { | ||||||
|  |                 uint32_t old_offset = mappings[i].offset; | ||||||
|  |                 if (mappings[i].spec == JANET_WIN64_STACK) { | ||||||
|  |                     mappings[i].offset = stack_count - 1 - old_offset; | ||||||
|  |                 } else if (mappings[i].spec == JANET_WIN64_STACK_REF) { | ||||||
|  |                     mappings[i].offset = stack_count - 1 - old_offset; | ||||||
|  |                 } | ||||||
|  |                 if (mappings[i].spec == JANET_WIN64_STACK_REF || mappings[i].spec == JANET_WIN64_REGISTER_REF) { | ||||||
|  |                     /* Align size to 16 bytes */ | ||||||
|  |                     size_t size = (type_size(mappings[i].type) + 15) & ~0xFUL; | ||||||
|  |                     mappings[i].offset2 = stack_count - mappings[i].offset2 - (size / 8); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifdef JANET_FFI_SYSV64_ENABLED | ||||||
|         case JANET_FFI_CC_SYSV_64: { |         case JANET_FFI_CC_SYSV_64: { | ||||||
|             JanetFFIWordSpec ret_spec = sysv64_classify(ret.type); |             JanetFFIWordSpec ret_spec = sysv64_classify(ret.type); | ||||||
|             ret.spec = ret_spec; |             ret.spec = ret_spec; | ||||||
|  |             if (ret_spec == JANET_SYSV64_SSE) variant = 1; | ||||||
|             /* Spill register overflow to memory */ |             /* Spill register overflow to memory */ | ||||||
|             uint32_t next_register = 0; |             uint32_t next_register = 0; | ||||||
|             uint32_t next_fp_register = 0; |             uint32_t next_fp_register = 0; | ||||||
| @@ -622,18 +701,19 @@ JANET_CORE_FN(cfun_ffi_signature, | |||||||
|                         stack_count += el_size; |                         stack_count += el_size; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|                 /* Invert stack */ |             /* Invert stack */ | ||||||
|                 for (uint32_t i = 0; i < arg_count; i++) { |             for (uint32_t i = 0; i < arg_count; i++) { | ||||||
|                     if (mappings[i].spec == JANET_SYSV64_MEMORY) { |                 if (mappings[i].spec == JANET_SYSV64_MEMORY) { | ||||||
|                         uint32_t old_offset = mappings[i].offset; |                     uint32_t old_offset = mappings[i].offset; | ||||||
|                         size_t el_size = type_size(mappings[i].type); |                     size_t el_size = type_size(mappings[i].type); | ||||||
|                         mappings[i].offset = stack_count - ((el_size + 7) / 8) - old_offset; |                     mappings[i].offset = stack_count - ((el_size + 7) / 8) - old_offset; | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Create signature abstract value */ |     /* Create signature abstract value */ | ||||||
| @@ -648,37 +728,39 @@ JANET_CORE_FN(cfun_ffi_signature, | |||||||
|     return janet_wrap_abstract(abst); |     return janet_wrap_abstract(abst); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* A common callback function signature. To avoid runtime code generation, which is prohibited | #ifdef JANET_FFI_SYSV64_ENABLED | ||||||
|  * on many platforms, often buggy (see libffi), and generally complicated, instead provide |  | ||||||
|  * a single (or small set of commonly used function signatures). All callbacks should |  | ||||||
|  * eventually call this. */ |  | ||||||
| void janet_ffi_trampoline(void *ctx, void *userdata) { |  | ||||||
|     if (NULL == userdata) { |  | ||||||
|         /* Userdata not set. */ |  | ||||||
|         janet_eprintf("no userdata found for janet callback"); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     Janet context = janet_wrap_pointer(ctx); |  | ||||||
|     JanetFunction *fun = userdata; |  | ||||||
|     janet_call(fun, 1, &context); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void janet_ffi_sysv64_standard_callback(void *ctx, void *userdata) { | static void janet_ffi_sysv64_standard_callback(void *ctx, void *userdata) { | ||||||
|     janet_ffi_trampoline(ctx, userdata); |     janet_ffi_trampoline(ctx, userdata); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Functions that set all argument registers. Two variants - one to read rax and rdx returns, another | ||||||
|  |  * to read xmm0 and xmm1 returns. */ | ||||||
|  | typedef struct { | ||||||
|  |     uint64_t x; | ||||||
|  |     uint64_t y; | ||||||
|  | } sysv64_int_return; | ||||||
|  | typedef struct { | ||||||
|  |     double x; | ||||||
|  |     double y; | ||||||
|  | } sysv64_sse_return; | ||||||
|  | typedef sysv64_int_return janet_sysv64_variant_1(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, | ||||||
|  |         double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); | ||||||
|  | typedef sysv64_sse_return janet_sysv64_variant_2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, | ||||||
|  |         double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8); | ||||||
|  |  | ||||||
| static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_pointer, const Janet *argv) { | static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_pointer, const Janet *argv) { | ||||||
|     uint64_t ret[2]; |     sysv64_int_return int_return; | ||||||
|     uint64_t fp_ret[2]; |     sysv64_sse_return sse_return; | ||||||
|     uint64_t regs[6]; |     uint64_t regs[6]; | ||||||
|     uint64_t fp_regs[8]; |     double fp_regs[8]; | ||||||
|     JanetFFIWordSpec ret_spec = signature->ret.spec; |     JanetFFIWordSpec ret_spec = signature->ret.spec; | ||||||
|     void *ret_mem = ret; |     void *ret_mem = &int_return; | ||||||
|     if (ret_spec == JANET_SYSV64_MEMORY) { |     if (ret_spec == JANET_SYSV64_MEMORY) { | ||||||
|         ret_mem = alloca(type_size(signature->ret.type)); |         ret_mem = alloca(type_size(signature->ret.type)); | ||||||
|         regs[0] = (uint64_t) ret_mem; |         regs[0] = (uint64_t) ret_mem; | ||||||
|     } else if (ret_spec == JANET_SYSV64_SSE) { |     } else if (ret_spec == JANET_SYSV64_SSE) { | ||||||
|         ret_mem = fp_ret; |         ret_mem = &sse_return; | ||||||
|     } |     } | ||||||
|     uint64_t *stack = alloca(sizeof(uint64_t) * signature->stack_count); |     uint64_t *stack = alloca(sizeof(uint64_t) * signature->stack_count); | ||||||
|     for (uint32_t i = 0; i < signature->arg_count; i++) { |     for (uint32_t i = 0; i < signature->arg_count; i++) { | ||||||
| @@ -692,7 +774,7 @@ static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_point | |||||||
|                 to = regs + arg.offset; |                 to = regs + arg.offset; | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSV64_SSE: |             case JANET_SYSV64_SSE: | ||||||
|                 to = fp_regs + arg.offset; |                 to = (uint64_t *)(fp_regs + arg.offset); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSV64_MEMORY: |             case JANET_SYSV64_MEMORY: | ||||||
|                 to = stack + arg.offset; |                 to = stack + arg.offset; | ||||||
| @@ -701,49 +783,30 @@ static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_point | |||||||
|         janet_ffi_write_one(to, argv, n, arg.type, JANET_FFI_MAX_RECUR); |         janet_ffi_write_one(to, argv, n, arg.type, JANET_FFI_MAX_RECUR); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* !!ACHTUNG!! */ |     if (signature->variant) { | ||||||
|  |         sse_return = ((janet_sysv64_variant_2 *)(function_pointer))( | ||||||
|  |                          regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], | ||||||
|  |                          fp_regs[0], fp_regs[1], fp_regs[2], fp_regs[3], | ||||||
|  |                          fp_regs[4], fp_regs[5], fp_regs[6], fp_regs[7]); | ||||||
|  |     } else { | ||||||
|  |         int_return = ((janet_sysv64_variant_1 *)(function_pointer))( | ||||||
|  |                          regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], | ||||||
|  |                          fp_regs[0], fp_regs[1], fp_regs[2], fp_regs[3], | ||||||
|  |                          fp_regs[4], fp_regs[5], fp_regs[6], fp_regs[7]); | ||||||
|  |  | ||||||
|     __asm__("mov %5, %%rdi\n\t" |     } | ||||||
|             "mov %6, %%rsi\n\t" |  | ||||||
|             "mov %7, %%rdx\n\t" |  | ||||||
|             "mov %8, %%rcx\n\t" |  | ||||||
|             "mov %9, %%r8\n\t" |  | ||||||
|             "mov %10, %%r9\n\t" |  | ||||||
|             "movq %11, %%xmm0\n\t" |  | ||||||
|             "movq %12, %%xmm1\n\t" |  | ||||||
|             "movq %13, %%xmm2\n\t" |  | ||||||
|             "movq %14, %%xmm3\n\t" |  | ||||||
|             "movq %15, %%xmm4\n\t" |  | ||||||
|             "movq %16, %%xmm5\n\t" |  | ||||||
|             "movq %17, %%xmm6\n\t" |  | ||||||
|             "movq %18, %%xmm7\n\t" |  | ||||||
|             "call *%4\n\t" |  | ||||||
|             "mov %%rax, %0\n\t" |  | ||||||
|             "mov %%rdx, %1\n\t" |  | ||||||
|             "movq %%xmm0, %2\n\t" |  | ||||||
|             "movq %%xmm1, %3" |  | ||||||
|             : "=g"(ret[0]), "=g"(ret[1]), "=g"(fp_ret[0]), "=g"(fp_ret[1]) |  | ||||||
|             : "g"(function_pointer), |  | ||||||
|             "g"(regs[0]), |  | ||||||
|             "g"(regs[1]), |  | ||||||
|             "g"(regs[2]), |  | ||||||
|             "g"(regs[3]), |  | ||||||
|             "g"(regs[4]), |  | ||||||
|             "g"(regs[5]), |  | ||||||
|             "g"(fp_regs[0]), |  | ||||||
|             "g"(fp_regs[1]), |  | ||||||
|             "g"(fp_regs[2]), |  | ||||||
|             "g"(fp_regs[3]), |  | ||||||
|             "g"(fp_regs[4]), |  | ||||||
|             "g"(fp_regs[5]), |  | ||||||
|             "g"(fp_regs[6]), |  | ||||||
|             "g"(fp_regs[7])); |  | ||||||
|  |  | ||||||
|     return janet_ffi_read_one(ret_mem, signature->ret.type, JANET_FFI_MAX_RECUR); |     return janet_ffi_read_one(ret_mem, signature->ret.type, JANET_FFI_MAX_RECUR); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef JANET_FFI_WIN64_ENABLED | #ifdef JANET_FFI_WIN64_ENABLED | ||||||
|  |  | ||||||
|  | static void janet_ffi_win64_standard_callback(void *ctx, void *userdata) { | ||||||
|  |     janet_ffi_trampoline(ctx, userdata); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Variants that allow setting all required registers for 64 bit windows calling convention. | /* Variants that allow setting all required registers for 64 bit windows calling convention. | ||||||
|  * win64 calling convention has up to 4 arguments on registers, and one register for returns. |  * win64 calling convention has up to 4 arguments on registers, and one register for returns. | ||||||
|  * Each register can either be an integer or floating point register, resulting in |  * Each register can either be an integer or floating point register, resulting in | ||||||
| @@ -799,18 +862,26 @@ static Janet janet_ffi_win64(JanetFFISignature *signature, void *function_pointe | |||||||
|         ret_mem = alloca(type_size(signature->ret.type)); |         ret_mem = alloca(type_size(signature->ret.type)); | ||||||
|         regs[0].integer = (uint64_t) ret_mem; |         regs[0].integer = (uint64_t) ret_mem; | ||||||
|     } |     } | ||||||
|     uint8_t *stack = alloca(signature->stack_count); |     uint64_t *stack = alloca(signature->stack_count * 8); | ||||||
|     for (uint32_t i = 0; i < signature->arg_count; i++) { |     for (uint32_t i = 0; i < signature->arg_count; i++) { | ||||||
|         int32_t n = i + 2; |         int32_t n = i + 2; | ||||||
|         JanetFFIMapping arg = signature->args[i]; |         JanetFFIMapping arg = signature->args[i]; | ||||||
|         if (arg.spec == JANET_WIN64_STACK) { |         if (arg.spec == JANET_WIN64_STACK) { | ||||||
|             janet_ffi_write_one(stack + arg.offset, argv, n, arg.type, JANET_FFI_MAX_RECUR); |             janet_ffi_write_one(stack + arg.offset, argv, n, arg.type, JANET_FFI_MAX_RECUR); | ||||||
|  |         } else if (arg.spec == JANET_WIN64_STACK_REF) { | ||||||
|  |             uint8_t *ptr = (uint8_t *)(stack + args.offset2); | ||||||
|  |             janet_ffi_write_one(ptr, argv, n, arg.type, JANET_FFI_MAX_RECUR); | ||||||
|  |             stack[args.offset] = (uint64_t) ptr; | ||||||
|  |         } else if (arg.spec == JANET_WIN64_REGISTER_REF) { | ||||||
|  |             uint8_t *ptr = (uint8_t *)(stack + args.offset2); | ||||||
|  |             janet_ffi_write_one(ptr, argv, n, arg.type, JANET_FFI_MAX_RECUR); | ||||||
|  |             regs[args.offset].integer = (uint64_t) ptr; | ||||||
|         } else { |         } else { | ||||||
|             janet_ffi_write_one((uint8_t *) ®s[arg.offset].integer, argv, n, arg.type, JANET_FFI_MAX_RECUR); |             janet_ffi_write_one((uint8_t *) ®s[arg.offset].integer, argv, n, arg.type, JANET_FFI_MAX_RECUR); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* the seasoned programmer who cut their teeth on assembly is probably queitly shaking their head by now... */ |     /* the seasoned programmer who cut their teeth on assembly is probably quietly shaking their head by now... */ | ||||||
|     switch (signature->variant) { |     switch (signature->variant) { | ||||||
|         default: |         default: | ||||||
|             janet_panic("unknown variant"); |             janet_panic("unknown variant"); | ||||||
| @@ -932,8 +1003,10 @@ JANET_CORE_FN(cfun_ffi_call, | |||||||
|         case JANET_FFI_CC_WIN_64: |         case JANET_FFI_CC_WIN_64: | ||||||
|             return janet_ffi_win64(signature, function_pointer, argv); |             return janet_ffi_win64(signature, function_pointer, argv); | ||||||
| #endif | #endif | ||||||
|  | #ifdef JANET_FFI_SYSV64_ENABLED | ||||||
|         case JANET_FFI_CC_SYSV_64: |         case JANET_FFI_CC_SYSV_64: | ||||||
|             return janet_ffi_sysv64(signature, function_pointer, argv); |             return janet_ffi_sysv64(signature, function_pointer, argv); | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -986,8 +1059,14 @@ JANET_CORE_FN(cfun_ffi_get_callback_trampoline, | |||||||
|     if (argc >= 1) cc = decode_ffi_cc(janet_getkeyword(argv, 0)); |     if (argc >= 1) cc = decode_ffi_cc(janet_getkeyword(argv, 0)); | ||||||
|     switch (cc) { |     switch (cc) { | ||||||
|         default: |         default: | ||||||
|  | #ifdef JANET_FFI_WIN64_ENABLED | ||||||
|  |         case JANET_FFI_CC_WIN_64: | ||||||
|  |             return janet_wrap_pointer(janet_ffi_win64_standard_callback); | ||||||
|  | #endif | ||||||
|  | #ifdef JANET_FFI_SYSV64_ENABLED | ||||||
|         case JANET_FFI_CC_SYSV_64: |         case JANET_FFI_CC_SYSV_64: | ||||||
|             return janet_wrap_pointer(janet_ffi_sysv64_standard_callback); |             return janet_wrap_pointer(janet_ffi_sysv64_standard_callback); | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose