github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-apply.c (about) 1 /* 2 * jit-apply.c - Dynamic invocation and closure support functions. 3 * 4 * Copyright (C) 2004 Southern Storm Software, Pty Ltd. 5 * 6 * This file is part of the libjit library. 7 * 8 * The libjit library is free software: you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public License 10 * as published by the Free Software Foundation, either version 2.1 of 11 * the License, or (at your option) any later version. 12 * 13 * The libjit library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with the libjit library. If not, see 20 * <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "jit-internal.h" 24 #include "jit-apply-rules.h" 25 #include "jit-apply-func.h" 26 #if HAVE_STDLIB_H 27 # include <stdlib.h> 28 #endif 29 #if HAVE_ALLOCA_H 30 # include <alloca.h> 31 #endif 32 #ifdef JIT_WIN32_PLATFORM 33 # include <malloc.h> 34 # ifndef alloca 35 # define alloca _alloca 36 # endif 37 #endif 38 39 /* 40 41 If you need to tweak the way that this code behaves for a specific 42 platform, then you would normally do it in "tools/gen-apply.c" or 43 the CPU-specific "jit-apply-XXX.h" file, not here. 44 45 */ 46 47 /*@ 48 49 @section Function application and closures 50 @cindex Function application 51 @cindex Closures 52 @cindex jit-apply.h 53 54 Sometimes all you have for a function is a pointer to it and a dynamic 55 description of its arguments. Calling such a function can be extremely 56 difficult in standard C. The routines in this section, particularly 57 @code{jit_apply}, provide a convenient interface for doing this. 58 59 At other times, you may wish to wrap up one of your own dynamic functions 60 in such a way that it appears to be a regular C function. This is 61 performed with @code{jit_closure_create}. 62 63 @*/ 64 65 typedef enum 66 { 67 _JIT_APPLY_RETURN_TYPE_OTHER = 0, 68 _JIT_APPLY_RETURN_TYPE_FLOAT32 = 1, 69 _JIT_APPLY_RETURN_TYPE_FLOAT64 = 2, 70 _JIT_APPLY_RETURN_TYPE_NFLOAT = 3 71 } _jit_apply_return_type; 72 73 /* 74 * Flags that indicate which structure sizes are returned in registers. 75 */ 76 unsigned char const _jit_apply_return_in_reg[] = 77 JIT_APPLY_STRUCT_RETURN_IN_REG_INIT; 78 79 /* 80 * Get the maximum argument stack size of a signature type. 81 */ 82 static unsigned int 83 jit_type_get_max_arg_size(jit_type_t signature) 84 { 85 unsigned int size; 86 unsigned int typeSize; 87 unsigned int param; 88 jit_type_t type; 89 if(signature->size) 90 { 91 /* We have a cached argument size from last time */ 92 return signature->size; 93 } 94 size = 0; 95 param = jit_type_num_params(signature); 96 while(param > 0) 97 { 98 --param; 99 type = jit_type_remove_tags(jit_type_get_param(signature, param)); 100 switch(type->kind) 101 { 102 case JIT_TYPE_SBYTE: 103 case JIT_TYPE_UBYTE: 104 case JIT_TYPE_SHORT: 105 case JIT_TYPE_USHORT: 106 case JIT_TYPE_INT: 107 case JIT_TYPE_UINT: 108 case JIT_TYPE_NINT: 109 case JIT_TYPE_NUINT: 110 case JIT_TYPE_PTR: 111 case JIT_TYPE_SIGNATURE: 112 size += sizeof(jit_nint); 113 break; 114 115 case JIT_TYPE_LONG: 116 case JIT_TYPE_ULONG: 117 #ifdef JIT_NATIVE_INT32 118 /* Add one extra word for possible alignment padding */ 119 size += sizeof(jit_long) + sizeof(jit_nint); 120 #else 121 size += sizeof(jit_nint); 122 #endif 123 break; 124 125 case JIT_TYPE_FLOAT32: 126 case JIT_TYPE_FLOAT64: 127 case JIT_TYPE_NFLOAT: 128 /* Allocate space for an "nfloat" and an alignment word */ 129 size += sizeof(jit_nfloat) + sizeof(jit_nint) * 2 - 1; 130 size &= ~(sizeof(jit_nint) - 1); 131 break; 132 133 case JIT_TYPE_STRUCT: 134 case JIT_TYPE_UNION: 135 /* Allocate space for the structure and an alignment word */ 136 typeSize = jit_type_get_size(type); 137 size += typeSize + sizeof(jit_nint) * 2 - 1; 138 size &= ~(sizeof(jit_nint) - 1); 139 break; 140 } 141 } 142 type = jit_type_get_return(signature); 143 if(jit_type_is_struct(type) || jit_type_is_union(type)) 144 { 145 /* Add one extra word for the possibility of a structure pointer */ 146 size += sizeof(jit_nint); 147 } 148 signature->size = size; 149 return size; 150 } 151 152 /* 153 * Copy apply arguments into position. 154 */ 155 static void 156 jit_apply_builder_add_arguments(jit_apply_builder *builder, jit_type_t signature, 157 void **args, unsigned int index, unsigned int num_args) 158 { 159 unsigned int param; 160 for(param = 0; param < num_args; ++param) 161 { 162 void *arg = args[param]; 163 jit_type_t type = jit_type_get_param(signature, index + param); 164 type = jit_type_remove_tags(type); 165 switch(type->kind) 166 { 167 case JIT_TYPE_SBYTE: 168 jit_apply_builder_add_sbyte(builder, *((jit_sbyte *) arg)); 169 break; 170 171 case JIT_TYPE_UBYTE: 172 jit_apply_builder_add_ubyte(builder, *((jit_ubyte *) arg)); 173 break; 174 175 case JIT_TYPE_SHORT: 176 jit_apply_builder_add_short(builder, *((jit_short *) arg)); 177 break; 178 179 case JIT_TYPE_USHORT: 180 jit_apply_builder_add_ushort(builder, *((jit_ushort *) arg)); 181 break; 182 183 case JIT_TYPE_INT: 184 jit_apply_builder_add_int(builder, *((jit_int *) arg)); 185 break; 186 187 case JIT_TYPE_UINT: 188 jit_apply_builder_add_uint(builder, *((jit_uint *) arg)); 189 break; 190 191 case JIT_TYPE_NINT: 192 case JIT_TYPE_PTR: 193 case JIT_TYPE_SIGNATURE: 194 jit_apply_builder_add_nint(builder, *((jit_nint *) arg)); 195 break; 196 197 case JIT_TYPE_NUINT: 198 jit_apply_builder_add_nuint(builder, *((jit_nuint *) arg)); 199 break; 200 201 case JIT_TYPE_LONG: 202 jit_apply_builder_add_long(builder, *((jit_long *) arg)); 203 break; 204 205 case JIT_TYPE_ULONG: 206 jit_apply_builder_add_ulong(builder, *((jit_ulong *) arg)); 207 break; 208 209 case JIT_TYPE_FLOAT32: 210 jit_apply_builder_add_float32(builder, *((jit_float32 *) arg)); 211 break; 212 213 case JIT_TYPE_FLOAT64: 214 jit_apply_builder_add_float64(builder, *((jit_float64 *) arg)); 215 break; 216 217 case JIT_TYPE_NFLOAT: 218 jit_apply_builder_add_nfloat(builder, *((jit_nfloat *) arg)); 219 break; 220 221 case JIT_TYPE_STRUCT: 222 case JIT_TYPE_UNION: 223 #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT 224 _jit_builtin_apply_add_struct(builder, arg, type); 225 #else 226 jit_apply_builder_add_struct(builder, arg, 227 jit_type_get_size(type), 228 jit_type_get_alignment(type)); 229 #endif 230 break; 231 } 232 } 233 } 234 235 /* 236 * Get the return value after calling a function using "__builtin_apply". 237 */ 238 static void 239 jit_apply_builder_get_return(jit_apply_builder *builder, void *rv, 240 jit_type_t type, jit_apply_return *result) 241 { 242 #ifndef HAVE_JIT_BUILTIN_APPLY_STRUCT_RETURN 243 unsigned int size; 244 #endif 245 246 switch(type->kind) 247 { 248 case JIT_TYPE_SBYTE: 249 *((jit_sbyte *) rv) = jit_apply_return_get_sbyte(result); 250 break; 251 252 case JIT_TYPE_UBYTE: 253 *((jit_ubyte *) rv) = jit_apply_return_get_ubyte(result); 254 break; 255 256 case JIT_TYPE_SHORT: 257 *((jit_short *) rv) = jit_apply_return_get_short(result); 258 break; 259 260 case JIT_TYPE_USHORT: 261 *((jit_ushort *) rv) = jit_apply_return_get_ushort(result); 262 break; 263 264 case JIT_TYPE_INT: 265 *((jit_int *) rv) = jit_apply_return_get_int(result); 266 break; 267 268 case JIT_TYPE_UINT: 269 *((jit_uint *) rv) = jit_apply_return_get_uint(result); 270 break; 271 272 case JIT_TYPE_NINT: 273 case JIT_TYPE_PTR: 274 case JIT_TYPE_SIGNATURE: 275 *((jit_nint *) rv) = jit_apply_return_get_nint(result); 276 break; 277 278 case JIT_TYPE_NUINT: 279 *((jit_nuint *) rv) = jit_apply_return_get_nuint(result); 280 break; 281 282 case JIT_TYPE_LONG: 283 *((jit_long *) rv) = jit_apply_return_get_long(result); 284 break; 285 286 case JIT_TYPE_ULONG: 287 *((jit_ulong *) rv) = jit_apply_return_get_ulong(result); 288 break; 289 290 case JIT_TYPE_FLOAT32: 291 *((jit_float32 *) rv) = jit_apply_return_get_float32(result); 292 break; 293 294 case JIT_TYPE_FLOAT64: 295 *((jit_float64 *) rv) = jit_apply_return_get_float64(result); 296 break; 297 298 case JIT_TYPE_NFLOAT: 299 *((jit_nfloat *) rv) = jit_apply_return_get_nfloat(result); 300 break; 301 302 case JIT_TYPE_STRUCT: 303 case JIT_TYPE_UNION: 304 #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT_RETURN 305 _jit_builtin_apply_get_struct_return(builder, rv, result, type); 306 #else 307 size = jit_type_get_size(type); 308 jit_apply_builder_get_struct_return(builder, size, rv, result); 309 #endif 310 break; 311 } 312 } 313 314 /*@ 315 * @deftypefun void jit_apply (jit_type_t signature, void *@var{func}, void **@var{args}, unsigned int @var{num_fixed_args}, void *@var{return_value}) 316 * Call a function that has a particular function signature. 317 * If the signature has more than @var{num_fixed_args} arguments, 318 * then it is assumed to be a vararg call, with the additional 319 * arguments passed in the vararg argument area on the stack. 320 * The @var{signature} must specify the type of all arguments, 321 * including those in the vararg argument area. 322 * @end deftypefun 323 @*/ 324 void 325 jit_apply(jit_type_t signature, void *func, 326 void **args, unsigned int num_fixed_args, 327 void *return_value) 328 { 329 jit_apply_builder builder; 330 unsigned int size; 331 jit_apply_return *apply_return; 332 jit_type_t type; 333 334 /* Initialize the argument builder */ 335 jit_apply_builder_init(&builder, signature); 336 337 /* Handle the structure return argument */ 338 type = jit_type_remove_tags(jit_type_get_return(signature)); 339 if(jit_type_is_struct(type) || jit_type_is_union(type)) 340 { 341 size = jit_type_get_size(type); 342 jit_apply_builder_add_struct_return(&builder, size, 343 return_value); 344 } 345 346 /* Copy the arguments into position */ 347 jit_apply_builder_add_arguments(&builder, signature, args, 0, 348 num_fixed_args); 349 jit_apply_builder_start_varargs(&builder); 350 jit_apply_builder_add_arguments(&builder, signature, 351 args + num_fixed_args, num_fixed_args, 352 jit_type_num_params(signature) - num_fixed_args); 353 354 /* Call the function using "__builtin_apply" or something similar */ 355 if(type->kind < JIT_TYPE_FLOAT32 || type->kind > JIT_TYPE_NFLOAT) 356 { 357 jit_builtin_apply(func, builder.apply_args, builder.stack_used, 358 0, apply_return); 359 } 360 else 361 { 362 jit_builtin_apply(func, builder.apply_args, builder.stack_used, 363 1, apply_return); 364 } 365 366 /* Copy the return value into position */ 367 if(return_value != 0 && type != jit_type_void) 368 { 369 jit_apply_builder_get_return(&builder, return_value, type, 370 apply_return); 371 } 372 } 373 374 /*@ 375 * @deftypefun void jit_apply_raw (jit_type_t @var{signature}, void *@var{func}, void *@var{args}, void *@var{return_value}) 376 * Call a function, passing a set of raw arguments. This can only 377 * be used if @code{jit_raw_supported} returns non-zero for the signature. 378 * The @var{args} value is assumed to be an array of @code{jit_nint} values 379 * that correspond to each of the arguments. Raw function calls 380 * are slightly faster than their non-raw counterparts, but can 381 * only be used in certain circumstances. 382 * @end deftypefun 383 @*/ 384 void 385 jit_apply_raw(jit_type_t signature, void *func, 386 void *args, void *return_value) 387 { 388 jit_apply_return *apply_return; 389 unsigned int size; 390 jit_type_t type; 391 392 /* Call the function using "__builtin_apply" or something similar */ 393 type = jit_type_remove_tags(jit_type_get_return(signature)); 394 size = jit_type_num_params(signature) * sizeof(jit_nint); 395 if(type->kind < JIT_TYPE_FLOAT32 || type->kind > JIT_TYPE_NFLOAT) 396 { 397 jit_builtin_apply(func, args, size, 0, apply_return); 398 } 399 else 400 { 401 jit_builtin_apply(func, args, size, 1, apply_return); 402 } 403 404 /* Copy the return value into position */ 405 if(return_value != 0 && type != jit_type_void) 406 { 407 jit_apply_builder_get_return(0, return_value, type, 408 apply_return); 409 } 410 } 411 412 /*@ 413 * @deftypefun int jit_raw_supported (jit_type_t @var{signature}) 414 * Determine if @code{jit_apply_raw} can be used to call functions 415 * with a particular signature. Returns zero if not. 416 * @end deftypefun 417 @*/ 418 int jit_raw_supported(jit_type_t signature) 419 { 420 #if JIT_APPLY_NUM_WORD_REGS == 0 && JIT_APPLY_NUM_FLOAT_REGS == 0 && \ 421 JIT_APPLY_STRUCT_RETURN_SPECIAL_REG == 0 422 423 unsigned int param; 424 jit_type_t type; 425 426 #if JIT_APPLY_X86_FASTCALL != 0 427 /* Cannot use raw calls with fastcall functions */ 428 if(jit_type_get_abi(signature) == jit_abi_fastcall) 429 { 430 return 0; 431 } 432 #endif 433 434 /* Check that all of the arguments are word-sized */ 435 param = jit_type_num_params(signature); 436 while(param > 0) 437 { 438 --param; 439 type = jit_type_normalize(jit_type_get_param(signature, param)); 440 if(type->kind < JIT_TYPE_SBYTE || type->kind > JIT_TYPE_NUINT) 441 { 442 return 0; 443 } 444 } 445 446 /* Check that the return value does not involve structures */ 447 type = jit_type_get_return(signature); 448 if(jit_type_is_struct(type) || jit_type_is_union(type)) 449 { 450 return 0; 451 } 452 453 /* The signature is suitable for use with "jit_apply_raw" */ 454 return 1; 455 456 #else 457 /* We cannot use raw calls if we need to use registers in applys */ 458 return 0; 459 #endif 460 } 461 462 /* 463 * Define the structure of a vararg list for closures. 464 */ 465 struct jit_closure_va_list 466 { 467 jit_apply_builder builder; 468 }; 469 470 #ifdef jit_closure_size 471 472 /* 473 * Define the closure structure. 474 */ 475 typedef struct jit_closure *jit_closure_t; 476 struct jit_closure 477 { 478 unsigned char buf[jit_closure_size]; 479 jit_type_t signature; 480 jit_closure_func func; 481 void *user_data; 482 }; 483 484 /* 485 * Handler that is called when a closure is invoked. 486 */ 487 static void closure_handler(jit_closure_t closure, void *apply_args) 488 { 489 jit_type_t signature = closure->signature; 490 jit_type_t type; 491 jit_apply_builder parser; 492 void *return_buffer; 493 void **args; 494 void *temp_arg; 495 unsigned int num_params; 496 unsigned int param; 497 jit_apply_return apply_return; 498 _jit_apply_return_type return_type; 499 500 /* Initialize the argument parser */ 501 jit_apply_parser_init(&parser, closure->signature, apply_args); 502 503 /* Allocate space for the return value */ 504 type = jit_type_normalize(jit_type_get_return(signature)); 505 if(!type || type == jit_type_void) 506 { 507 return_buffer = 0; 508 } 509 else if(jit_type_return_via_pointer(type)) 510 { 511 jit_apply_parser_get_struct_return(&parser, return_buffer); 512 } 513 else 514 { 515 return_buffer = alloca(jit_type_get_size(type)); 516 } 517 518 /* Allocate space for the argument buffer. We allow for one 519 extra argument to hold the "va" list */ 520 num_params = jit_type_num_params(signature); 521 args = (void **)alloca((num_params + 1) * sizeof(void *)); 522 523 /* Extract the fixed arguments */ 524 for(param = 0; param < num_params; ++param) 525 { 526 type = jit_type_normalize(jit_type_get_param(signature, param)); 527 if(!type) 528 { 529 args[param] = 0; 530 continue; 531 } 532 temp_arg = alloca(jit_type_get_size(type)); 533 args[param] = temp_arg; 534 switch(type->kind) 535 { 536 case JIT_TYPE_SBYTE: 537 { 538 jit_apply_parser_get_sbyte 539 (&parser, *((jit_sbyte *)temp_arg)); 540 } 541 break; 542 543 case JIT_TYPE_UBYTE: 544 { 545 jit_apply_parser_get_ubyte 546 (&parser, *((jit_ubyte *)temp_arg)); 547 } 548 break; 549 550 case JIT_TYPE_SHORT: 551 { 552 jit_apply_parser_get_short 553 (&parser, *((jit_short *)temp_arg)); 554 } 555 break; 556 557 case JIT_TYPE_USHORT: 558 { 559 jit_apply_parser_get_ushort 560 (&parser, *((jit_ushort *)temp_arg)); 561 } 562 break; 563 564 case JIT_TYPE_INT: 565 { 566 jit_apply_parser_get_int 567 (&parser, *((jit_int *)temp_arg)); 568 } 569 break; 570 571 case JIT_TYPE_UINT: 572 { 573 jit_apply_parser_get_uint 574 (&parser, *((jit_uint *)temp_arg)); 575 } 576 break; 577 578 case JIT_TYPE_LONG: 579 { 580 jit_apply_parser_get_long 581 (&parser, *((jit_long *)temp_arg)); 582 } 583 break; 584 585 case JIT_TYPE_ULONG: 586 { 587 jit_apply_parser_get_ulong 588 (&parser, *((jit_ulong *)temp_arg)); 589 } 590 break; 591 592 case JIT_TYPE_FLOAT32: 593 { 594 jit_apply_parser_get_float32 595 (&parser, *((jit_float32 *)temp_arg)); 596 } 597 break; 598 599 case JIT_TYPE_FLOAT64: 600 { 601 jit_apply_parser_get_float64 602 (&parser, *((jit_float64 *)temp_arg)); 603 } 604 break; 605 606 case JIT_TYPE_NFLOAT: 607 { 608 jit_apply_parser_get_nfloat 609 (&parser, *((jit_nfloat *)temp_arg)); 610 } 611 break; 612 613 case JIT_TYPE_STRUCT: 614 case JIT_TYPE_UNION: 615 { 616 #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT 617 _jit_builtin_apply_get_struct(&parser, temp_arg, type); 618 #else 619 jit_apply_parser_get_struct(&parser, jit_type_get_size(type), 620 jit_type_get_alignment(type), temp_arg); 621 #endif 622 } 623 break; 624 } 625 } 626 627 /* Adjust the argument parser for the start of the va arguments */ 628 jit_apply_parser_start_varargs(&parser); 629 630 /* Record the address of the va handler in the last argument slot. 631 Not all functions will need this, but it doesn't hurt to include it */ 632 args[num_params] = &parser; 633 634 /* Call the user's closure handling function */ 635 (*(closure->func))(signature, return_buffer, args, closure->user_data); 636 637 /* Set up the "apply return" buffer */ 638 jit_memzero(&apply_return, sizeof(apply_return)); 639 type = jit_type_normalize(jit_type_get_return(signature)); 640 return_type = _JIT_APPLY_RETURN_TYPE_OTHER; 641 if(type) 642 { 643 switch(type->kind) 644 { 645 case JIT_TYPE_SBYTE: 646 { 647 jit_apply_return_set_sbyte 648 (&apply_return, *((jit_sbyte *)return_buffer)); 649 } 650 break; 651 652 case JIT_TYPE_UBYTE: 653 { 654 jit_apply_return_set_ubyte 655 (&apply_return, *((jit_ubyte *)return_buffer)); 656 } 657 break; 658 659 case JIT_TYPE_SHORT: 660 { 661 jit_apply_return_set_short 662 (&apply_return, *((jit_short *)return_buffer)); 663 } 664 break; 665 666 case JIT_TYPE_USHORT: 667 { 668 jit_apply_return_set_ushort 669 (&apply_return, *((jit_ushort *)return_buffer)); 670 } 671 break; 672 673 case JIT_TYPE_INT: 674 { 675 jit_apply_return_set_int 676 (&apply_return, *((jit_int *)return_buffer)); 677 } 678 break; 679 680 case JIT_TYPE_UINT: 681 { 682 jit_apply_return_set_uint 683 (&apply_return, *((jit_uint *)return_buffer)); 684 } 685 break; 686 687 case JIT_TYPE_LONG: 688 { 689 jit_apply_return_set_long 690 (&apply_return, *((jit_long *)return_buffer)); 691 } 692 break; 693 694 case JIT_TYPE_ULONG: 695 { 696 jit_apply_return_set_ulong 697 (&apply_return, *((jit_ulong *)return_buffer)); 698 } 699 break; 700 701 case JIT_TYPE_FLOAT32: 702 { 703 jit_apply_return_set_float32 704 (&apply_return, *((jit_float32 *)return_buffer)); 705 return_type = _JIT_APPLY_RETURN_TYPE_FLOAT32; 706 } 707 break; 708 709 case JIT_TYPE_FLOAT64: 710 { 711 jit_apply_return_set_float64 712 (&apply_return, *((jit_float64 *)return_buffer)); 713 return_type = _JIT_APPLY_RETURN_TYPE_FLOAT64; 714 } 715 break; 716 717 case JIT_TYPE_NFLOAT: 718 { 719 jit_apply_return_set_nfloat 720 (&apply_return, *((jit_nfloat *)return_buffer)); 721 return_type = _JIT_APPLY_RETURN_TYPE_NFLOAT; 722 } 723 break; 724 725 case JIT_TYPE_STRUCT: 726 case JIT_TYPE_UNION: 727 { 728 if(!jit_type_return_via_pointer(type)) 729 { 730 jit_memcpy(&apply_return, return_buffer, 731 jit_type_get_size(type)); 732 } 733 } 734 break; 735 } 736 } 737 738 /* Return the result to the caller */ 739 switch(return_type) 740 { 741 case _JIT_APPLY_RETURN_TYPE_FLOAT32: 742 { 743 jit_builtin_return_float(&apply_return); 744 } 745 break; 746 747 case _JIT_APPLY_RETURN_TYPE_FLOAT64: 748 { 749 jit_builtin_return_double(&apply_return); 750 } 751 break; 752 753 case _JIT_APPLY_RETURN_TYPE_NFLOAT: 754 { 755 jit_builtin_return_nfloat(&apply_return); 756 } 757 break; 758 759 default: 760 { 761 jit_builtin_return_int(&apply_return); 762 } 763 } 764 } 765 766 #endif /* jit_closure_size */ 767 768 /*@ 769 * @deftypefun {void *} jit_closure_create (jit_context_t @var{context}, jit_type_t @var{signature}, jit_closure_func @var{func}, void *@var{user_data}) 770 * Create a closure from a function signature, a closure handling function, 771 * and a user data value. Returns NULL if out of memory, or if closures are 772 * not supported. The @var{func} argument should have the following 773 * prototype: 774 * 775 * @example 776 * void func(jit_type_t signature, void *result, void **args, void *user_data); 777 * @end example 778 * 779 * If the closure signature includes variable arguments, then @code{args} 780 * will contain pointers to the fixed arguments, followed by a 781 * @code{jit_closure_va_list_t} value for accessing the remainder of 782 * the arguments. 783 * 784 * The memory for the closure will be reclaimed when the @var{context} 785 * is destroyed. 786 * @end deftypefun 787 @*/ 788 void * 789 jit_closure_create(jit_context_t context, jit_type_t signature, jit_closure_func func, void *user_data) 790 { 791 #ifdef jit_closure_size 792 jit_closure_t closure; 793 794 /* Validate the parameters */ 795 if(!context || !signature || !func) 796 { 797 return 0; 798 } 799 800 /* Acquire the memory context */ 801 _jit_memory_lock(context); 802 if(!_jit_memory_ensure(context)) 803 { 804 _jit_memory_unlock(context); 805 return 0; 806 } 807 808 /* Allocate memory space for the closure */ 809 closure = (jit_closure_t) _jit_memory_alloc_closure(context); 810 if(!closure) 811 { 812 _jit_memory_unlock(context); 813 return 0; 814 } 815 816 /* Fill in the closure fields */ 817 _jit_create_closure(closure->buf, (void *)closure_handler, closure, signature); 818 closure->signature = signature; 819 closure->func = func; 820 closure->user_data = user_data; 821 822 /* Release the memory context, as we are finished with it */ 823 _jit_memory_unlock(context); 824 825 /* Perform a cache flush on the closure's code */ 826 _jit_flush_exec(closure->buf, sizeof(closure->buf)); 827 828 /* Return the completed closure to the caller */ 829 return closure; 830 831 #else 832 /* Closures are not supported on this platform */ 833 return 0; 834 #endif 835 } 836 837 /*@ 838 * @deftypefun int jit_supports_closures (void) 839 * Determine if this platform has support for closures. 840 * @end deftypefun 841 @*/ 842 int 843 jit_supports_closures(void) 844 { 845 #ifdef jit_closure_size 846 return 1; 847 #else 848 return 0; 849 #endif 850 } 851 852 unsigned int 853 jit_get_closure_size(void) 854 { 855 #ifdef jit_closure_size 856 return jit_closure_size; 857 #else 858 return 0; 859 #endif 860 } 861 862 unsigned int 863 jit_get_closure_alignment(void) 864 { 865 #ifdef jit_closure_size 866 return jit_closure_align; 867 #else 868 return 0; 869 #endif 870 } 871 872 unsigned int 873 jit_get_trampoline_size(void) 874 { 875 int size = 0; 876 #if defined(jit_redirector_size) 877 size += jit_redirector_size; 878 #endif 879 #if defined(jit_indirector_size) 880 size += jit_indirector_size; 881 #endif 882 return size; 883 } 884 885 unsigned int 886 jit_get_trampoline_alignment(void) 887 { 888 #if defined(jit_redirector_size) || defined(jit_indirector_size) 889 return 1; 890 #else 891 return 0; 892 #endif 893 } 894 895 /*@ 896 * @deftypefun jit_nint jit_closure_va_get_nint (jit_closure_va_list_t @var{va}) 897 * @deftypefunx jit_nuint jit_closure_va_get_nuint (jit_closure_va_list_t @var{va}) 898 * @deftypefunx jit_long jit_closure_va_get_long (jit_closure_va_list_t @var{va}) 899 * @deftypefunx jit_ulong jit_closure_va_get_ulong (jit_closure_va_list_t @var{va}) 900 * @deftypefunx jit_float32 jit_closure_va_get_float32 (jit_closure_va_list_t @var{va}) 901 * @deftypefunx jit_float64 jit_closure_va_get_float64 (jit_closure_va_list_t @var{va}) 902 * @deftypefunx jit_nfloat jit_closure_va_get_nfloat (jit_closure_va_list_t @var{va}) 903 * @deftypefunx {void *} jit_closure_va_get_ptr (jit_closure_va_list_t @var{va}) 904 * Get the next value of a specific type from a closure's variable arguments. 905 * @end deftypefun 906 @*/ 907 jit_nint jit_closure_va_get_nint(jit_closure_va_list_t va) 908 { 909 jit_nint value; 910 jit_apply_parser_get_nint(&(va->builder), value); 911 return value; 912 } 913 914 jit_nuint jit_closure_va_get_nuint(jit_closure_va_list_t va) 915 { 916 jit_nuint value; 917 jit_apply_parser_get_nuint(&(va->builder), value); 918 return value; 919 } 920 921 jit_long jit_closure_va_get_long(jit_closure_va_list_t va) 922 { 923 jit_long value; 924 jit_apply_parser_get_long(&(va->builder), value); 925 return value; 926 } 927 928 jit_ulong jit_closure_va_get_ulong(jit_closure_va_list_t va) 929 { 930 jit_ulong value; 931 jit_apply_parser_get_ulong(&(va->builder), value); 932 return value; 933 } 934 935 jit_float32 jit_closure_va_get_float32(jit_closure_va_list_t va) 936 { 937 jit_float32 value; 938 jit_apply_parser_get_float32(&(va->builder), value); 939 return value; 940 } 941 942 jit_float64 jit_closure_va_get_float64(jit_closure_va_list_t va) 943 { 944 jit_float64 value; 945 jit_apply_parser_get_float64(&(va->builder), value); 946 return value; 947 } 948 949 jit_nfloat jit_closure_va_get_nfloat(jit_closure_va_list_t va) 950 { 951 jit_nfloat value; 952 jit_apply_parser_get_nfloat(&(va->builder), value); 953 return value; 954 } 955 956 void *jit_closure_va_get_ptr(jit_closure_va_list_t va) 957 { 958 jit_nint value; 959 jit_apply_parser_get_nint(&(va->builder), value); 960 return (void *)value; 961 } 962 963 /*@ 964 * @deftypefun void jit_closure_va_get_struct (jit_closure_va_list_t @var{va}, void *@var{buf}, jit_type_t @var{type}) 965 * Get a structure or union value of a specific @var{type} from a closure's 966 * variable arguments, and copy it into @var{buf}. 967 * @end deftypefun 968 @*/ 969 void 970 jit_closure_va_get_struct(jit_closure_va_list_t va, void *buf, jit_type_t type) 971 { 972 #ifdef HAVE_JIT_BUILTIN_APPLY_STRUCT 973 _jit_builtin_apply_get_struct(&(va->builder), buf, type); 974 #else 975 jit_apply_parser_get_struct 976 (&(va->builder), jit_type_get_size(type), 977 jit_type_get_alignment(type), buf); 978 #endif 979 }