OLD | NEW |
1 /* | 1 /* |
2 * Expression handling | 2 * Expression handling |
3 * | 3 * |
4 * Copyright (C) 2001-2007 Michael Urman, Peter Johnson | 4 * Copyright (C) 2001-2007 Michael Urman, Peter Johnson |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' | 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE | 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * POSSIBILITY OF SUCH DAMAGE. | 25 * POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 #include "util.h" | 27 #include "util.h" |
28 /*@unused@*/ RCSID("$Id: expr.c 2130 2008-10-07 05:38:11Z peter $"); | |
29 | 28 |
30 #include "libyasm-stdint.h" | 29 #include "libyasm-stdint.h" |
31 #include "coretype.h" | 30 #include "coretype.h" |
32 #include "bitvect.h" | 31 #include "bitvect.h" |
33 | 32 |
34 #include "errwarn.h" | 33 #include "errwarn.h" |
35 #include "intnum.h" | 34 #include "intnum.h" |
36 #include "floatnum.h" | 35 #include "floatnum.h" |
37 #include "expr.h" | 36 #include "expr.h" |
38 #include "symrec.h" | 37 #include "symrec.h" |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 } | 527 } |
529 | 528 |
530 /* Check for and simplify identities. Returns new number of expr terms. | 529 /* Check for and simplify identities. Returns new number of expr terms. |
531 * Sets e->op = EXPR_IDENT if numterms ends up being 1. | 530 * Sets e->op = EXPR_IDENT if numterms ends up being 1. |
532 * Uses numterms parameter instead of e->numterms for basis of "new" number | 531 * Uses numterms parameter instead of e->numterms for basis of "new" number |
533 * of terms. | 532 * of terms. |
534 * Assumes int_term is *only* integer term in e. | 533 * Assumes int_term is *only* integer term in e. |
535 * NOTE: Really designed to only be used by expr_level_op(). | 534 * NOTE: Really designed to only be used by expr_level_op(). |
536 */ | 535 */ |
537 static int | 536 static int |
538 expr_simplify_identity(yasm_expr *e, int numterms, int int_term, | 537 expr_simplify_identity(yasm_expr *e, int numterms, int *int_term, |
539 int simplify_reg_mul) | 538 int simplify_reg_mul) |
540 { | 539 { |
541 int i; | 540 int i; |
542 int save_numterms; | 541 int save_numterms; |
543 | 542 |
544 /* Don't do this step if it's 1*REG. Save and restore numterms so | 543 /* Don't do this step if it's 1*REG. Save and restore numterms so |
545 * yasm_expr__contains() works correctly. | 544 * yasm_expr__contains() works correctly. |
546 */ | 545 */ |
547 save_numterms = e->numterms; | 546 save_numterms = e->numterms; |
548 e->numterms = numterms; | 547 e->numterms = numterms; |
549 if (simplify_reg_mul || e->op != YASM_EXPR_MUL | 548 if (simplify_reg_mul || e->op != YASM_EXPR_MUL |
550 || !yasm_intnum_is_pos1(e->terms[int_term].data.intn) | 549 || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn) |
551 || !yasm_expr__contains(e, YASM_EXPR_REG)) { | 550 || !yasm_expr__contains(e, YASM_EXPR_REG)) { |
552 /* Check for simple identities that delete the intnum. | 551 /* Check for simple identities that delete the intnum. |
553 * Don't delete if the intnum is the only thing in the expn. | 552 * Don't delete if the intnum is the only thing in the expn. |
554 */ | 553 */ |
555 if ((int_term == 0 && numterms > 1 && | 554 if ((*int_term == 0 && numterms > 1 && |
556 expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) || | 555 expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) || |
557 (int_term > 0 && | 556 (*int_term > 0 && |
558 expr_can_destroy_int_right(e->op, e->terms[int_term].data.intn))) { | 557 expr_can_destroy_int_right(e->op, |
| 558 e->terms[*int_term].data.intn))) { |
559 /* Delete the intnum */ | 559 /* Delete the intnum */ |
560 yasm_intnum_destroy(e->terms[int_term].data.intn); | 560 yasm_intnum_destroy(e->terms[*int_term].data.intn); |
561 | 561 |
562 /* Slide everything to its right over by 1 */ | 562 /* Slide everything to its right over by 1 */ |
563 if (int_term != numterms-1) /* if it wasn't last.. */ | 563 if (*int_term != numterms-1) /* if it wasn't last.. */ |
564 memmove(&e->terms[int_term], &e->terms[int_term+1], | 564 memmove(&e->terms[*int_term], &e->terms[*int_term+1], |
565 (numterms-1-int_term)*sizeof(yasm_expr__item)); | 565 (numterms-1-*int_term)*sizeof(yasm_expr__item)); |
566 | 566 |
567 /* Update numterms */ | 567 /* Update numterms */ |
568 numterms--; | 568 numterms--; |
569 int_term = -1; /* no longer an int term */ | 569 *int_term = -1; /* no longer an int term */ |
570 } | 570 } |
571 } | 571 } |
572 e->numterms = save_numterms; | 572 e->numterms = save_numterms; |
573 | 573 |
574 /* Check for simple identites that delete everything BUT the intnum. | 574 /* Check for simple identites that delete everything BUT the intnum. |
575 * Don't bother if the intnum is the only thing in the expn. | 575 * Don't bother if the intnum is the only thing in the expn. |
576 */ | 576 */ |
577 if (numterms > 1 && int_term != -1 && | 577 if (numterms > 1 && *int_term != -1 && |
578 expr_is_constant(e->op, e->terms[int_term].data.intn)) { | 578 expr_is_constant(e->op, e->terms[*int_term].data.intn)) { |
579 /* Loop through, deleting everything but the integer term */ | 579 /* Loop through, deleting everything but the integer term */ |
580 for (i=0; i<e->numterms; i++) | 580 for (i=0; i<e->numterms; i++) |
581 if (i != int_term) | 581 if (i != *int_term) |
582 expr_delete_term(&e->terms[i], 1); | 582 expr_delete_term(&e->terms[i], 1); |
583 | 583 |
584 /* Move integer term to the first term (if not already there) */ | 584 /* Move integer term to the first term (if not already there) */ |
585 if (int_term != 0) | 585 if (*int_term != 0) |
586 e->terms[0] = e->terms[int_term]; /* structure copy */ | 586 e->terms[0] = e->terms[*int_term]; /* structure copy */ |
587 | 587 |
588 /* Set numterms to 1 */ | 588 /* Set numterms to 1 */ |
589 numterms = 1; | 589 numterms = 1; |
590 } | 590 } |
591 | 591 |
592 /* Compute NOT, NEG, and LNOT on single intnum. */ | 592 /* Compute NOT, NEG, and LNOT on single intnum. */ |
593 if (numterms == 1 && int_term == 0 && | 593 if (numterms == 1 && *int_term == 0 && |
594 (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG || | 594 (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG || |
595 e->op == YASM_EXPR_LNOT)) | 595 e->op == YASM_EXPR_LNOT)) |
596 yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL); | 596 yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL); |
597 | 597 |
598 /* Change expression to IDENT if possible. */ | 598 /* Change expression to IDENT if possible. */ |
599 if (numterms == 1) | 599 if (numterms == 1) |
600 e->op = YASM_EXPR_IDENT; | 600 e->op = YASM_EXPR_IDENT; |
601 | 601 |
602 /* Return the updated numterms */ | 602 /* Return the updated numterms */ |
603 return numterms; | 603 return numterms; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 /* copy term if it changed places */ | 691 /* copy term if it changed places */ |
692 e->terms[o++] = e->terms[i]; | 692 e->terms[o++] = e->terms[i]; |
693 } else | 693 } else |
694 o++; | 694 o++; |
695 } | 695 } |
696 | 696 |
697 if (simplify_ident) { | 697 if (simplify_ident) { |
698 int new_fold_numterms; | 698 int new_fold_numterms; |
699 /* Simplify identities and make IDENT if possible. */ | 699 /* Simplify identities and make IDENT if possible. */ |
700 new_fold_numterms = | 700 new_fold_numterms = |
701 expr_simplify_identity(e, fold_numterms, first_int_term, | 701 expr_simplify_identity(e, fold_numterms, &first_int_term, |
702 simplify_reg_mul); | 702 simplify_reg_mul); |
703 level_numterms -= fold_numterms-new_fold_numterms; | 703 level_numterms -= fold_numterms-new_fold_numterms; |
704 fold_numterms = new_fold_numterms; | 704 fold_numterms = new_fold_numterms; |
705 } | 705 } |
706 if (fold_numterms == 1) | 706 if (fold_numterms == 1) |
707 e->op = YASM_EXPR_IDENT; | 707 e->op = YASM_EXPR_IDENT; |
708 } | 708 } |
709 | 709 |
710 /* Only level operators that allow more than two operand terms. | 710 /* Only level operators that allow more than two operand terms. |
711 * Also don't bother leveling if it's not necessary to bring up any terms. | 711 * Also don't bother leveling if it's not necessary to bring up any terms. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 if (i == first_int_term) | 782 if (i == first_int_term) |
783 first_int_term = o; | 783 first_int_term = o; |
784 o--; | 784 o--; |
785 } else | 785 } else |
786 o--; | 786 o--; |
787 } | 787 } |
788 | 788 |
789 /* Simplify identities, make IDENT if possible, and save to e->numterms. */ | 789 /* Simplify identities, make IDENT if possible, and save to e->numterms. */ |
790 if (simplify_ident && first_int_term != -1) { | 790 if (simplify_ident && first_int_term != -1) { |
791 e->numterms = expr_simplify_identity(e, level_numterms, | 791 e->numterms = expr_simplify_identity(e, level_numterms, |
792 first_int_term, simplify_reg_mul); | 792 &first_int_term, simplify_reg_mul); |
793 } else { | 793 } else { |
794 e->numterms = level_numterms; | 794 e->numterms = level_numterms; |
795 if (level_numterms == 1) | 795 if (level_numterms == 1) |
796 e->op = YASM_EXPR_IDENT; | 796 e->op = YASM_EXPR_IDENT; |
797 } | 797 } |
798 | 798 |
799 return e; | 799 return e; |
800 } | 800 } |
801 /*@=mustfree@*/ | 801 /*@=mustfree@*/ |
802 | 802 |
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 /* either sum of idents (?!) or substract of idents */ | 1507 /* either sum of idents (?!) or substract of idents */ |
1508 return NULL; | 1508 return NULL; |
1509 } | 1509 } |
1510 seen = 1; | 1510 seen = 1; |
1511 } | 1511 } |
1512 } | 1512 } |
1513 } | 1513 } |
1514 /* exactly one offset */ | 1514 /* exactly one offset */ |
1515 return segment; | 1515 return segment; |
1516 } | 1516 } |
OLD | NEW |