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
yasm_value_initialize(yasm_value * value,yasm_expr * e,unsigned int size)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
yasm_value_init_sym(yasm_value * value,yasm_symrec * sym,unsigned int size)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
yasm_value_init_copy(yasm_value * value,const yasm_value * orig)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
yasm_value_delete(yasm_value * value)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
yasm_value_set_curpos_rel(yasm_value * value,yasm_bytecode * bc,unsigned int ip_rel)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
value_finalize_scan(yasm_value * value,yasm_expr * e,yasm_bytecode * expr_precbc,int ssym_not_ok)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
yasm_value_finalize_expr(yasm_value * value,yasm_expr * e,yasm_bytecode * precbc,unsigned int size)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
yasm_value_finalize(yasm_value * value,yasm_bytecode * precbc)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 *
yasm_value_get_intnum(yasm_value * value,yasm_bytecode * bc,int calc_bc_dist)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
yasm_value_output_basic(yasm_value * value,unsigned char * buf,size_t destsize,yasm_bytecode * bc,int warn,yasm_arch * arch)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
yasm_value_print(const yasm_value * value,FILE * f,int indent_level)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