1 /* Instruction rewrite functionality header. 2 3 Copyright (C) 2017, 2018 Luca Saiu 4 Updated in 2019 by Luca Saiu 5 Written by Luca Saiu 6 7 This file is part of Jitter. 8 9 Jitter is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Jitter is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Jitter. If not, see <http://www.gnu.org/licenses/>. */ 21 22 23 #ifndef JITTER_REWRITE_H_ 24 #define JITTER_REWRITE_H_ 25 26 #include <jitter/jitter.h> 27 #include <jitter/jitter-instruction.h> 28 #include <jitter/jitter-mutable-routine.h> 29 30 31 /* Rewriter API. 32 * ************************************************************************** */ 33 34 /* Instruction rewriting entails replacing a sequence of one or more 35 unspecialized instructions with another sequence of zero or more equivalent 36 unspecified instructions; each instruction in the replacement will be 37 specializable, while the original instruction might not be. 38 39 There are two distinct use cases for rewriting: 40 (a) peephole optimization; 41 (b) reducing the number of specialized instructions in order to make the 42 generated C code smaller, possibly enabling the user of more fast 43 registers. 44 Case (b) is important, but is not exploited yet. 45 46 About case (b): 47 The rewriting mechanism can reduce the number of specialized instructions by 48 removing redundant ways of describing the same operation. Let us assume for 49 example a meta-instruction add (?r, ?r, !r); then the two unspecialized 50 instructions 51 add %r0, %r1, %r2 52 and 53 add %r1, %r0, %r2 54 have the same semantics because of commutativity, and we can systematically 55 rewrite one of them into the other (for example the one having input register 56 indices in non-decreasing order), arbitrarily chosen as the normal form. 57 This cuts the specialized instructions in half, allowing the user to compile 58 a Jittery system using less resources, or to keep using the same resources 59 but affording a higher number of fast registers. 60 61 Other rewritings yield slightly suboptimal code, but reduce the specialized 62 instruction set even more dramatically. The add instruction above has O(n^3) 63 specializations, but by requring the second and third arguments to be equal 64 we can cut specialized instructions to O(n^2). Assuming a register copying 65 meta-instruction mov (?r, !r) such a rewriting would require replacing, for 66 example, 67 add %r0, %r1, %r2 68 with the two-instruction sequence 69 mov %r1, %r2 70 add %r0, %r2, %r2 71 . Other add instructions already having the same register as their second 72 and third arguments would not be rewritten. 73 74 Rewriting happens after each instruction is completed, by a call to 75 jitter_mutable_routine_append_instruction_name or one of the jitter_mutable_routine_append_*_parameter 76 functions. Rewriting can never happen "across" a label: an original 77 unspecialized instruction before rewriting is replaced with a sequence, and 78 both the original and the rewritten sequence lie completely before or 79 completely after each label: it is not possible, by construction, to have 80 part of the replacement before and part of the replacement after a label. 81 82 As an exception the implicit label added after a callee instruction is not 83 restricted by the limitation above, at least for the purposes of case (a): it 84 is possible, and in fact useful, to rewrite a sequence containing a call 85 instruction into a more efficient sequence. As always the user has the 86 responsibility of ensuring that her rewritten code is semantically equivalent 87 to the original, but calls seem to present no particular problem. */ 88 89 90 91 92 /* This API is not for the user. 93 * ************************************************************************** */ 94 95 /* The functions and macros delcared here are used internally by the rewriter or 96 by generated code, and not intended for the user. The user specifies rewrite 97 rules as part of the Jitter VM speciefication, using Jitter syntax. */ 98 99 100 101 102 /* Rewriter entry point. 103 * ************************************************************************** */ 104 105 /* The rewriter entry point is the machine-generated vmprefix_rewrite , called 106 at instruction closing thru the rewrite function pointer within struct 107 jitter_vm. 108 109 See the comment for vmprefix_rewrite in the template header. */ 110 111 112 113 114 /* Rewriter internal functions. 115 * ************************************************************************** */ 116 117 /* These functions are used internally for the implementation of 118 vmprefix_rewrite. */ 119 120 /* Return a pointer to the last instruction in the given program; the returned 121 pointer refers the only instance of the instruction, and is not a copy. Fail 122 fatally if no instructions exist or if the last one is not complete, or if the 123 program is not unspecialized. */ 124 struct jitter_instruction* 125 jitter_last_instruction (struct jitter_mutable_routine *p); 126 127 /* Return a pointer pointing within an array of pointers to instructions, 128 how_many elements from the last one. The pointed memory may be invalidated 129 by any instruction modification, so this is only meant for *reading* the last 130 few instructions in order to check whether a rewrite rule applies. 131 The intended way of using this is for checking whether a rule applying 132 to N instruction can fire: it will be called with how_many = N, and 133 the result will be an array of N pointers to the last instructions. */ 134 /* Fail fatally if no instructions exist or if the last one is not complete, or 135 if the program is not unspecialized. [FIXME: possibly change this] */ 136 struct jitter_instruction** 137 jitter_last_instructions (struct jitter_mutable_routine *p, size_t how_many); 138 139 /* Pop the last instruction off the pointed program, which must be complete, and 140 return a pointer to it; fail fatally if the instruction is not complete or 141 does not exist, or if the program is unspecialized. This removes the pointer 142 to the instruction from the dynamic buffer in the program, but does not 143 deallocate the instruction: in fact the result of this function is the 144 pointer to the still-valid instruction, allocated according to the 145 conventions in jitter-instruction.h . It is the caller's responsibility to 146 release memory after usage, normally by a call to jitter_destroy_instruction 147 . The intended use case for this is fisrt checking whether a replacement 148 should occour, and then if so calling jitter_pop_instruction once; the result 149 pointer will be used to determine which instructions to append as a 150 replacement, by the usual jitter_mutable_routine_append_instruction_name / 151 jitter_mutable_routine_append_*_parameter functions, which may in their turn trigger rewrites 152 -- or by jitter_mutable_routine_append_instruction, which also triggers rewrites. 153 154 Notice that rewrites are applied eagerly, as soon as each appended 155 instruction is complete and until no more rewrites are possible. For this 156 reason simply removing instructions from the end of a program never triggers 157 new rewrites, and therefore the caller of this function can assume that after 158 the function returns every program instruction before the last one which was 159 removed remain unchanged. 160 161 It is the user's responsiblity to ensure that her rewrite rules don't loop 162 forever. */ 163 struct jitter_instruction* 164 jitter_pop_instruction (struct jitter_mutable_routine *p); 165 166 /* Pop the last how_many instructions from the given program, and destroy them. 167 Undefined behavior if the program has less than how_many rewritable 168 instructions. The last instruction must be complete. 169 170 Notice, again, that destroying the last how_many instructions of a program 171 can never trigger a rewrite: see the jitter_pop_instruction comment for a 172 justification. */ 173 void 174 jitter_destroy_last_instructions (struct jitter_mutable_routine *p, 175 size_t how_many); 176 177 178 179 180 /* Fixed code for vmprefix_rewrite. 181 * ************************************************************************** */ 182 183 /* Expand to C declarations and statements to be emitted at the beginning of 184 vmprefix_rewrite . This macro is used in the machine-generated definition of 185 vmprefix_rewrite . It may expand to a sequence of statements and 186 declarations of variables to be visible to the entire function, so it is not 187 do..while(false)-protected. */ 188 #define JITTTER_REWRITE_FUNCTION_PROLOG_ \ 189 /* How many instructions are rewritable in the current program. This */ \ 190 /* value will be used a lot in the function, and it's better to cache */ \ 191 /* it in an automatic const variable rather than re-loading it from */ \ 192 /* memory every time, in a context where GCC might not be able to infer */ \ 193 /* that the value is, in fact, constant. */ \ 194 const int jitter_rewritable_instruction_no = \ 195 jitter_mutable_routine_p->rewritable_instruction_no; \ 196 /* A pointer to the first instruction which is potentially a candidate */ \ 197 /* for rewriting, with any rule. Making this a constant pointer to */ \ 198 /* constant data should help GCC to share condition computations across */ \ 199 /* rules; this is correct, as rule conditions don't in fact change */ \ 200 /* instructions -- Only if a rule matches some memory changes are made, */ \ 201 /* and in that case we exit this function after the rule section ends. */ \ 202 const struct jitter_instruction * const * const \ 203 jitter_all_rewritable_instructions __attribute__ ((unused)) \ 204 = ((const struct jitter_instruction * const * const) \ 205 jitter_last_instructions (jitter_mutable_routine_p, \ 206 jitter_rewritable_instruction_no)) 207 208 209 210 211 212 /* Rewriting macros for rule compilation: introduction. 213 * ************************************************************************** */ 214 215 /* The macros in the following sections provide a facility for executing rewrite 216 rules at runtime (not at generation time) from machine-generated C, expressed 217 in a structured, abstract way. The expanded C code is meant to be fast in 218 the more common case, which is to say when rules do *not* fire. 219 220 Each rewrite rule is translated into a C conditional with a complex condition 221 made of clauses all in logical and, having side effects on local variables, 222 which eventually evaluates to true if the rule fires. In that case some head 223 instruction arguments are cloned heap-to-heap into templates, head 224 instruction destroyed, and new instructions appended in their place, using 225 the cloned placeholder to instantiate the rule template; after the new 226 instructions are appended the cloned templates are destroyed, and the 227 rewriting function returns. When a rule does not match, instead, evaluation 228 falls thru to the conditional for the next rule. 229 230 The rewriting process is inherently recursive: appending an instruction, be 231 it from the user C code or from another rewrite, may in its turn trigger a 232 rewrite. This recursion is indirect and spans compilation units, which can 233 make it difficult for the C compiler to optimize away; however recursive 234 calls are at least in tail position when there are no templates to destroy. 235 236 Notice that macro-level rule "sections" don't match the statement nesting of 237 C-level blocks: in particular the rule conditional body is opened by 238 JITTER_RULE_END_CONDITIONS and closed by 239 JITTER_RULE_END_PLACEHOLDER_DESTRUCTION . Macro-level sections are nested in 240 a rigid, fixed way, to keep the generated code legible. Their C 241 implementation is focused on exploiting C's statement evaluation in an 242 appropriate way (in particular, there are complex side-effects within an if 243 conditional) and that C variables have the intended scope. 244 Some sections may be empty, but their opening and closing is mandatory for 245 every rule, in the required order. 246 247 An example of the rewrite rule changing 248 pop $a; push $a 249 into 250 copy-to-r $a 251 translated into C: 252 253 JITTER_RULE_BEGIN(2) 254 JITTER_RULE_BEGIN_PLACEHOLDER_DECLARATIONS 255 JITTER_RULE_DECLARE_PLACEHOLDER_(a); 256 JITTER_RULE_END_PLACEHOLDER_DECLARATIONS 257 JITTER_RULE_BEGIN_CONDITIONS 258 JITTER_RULE_CONDITION_MATCH_OPCODE(0, pop) 259 JITTER_RULE_CONDITION_MATCH_OPCODE(1, push) 260 JITTER_RULE_CONDITION_MATCH_PLACEHOLDER(0, 0, a) 261 JITTER_RULE_CONDITION_MATCH_PLACEHOLDER(1, 0, a) 262 JITTER_RULE_END_CONDITIONS 263 JITTER_RULE_BEGIN_PLACEHOLDER_CLONING 264 JITTER_RULE_CLONE_PLACEHOLDER_(a); 265 JITTER_RULE_END_PLACEHOLDER_CLONING 266 JITTER_RULE_BEGIN_BODY 267 JITTER_RULE_APPEND_INSTRUCTION_(copy_mto_mr); 268 JITTER_RULE_APPEND_PLACEHOLDER_(a); 269 JITTER_RULE_END_BODY 270 JITTER_RULE_BEGIN_PLACEHOLDER_DESTRUCTION 271 JITTER_RULE_DESTROY_PLACEHOLDER_(a); 272 JITTER_RULE_END_PLACEHOLDER_DESTRUCTION 273 JITTER_RULE_END */ 274 275 276 277 278 /* Rewriting macros for rule compilation: sections. 279 * ************************************************************************** */ 280 281 /* Open a rule section, for a rule whose head matches the given number of VM 282 instructions. This must be followed by a call to 283 JITTER_RULE_BEGIN_PLACEHOLDER_DECLARATIONS . */ 284 #define JITTER_RULE_BEGIN(_jitter_head_instruction_no) \ 285 { /* Begin the rule block. */ \ 286 /* Set the head size as a variable, so that we don't have to pass */ \ 287 /* _jitter_head_instruction_no to multiple macros. */ \ 288 const int jitter_head_instruction_no = (_jitter_head_instruction_no); \ 289 /* A pointer to the first instruction which is potentially a */ \ 290 /* candidate for rewriting, with the current rule. This might not */ \ 291 /* even point to a valid instruction: we have to check how many */ \ 292 /* rewritable instructions there are before using it. */ \ 293 const struct jitter_instruction * const * const \ 294 jitter_candidate_instructions __attribute__ ((unused)) \ 295 = (jitter_all_rewritable_instructions \ 296 + jitter_rewritable_instruction_no - jitter_head_instruction_no); \ 297 /* This will contain placeholder variable declarations, and then */ \ 298 /* the rule conditional. */ 299 300 /* Close a rule section. */ 301 #define JITTER_RULE_END \ 302 } /* Close the rule block. */ 303 304 /* Open the placeholder declaration section. This must come right after the 305 JITTER_RULE_BEGIN call. */ 306 #define JITTER_RULE_BEGIN_PLACEHOLDER_DECLARATIONS \ 307 /* Nothing, not even a "{": we need the coming variable declarations to */ \ 308 /* be visible in the following code, up until placeholder destruction. */ 309 310 /* Close the placeholder declaration section. */ 311 #define JITTER_RULE_END_PLACEHOLDER_DECLARATIONS \ 312 /* Nothing, not even a "}". See above. */ 313 314 /* Begin the rule condition section. This must come right after placeholder 315 declarations. The condition sections may contain any number of conditions, 316 which must *all* evaluate to true for the rule to fire. */ 317 #define JITTER_RULE_BEGIN_CONDITIONS \ 318 if ( (jitter_rewritable_instruction_no \ 319 >= (jitter_head_instruction_no)) \ 320 /* Here will come the other conditions, all in && */ 321 /* with one another. */ 322 323 /* Close the rule condition section. */ 324 #define JITTER_RULE_END_CONDITIONS \ 325 ) /* Close the if condition */ \ 326 { /* Begin the rule conditional body, executed when the rule fires. */ \ 327 /* The rule conditional body is distinct from the rule body! */ 328 329 /* Open the block holding placeholder cloning calls. This block must occur 330 after rule conditions and before the rule body. */ 331 #define JITTER_RULE_BEGIN_PLACEHOLDER_CLONING \ 332 { /* Open the placeholder cloning block. */ 333 334 /* Close the block holding placeholder cloning calls. */ 335 #define JITTER_RULE_END_PLACEHOLDER_CLONING \ 336 } /* Close the placeholder cloning block. */ 337 338 /* Open the block holding placeholder destructions calls. This block must occur 339 after the rule body. */ 340 #define JITTER_RULE_BEGIN_PLACEHOLDER_DESTRUCTION \ 341 { /* Open the placeholder destruction block... */ 342 343 /* Close the block holding placeholder destructions calls. */ 344 #define JITTER_RULE_END_PLACEHOLDER_DESTRUCTION \ 345 } /* ...Close the placeholder destruction block. */ \ 346 /* One rewrite rule fired, and if we have appended new */ \ 347 /* instructions they have been rewritten as well. Done. */ \ 348 return; /*goto jitter_rewrite_again_label;*/ \ 349 } /* Close the rule conditional body. */ 350 351 /* Open the rule body section. This must come after placeholder cloning. */ 352 #define JITTER_RULE_BEGIN_BODY \ 353 { /* Open the rule body block, which occurs within the rule */ \ 354 /* conditional body. */ \ 355 /* Destroy the instructions matching the rule head. We have already */ \ 356 /* copied the arguments we need for rewriting. */ \ 357 jitter_destroy_last_instructions (jitter_mutable_routine_p, \ 358 jitter_head_instruction_no); \ 359 /* From here on it's incorrect to use head instructions or non-cloned */ \ 360 /* placeholders. */ 361 362 /* Close the rule body section. */ 363 #define JITTER_RULE_END_BODY \ 364 } /* Close the rule body block, but not the rule conditional body. */ \ 365 /* That will be closed later, after placeholders are destroyed. */ 366 367 368 369 370 /* Rewriting macros for rule compilation: placeholders. 371 * ************************************************************************** */ 372 373 /* The name of a placeholder variable as a C identifier. */ 374 #define JITTER_PLACEHOLDER_NAME(_jitter_suffix) \ 375 JITTER_CONCATENATE_TWO(jitter_placeholder_, _jitter_suffix) 376 377 /* Expand to a pointer variable declaration for the given placeholder, also 378 initializing the pointer to NULL so that it matches any instruction argument. 379 It is sensible to declare the variable to point to const data: this will 380 allow GCC to share checks on arguments across different rule conditions; 381 arguments are in fact not modified, until one rule matches -- and then 382 the other rules become irrelevent. Not do..while(false)-protected. */ 383 #define JITTER_RULE_DECLARE_PLACEHOLDER_(_jitter_placeholder_name) \ 384 const struct jitter_parameter * \ 385 JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name) \ 386 = NULL 387 388 /* Replace the pointer variable for the given placeholder, which must be 389 non-NULL, with a pointer to a freshly cloned argument. This way the 390 placeholder will be usable from the rule body to fill the rule template, 391 after the matching head instructions are destroyed. Not 392 do..while(false)-protected. */ 393 #define JITTER_RULE_CLONE_PLACEHOLDER_(_jitter_placeholder_name) \ 394 JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name) \ 395 = jitter_clone_instruction_parameter \ 396 (JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name)) 397 398 /* Destroy the instruction parameter pointed by the local placeholder variable 399 for the named placeholder. The pointer must be non-NULL. Not 400 do..while(false)-protected. */ 401 #define JITTER_RULE_DESTROY_PLACEHOLDER_(_jitter_placeholder_name) \ 402 jitter_destroy_instruction_parameter \ 403 ((struct jitter_parameter *) \ 404 JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name)); 405 406 407 408 409 /* Rewriting macros for rule compilation: instruction/argument access. 410 * ************************************************************************** */ 411 412 /* Expand to a struct jitter_instruction * r-value evaluating to the 413 _jitter_instruction_idx-th (0-based) candidate instruction. 414 This is useful for referring to the first, second, and so on, instrction 415 among the ones matching the head of a rule. */ 416 #define JITTER_RULE_INSTRUCTION(_jitter_instruction_idx) \ 417 (jitter_candidate_instructions [_jitter_instruction_idx]) 418 419 /* Expand to a struct jitter_parameter * r-value evaluating to the 420 _jitter_argument_idx-th (0-based) argument of the 421 _jitter_instruction_idx-th (0-based) candidate instruction. 422 This is useful for referring to a given argument of a given instruction 423 among the ones matching the head of a rule. */ 424 #define JITTER_RULE_INSTRUCTION_ARGUMENT(_jitter_instruction_idx, \ 425 _jitter_argument_idx) \ 426 (JITTER_RULE_INSTRUCTION(_jitter_instruction_idx) \ 427 ->parameters [_jitter_argument_idx]) 428 429 /* Expand to an r-value of type enum jitter_parameter_type evaluating to the 430 actual type of the given argument. */ 431 #define JITTER_RULE_ARGUMENT_TYPE(_jitter_instruction_idx, \ 432 _jitter_argument_idx) \ 433 (JITTER_RULE_INSTRUCTION_ARGUMENT(_jitter_instruction_idx, \ 434 _jitter_argument_idx) \ 435 ->type) 436 437 438 439 440 /* Rewriting macros for rule compilation: macros for argument field extraction. 441 * ************************************************************************** */ 442 443 /* Given an r-value evaluating to a pointer to a (possibly const) struct 444 jitter_parameter , expand to an r-value which evaluates to its content as 445 literal. The argument type is not checked. */ 446 #define JITTER_RULE_LITERAL_FIELD(_jitter_argument_expression) \ 447 ((_jitter_argument_expression)->literal) 448 449 /* Given an r-value evaluating to a pointer to a (possibly const) struct 450 jitter_parameter , expand to an r-value which evaluates to its register-index 451 content. The argument type is not checked. */ 452 #define JITTER_RULE_REGISTER_INDEX_FIELD(_jitter_argument_expression) \ 453 ((_jitter_argument_expression)->register_index) 454 455 456 457 458 /* Rewriting macros for rule compilation: macros for condition evaluation. 459 * ************************************************************************** */ 460 461 /* Expand to a boolean r-value, evaluating to true iff the given actual 462 argument is a register. */ 463 #define JITTER_RULE_ARGUMENT_IS_A_REGISTER(_jitter_instruction_idx, \ 464 _jitter_argument_idx) \ 465 (JITTER_RULE_ARGUMENT_TYPE(_jitter_instruction_idx, \ 466 _jitter_argument_idx) \ 467 == jitter_parameter_type_register_id) 468 469 /* Expand to a boolean r-value, evaluating to true iff the given actual 470 argument is a literal. */ 471 #define JITTER_RULE_ARGUMENT_IS_A_LITERAL(_jitter_instruction_idx, \ 472 _jitter_argument_idx) \ 473 (JITTER_RULE_ARGUMENT_TYPE(_jitter_instruction_idx, \ 474 _jitter_argument_idx) \ 475 == jitter_parameter_type_literal) 476 477 /* Expand to a boolean r-value, evaluating to true iff the given actual 478 argument is a label -- there is no distinction here between fast 479 and slow labels. */ 480 #define JITTER_RULE_ARGUMENT_IS_A_LABEL(_jitter_instruction_idx, \ 481 _jitter_argument_idx) \ 482 (JITTER_RULE_ARGUMENT_TYPE(_jitter_instruction_idx, \ 483 _jitter_argument_idx) \ 484 == jitter_parameter_type_label) 485 486 487 488 489 /* Rewriting macros for rule compilation: conditions. 490 * ************************************************************************** */ 491 492 /* Expand to a condition, to be &&'ed to the previous conditions in the rule 493 conditional. A condition expression may have side effects, and its result 494 must be non-zero if evaluation of the following conditions is to continue; 495 when a condition expression evaluates to zero the following conditions are 496 not evaluated, and the current rule does not fire. 497 A condition must not have side effects visible out of the current rule 498 block, since any following condition may fail. Setting placeholders is 499 allowed because placeholder variables are just pointers local to the block, 500 and don't refer to newly allocated memory during the condition evaluation. 501 Only if the condition eventually evaluates to a non-zero value 502 placeholders are cloned, and head instructions are destroyed: at that point 503 the rule is known to fire, and its effects will be visible. */ 504 #define JITTER_RULE_CONDITION(_jitter_condition_expression) \ 505 && (_jitter_condition_expression) 506 507 /* Expand to a condition on the opcode of the _jitter_instruction_idx-th 508 instruction (0-based, from the first head candidate). Conditions like these 509 should always be the first ones in a rule conditional: after they have all 510 matched we can safely access instruction arguments knowing that the arities 511 will be what we are expecting from their respective instructions. 512 The opcode is given with the same conventions as the second argument of 513 VMPREFIX_APPEND_INSTRUCTION . */ 514 #define JITTER_RULE_CONDITION_MATCH_OPCODE(_jitter_instruction_idx, \ 515 _jitter_mangled_opcode_suffix) \ 516 JITTER_RULE_CONDITION( \ 517 (JITTER_RULE_INSTRUCTION(_jitter_instruction_idx) \ 518 ->meta_instruction->id) \ 519 == JITTER_CONCATENATE_THREE(JITTER_VM_PREFIX_LOWER_CASE, \ 520 _meta_instruction_id_, \ 521 _jitter_mangled_opcode_suffix)) 522 523 /* Match the _jitter_argument_idx-th (0-based) argument of the 524 _jitter_instruction_idx-th (0-based) instruction with the given 525 placeholder. 526 - if the placeholder is NULL, set it to the argument pointer and evaluate to 527 true; 528 - if the placeholder is already set, check if it's equal to the given 529 parameter (this will occur in non-linear patterns): if so evaluate to true, 530 otherwise evaluate to false. 531 In either case the parameter is not cloned: the placeholder at this 532 point may only hold a pointer to an *existing* heap-allocated datum. */ 533 #define JITTER_RULE_CONDITION_MATCH_PLACEHOLDER(_jitter_instruction_idx, \ 534 _jitter_argument_idx, \ 535 _jitter_placeholder_name) \ 536 JITTER_RULE_CONDITION( \ 537 ((JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name) == NULL) \ 538 ? ((JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name) \ 539 = JITTER_RULE_INSTRUCTION_ARGUMENT(_jitter_instruction_idx, \ 540 _jitter_argument_idx)) \ 541 /* Without ", true" GCC would complain about ? : having a */ \ 542 /* pointer and and integer on different branches. */ \ 543 , true) \ 544 : jitter_instruction_parameters_equal \ 545 (JITTER_PLACEHOLDER_NAME(_jitter_placeholder_name), \ 546 JITTER_RULE_INSTRUCTION_ARGUMENT(_jitter_instruction_idx, \ 547 _jitter_argument_idx)))) 548 549 /* Expand to a rule condition like above, evaluating to true iff the mentioned 550 instruction argument is a literal with the given value. Do not check the 551 register class, as each instruction register argument can have only one, and 552 that has been already checked statically. No side effects. */ 553 #define JITTER_RULE_CONDITION_MATCH_REGISTER_ARGUMENT(_jitter_instruction_idx, \ 554 _jitter_argument_idx, \ 555 _jitter_register_index) \ 556 JITTER_RULE_CONDITION( \ 557 JITTER_RULE_ARGUMENT_IS_A_REGISTER(_jitter_instruction_idx, \ 558 _jitter_argument_idx) \ 559 && (JITTER_RULE_INSTRUCTION_ARGUMENT(_jitter_instruction_idx, \ 560 _jitter_argument_idx) \ 561 ->register_index \ 562 == (_jitter_argument_value))) 563 564 /* Expand to a rule condition like above, evaluating to true iff the mentioned 565 instruction argument is a register with the given index. No side effects. */ 566 #define JITTER_RULE_CONDITION_MATCH_LITERAL_ARGUMENT(_jitter_instruction_idx, \ 567 _jitter_argument_idx, \ 568 _jitter_argument_value) \ 569 JITTER_RULE_CONDITION( \ 570 JITTER_RULE_ARGUMENT_IS_A_LITERAL(_jitter_instruction_idx, \ 571 _jitter_argument_idx) \ 572 && (JITTER_RULE_LITERAL_FIELD( \ 573 JITTER_RULE_INSTRUCTION_ARGUMENT(_jitter_instruction_idx, \ 574 _jitter_argument_idx)) \ 575 .fixnum \ 576 == (_jitter_argument_value))) 577 578 /* Expand to the predicate JITTER_RULE_ARGUMENT_IS_A_REGISTER within a 579 condition. Like in the case of JITTER_RULE_ARGUMENT_IS_A_REGISTER there is 580 no need to supply a register class; see its comment. */ 581 #define JITTER_RULE_CONDITION_ARGUMENT_IS_A_REGISTER(_jitter_instruction_idx, \ 582 _jitter_argument_idx) \ 583 JITTER_RULE_CONDITION( \ 584 JITTER_RULE_ARGUMENT_IS_A_REGISTER(_jitter_instruction_idx, \ 585 _jitter_argument_idx)) 586 587 /* Expand to the predicate JITTER_RULE_ARGUMENT_IS_A_LITERAL within a 588 condition. */ 589 #define JITTER_RULE_CONDITION_ARGUMENT_IS_A_LITERAL(_jitter_instruction_idx, \ 590 _jitter_argument_idx) \ 591 JITTER_RULE_CONDITION( \ 592 JITTER_RULE_ARGUMENT_IS_A_LITERAL(_jitter_instruction_idx, \ 593 _jitter_argument_idx)) 594 595 /* Expand to the predicate JITTER_RULE_ARGUMENT_IS_A_LABEL within a 596 condition. There is no distinction between fast and slow labels. */ 597 #define JITTER_RULE_CONDITION_ARGUMENT_IS_A_LABEL(_jitter_instruction_idx, \ 598 _jitter_argument_idx) \ 599 JITTER_RULE_CONDITION( \ 600 JITTER_RULE_ARGUMENT_IS_A_LABEL(_jitter_instruction_idx, \ 601 _jitter_argument_idx)) 602 603 604 605 606 /* Rewriting macros for rule compilation: template expressions. 607 * ************************************************************************** */ 608 609 /* Template expressions expand to C r-values, having access to constants and 610 placeholders but not to the original instructions, which except for the case 611 of the rule guard have already been destroyed. 612 The expansion has no side effects except in the case of errors, which should 613 never happen if typechecking has passed. 614 The C type of the expansion depends on the context, and is checked 615 statically. */ 616 617 /* Expand to a template expression evaluating to the boolean constants true and 618 false. */ 619 #define JITTER_RULE_EXPRESSION_TRUE \ 620 true 621 #define JITTER_RULE_EXPRESSION_FALSE \ 622 false 623 624 /* Expand to a template expression evaluating to an integer expression 625 containing the given constant. */ 626 #define JITTER_RULE_EXPRESSION_INTEGER(_jitter_literal1) \ 627 (_jitter_literal1) 628 629 /* Expand to a template expression evaluating to a boolean expression combining 630 the given operands with the appropriate connective. */ 631 #define JITTER_RULE_EXPRESSION_LOGICAL_AND(_jitter_e1, _jitter_e2) \ 632 ((_jitter_e1) && (_jitter_e2)) 633 #define JITTER_RULE_EXPRESSION_LOGICAL_OR(_jitter_e1, _jitter_e2) \ 634 ((_jitter_e1) || (_jitter_e2)) 635 #define JITTER_RULE_EXPRESSION_LOGICAL_NOT(_jitter_e1) \ 636 (! (_jitter_e1)) 637 638 /* Expand to a template expression evaluating to an arithmetic expression 639 combining the given operands with the appropriate operation. */ 640 #define JITTER_RULE_EXPRESSION_PLUS(_jitter_e1, _jitter_e2) \ 641 ((_jitter_e1) + (_jitter_e2)) 642 #define JITTER_RULE_EXPRESSION_MINUS(_jitter_e1, _jitter_e2) \ 643 ((_jitter_e1) - (_jitter_e2)) 644 #define JITTER_RULE_EXPRESSION_TIMES(_jitter_e1, _jitter_e2) \ 645 ((_jitter_e1) * (_jitter_e2)) 646 #define JITTER_RULE_EXPRESSION_DIVIDED(_jitter_e1, _jitter_e2) \ 647 ((_jitter_e1) / (_jitter_e2)) 648 #define JITTER_RULE_EXPRESSION_REMAINDER(_jitter_e1, _jitter_e2) \ 649 ((_jitter_e1) % (_jitter_e2)) 650 651 /* Expand to a template boolean expression comparing the given arithmetic 652 operands with the appropriate. */ 653 #define JITTER_RULE_EXPRESSION_EQUAL(_jitter_e1, _jitter_e2) \ 654 ((_jitter_e1) == (_jitter_e2)) 655 #define JITTER_RULE_EXPRESSION_NOTEQUAL(_jitter_e1, _jitter_e2) \ 656 ((_jitter_e1) != (_jitter_e2)) 657 #define JITTER_RULE_EXPRESSION_LESS(_jitter_e1, _jitter_e2) \ 658 ((_jitter_e1) < (_jitter_e2)) 659 #define JITTER_RULE_EXPRESSION_LESSEQUAL(_jitter_e1, _jitter_e2) \ 660 ((_jitter_e1) <= (_jitter_e2)) 661 #define JITTER_RULE_EXPRESSION_GREATER(_jitter_e1, _jitter_e2) \ 662 ((_jitter_e1) > (_jitter_e2)) 663 #define JITTER_RULE_EXPRESSION_GREATEREQUAL(_jitter_e1, _jitter_e2) \ 664 ((_jitter_e1) >= (_jitter_e2)) 665 666 667 668 669 /* Rewriting macros for rule compilation: body. 670 * ************************************************************************** */ 671 672 /* Append the instruction opcode whose mangled suffix (see the comment for 673 VMPREFIX_APPEND_INSTRUCTION ) is given; the arguments, if any, need to be 674 added explicitly after calling this macro. Not 675 do..while(false)-protected. */ 676 #define JITTER_RULE_APPEND_INSTRUCTION_(_jitter_mangled_suffix) \ 677 JITTER_CONCATENATE_TWO(JITTER_VM_PREFIX_UPPER_CASE, \ 678 _MUTABLE_ROUTINE_APPEND_INSTRUCTION) \ 679 (jitter_mutable_routine_p, _jitter_mangled_suffix) 680 681 /* Append a copy of the parameter pointed by the named placeholder variable, 682 which must be non-NULL, to the current instruction. Not 683 do..while(false)-protected. */ 684 #define JITTER_RULE_APPEND_PLACEHOLDER_(_jitter_placeholder_name) \ 685 jitter_mutable_routine_append_parameter_copy (jitter_mutable_routine_p, \ 686 JITTER_PLACEHOLDER_NAME( \ 687 _jitter_placeholder_name)); 688 689 690 #endif // #ifndef JITTER_REWRITE_H_ 691