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
46void
47yasm_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
64void
65yasm_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
82void
83yasm_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
99void
100yasm_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
108void
109yasm_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
124static int
125value_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
447int
448yasm_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
459int
460yasm_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
558yasm_intnum *
559yasm_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
621int
622yasm_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
741void
742yasm_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