github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-rules-interp.c (about) 1 /* 2 * jit-rules-interp.c - Rules that define the interpreter characteristics. 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-rules.h" 25 #include "jit-reg-alloc.h" 26 27 #if defined(JIT_BACKEND_INTERP) 28 29 #include "jit-interp.h" 30 31 /*@ 32 33 The architecture definition rules for a CPU are placed into the files 34 @code{jit-rules-ARCH.h} and @code{jit-rules-ARCH.c}. You should add 35 both of these files to @code{Makefile.am} in @code{libjit/jit}. 36 37 You will also need to edit @code{jit-rules.h} in two places. First, 38 place detection logic at the top of the file to detect your platform 39 and define @code{JIT_BACKEND_ARCH} to 1. Further down the file, 40 you should add the following two lines to the include file logic: 41 42 @example 43 #elif defined(JIT_BACKEND_ARCH) 44 #include "jit-rules-ARCH.h" 45 @end example 46 47 @subsection Defining the registers 48 49 Every rule header file needs to define the macro @code{JIT_REG_INFO} to 50 an array of values that represents the properties of the CPU's 51 registers. The @code{_jit_reg_info} array is populated with 52 these values. @code{JIT_NUM_REGS} defines the number of 53 elements in the array. Each element in the array has the 54 following members: 55 56 @table @code 57 @item name 58 The name of the register. This is used for debugging purposes. 59 60 @item cpu_reg 61 The raw CPU register number. Registers in @code{libjit} are 62 referred to by their pseudo register numbers, corresponding to 63 their index within @code{JIT_REG_INFO}. However, these pseudo 64 register numbers may not necessarily correspond to the register 65 numbers used by the actual CPU. This field provides a mapping. 66 67 @item other_reg 68 The second pseudo register in a 64-bit register pair, or -1 if 69 the current register cannot be used as the first pseudo register 70 in a 64-bit register pair. This field only has meaning on 32-bit 71 platforms, and should always be set to -1 on 64-bit platforms. 72 73 @item flags 74 Flag bits that describe the pseudo register's properties. 75 @end table 76 77 @noindent 78 The following flags may be present: 79 80 @table @code 81 @item JIT_REG_WORD 82 This register can hold an integer word value. 83 84 @item JIT_REG_LONG 85 This register can hold a 64-bit long value without needing a 86 second register. Normally only used on 64-bit platforms. 87 88 @item JIT_REG_FLOAT32 89 This register can hold a 32-bit floating-point value. 90 91 @item JIT_REG_FLOAT64 92 This register can hold a 64-bit floating-point value. 93 94 @item JIT_REG_NFLOAT 95 This register can hold a native floating-point value. 96 97 @item JIT_REG_FRAME 98 This register holds the frame pointer. You will almost always supply 99 @code{JIT_REG_FIXED} for this register. 100 101 @item JIT_REG_STACK_PTR 102 This register holds the stack pointer. You will almost always supply 103 @code{JIT_REG_FIXED} for this register. 104 105 @item JIT_REG_FIXED 106 This register has a fixed meaning and cannot be used for general allocation. 107 108 @item JIT_REG_CALL_USED 109 This register will be destroyed by a function call. 110 111 @item JIT_REG_IN_STACK 112 This register is in a stack-like arrangement. 113 114 @item JIT_REG_GLOBAL 115 This register is a candidate for global register allocation. 116 @end table 117 118 A CPU may have some registers arranged into a stack. In this case 119 operations can typically only occur at the top of the stack, and 120 may automatically pop values as a side-effect of the operation. 121 An example of such architecture is x87 floating point unit. Such 122 CPU requires three additional macros. 123 124 @table @code 125 126 @item JIT_REG_STACK 127 If defined, this indicates the presence of the register stack. 128 129 @item JIT_REG_STACK_START 130 The index of the first register in the @code{JIT_REG_INFO} array that is used 131 in a stack-like arrangement. 132 133 @item JIT_REG_STACK_END 134 The index of the last register in the @code{JIT_REG_INFO} array that is used 135 in a stack-like arrangement. 136 137 @end table 138 139 The entries in the @code{JIT_REG_INFO} array from @code{JIT_REG_STACK_START} 140 up to @code{JIT_REG_STACK_END} must also have the @code{JIT_REG_IN_STACK} 141 flag set. 142 143 @subsection Other architecture macros 144 145 @noindent 146 The rule file may also have definitions of the following macros: 147 148 @table @code 149 @item JIT_NUM_GLOBAL_REGS 150 The number of registers that are used for global register allocation. 151 Set to zero if global register allocation should not be used. 152 153 @item JIT_ALWAYS_REG_REG 154 Define this to 1 if arithmetic operations must always be performed 155 on registers. Define this to 0 if register/memory and memory/register 156 operations are possible. 157 158 @item JIT_PROLOG_SIZE 159 If defined, this indicates the maximum size of the function prolog. 160 161 @item JIT_FUNCTION_ALIGNMENT 162 This value indicates the alignment required for the start of a function. 163 e.g. define this to 32 if functions should be aligned on a 32-byte 164 boundary. 165 166 @item JIT_ALIGN_OVERRIDES 167 Define this to 1 if the platform allows reads and writes on 168 any byte boundary. Define to 0 if only properly-aligned 169 memory accesses are allowed. Normally only defined to 1 under x86. 170 171 @item jit_extra_gen_state 172 @itemx jit_extra_gen_init 173 @itemx jit_extra_gen_cleanup 174 The @code{jit_extra_gen_state} macro can be supplied to add extra fields 175 to the @code{struct jit_gencode} type in @code{jit-rules.h}, for 176 extra CPU-specific code generation state information. 177 178 The @code{jit_extra_gen_init} macro initializes this extra information, 179 and the @code{jit_extra_gen_cleanup} macro cleans it up when code 180 generation is complete. 181 @end table 182 183 @subsection Architecture-dependent functions 184 185 @*/ 186 187 /* 188 * Output a native word to the current method. 189 */ 190 #define jit_cache_native(gen,value) \ 191 do { \ 192 _jit_gen_check_space((gen), sizeof(jit_nuint)); \ 193 *((jit_nuint *)((gen)->ptr)) = (jit_nuint)(value); \ 194 (gen)->ptr += sizeof(jit_nuint); \ 195 } while (0) 196 197 /* 198 * Write an interpreter opcode to the cache. 199 */ 200 #define jit_cache_opcode(gen,opcode) \ 201 jit_cache_native((gen), (jit_nint)(opcode)) 202 203 /* 204 * Write "n" bytes to the cache, rounded up to a multiple of "void *". 205 */ 206 #define jit_cache_add_n(gen,buf,size) \ 207 do { \ 208 unsigned int __size = \ 209 ((size) + sizeof(void *) - 1) & ~(sizeof(void *) - 1); \ 210 _jit_gen_check_space((gen), __size); \ 211 jit_memcpy((gen)->ptr, (buf), (size)); \ 212 (gen)->ptr += __size; \ 213 } while (0) 214 215 /* 216 * Adjust the height of the working area. 217 */ 218 #define adjust_working(gen,adjust) \ 219 do { \ 220 (gen)->working_area += (adjust); \ 221 if((gen)->working_area > (gen)->max_working_area) \ 222 { \ 223 (gen)->max_working_area = (gen)->working_area; \ 224 } \ 225 } while (0) 226 227 /*@ 228 * @deftypefun void _jit_init_backend (void) 229 * Initialize the backend. This is normally used to configure registers 230 * that may not appear on all CPU's in a given family. For example, only 231 * some ARM cores have floating-point registers. 232 * @end deftypefun 233 @*/ 234 void _jit_init_backend(void) 235 { 236 /* Nothing to do here for the interpreter */ 237 } 238 239 /*@ 240 * @deftypefun void _jit_gen_get_elf_info (jit_elf_info_t *@var{info}) 241 * Get the ELF machine and ABI type information for this platform. 242 * The @code{machine} field should be set to one of the @code{EM_*} 243 * values in @code{jit-elf-defs.h}. The @code{abi} field should 244 * be set to one of the @code{ELFOSABI_*} values in @code{jit-elf-defs.h} 245 * (@code{ELFOSABI_SYSV} will normally suffice if you are unsure). 246 * The @code{abi_version} field should be set to the ABI version, 247 * which is usually zero. 248 * @end deftypefun 249 @*/ 250 void _jit_gen_get_elf_info(jit_elf_info_t *info) 251 { 252 /* The interpreter's ELF machine type is defined to be "Lj", 253 which hopefully won't clash with any standard types */ 254 info->machine = 0x4C6A; 255 info->abi = 0; 256 info->abi_version = JIT_OPCODE_VERSION; 257 } 258 259 /*@ 260 * @deftypefun int _jit_create_entry_insns (jit_function_t @var{func}) 261 * Create instructions in the entry block to initialize the 262 * registers and frame offsets that contain the parameters. 263 * Returns zero if out of memory. 264 * 265 * This function is called when a builder is initialized. It should 266 * scan the signature and decide which register or frame position 267 * contains each of the parameters and then call either 268 * @code{jit_insn_incoming_reg} or @code{jit_insn_incoming_frame_posn} 269 * to notify @code{libjit} of the location. 270 * @end deftypefun 271 @*/ 272 int _jit_create_entry_insns(jit_function_t func) 273 { 274 jit_type_t signature = func->signature; 275 jit_type_t type; 276 jit_nint offset; 277 jit_value_t value; 278 unsigned int num_params; 279 unsigned int param; 280 281 /* Reset the frame size for this function */ 282 func->builder->frame_size = 0; 283 284 /* The starting parameter offset. We use negative offsets to indicate 285 an offset into the "args" block, and positive offsets to indicate 286 an offset into the "frame" block. The negative values will be 287 flipped when we output the argument opcodes for interpretation */ 288 offset = -1; 289 290 /* Allocate the structure return pointer */ 291 value = jit_value_get_struct_pointer(func); 292 if(value) 293 { 294 if(!jit_insn_incoming_frame_posn(func, value, offset)) 295 { 296 return 0; 297 } 298 --offset; 299 } 300 301 /* If the function is nested, then we an extra parameter 302 to pass the pointer to the parent's frame */ 303 if(func->nested_parent) 304 { 305 value = jit_value_create(func, jit_type_void_ptr); 306 if(!value) 307 { 308 return 0; 309 } 310 311 value->is_parameter = 1; 312 313 if(!jit_insn_incoming_frame_posn(func, value, offset)) 314 { 315 return 0; 316 } 317 318 jit_function_set_parent_frame(func, value); 319 --offset; 320 } 321 322 /* Allocate the parameter offsets */ 323 num_params = jit_type_num_params(signature); 324 for(param = 0; param < num_params; ++param) 325 { 326 value = jit_value_get_param(func, param); 327 if(!value) 328 { 329 continue; 330 } 331 332 type = jit_type_remove_tags(jit_value_get_type(value)); 333 switch(type->kind) 334 { 335 case JIT_TYPE_SBYTE: 336 case JIT_TYPE_UBYTE: 337 if(!jit_insn_incoming_frame_posn(func, value, 338 offset - _jit_int_lowest_byte())) 339 { 340 return 0; 341 } 342 --offset; 343 break; 344 345 case JIT_TYPE_SHORT: 346 case JIT_TYPE_USHORT: 347 if(!jit_insn_incoming_frame_posn(func, value, 348 offset - _jit_int_lowest_short())) 349 { 350 return 0; 351 } 352 --offset; 353 break; 354 355 case JIT_TYPE_INT: 356 case JIT_TYPE_UINT: 357 case JIT_TYPE_NINT: 358 case JIT_TYPE_NUINT: 359 case JIT_TYPE_SIGNATURE: 360 case JIT_TYPE_PTR: 361 case JIT_TYPE_LONG: 362 case JIT_TYPE_ULONG: 363 case JIT_TYPE_FLOAT32: 364 case JIT_TYPE_FLOAT64: 365 case JIT_TYPE_NFLOAT: 366 if(!jit_insn_incoming_frame_posn(func, value, offset)) 367 { 368 return 0; 369 } 370 --offset; 371 break; 372 373 case JIT_TYPE_STRUCT: 374 case JIT_TYPE_UNION: 375 if(!jit_insn_incoming_frame_posn(func, value, offset)) 376 { 377 return 0; 378 } 379 offset -= JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(type)); 380 break; 381 } 382 } 383 return 1; 384 } 385 386 /*@ 387 * @deftypefun int _jit_create_call_setup_insns (jit_function_t @var{func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, int @var{is_nested}, jit_value_t @var{parent_frame}, jit_value_t *@var{struct_return}, int @var{flags}) 388 * Create instructions within @var{func} necessary to set up for a 389 * function call to a function with the specified @var{signature}. 390 * Use @code{jit_insn_push} to push values onto the system stack, 391 * or @code{jit_insn_outgoing_reg} to copy values into call registers. 392 * 393 * If @var{is_nested} is non-zero, then it indicates that we are calling a 394 * nested function within the current function's nested relationship tree. 395 * The @var{parent_frame} value will be a pointer to the start of the frame 396 * of the parent of the callee. 397 * 398 * If the function returns a structure by pointer, then @var{struct_return} 399 * must be set to a new local variable that will contain the returned 400 * structure. Otherwise it should be set to NULL. 401 * @end deftypefun 402 @*/ 403 int _jit_create_call_setup_insns 404 (jit_function_t func, jit_type_t signature, 405 jit_value_t *args, unsigned int num_args, 406 int is_nested, jit_value_t parent_frame, 407 jit_value_t *struct_return, int flags) 408 { 409 jit_type_t type; 410 jit_type_t vtype; 411 jit_value_t value; 412 unsigned int arg_num; 413 jit_nint offset; 414 jit_nuint size; 415 416 /* Regular or tail call? */ 417 if((flags & JIT_CALL_TAIL) == 0) 418 { 419 /* Push all of the arguments in reverse order */ 420 while(num_args > 0) 421 { 422 --num_args; 423 type = jit_type_get_param(signature, num_args); 424 type = jit_type_remove_tags(type); 425 if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) 426 { 427 /* If the value is a pointer, then we are pushing a structure 428 argument by pointer rather than by local variable */ 429 vtype = jit_type_normalize(jit_value_get_type(args[num_args])); 430 if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE) 431 { 432 if(!jit_insn_push_ptr(func, args[num_args], type)) 433 { 434 return 0; 435 } 436 continue; 437 } 438 } 439 if(!jit_insn_push(func, args[num_args])) 440 { 441 return 0; 442 } 443 } 444 445 /* Do we need to add nested function scope information? */ 446 if(is_nested) 447 { 448 if(!jit_insn_push(func, parent_frame)) 449 { 450 return 0; 451 } 452 } 453 454 /* Do we need to add a structure return pointer argument? */ 455 type = jit_type_get_return(signature); 456 if(jit_type_return_via_pointer(type)) 457 { 458 value = jit_value_create(func, type); 459 if(!value) 460 { 461 return 0; 462 } 463 *struct_return = value; 464 value = jit_insn_address_of(func, value); 465 if(!value) 466 { 467 return 0; 468 } 469 if(!jit_insn_push(func, value)) 470 { 471 return 0; 472 } 473 } 474 else if((flags & JIT_CALL_NATIVE) != 0) 475 { 476 /* Native calls always return a return area pointer */ 477 if(!jit_insn_push_return_area_ptr(func)) 478 { 479 return 0; 480 } 481 *struct_return = 0; 482 } 483 else 484 { 485 *struct_return = 0; 486 } 487 } 488 else 489 { 490 /* Copy the arguments into our own parameter slots */ 491 offset = -1; 492 type = jit_type_get_return(signature); 493 if(jit_type_return_via_pointer(type)) 494 { 495 --offset; 496 } 497 if(func->nested_parent) 498 { 499 --offset; 500 } 501 for(arg_num = 0; arg_num < num_args; ++arg_num) 502 { 503 type = jit_type_get_param(signature, arg_num); 504 value = jit_value_create(func, type); 505 if(!value) 506 { 507 return 0; 508 } 509 if(!jit_insn_outgoing_frame_posn(func, value, offset)) 510 { 511 return 0; 512 } 513 type = jit_type_remove_tags(type); 514 size = jit_type_get_size(type); 515 offset -= (jit_nint)(JIT_NUM_ITEMS_IN_STRUCT(size)); 516 if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) 517 { 518 /* If the value is a pointer, then we are pushing a structure 519 argument by pointer rather than by local variable */ 520 vtype = jit_type_normalize(jit_value_get_type(args[arg_num])); 521 if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE) 522 { 523 value = jit_insn_address_of(func, value); 524 if(!value) 525 { 526 return 0; 527 } 528 if(!jit_insn_memcpy 529 (func, value, args[arg_num], 530 jit_value_create_nint_constant 531 (func, jit_type_nint, (jit_nint)size))) 532 { 533 return 0; 534 } 535 continue; 536 } 537 } 538 if(!jit_insn_store(func, value, args[arg_num])) 539 { 540 return 0; 541 } 542 } 543 *struct_return = 0; 544 } 545 546 /* The call is ready to proceed */ 547 return 1; 548 } 549 550 /*@ 551 * @deftypefun int _jit_setup_indirect_pointer (jit_function_t @var{func}, jit_value_t @var{value}) 552 * Place the indirect function pointer @var{value} into a suitable register 553 * or stack location for a subsequent indirect call. 554 * @end deftypefun 555 @*/ 556 int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value) 557 { 558 //return jit_insn_outgoing_reg(func, value, 1); 559 return 1; 560 } 561 562 /*@ 563 * @deftypefun int _jit_create_call_return_insns (jit_function_t @var{func}, jit_type_t @var{signature}, jit_value_t *@var{args}, unsigned int @var{num_args}, jit_value_t @var{return_value}, int @var{is_nested}) 564 * Create instructions within @var{func} to clean up after a function call 565 * and to place the function's result into @var{return_value}. 566 * This should use @code{jit_insn_pop_stack} to pop values off the system 567 * stack and @code{jit_insn_return_reg} to tell @code{libjit} which 568 * register contains the return value. In the case of a @code{void} 569 * function, @var{return_value} will be NULL. 570 * 571 * Note: the argument values are passed again because it may not be possible 572 * to determine how many bytes to pop from the stack from the @var{signature} 573 * alone; especially if the called function is vararg. 574 * @end deftypefun 575 @*/ 576 int _jit_create_call_return_insns 577 (jit_function_t func, jit_type_t signature, 578 jit_value_t *args, unsigned int num_args, 579 jit_value_t return_value, int is_nested) 580 { 581 jit_nint pop_items; 582 unsigned int size; 583 jit_type_t return_type; 584 int ptr_return; 585 586 /* Calculate the number of items that we need to pop */ 587 pop_items = 0; 588 while(num_args > 0) 589 { 590 --num_args; 591 size = jit_type_get_size(jit_value_get_type(args[num_args])); 592 pop_items += JIT_NUM_ITEMS_IN_STRUCT(size); 593 } 594 return_type = jit_type_get_return(signature); 595 return_type = jit_type_remove_tags(return_type); 596 ptr_return = jit_type_return_via_pointer(return_type); 597 if(ptr_return) 598 { 599 ++pop_items; 600 } 601 if(is_nested) 602 { 603 /* The interpreter needs two arguments for the parent frame info */ 604 pop_items += 2; 605 } 606 607 /* Pop the items from the system stack */ 608 if(pop_items > 0) 609 { 610 if(!jit_insn_pop_stack(func, pop_items)) 611 { 612 return 0; 613 } 614 } 615 616 /* Bail out now if we don't need to worry about return values */ 617 if(!return_value || ptr_return) 618 { 619 return 1; 620 } 621 622 /* Structure values must be flushed into the frame, and 623 everything else ends up in the top-most stack register */ 624 if(jit_type_is_struct(return_type) || jit_type_is_union(return_type)) 625 { 626 if(!jit_insn_flush_struct(func, return_value)) 627 { 628 return 0; 629 } 630 } 631 else if(return_type->kind != JIT_TYPE_VOID) 632 { 633 if(!jit_insn_return_reg(func, return_value, 0)) 634 { 635 return 0; 636 } 637 } 638 639 /* Everything is back where it needs to be */ 640 return 1; 641 } 642 643 /*@ 644 * @deftypefun int _jit_opcode_is_supported (int @var{opcode}) 645 * Not all CPU's support all arithmetic, conversion, bitwise, or 646 * comparison operators natively. For example, most ARM platforms 647 * need to call out to helper functions to perform floating-point. 648 * 649 * If this function returns zero, then @code{jit-insn.c} will output a 650 * call to an intrinsic function that is equivalent to the desired opcode. 651 * This is how you tell @code{libjit} that you cannot handle the 652 * opcode natively. 653 * 654 * This function can also help you develop your back end incrementally. 655 * Initially, you can report that only integer operations are supported, 656 * and then once you have them working you can move on to the floating point 657 * operations. 658 * @end deftypefun 659 @*/ 660 int _jit_opcode_is_supported(int opcode) 661 { 662 /* We support all opcodes in the interpreter */ 663 return 1; 664 } 665 666 /* 667 * Calculate the size of the argument area for an interpreted function. 668 */ 669 unsigned int _jit_interp_calculate_arg_size 670 (jit_function_t func, jit_type_t signature) 671 { 672 unsigned int size = 0; 673 jit_type_t type; 674 unsigned int num_params; 675 unsigned int param; 676 677 /* Determine if we need nested parameter information */ 678 if(func->nested_parent) 679 { 680 size += 2 * sizeof(jit_item); 681 } 682 683 /* Determine if we need a structure pointer argument */ 684 type = jit_type_get_return(signature); 685 if(jit_type_return_via_pointer(type)) 686 { 687 size += sizeof(jit_item); 688 } 689 690 /* Calculate the total size of the regular arguments */ 691 num_params = jit_type_num_params(signature); 692 for(param = 0; param < num_params; ++param) 693 { 694 type = jit_type_get_param(signature, param); 695 type = jit_type_remove_tags(type); 696 if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION) 697 { 698 size += JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(type)) * 699 sizeof(jit_item); 700 } 701 else 702 { 703 size += sizeof(jit_item); 704 } 705 } 706 707 /* Return the final size to the caller */ 708 return size; 709 } 710 711 /*@ 712 * @deftypefun {void *} _jit_gen_prolog (jit_gencode_t @var{gen}, jit_function_t @var{func}, void *@var{buf}) 713 * Generate the prolog for a function into a previously-prepared 714 * buffer area of @code{JIT_PROLOG_SIZE} bytes in size. Returns 715 * the start of the prolog, which may be different than @var{buf}. 716 * 717 * This function is called at the end of the code generation process, 718 * not the beginning. At this point, it is known which callee save 719 * registers must be preserved, allowing the back end to output the 720 * most compact prolog possible. 721 * @end deftypefun 722 @*/ 723 void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) 724 { 725 /* Output the jit_function_interp structure at the beginning */ 726 jit_function_interp_t interp = (jit_function_interp_t)buf; 727 unsigned int max_working_area = 728 gen->max_working_area + gen->extra_working_space; 729 interp->func = func; 730 interp->args_size = _jit_interp_calculate_arg_size(func, func->signature); 731 interp->frame_size = 732 (func->builder->frame_size + max_working_area) * sizeof(jit_item); 733 interp->working_area = max_working_area; 734 return buf; 735 } 736 737 /*@ 738 * @deftypefun void _jit_gen_epilog (jit_gencode_t @var{gen}, jit_function_t @var{func}) 739 * Generate a function epilog, restoring the registers that 740 * were saved on entry to the function, and then returning. 741 * 742 * Only one epilog is generated per function. Functions with multiple 743 * @code{jit_insn_return} instructions will all jump to the common epilog. 744 * This is needed because the code generator may not know which callee 745 * save registers need to be restored by the epilog until the full function 746 * has been processed. 747 * @end deftypefun 748 @*/ 749 void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) 750 { 751 /* The interpreter doesn't use epilogs */ 752 } 753 754 /*@ 755 * @deftypefun {void *} _jit_gen_redirector (jit_gencode_t @var{gen}, jit_function_t @var{func}) 756 * Generate code for a redirector, which makes an indirect jump 757 * to the contents of @code{@var{func}->entry_point}. Redirectors 758 * are used on recompilable functions in place of the regular 759 * entry point. This allows @code{libjit} to redirect existing 760 * calls to the new version after recompilation. 761 * @end deftypefun 762 @*/ 763 void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) 764 { 765 /* The interpreter doesn't need redirectors */ 766 return 0; 767 } 768 769 /*@ 770 * @deftypefun void _jit_gen_spill_reg (jit_gencode_t @var{gen}, int @var{reg}, int @var{other_reg}, jit_value_t @var{value}) 771 * Generate instructions to spill a pseudo register to the local 772 * variable frame. If @var{other_reg} is not -1, then it indicates 773 * the second register in a 64-bit register pair. 774 * 775 * This function will typically call @code{_jit_gen_fix_value} to 776 * fix the value's frame position, and will then generate the 777 * appropriate spill instructions. 778 * @end deftypefun 779 @*/ 780 void _jit_gen_spill_reg(jit_gencode_t gen, int reg, 781 int other_reg, jit_value_t value) 782 { 783 /* Registers are not used in the interpreted back end */ 784 } 785 786 /*@ 787 * @deftypefun void _jit_gen_free_reg (jit_gencode_t @var{gen}, int @var{reg}, int @var{other_reg}, int @var{value_used}) 788 * Generate instructions to free a register without spilling its value. 789 * This is called when a register's contents become invalid, or its 790 * value is no longer required. If @var{value_used} is set to a non-zero 791 * value, then it indicates that the register's value was just used. 792 * Otherwise, there is a value in the register but it was never used. 793 * 794 * On most platforms, this function won't need to do anything to free 795 * the register. But some do need to take explicit action. For example, 796 * x86 needs an explicit instruction to remove a floating-point value 797 * from the FPU's stack if its value has not been used yet. 798 * @end deftypefun 799 @*/ 800 void _jit_gen_free_reg(jit_gencode_t gen, int reg, 801 int other_reg, int value_used) 802 { 803 /* Registers are not used in the interpreted back end */ 804 } 805 806 /*@ 807 * @deftypefun void _jit_gen_load_value (jit_gencode_t @var{gen}, int @var{reg}, int @var{other_reg}, jit_value_t @var{value}) 808 * Generate instructions to load a value into a register. The value will 809 * either be a constant or a slot in the frame. You should fix frame slots 810 * with @code{_jit_gen_fix_value}. 811 * @end deftypefun 812 @*/ 813 void _jit_gen_load_value 814 (jit_gencode_t gen, int reg, int other_reg, jit_value_t value) 815 { 816 /* Registers are not used in the interpreted back end */ 817 } 818 819 /*@ 820 * @deftypefun void _jit_gen_spill_global (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value}) 821 * Spill the contents of @var{value} from its corresponding global register. 822 * This is used in rare cases when a machine instruction requires its operand 823 * to be in the specific register that happens to be global. In such cases the 824 * register is spilled just before the instruction and loaded back immediately 825 * after it. 826 * @end deftypefun 827 @*/ 828 void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value) 829 { 830 /* Global registers are not used in the interpreted back end */ 831 } 832 833 /*@ 834 * @deftypefun void _jit_gen_load_global (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value}) 835 * Load the contents of @var{value} into its corresponding global register. 836 * This is used at the head of a function to pull parameters out of stack 837 * slots into their global register copies. 838 * @end deftypefun 839 @*/ 840 void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) 841 { 842 /* Global registers are not used in the interpreted back end */ 843 } 844 845 /*@ 846 * @deftypefun void _jit_gen_exch_top (jit_gencode_t @var{gen}, int @var{reg}) 847 * Generate instructions to exchange the contents of the top stack register 848 * with a stack register specified by the @var{reg} argument. 849 * 850 * It needs to be implemented only by backends that support stack registers. 851 * @end deftypefun 852 @*/ 853 void _jit_gen_exch_top(jit_gencode_t gen, int reg) 854 { 855 /* Stack registers are not used in the interpreted back end */ 856 } 857 858 /*@ 859 * @deftypefun void _jit_gen_move_top (jit_gencode_t @var{gen}, int @var{reg}) 860 * Generate instructions to copy the contents of the top stack register 861 * into a stack register specified by the @code{reg} argument and pop 862 * the top register after this. If @code{reg} is equal to the top register 863 * then the top register is just popped without copying it. 864 * 865 * It needs to be implemented only by backends that support stack registers. 866 * @end deftypefun 867 @*/ 868 void _jit_gen_move_top(jit_gencode_t gen, int reg) 869 { 870 /* Stack registers are not used in the interpreted back end */ 871 } 872 873 /*@ 874 * @deftypefun void _jit_gen_spill_top (jit_gencode_t @var{gen}, int @var{reg}, jit_value_t @var{value}, int @var{pop}) 875 * Generate instructions to spill the top stack register to the local 876 * variable frame. The @var{pop} argument indicates if the top register 877 * is popped from the stack. 878 * 879 * It needs to be implemented only by backends that support stack registers. 880 * @end deftypefun 881 @*/ 882 void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop) 883 { 884 /* Stack registers are not used in the interpreted back end */ 885 } 886 887 /*@ 888 * @deftypefun void _jit_gen_fix_value (jit_value_t @var{value}) 889 * Fix the position of a value within the local variable frame. 890 * If it doesn't already have a position, then assign one for it. 891 * @end deftypefun 892 @*/ 893 void _jit_gen_fix_value(jit_value_t value) 894 { 895 if(!(value->has_frame_offset) && !(value->is_constant)) 896 { 897 jit_nint size = (jit_nint) 898 (JIT_NUM_ITEMS_IN_STRUCT(jit_type_get_size(value->type))); 899 value->frame_offset = value->block->func->builder->frame_size; 900 value->block->func->builder->frame_size += size; 901 value->has_frame_offset = 1; 902 } 903 } 904 905 static void 906 load_value(jit_gencode_t gen, jit_value_t value, int index) 907 { 908 int opcode; 909 jit_nint offset; 910 911 if(value->is_constant) 912 { 913 /* Determine the type of constant to be loaded */ 914 switch(jit_type_normalize(value->type)->kind) 915 { 916 case JIT_TYPE_SBYTE: 917 case JIT_TYPE_UBYTE: 918 case JIT_TYPE_SHORT: 919 case JIT_TYPE_USHORT: 920 case JIT_TYPE_INT: 921 case JIT_TYPE_UINT: 922 jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_INT + index); 923 jit_cache_native(gen, (jit_nint)(value->address)); 924 break; 925 926 case JIT_TYPE_LONG: 927 case JIT_TYPE_ULONG: 928 { 929 jit_long long_value; 930 long_value = jit_value_get_long_constant(value); 931 jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_LONG + index); 932 #ifdef JIT_NATIVE_INT64 933 jit_cache_native(gen, long_value); 934 #else 935 jit_cache_add_n(gen, &long_value, sizeof(long_value)); 936 #endif 937 break; 938 } 939 940 case JIT_TYPE_FLOAT32: 941 { 942 jit_float32 float32_value; 943 float32_value = jit_value_get_float32_constant(value); 944 jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_FLOAT32 + index); 945 jit_cache_add_n(gen, &float32_value, sizeof(float32_value)); 946 break; 947 } 948 949 case JIT_TYPE_FLOAT64: 950 { 951 jit_float64 float64_value; 952 float64_value = jit_value_get_float64_constant(value); 953 jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_FLOAT64 + index); 954 jit_cache_add_n (gen, &float64_value, sizeof(float64_value)); 955 break; 956 } 957 958 case JIT_TYPE_NFLOAT: 959 { 960 jit_nfloat nfloat_value; 961 nfloat_value = jit_value_get_nfloat_constant(value); 962 jit_cache_opcode(gen, JIT_INTERP_OP_LDC_0_NFLOAT + index); 963 jit_cache_add_n (gen, &nfloat_value, sizeof(nfloat_value)); 964 break; 965 } 966 } 967 } 968 else 969 { 970 /* Fix the position of the value in the stack frame */ 971 _jit_gen_fix_value(value); 972 973 /* Generate a local or argument access opcode, as appropriate */ 974 if(value->frame_offset >= 0) 975 { 976 /* Load a local variable value onto the stack */ 977 switch(index) 978 { 979 case 0: 980 opcode = JIT_INTERP_OP_LDL_0_SBYTE; 981 break; 982 case 1: 983 opcode = JIT_INTERP_OP_LDL_1_SBYTE; 984 break; 985 case 2: 986 opcode = JIT_INTERP_OP_LDL_2_SBYTE; 987 break; 988 default: 989 return; 990 } 991 opcode = _jit_load_opcode(opcode, value->type); 992 offset = value->frame_offset; 993 } 994 else 995 { 996 /* Load an argument value onto the stack */ 997 switch(index) 998 { 999 case 0: 1000 opcode = JIT_INTERP_OP_LDA_0_SBYTE; 1001 break; 1002 case 1: 1003 opcode = JIT_INTERP_OP_LDA_1_SBYTE; 1004 break; 1005 case 2: 1006 opcode = JIT_INTERP_OP_LDA_2_SBYTE; 1007 break; 1008 default: 1009 return; 1010 } 1011 opcode = _jit_load_opcode(opcode, value->type); 1012 offset = -(value->frame_offset + 1); 1013 } 1014 1015 jit_cache_opcode(gen, opcode); 1016 jit_cache_native(gen, offset); 1017 } 1018 } 1019 1020 static void 1021 store_value(jit_gencode_t gen, jit_value_t value) 1022 { 1023 int opcode; 1024 jit_nint offset; 1025 1026 /* Fix the value in place within the local variable frame */ 1027 _jit_gen_fix_value(value); 1028 1029 /* Output an appropriate instruction to store the value */ 1030 offset = value->frame_offset; 1031 if(offset >= 0) 1032 { 1033 opcode = _jit_store_opcode(JIT_INTERP_OP_STL_0_BYTE, 0, value->type); 1034 } 1035 else 1036 { 1037 opcode = _jit_store_opcode(JIT_INTERP_OP_STA_0_BYTE, 0, value->type); 1038 offset = -(offset + 1); 1039 } 1040 jit_cache_opcode(gen, opcode); 1041 jit_cache_native(gen, offset); 1042 } 1043 1044 /*@ 1045 * @deftypefun void _jit_gen_insn (jit_gencode_t @var{gen}, jit_function_t @var{func}, jit_block_t @var{block}, jit_insn_t @var{insn}) 1046 * Generate native code for the specified @var{insn}. This function should 1047 * call the appropriate register allocation routines, output the instruction, 1048 * and then arrange for the result to be placed in an appropriate register 1049 * or memory destination. 1050 * @end deftypefun 1051 @*/ 1052 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, 1053 jit_block_t block, jit_insn_t insn) 1054 { 1055 jit_label_t label; 1056 jit_function_t target_func; 1057 void **pc; 1058 jit_nint offset; 1059 jit_nint size; 1060 1061 switch(insn->opcode) 1062 { 1063 case JIT_OP_BR_IEQ: 1064 case JIT_OP_BR_INE: 1065 case JIT_OP_BR_ILT: 1066 case JIT_OP_BR_ILT_UN: 1067 case JIT_OP_BR_ILE: 1068 case JIT_OP_BR_ILE_UN: 1069 case JIT_OP_BR_IGT: 1070 case JIT_OP_BR_IGT_UN: 1071 case JIT_OP_BR_IGE: 1072 case JIT_OP_BR_IGE_UN: 1073 case JIT_OP_BR_LEQ: 1074 case JIT_OP_BR_LNE: 1075 case JIT_OP_BR_LLT: 1076 case JIT_OP_BR_LLT_UN: 1077 case JIT_OP_BR_LLE: 1078 case JIT_OP_BR_LLE_UN: 1079 case JIT_OP_BR_LGT: 1080 case JIT_OP_BR_LGT_UN: 1081 case JIT_OP_BR_LGE: 1082 case JIT_OP_BR_LGE_UN: 1083 case JIT_OP_BR_FEQ: 1084 case JIT_OP_BR_FNE: 1085 case JIT_OP_BR_FLT: 1086 case JIT_OP_BR_FLE: 1087 case JIT_OP_BR_FGT: 1088 case JIT_OP_BR_FGE: 1089 case JIT_OP_BR_FLT_INV: 1090 case JIT_OP_BR_FLE_INV: 1091 case JIT_OP_BR_FGT_INV: 1092 case JIT_OP_BR_FGE_INV: 1093 case JIT_OP_BR_DEQ: 1094 case JIT_OP_BR_DNE: 1095 case JIT_OP_BR_DLT: 1096 case JIT_OP_BR_DLE: 1097 case JIT_OP_BR_DGT: 1098 case JIT_OP_BR_DGE: 1099 case JIT_OP_BR_DLT_INV: 1100 case JIT_OP_BR_DLE_INV: 1101 case JIT_OP_BR_DGT_INV: 1102 case JIT_OP_BR_DGE_INV: 1103 case JIT_OP_BR_NFEQ: 1104 case JIT_OP_BR_NFNE: 1105 case JIT_OP_BR_NFLT: 1106 case JIT_OP_BR_NFLE: 1107 case JIT_OP_BR_NFGT: 1108 case JIT_OP_BR_NFGE: 1109 case JIT_OP_BR_NFLT_INV: 1110 case JIT_OP_BR_NFLE_INV: 1111 case JIT_OP_BR_NFGT_INV: 1112 case JIT_OP_BR_NFGE_INV: 1113 /* Binary branch */ 1114 load_value(gen, insn->value2, 2); 1115 /* Fall through */ 1116 1117 case JIT_OP_BR_IFALSE: 1118 case JIT_OP_BR_ITRUE: 1119 case JIT_OP_BR_LFALSE: 1120 case JIT_OP_BR_LTRUE: 1121 /* Unary branch */ 1122 load_value(gen, insn->value1, 1); 1123 /* Fall through */ 1124 1125 case JIT_OP_BR: 1126 case JIT_OP_CALL_FINALLY: 1127 /* Unconditional branch */ 1128 branch: 1129 label = (jit_label_t)(insn->dest); 1130 pc = (void **)(gen->ptr); 1131 jit_cache_opcode(gen, insn->opcode); 1132 block = jit_block_from_label(func, label); 1133 if(!block) 1134 { 1135 break; 1136 } 1137 if(block->address) 1138 { 1139 /* We already know the address of the block */ 1140 jit_cache_native(gen, ((void **)(block->address)) - pc); 1141 } 1142 else 1143 { 1144 /* Record this position on the block's fixup list */ 1145 jit_cache_native(gen, block->fixup_list); 1146 block->fixup_list = (void *)pc; 1147 } 1148 break; 1149 1150 case JIT_OP_CALL_FILTER: 1151 /* Branch to a filter subroutine, load the filter 1152 parameter to the r0 register */ 1153 load_value(gen, insn->value1, 0); 1154 goto branch; 1155 1156 case JIT_OP_JUMP_TABLE: 1157 { 1158 jit_label_t *labels; 1159 jit_nint num_labels; 1160 jit_nint index; 1161 1162 load_value(gen, insn->dest, 0); 1163 1164 labels = (jit_label_t *) insn->value1->address; 1165 num_labels = insn->value2->address; 1166 1167 jit_cache_opcode(gen, insn->opcode); 1168 jit_cache_native(gen, num_labels); 1169 for(index = 0; index < num_labels; index++) 1170 { 1171 block = jit_block_from_label(func, labels[index]); 1172 if(!block) 1173 { 1174 return; 1175 } 1176 if(block->address) 1177 { 1178 /* We already know the address of the block */ 1179 jit_cache_native(gen, block->address); 1180 } 1181 else 1182 { 1183 /* Record this position on the block's fixup list */ 1184 pc = (void **)(gen->ptr); 1185 jit_cache_native(gen, block->fixup_absolute_list); 1186 block->fixup_absolute_list = pc; 1187 } 1188 } 1189 break; 1190 } 1191 1192 case JIT_OP_ADDRESS_OF_LABEL: 1193 /* Get the address of a particular label */ 1194 label = (jit_label_t)(insn->value1); 1195 block = jit_block_from_label(func, label); 1196 if(!block) 1197 { 1198 break; 1199 } 1200 pc = (void **)(gen->ptr); 1201 jit_cache_opcode(gen, insn->opcode); 1202 if(block->address) 1203 { 1204 /* We already know the address of the block */ 1205 jit_cache_native(gen, ((void **)(block->address)) - pc); 1206 } 1207 else 1208 { 1209 /* Record this position on the block's fixup list */ 1210 jit_cache_native(gen, block->fixup_list); 1211 block->fixup_list = (void *)pc; 1212 } 1213 store_value(gen, insn->dest); 1214 break; 1215 1216 case JIT_OP_CALL: 1217 case JIT_OP_CALL_TAIL: 1218 /* Call a function, whose pointer is supplied explicitly */ 1219 jit_cache_opcode(gen, insn->opcode); 1220 jit_cache_native(gen, (jit_nint)(insn->dest)); 1221 break; 1222 1223 case JIT_OP_CALL_INDIRECT: 1224 case JIT_OP_CALL_INDIRECT_TAIL: 1225 /* Call a function, whose pointer is supplied in the register */ 1226 load_value(gen, insn->value1, 1); 1227 jit_cache_opcode(gen, insn->opcode); 1228 jit_cache_native(gen, (jit_nint)(insn->value2)); 1229 jit_cache_native(gen, (jit_nint) 1230 (jit_type_num_params((jit_type_t)(insn->value2)))); 1231 break; 1232 1233 case JIT_OP_CALL_VTABLE_PTR: 1234 case JIT_OP_CALL_VTABLE_PTR_TAIL: 1235 /* Call a function, whose vtable pointer is supplied in the register */ 1236 load_value(gen, insn->value1, 1); 1237 jit_cache_opcode(gen, insn->opcode); 1238 break; 1239 1240 case JIT_OP_CALL_EXTERNAL: 1241 case JIT_OP_CALL_EXTERNAL_TAIL: 1242 /* Call a native function, whose pointer is supplied explicitly */ 1243 jit_cache_opcode(gen, insn->opcode); 1244 jit_cache_native(gen, (jit_nint)(insn->value2)); 1245 jit_cache_native(gen, (jit_nint)(insn->dest)); 1246 jit_cache_native(gen, (jit_nint) 1247 (jit_type_num_params((jit_type_t)(insn->value2)))); 1248 break; 1249 1250 case JIT_OP_RETURN: 1251 /* Return from the current function with no result */ 1252 jit_cache_opcode(gen, JIT_OP_RETURN); 1253 break; 1254 1255 case JIT_OP_RETURN_INT: 1256 case JIT_OP_RETURN_LONG: 1257 case JIT_OP_RETURN_FLOAT32: 1258 case JIT_OP_RETURN_FLOAT64: 1259 case JIT_OP_RETURN_NFLOAT: 1260 /* Return from the current function with a specific result */ 1261 load_value(gen, insn->value1, 1); 1262 jit_cache_opcode(gen, insn->opcode); 1263 break; 1264 1265 case JIT_OP_RETURN_SMALL_STRUCT: 1266 /* Return from current function with a small structure result */ 1267 load_value(gen, insn->value1, 1); 1268 jit_cache_opcode(gen, insn->opcode); 1269 jit_cache_native(gen, jit_value_get_nint_constant(insn->value2)); 1270 break; 1271 1272 case JIT_OP_IMPORT: 1273 /* make sure the target value has a frame offset */ 1274 _jit_gen_fix_value(insn->value2); 1275 offset = insn->value2->frame_offset; 1276 1277 if(offset > 0) 1278 { 1279 /* load the pointer to the stack frame the target value resides in 1280 into r0 */ 1281 load_value(gen, insn->value1, 1); 1282 } 1283 else if(offset < 0) 1284 { 1285 /* The target value is in the argument frame of its function. We 1286 have to load the argument frame pointer first */ 1287 target_func = insn->value2->block->func; 1288 _jit_gen_fix_value(target_func->arguments_pointer); 1289 target_func->arguments_pointer_offset = 1290 target_func->arguments_pointer->frame_offset; 1291 1292 /* This will load the argument frame pointer into r1 */ 1293 load_value(gen, insn->value1, 1); 1294 jit_cache_native(gen, JIT_OP_LOAD_RELATIVE_LONG); 1295 jit_cache_native(gen, 1296 target_func->arguments_pointer_offset * sizeof(jit_item)); 1297 1298 offset = -(offset + 1); 1299 1300 if(offset != 0) 1301 { 1302 /* We need the argument frame pointer in r1 but it is in r0. 1303 There does not seem to be a r1 <- r0 op though. */ 1304 store_value(gen, insn->dest); 1305 load_value(gen, insn->dest, 1); 1306 } 1307 } 1308 else 1309 { 1310 /* The import targets address is 0 bytes off the frame pointer. This 1311 means the import basically becomes an dest <- value1 op */ 1312 load_value(gen, insn->value1, 0); 1313 } 1314 1315 if(offset != 0) 1316 { 1317 jit_cache_opcode(gen, JIT_OP_ADD_RELATIVE); 1318 jit_cache_native(gen, offset * sizeof(jit_item)); 1319 } 1320 store_value(gen, insn->dest); 1321 break; 1322 1323 case JIT_OP_THROW: 1324 /* Throw an exception */ 1325 load_value(gen, insn->value1, 1); 1326 jit_cache_opcode(gen, insn->opcode); 1327 break; 1328 1329 case JIT_OP_LOAD_PC: 1330 case JIT_OP_LOAD_EXCEPTION_PC: 1331 /* Load the current program counter onto the stack */ 1332 jit_cache_opcode(gen, insn->opcode); 1333 store_value(gen, insn->dest); 1334 break; 1335 1336 case JIT_OP_CALL_FILTER_RETURN: 1337 /* The r0 register currently contains "dest" */ 1338 store_value(gen, insn->dest); 1339 break; 1340 1341 case JIT_OP_ENTER_FINALLY: 1342 /* Record that the finally return address is on the stack */ 1343 ++(gen->extra_working_space); 1344 break; 1345 1346 case JIT_OP_LEAVE_FINALLY: 1347 /* Leave a finally clause */ 1348 jit_cache_opcode(gen, insn->opcode); 1349 break; 1350 1351 case JIT_OP_ENTER_FILTER: 1352 /* The top of the stack contains the return address, 1353 the r0 register contains the "dest" (filter parameter). */ 1354 ++(gen->extra_working_space); 1355 store_value(gen, insn->dest); 1356 break; 1357 1358 case JIT_OP_LEAVE_FILTER: 1359 /* Leave a filter clause, returning a particular value */ 1360 load_value(gen, insn->value1, 0); 1361 jit_cache_opcode(gen, insn->opcode); 1362 break; 1363 1364 case JIT_OP_INCOMING_REG: 1365 /* Store incoming value (in interpreter this is used to 1366 pass an exception object to the catcher) */ 1367 store_value(gen, insn->value1); 1368 break; 1369 1370 case JIT_OP_RETURN_REG: 1371 /* Push a function return value back onto the stack */ 1372 switch(jit_type_normalize(insn->value1->type)->kind) 1373 { 1374 case JIT_TYPE_SBYTE: 1375 case JIT_TYPE_UBYTE: 1376 case JIT_TYPE_SHORT: 1377 case JIT_TYPE_USHORT: 1378 case JIT_TYPE_INT: 1379 case JIT_TYPE_UINT: 1380 jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_INT); 1381 store_value(gen, insn->value1); 1382 break; 1383 1384 case JIT_TYPE_LONG: 1385 case JIT_TYPE_ULONG: 1386 jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_LONG); 1387 store_value(gen, insn->value1); 1388 break; 1389 1390 case JIT_TYPE_FLOAT32: 1391 jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_FLOAT32); 1392 store_value(gen, insn->value1); 1393 break; 1394 1395 case JIT_TYPE_FLOAT64: 1396 jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_FLOAT64); 1397 store_value(gen, insn->value1); 1398 break; 1399 1400 case JIT_TYPE_NFLOAT: 1401 jit_cache_opcode(gen, JIT_INTERP_OP_LDR_0_NFLOAT); 1402 store_value(gen, insn->value1); 1403 break; 1404 } 1405 break; 1406 1407 case JIT_OP_COPY_LOAD_SBYTE: 1408 case JIT_OP_COPY_LOAD_UBYTE: 1409 case JIT_OP_COPY_LOAD_SHORT: 1410 case JIT_OP_COPY_LOAD_USHORT: 1411 case JIT_OP_COPY_INT: 1412 case JIT_OP_COPY_LONG: 1413 case JIT_OP_COPY_FLOAT32: 1414 case JIT_OP_COPY_FLOAT64: 1415 case JIT_OP_COPY_NFLOAT: 1416 case JIT_OP_COPY_STORE_BYTE: 1417 case JIT_OP_COPY_STORE_SHORT: 1418 /* Copy a value from one temporary variable to another */ 1419 load_value(gen, insn->value1, 0); 1420 store_value(gen, insn->dest); 1421 break; 1422 1423 case JIT_OP_COPY_STRUCT: 1424 /* Copy a struct from one address to another */ 1425 load_value(gen, insn->dest, 0); 1426 load_value(gen, insn->value1, 1); 1427 size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest)); 1428 jit_cache_opcode(gen, insn->opcode); 1429 jit_cache_native(gen, size); 1430 break; 1431 1432 case JIT_OP_ADDRESS_OF: 1433 /* Get the address of a local variable */ 1434 _jit_gen_fix_value(insn->value1); 1435 if(insn->value1->frame_offset >= 0) 1436 { 1437 jit_cache_opcode(gen, JIT_INTERP_OP_LDLA_0); 1438 jit_cache_native(gen, insn->value1->frame_offset); 1439 } 1440 else 1441 { 1442 jit_cache_opcode(gen, JIT_INTERP_OP_LDAA_0); 1443 jit_cache_native(gen, -(insn->value1->frame_offset + 1)); 1444 } 1445 store_value(gen, insn->dest); 1446 break; 1447 1448 case JIT_OP_PUSH_INT: 1449 case JIT_OP_PUSH_LONG: 1450 case JIT_OP_PUSH_FLOAT32: 1451 case JIT_OP_PUSH_FLOAT64: 1452 case JIT_OP_PUSH_NFLOAT: 1453 /* Push an item onto the stack, ready for a function call */ 1454 load_value(gen, insn->value1, 1); 1455 jit_cache_opcode(gen, insn->opcode); 1456 adjust_working(gen, 1); 1457 break; 1458 1459 case JIT_OP_PUSH_STRUCT: 1460 /* Load the pointer value */ 1461 load_value(gen, insn->value1, 1); 1462 /* Push the structure at the designated pointer */ 1463 size = jit_value_get_nint_constant(insn->value2); 1464 jit_cache_opcode(gen, insn->opcode); 1465 jit_cache_native(gen, size); 1466 adjust_working(gen, JIT_NUM_ITEMS_IN_STRUCT(size)); 1467 break; 1468 1469 case JIT_OP_PUSH_RETURN_AREA_PTR: 1470 /* Push the address of the interpreter's return area */ 1471 jit_cache_opcode(gen, insn->opcode); 1472 adjust_working(gen, 1); 1473 break; 1474 1475 case JIT_OP_POP_STACK: 1476 /* Pop parameter values from the stack after a function returns */ 1477 size = jit_value_get_nint_constant(insn->value1); 1478 if(size == 1) 1479 { 1480 jit_cache_opcode(gen, JIT_INTERP_OP_POP); 1481 } 1482 else if(size == 2) 1483 { 1484 jit_cache_opcode(gen, JIT_INTERP_OP_POP_2); 1485 } 1486 else if(size == 3) 1487 { 1488 jit_cache_opcode(gen, JIT_INTERP_OP_POP_3); 1489 } 1490 else if(size != 0) 1491 { 1492 jit_cache_opcode(gen, JIT_OP_POP_STACK); 1493 jit_cache_native(gen, size); 1494 } 1495 break; 1496 1497 case JIT_OP_FLUSH_SMALL_STRUCT: 1498 /* Flush a small structure return value back into the frame */ 1499 load_value(gen, insn->value1, 0); 1500 size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->value1)); 1501 jit_cache_opcode(gen, insn->opcode); 1502 jit_cache_native(gen, size); 1503 break; 1504 1505 case JIT_OP_LOAD_RELATIVE_SBYTE: 1506 case JIT_OP_LOAD_RELATIVE_UBYTE: 1507 case JIT_OP_LOAD_RELATIVE_SHORT: 1508 case JIT_OP_LOAD_RELATIVE_USHORT: 1509 case JIT_OP_LOAD_RELATIVE_INT: 1510 case JIT_OP_LOAD_RELATIVE_LONG: 1511 case JIT_OP_LOAD_RELATIVE_FLOAT32: 1512 case JIT_OP_LOAD_RELATIVE_FLOAT64: 1513 case JIT_OP_LOAD_RELATIVE_NFLOAT: 1514 /* Load a value from a relative pointer */ 1515 load_value(gen, insn->value1, 1); 1516 offset = jit_value_get_nint_constant(insn->value2); 1517 jit_cache_opcode(gen, insn->opcode); 1518 jit_cache_native(gen, offset); 1519 store_value(gen, insn->dest); 1520 break; 1521 1522 case JIT_OP_LOAD_RELATIVE_STRUCT: 1523 /* Load a structured value from a relative pointer */ 1524 load_value(gen, insn->dest, 0); 1525 load_value(gen, insn->value1, 1); 1526 offset = jit_value_get_nint_constant(insn->value2); 1527 size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest)); 1528 jit_cache_opcode(gen, insn->opcode); 1529 jit_cache_native(gen, offset); 1530 jit_cache_native(gen, size); 1531 break; 1532 1533 case JIT_OP_STORE_RELATIVE_BYTE: 1534 case JIT_OP_STORE_RELATIVE_SHORT: 1535 case JIT_OP_STORE_RELATIVE_INT: 1536 case JIT_OP_STORE_RELATIVE_LONG: 1537 case JIT_OP_STORE_RELATIVE_FLOAT32: 1538 case JIT_OP_STORE_RELATIVE_FLOAT64: 1539 case JIT_OP_STORE_RELATIVE_NFLOAT: 1540 /* Store a value to a relative pointer */ 1541 load_value(gen, insn->dest, 0); 1542 load_value(gen, insn->value1, 1); 1543 offset = jit_value_get_nint_constant(insn->value2); 1544 jit_cache_opcode(gen, insn->opcode); 1545 jit_cache_native(gen, offset); 1546 break; 1547 1548 case JIT_OP_STORE_RELATIVE_STRUCT: 1549 /* Store a structured value to a relative pointer */ 1550 load_value(gen, insn->dest, 0); 1551 load_value(gen, insn->value1, 1); 1552 offset = jit_value_get_nint_constant(insn->value2); 1553 size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->value1)); 1554 jit_cache_opcode(gen, insn->opcode); 1555 jit_cache_native(gen, offset); 1556 jit_cache_native(gen, size); 1557 break; 1558 1559 case JIT_OP_ADD_RELATIVE: 1560 /* Add a relative offset to a pointer */ 1561 offset = jit_value_get_nint_constant(insn->value2); 1562 if(offset != 0) 1563 { 1564 load_value(gen, insn->value1, 1); 1565 jit_cache_opcode(gen, insn->opcode); 1566 jit_cache_native(gen, offset); 1567 store_value(gen, insn->dest); 1568 } 1569 else 1570 { 1571 load_value(gen, insn->value1, 0); 1572 store_value(gen, insn->dest); 1573 } 1574 break; 1575 1576 case JIT_OP_MARK_BREAKPOINT: 1577 /* Mark the current location as a potential breakpoint */ 1578 jit_cache_opcode(gen, insn->opcode); 1579 jit_cache_native(gen, insn->value1->address); 1580 jit_cache_native(gen, insn->value2->address); 1581 break; 1582 1583 default: 1584 if(insn->dest && (insn->flags & JIT_INSN_DEST_IS_VALUE) != 0) 1585 { 1586 load_value(gen, insn->dest, 0); 1587 } 1588 if(insn->value1) 1589 { 1590 load_value(gen, insn->value1, 1); 1591 } 1592 if(insn->value2) 1593 { 1594 load_value(gen, insn->value2, 2); 1595 } 1596 jit_cache_opcode(gen, insn->opcode); 1597 if(insn->dest && (insn->flags & JIT_INSN_DEST_IS_VALUE) == 0) 1598 { 1599 store_value(gen, insn->dest); 1600 } 1601 break; 1602 } 1603 } 1604 1605 /*@ 1606 * @deftypefun void _jit_gen_start_block (jit_gencode_t @var{gen}, jit_block_t @var{block}) 1607 * Called to notify the back end that the start of a basic block 1608 * has been reached. 1609 * @end deftypefun 1610 @*/ 1611 void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block) 1612 { 1613 void **fixup; 1614 void **next; 1615 1616 /* Set the address of this block */ 1617 block->address = (void *)(gen->ptr); 1618 1619 /* If this block has pending fixups, then apply them now */ 1620 fixup = (void **)(block->fixup_list); 1621 while(fixup != 0) 1622 { 1623 next = (void **)(fixup[1]); 1624 fixup[1] = (void *)(jit_nint)(((void **)(block->address)) - fixup); 1625 fixup = next; 1626 } 1627 block->fixup_list = 0; 1628 1629 fixup = (void **)(block->fixup_absolute_list); 1630 while(fixup != 0) 1631 { 1632 next = (void **)(fixup[0]); 1633 fixup[0] = (void *)(jit_nint)((void **)(block->address)); 1634 fixup = next; 1635 } 1636 block->fixup_absolute_list = 0; 1637 1638 /* If this is the exception catcher block, then we need to update 1639 the exception cookie for the function to point to here */ 1640 if(block->label == block->func->builder->catcher_label && 1641 block->func->has_try) 1642 { 1643 block->func->cookie = block->address; 1644 } 1645 } 1646 1647 /*@ 1648 * @deftypefun void _jit_gen_end_block (jit_gencode_t @var{gen}) 1649 * Called to notify the back end that the end of a basic block 1650 * has been reached. 1651 * @end deftypefun 1652 @*/ 1653 void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block) 1654 { 1655 /* Reset the working area size to zero for the next block */ 1656 gen->working_area = 0; 1657 } 1658 1659 /*@ 1660 * @deftypefun int _jit_gen_is_global_candidate (jit_type_t @var{type}) 1661 * Determine if @var{type} is a candidate for allocation within 1662 * global registers. 1663 * @end deftypefun 1664 @*/ 1665 int _jit_gen_is_global_candidate(jit_type_t type) 1666 { 1667 /* Global register allocation is not used by the interpreter */ 1668 return 0; 1669 } 1670 1671 /*@ 1672 * @deftypefun int _jit_reg_get_pair (jit_type_t @var{type}, int @var{reg}) 1673 * Determine if a type requires a register pair. If so then for the specified 1674 * register @var{reg} return the other register of the corresponding pair. 1675 * Return -1 if no pair is required. 1676 * 1677 * This function is used only for native 32-bit backends. 1678 * @end deftypefun 1679 @*/ 1680 int _jit_reg_get_pair(jit_type_t type, int reg) 1681 { 1682 /* We don't register pairs on 64-bit platforms or the interpreter */ 1683 return -1; 1684 } 1685 1686 #endif /* JIT_BACKEND_INTERP */