Home | History | Annotate | Download | only in libyasm
      1 /*
      2  * Value handling
      3  *
      4  *  Copyright (C) 2006-2007  Peter Johnson
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     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
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     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
     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
     25  * POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 #include "util.h"
     28 
     29 #include "libyasm-stdint.h"
     30 #include "coretype.h"
     31 #include "bitvect.h"
     32 
     33 #include "errwarn.h"
     34 #include "intnum.h"
     35 #include "floatnum.h"
     36 #include "expr.h"
     37 #include "value.h"
     38 #include "symrec.h"
     39 
     40 #include "bytecode.h"
     41 #include "section.h"
     42 
     43 #include "arch.h"
     44 
     45 
     46 void
     47 yasm_value_initialize(/*@out@*/ yasm_value *value,
     48                       /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size)
     49 {
     50     value->abs = e;
     51     value->rel = NULL;
     52     value->wrt = NULL;
     53     value->seg_of = 0;
     54     value->rshift = 0;
     55     value->curpos_rel = 0;
     56     value->ip_rel = 0;
     57     value->jump_target = 0;
     58     value->section_rel = 0;
     59     value->no_warn = 0;
     60     value->sign = 0;
     61     value->size = size;
     62 }
     63 
     64 void
     65 yasm_value_init_sym(/*@out@*/ yasm_value *value, /*@null@*/ yasm_symrec *sym,
     66                     unsigned int size)
     67 {
     68     value->abs = NULL;
     69     value->rel = sym;
     70     value->wrt = NULL;
     71     value->seg_of = 0;
     72     value->rshift = 0;
     73     value->curpos_rel = 0;
     74     value->ip_rel = 0;
     75     value->jump_target = 0;
     76     value->section_rel = 0;
     77     value->no_warn = 0;
     78     value->sign = 0;
     79     value->size = size;
     80 }
     81 
     82 void
     83 yasm_value_init_copy(yasm_value *value, const yasm_value *orig)
     84 {
     85     value->abs = orig->abs ? yasm_expr_copy(orig->abs) : NULL;
     86     value->rel = orig->rel;
     87     value->wrt = orig->wrt;
     88     value->seg_of = orig->seg_of;
     89     value->rshift = orig->rshift;
     90     value->curpos_rel = orig->curpos_rel;
     91     value->ip_rel = orig->ip_rel;
     92     value->jump_target = orig->jump_target;
     93     value->section_rel = orig->section_rel;
     94     value->no_warn = orig->no_warn;
     95     value->sign = orig->sign;
     96     value->size = orig->size;
     97 }
     98 
     99 void
    100 yasm_value_delete(yasm_value *value)
    101 {
    102     if (value->abs)
    103         yasm_expr_destroy(value->abs);
    104     value->abs = NULL;
    105     value->rel = NULL;
    106 }
    107 
    108 void
    109 yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
    110                           unsigned int ip_rel)
    111 {
    112     value->curpos_rel = 1;
    113     value->ip_rel = ip_rel;
    114     /* In order for us to correctly output curpos-relative values, we must
    115      * have a relative portion of the value.  If one doesn't exist, point
    116      * to a custom absolute symbol.
    117      */
    118     if (!value->rel) {
    119         yasm_object *object = yasm_section_get_object(yasm_bc_get_section(bc));
    120         value->rel = yasm_symtab_abs_sym(object->symtab);
    121     }
    122 }
    123 
    124 static int
    125 value_finalize_scan(yasm_value *value, yasm_expr *e,
    126                     /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok)
    127 {
    128     int i;
    129     /*@dependent@*/ yasm_section *sect;
    130     /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
    131 
    132     unsigned long shamt;    /* for SHR */
    133 
    134     /* Yes, this has a maximum upper bound on 32 terms, based on an
    135      * "insane number of terms" (and ease of implementation) WAG.
    136      * The right way to do this would be a stack-based alloca, but that's
    137      * not ISO C.  We really don't want to malloc here as this function is
    138      * hit a lot!
    139      *
    140      * This is a bitmask to keep things small, as this is a recursive
    141      * routine and we don't want to eat up stack space.
    142      */
    143     unsigned long used;     /* for ADD */
    144 
    145     /* Thanks to this running after a simplify, we don't need to iterate
    146      * down through IDENTs or handle SUB.
    147      *
    148      * We scan for a single symrec, gathering info along the way.  After
    149      * we've found the symrec, we keep scanning but error if we find
    150      * another one.  We pull out the single symrec and any legal operations
    151      * performed on it.
    152      *
    153      * Also, if we find a float anywhere, we don't allow mixing of a single
    154      * symrec with it.
    155      */
    156     switch (e->op) {
    157         case YASM_EXPR_ADD:
    158             /* Okay for single symrec anywhere in expr.
    159              * Check for single symrec anywhere.
    160              * Handle symrec-symrec by checking for (-1*symrec)
    161              * and symrec term pairs (where both symrecs are in the same
    162              * segment).
    163              */
    164             if (e->numterms > 32)
    165                 yasm__fatal(N_("expression on line %d has too many add terms;"
    166                                " internal limit of 32"), e->line);
    167 
    168             used = 0;
    169 
    170             for (i=0; i<e->numterms; i++) {
    171                 int j;
    172                 yasm_expr *sube;
    173                 yasm_intnum *intn;
    174                 yasm_symrec *sym;
    175                 /*@dependent@*/ yasm_section *sect2;
    176                 /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
    177 
    178                 /* First look for an (-1*symrec) term */
    179                 if (e->terms[i].type != YASM_EXPR_EXPR)
    180                     continue;
    181                 sube = e->terms[i].data.expn;
    182 
    183                 if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) {
    184                     /* recurse instead */
    185                     if (value_finalize_scan(value, sube, expr_precbc,
    186                                             ssym_not_ok))
    187                         return 1;
    188                     continue;
    189                 }
    190 
    191                 if (sube->terms[0].type == YASM_EXPR_INT &&
    192                     sube->terms[1].type == YASM_EXPR_SYM) {
    193                     intn = sube->terms[0].data.intn;
    194                     sym = sube->terms[1].data.sym;
    195                 } else if (sube->terms[0].type == YASM_EXPR_SYM &&
    196                            sube->terms[1].type == YASM_EXPR_INT) {
    197                     sym = sube->terms[0].data.sym;
    198                     intn = sube->terms[1].data.intn;
    199                 } else {
    200                     if (value_finalize_scan(value, sube, expr_precbc,
    201                                             ssym_not_ok))
    202                         return 1;
    203                     continue;
    204                 }
    205 
    206                 if (!yasm_intnum_is_neg1(intn)) {
    207                     if (value_finalize_scan(value, sube, expr_precbc,
    208                                             ssym_not_ok))
    209                         return 1;
    210                     continue;
    211                 }
    212 
    213                 /* Look for the same symrec term; even if both are external,
    214                  * they should cancel out.
    215                  */
    216                 for (j=0; j<e->numterms; j++) {
    217                     if (e->terms[j].type == YASM_EXPR_SYM
    218                         && e->terms[j].data.sym == sym
    219                         && (used & (1<<j)) == 0) {
    220                         /* Mark as used */
    221                         used |= 1<<j;
    222 
    223                         /* Replace both symrec portions with 0 */
    224                         yasm_expr_destroy(sube);
    225                         e->terms[i].type = YASM_EXPR_INT;
    226                         e->terms[i].data.intn = yasm_intnum_create_uint(0);
    227                         e->terms[j].type = YASM_EXPR_INT;
    228                         e->terms[j].data.intn = yasm_intnum_create_uint(0);
    229 
    230                         break;  /* stop looking */
    231                     }
    232                 }
    233                 if (j != e->numterms)
    234                     continue;
    235 
    236                 if (!yasm_symrec_get_label(sym, &precbc)) {
    237                     if (value_finalize_scan(value, sube, expr_precbc,
    238                                             ssym_not_ok))
    239                         return 1;
    240                     continue;
    241                 }
    242                 sect2 = yasm_bc_get_section(precbc);
    243 
    244                 /* Now look for a unused symrec term in the same segment */
    245                 for (j=0; j<e->numterms; j++) {
    246                     if (e->terms[j].type == YASM_EXPR_SYM
    247                         && yasm_symrec_get_label(e->terms[j].data.sym,
    248                                                  &precbc2)
    249                         && (sect = yasm_bc_get_section(precbc2))
    250                         && sect == sect2
    251                         && (used & (1<<j)) == 0) {
    252                         /* Mark as used */
    253                         used |= 1<<j;
    254                         break;  /* stop looking */
    255                     }
    256                 }
    257 
    258                 /* We didn't match in the same segment.  If the
    259                  * -1*symrec is actually -1*curpos, we can match
    260                  * unused symrec terms in other segments and generate
    261                  * a curpos-relative reloc.
    262                  *
    263                  * Similarly, handle -1*symrec in other segment via the
    264                  * following transformation:
    265                  * other-this = (other-.)+(.-this)
    266                  * We can only do this transformation if "this" is in
    267                  * this expr's segment.
    268                  *
    269                  * Don't do this if we've already become curpos-relative.
    270                  * The unmatched symrec will be caught below.
    271                  */
    272                 if (j == e->numterms && !value->curpos_rel
    273                     && (yasm_symrec_is_curpos(sym)
    274                         || (expr_precbc
    275                             && sect2 == yasm_bc_get_section(expr_precbc)))) {
    276                     for (j=0; j<e->numterms; j++) {
    277                         if (e->terms[j].type == YASM_EXPR_SYM
    278                             && !yasm_symrec_get_equ(e->terms[j].data.sym)
    279                             && !yasm_symrec_is_special(e->terms[j].data.sym)
    280                             && (used & (1<<j)) == 0) {
    281                             /* Mark as used */
    282                             used |= 1<<j;
    283                             /* Mark value as curpos-relative */
    284                             if (value->rel || ssym_not_ok)
    285                                 return 1;
    286                             value->rel = e->terms[j].data.sym;
    287                             value->curpos_rel = 1;
    288                             if (yasm_symrec_is_curpos(sym)) {
    289                                 /* Replace both symrec portions with 0 */
    290                                 yasm_expr_destroy(sube);
    291                                 e->terms[i].type = YASM_EXPR_INT;
    292                                 e->terms[i].data.intn =
    293                                     yasm_intnum_create_uint(0);
    294                                 e->terms[j].type = YASM_EXPR_INT;
    295                                 e->terms[j].data.intn =
    296                                     yasm_intnum_create_uint(0);
    297                             } else {
    298                                 /* Replace positive portion with curpos */
    299                                 yasm_object *object =
    300                                     yasm_section_get_object(sect2);
    301                                 yasm_symtab *symtab = object->symtab;
    302                                 e->terms[j].data.sym =
    303                                     yasm_symtab_define_curpos
    304                                     (symtab, ".", expr_precbc, e->line);
    305                             }
    306                             break;      /* stop looking */
    307                         }
    308                     }
    309                 }
    310 
    311 
    312                 if (j == e->numterms)
    313                     return 1;   /* We didn't find a match! */
    314             }
    315 
    316             /* Look for unmatched symrecs.  If we've already found one or
    317              * we don't WANT to find one, error out.
    318              */
    319             for (i=0; i<e->numterms; i++) {
    320                 if (e->terms[i].type == YASM_EXPR_SYM
    321                     && (used & (1<<i)) == 0) {
    322                     if (value->rel || ssym_not_ok)
    323                         return 1;
    324                     value->rel = e->terms[i].data.sym;
    325                     /* and replace with 0 */
    326                     e->terms[i].type = YASM_EXPR_INT;
    327                     e->terms[i].data.intn = yasm_intnum_create_uint(0);
    328                 }
    329             }
    330             break;
    331         case YASM_EXPR_SHR:
    332             /* Okay for single symrec in LHS and constant on RHS.
    333              * Single symrecs are not okay on RHS.
    334              * If RHS is non-constant, don't allow single symrec on LHS.
    335              * XXX: should rshift be an expr instead??
    336              */
    337 
    338             /* Check for single sym on LHS */
    339             if (e->terms[0].type != YASM_EXPR_SYM)
    340                 break;
    341 
    342             /* If we already have a sym, we can't take another one */
    343             if (value->rel || ssym_not_ok)
    344                 return 1;
    345 
    346             /* RHS must be a positive integer */
    347             if (e->terms[1].type != YASM_EXPR_INT)
    348                 return 1;       /* can't shift sym by non-constant integer */
    349             shamt = yasm_intnum_get_uint(e->terms[1].data.intn);
    350             if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX)
    351                 return 1;       /* total shift would be too large */
    352 
    353             /* Update value */
    354             value->rshift += shamt;
    355             value->rel = e->terms[0].data.sym;
    356 
    357             /* Replace symbol with 0 */
    358             e->terms[0].type = YASM_EXPR_INT;
    359             e->terms[0].data.intn = yasm_intnum_create_uint(0);
    360 
    361             /* Just leave SHR in place */
    362             break;
    363         case YASM_EXPR_SEG:
    364             /* Okay for single symrec (can only be done once).
    365              * Not okay for anything BUT a single symrec as an immediate
    366              * child.
    367              */
    368             if (e->terms[0].type != YASM_EXPR_SYM)
    369                 return 1;
    370 
    371             if (value->seg_of)
    372                 return 1;       /* multiple SEG not legal */
    373             value->seg_of = 1;
    374 
    375             if (value->rel || ssym_not_ok)
    376                 return 1;       /* got a relative portion somewhere else? */
    377             value->rel = e->terms[0].data.sym;
    378 
    379             /* replace with ident'ed 0 */
    380             e->op = YASM_EXPR_IDENT;
    381             e->terms[0].type = YASM_EXPR_INT;
    382             e->terms[0].data.intn = yasm_intnum_create_uint(0);
    383             break;
    384         case YASM_EXPR_WRT:
    385             /* Okay for single symrec in LHS and either a register or single
    386              * symrec (as an immediate child) on RHS.
    387              * If a single symrec on RHS, can only be done once.
    388              * WRT reg is left in expr for arch to look at.
    389              */
    390 
    391             /* Handle RHS */
    392             switch (e->terms[1].type) {
    393                 case YASM_EXPR_SYM:
    394                     if (value->wrt)
    395                         return 1;
    396                     value->wrt = e->terms[1].data.sym;
    397                     /* and drop the WRT portion */
    398                     e->op = YASM_EXPR_IDENT;
    399                     e->numterms = 1;
    400                     break;
    401                 case YASM_EXPR_REG:
    402                     break;  /* ignore */
    403                 default:
    404                     return 1;
    405             }
    406 
    407             /* Handle LHS */
    408             switch (e->terms[0].type) {
    409                 case YASM_EXPR_SYM:
    410                     if (value->rel || ssym_not_ok)
    411                         return 1;
    412                     value->rel = e->terms[0].data.sym;
    413                     /* and replace with 0 */
    414                     e->terms[0].type = YASM_EXPR_INT;
    415                     e->terms[0].data.intn = yasm_intnum_create_uint(0);
    416                     break;
    417                 case YASM_EXPR_EXPR:
    418                     /* recurse */
    419                     return value_finalize_scan(value, e->terms[0].data.expn,
    420                                                expr_precbc, ssym_not_ok);
    421                 default:
    422                     break;  /* ignore */
    423             }
    424 
    425             break;
    426         default:
    427             /* Single symrec not allowed anywhere */
    428             for (i=0; i<e->numterms; i++) {
    429                 switch (e->terms[i].type) {
    430                     case YASM_EXPR_SYM:
    431                         return 1;
    432                     case YASM_EXPR_EXPR:
    433                         /* recurse */
    434                         return value_finalize_scan(value,
    435                                                    e->terms[i].data.expn,
    436                                                    expr_precbc, 1);
    437                     default:
    438                         break;
    439                 }
    440             }
    441             break;
    442     }
    443 
    444     return 0;
    445 }
    446 
    447 int
    448 yasm_value_finalize_expr(yasm_value *value, yasm_expr *e,
    449                          yasm_bytecode *precbc, unsigned int size)
    450 {
    451     if (!e) {
    452         yasm_value_initialize(value, NULL, size);
    453         return 0;
    454     }
    455     yasm_value_initialize(value, e, size);
    456     return yasm_value_finalize(value, precbc);
    457 }
    458 
    459 int
    460 yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
    461 {
    462     if (!value->abs)
    463         return 0;
    464 
    465     value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
    466 
    467     /* quit early if there was an issue in simplify() */
    468     if (yasm_error_occurred())
    469         return 1;
    470 
    471     /* Strip top-level AND masking to an all-1s mask the same size
    472      * of the value size.  This allows forced avoidance of overflow warnings.
    473      */
    474     if (value->abs->op == YASM_EXPR_AND) {
    475         int term;
    476 
    477         /* Calculate 1<<size - 1 value */
    478         yasm_intnum *mask = yasm_intnum_create_uint(1);
    479         yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size);
    480         yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp);
    481         yasm_intnum_set_uint(mask_tmp, 1);
    482         yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp);
    483         yasm_intnum_destroy(mask_tmp);
    484 
    485         /* Walk terms and delete matching masks */
    486         for (term=value->abs->numterms-1; term>=0; term--) {
    487             if (value->abs->terms[term].type == YASM_EXPR_INT &&
    488                 yasm_intnum_compare(value->abs->terms[term].data.intn,
    489                                     mask) == 0) {
    490                 /* Delete the intnum */
    491                 yasm_intnum_destroy(value->abs->terms[term].data.intn);
    492 
    493                 /* Slide everything to its right over by 1 */
    494                 if (term != value->abs->numterms-1) /* if it wasn't last.. */
    495                     memmove(&value->abs->terms[term],
    496                             &value->abs->terms[term+1],
    497                             (value->abs->numterms-1-term)*
    498                                 sizeof(yasm_expr__item));
    499 
    500                 /* Update numterms */
    501                 value->abs->numterms--;
    502 
    503                 /* Indicate warnings have been disabled */
    504                 value->no_warn = 1;
    505             }
    506         }
    507         if (value->abs->numterms == 1)
    508             value->abs->op = YASM_EXPR_IDENT;
    509         yasm_intnum_destroy(mask);
    510     }
    511 
    512     /* Handle trivial (IDENT) cases immediately */
    513     if (value->abs->op == YASM_EXPR_IDENT) {
    514         switch (value->abs->terms[0].type) {
    515             case YASM_EXPR_INT:
    516                 if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
    517                     yasm_expr_destroy(value->abs);
    518                     value->abs = NULL;
    519                 }
    520                 return 0;
    521             case YASM_EXPR_REG:
    522             case YASM_EXPR_FLOAT:
    523                 return 0;
    524             case YASM_EXPR_SYM:
    525                 value->rel = value->abs->terms[0].data.sym;
    526                 yasm_expr_destroy(value->abs);
    527                 value->abs = NULL;
    528                 return 0;
    529             case YASM_EXPR_EXPR:
    530                 /* Bring up lower values. */
    531                 while (value->abs->op == YASM_EXPR_IDENT
    532                        && value->abs->terms[0].type == YASM_EXPR_EXPR) {
    533                     yasm_expr *sube = value->abs->terms[0].data.expn;
    534                     yasm_xfree(value->abs);
    535                     value->abs = sube;
    536                 }
    537                 break;
    538             default:
    539                 yasm_internal_error(N_("unexpected expr term type"));
    540         }
    541     }
    542 
    543     if (value_finalize_scan(value, value->abs, precbc, 0))
    544         return 1;
    545 
    546     value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
    547 
    548     /* Simplify 0 in abs to NULL */
    549     if (value->abs->op == YASM_EXPR_IDENT
    550         && value->abs->terms[0].type == YASM_EXPR_INT
    551         && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
    552         yasm_expr_destroy(value->abs);
    553         value->abs = NULL;
    554     }
    555     return 0;
    556 }
    557 
    558 yasm_intnum *
    559 yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
    560 {
    561     /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
    562     /*@only@*/ yasm_intnum *outval;
    563     int sym_local;
    564 
    565     if (value->abs) {
    566         /* Handle integer expressions, if non-integer or too complex, return
    567          * NULL.
    568          */
    569         intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist);
    570         if (!intn)
    571             return NULL;
    572     }
    573 
    574     if (value->rel) {
    575         /* If relative portion is not in bc section, return NULL.
    576          * Otherwise get the relative portion's offset.
    577          */
    578         /*@dependent@*/ yasm_bytecode *rel_prevbc;
    579         unsigned long dist;
    580 
    581         if (!bc)
    582             return NULL;    /* Can't calculate relative value */
    583 
    584         sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
    585         if (value->wrt || value->seg_of || value->section_rel || !sym_local)
    586             return NULL;    /* we can't handle SEG, WRT, or external symbols */
    587         if (rel_prevbc->section != bc->section)
    588             return NULL;    /* not in this section */
    589         if (!value->curpos_rel)
    590             return NULL;    /* not PC-relative */
    591 
    592         /* Calculate value relative to current assembly position */
    593         dist = yasm_bc_next_offset(rel_prevbc);
    594         if (dist < bc->offset) {
    595             outval = yasm_intnum_create_uint(bc->offset - dist);
    596             yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
    597         } else {
    598             dist -= bc->offset;
    599             outval = yasm_intnum_create_uint(dist);
    600         }
    601 
    602         if (value->rshift > 0) {
    603             /*@only@*/ yasm_intnum *shamt =
    604                 yasm_intnum_create_uint((unsigned long)value->rshift);
    605             yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
    606             yasm_intnum_destroy(shamt);
    607         }
    608         /* Add in absolute portion */
    609         if (intn)
    610             yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
    611         return outval;
    612     }
    613 
    614     if (intn)
    615         return yasm_intnum_copy(intn);
    616 
    617     /* No absolute or relative portions: output 0 */
    618     return yasm_intnum_create_uint(0);
    619 }
    620 
    621 int
    622 yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf,
    623                         size_t destsize, yasm_bytecode *bc, int warn,
    624                         yasm_arch *arch)
    625 {
    626     /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
    627     /*@only@*/ yasm_intnum *outval;
    628     int sym_local;
    629     int retval = 1;
    630     unsigned int valsize = value->size;
    631 
    632     if (value->no_warn)
    633         warn = 0;
    634 
    635     if (value->abs) {
    636         /* Handle floating point expressions */
    637         if (!value->rel && value->abs->op == YASM_EXPR_IDENT
    638             && value->abs->terms[0].type == YASM_EXPR_FLOAT) {
    639             if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt,
    640                                            buf, destsize, valsize, 0, warn))
    641                 return -1;
    642             else
    643                 return 1;
    644         }
    645 
    646         /* Check for complex float expressions */
    647         if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) {
    648             yasm_error_set(YASM_ERROR_FLOATING_POINT,
    649                            N_("floating point expression too complex"));
    650             return -1;
    651         }
    652 
    653         /* Handle normal integer expressions */
    654         intn = yasm_expr_get_intnum(&value->abs, 1);
    655 
    656         if (!intn) {
    657             /* Second try before erroring: yasm_expr_get_intnum doesn't handle
    658              * SEG:OFF, so try simplifying out any to just the OFF portion,
    659              * then getting the intnum again.
    660              */
    661             yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs);
    662             if (seg)
    663                 yasm_expr_destroy(seg);
    664             intn = yasm_expr_get_intnum(&value->abs, 1);
    665         }
    666 
    667         if (!intn) {
    668             /* Still don't have an integer! */
    669             yasm_error_set(YASM_ERROR_TOO_COMPLEX,
    670                            N_("expression too complex"));
    671             return -1;
    672         }
    673     }
    674 
    675     /* Adjust warn for signed/unsigned integer warnings */
    676     if (warn != 0)
    677         warn = value->sign ? -1 : 1;
    678 
    679     if (value->rel) {
    680         /* If relative portion is not in bc section, don't try to handle it
    681          * here.  Otherwise get the relative portion's offset.
    682          */
    683         /*@dependent@*/ yasm_bytecode *rel_prevbc;
    684         unsigned long dist;
    685 
    686         sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
    687         if (value->wrt || value->seg_of || value->section_rel || !sym_local)
    688             return 0;       /* we can't handle SEG, WRT, or external symbols */
    689         if (rel_prevbc->section != bc->section)
    690             return 0;       /* not in this section */
    691         if (!value->curpos_rel)
    692             return 0;       /* not PC-relative */
    693 
    694         /* Calculate value relative to current assembly position */
    695         dist = yasm_bc_next_offset(rel_prevbc);
    696         if (dist < bc->offset) {
    697             outval = yasm_intnum_create_uint(bc->offset - dist);
    698             yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
    699         } else {
    700             dist -= bc->offset;
    701             outval = yasm_intnum_create_uint(dist);
    702         }
    703 
    704         if (value->rshift > 0) {
    705             /*@only@*/ yasm_intnum *shamt =
    706                 yasm_intnum_create_uint((unsigned long)value->rshift);
    707             yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
    708             yasm_intnum_destroy(shamt);
    709         }
    710         /* Add in absolute portion */
    711         if (intn)
    712             yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
    713         /* Output! */
    714         if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
    715                                      bc, warn))
    716             retval = -1;
    717         yasm_intnum_destroy(outval);
    718         return retval;
    719     }
    720 
    721     if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel
    722         || value->section_rel)
    723         return 0;   /* We can't handle this with just an absolute */
    724 
    725     if (intn) {
    726         /* Output just absolute portion */
    727         if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc,
    728                                      warn))
    729             retval = -1;
    730     } else {
    731         /* No absolute or relative portions: output 0 */
    732         outval = yasm_intnum_create_uint(0);
    733         if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
    734                                      bc, warn))
    735             retval = -1;
    736         yasm_intnum_destroy(outval);
    737     }
    738     return retval;
    739 }
    740 
    741 void
    742 yasm_value_print(const yasm_value *value, FILE *f, int indent_level)
    743 {
    744     fprintf(f, "%*s%u-bit, %ssigned", indent_level, "", value->size,
    745             value->sign ? "" : "un");
    746     fprintf(f, "%*sAbsolute portion=", indent_level, "");
    747     yasm_expr_print(value->abs, f);
    748     fprintf(f, "\n");
    749     if (value->rel) {
    750         fprintf(f, "%*sRelative to=%s%s\n", indent_level, "",
    751                 value->seg_of ? "SEG " : "",
    752                 yasm_symrec_get_name(value->rel));
    753         if (value->wrt)
    754             fprintf(f, "%*s(With respect to=%s)\n", indent_level, "",
    755                     yasm_symrec_get_name(value->wrt));
    756         if (value->rshift > 0)
    757             fprintf(f, "%*s(Right shifted by=%u)\n", indent_level, "",
    758                     value->rshift);
    759         if (value->curpos_rel)
    760             fprintf(f, "%*s(Relative to current position)\n", indent_level,
    761                     "");
    762         if (value->ip_rel)
    763             fprintf(f, "%*s(IP-relative)\n", indent_level, "");
    764         if (value->jump_target)
    765             fprintf(f, "%*s(Jump target)\n", indent_level, "");
    766         if (value->section_rel)
    767             fprintf(f, "%*s(Section-relative)\n", indent_level, "");
    768         if (value->no_warn)
    769             fprintf(f, "%*s(Overflow warnings disabled)\n", indent_level, "");
    770     }
    771 }
    772