1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2018 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
34 /*
35 * eval.c expression evaluator for the Netwide Assembler
36 */
37
38 #include "compiler.h"
39
40 #include "nctype.h"
41
42 #include "nasm.h"
43 #include "nasmlib.h"
44 #include "ilog2.h"
45 #include "error.h"
46 #include "eval.h"
47 #include "labels.h"
48 #include "floats.h"
49 #include "assemble.h"
50
51 #define TEMPEXPRS_DELTA 128
52 #define TEMPEXPR_DELTA 8
53
54 static scanner scanfunc; /* Address of scanner routine */
55 static void *scpriv; /* Scanner private pointer */
56
57 static expr **tempexprs = NULL;
58 static int ntempexprs;
59 static int tempexprs_size = 0;
60
61 static expr *tempexpr;
62 static int ntempexpr;
63 static int tempexpr_size;
64
65 static struct tokenval *tokval; /* The current token */
66 static int tt; /* The t_type of tokval */
67
68 static bool critical;
69 static int *opflags;
70
71 static struct eval_hints *hint;
72 static int64_t deadman;
73
74
75 /*
76 * Unimportant cleanup is done to avoid confusing people who are trying
77 * to debug real memory leaks
78 */
eval_cleanup(void)79 void eval_cleanup(void)
80 {
81 while (ntempexprs)
82 nasm_free(tempexprs[--ntempexprs]);
83 nasm_free(tempexprs);
84 }
85
86 /*
87 * Construct a temporary expression.
88 */
begintemp(void)89 static void begintemp(void)
90 {
91 tempexpr = NULL;
92 tempexpr_size = ntempexpr = 0;
93 }
94
addtotemp(int32_t type,int64_t value)95 static void addtotemp(int32_t type, int64_t value)
96 {
97 while (ntempexpr >= tempexpr_size) {
98 tempexpr_size += TEMPEXPR_DELTA;
99 tempexpr = nasm_realloc(tempexpr,
100 tempexpr_size * sizeof(*tempexpr));
101 }
102 tempexpr[ntempexpr].type = type;
103 tempexpr[ntempexpr++].value = value;
104 }
105
finishtemp(void)106 static expr *finishtemp(void)
107 {
108 addtotemp(0L, 0L); /* terminate */
109 while (ntempexprs >= tempexprs_size) {
110 tempexprs_size += TEMPEXPRS_DELTA;
111 tempexprs = nasm_realloc(tempexprs,
112 tempexprs_size * sizeof(*tempexprs));
113 }
114 return tempexprs[ntempexprs++] = tempexpr;
115 }
116
117 /*
118 * Add two vector datatypes. We have some bizarre behaviour on far-
119 * absolute segment types: we preserve them during addition _only_
120 * if one of the segments is a truly pure scalar.
121 */
add_vectors(expr * p,expr * q)122 static expr *add_vectors(expr * p, expr * q)
123 {
124 int preserve;
125
126 preserve = is_really_simple(p) || is_really_simple(q);
127
128 begintemp();
129
130 while (p->type && q->type &&
131 p->type < EXPR_SEGBASE + SEG_ABS &&
132 q->type < EXPR_SEGBASE + SEG_ABS) {
133 int lasttype;
134
135 if (p->type > q->type) {
136 addtotemp(q->type, q->value);
137 lasttype = q++->type;
138 } else if (p->type < q->type) {
139 addtotemp(p->type, p->value);
140 lasttype = p++->type;
141 } else { /* *p and *q have same type */
142 int64_t sum = p->value + q->value;
143 if (sum) {
144 addtotemp(p->type, sum);
145 if (hint)
146 hint->type = EAH_SUMMED;
147 }
148 lasttype = p->type;
149 p++, q++;
150 }
151 if (lasttype == EXPR_UNKNOWN) {
152 return finishtemp();
153 }
154 }
155 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
156 addtotemp(p->type, p->value);
157 p++;
158 }
159 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
160 addtotemp(q->type, q->value);
161 q++;
162 }
163
164 return finishtemp();
165 }
166
167 /*
168 * Multiply a vector by a scalar. Strip far-absolute segment part
169 * if present.
170 *
171 * Explicit treatment of UNKNOWN is not required in this routine,
172 * since it will silently do the Right Thing anyway.
173 *
174 * If `affect_hints' is set, we also change the hint type to
175 * NOTBASE if a MAKEBASE hint points at a register being
176 * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
177 * as the base register.
178 */
scalar_mult(expr * vect,int64_t scalar,int affect_hints)179 static expr *scalar_mult(expr * vect, int64_t scalar, int affect_hints)
180 {
181 expr *p = vect;
182
183 while (p->type && p->type < EXPR_SEGBASE + SEG_ABS) {
184 p->value = scalar * (p->value);
185 if (hint && hint->type == EAH_MAKEBASE &&
186 p->type == hint->base && affect_hints)
187 hint->type = EAH_NOTBASE;
188 p++;
189 }
190 p->type = 0;
191
192 return vect;
193 }
194
scalarvect(int64_t scalar)195 static expr *scalarvect(int64_t scalar)
196 {
197 begintemp();
198 addtotemp(EXPR_SIMPLE, scalar);
199 return finishtemp();
200 }
201
unknown_expr(void)202 static expr *unknown_expr(void)
203 {
204 begintemp();
205 addtotemp(EXPR_UNKNOWN, 1L);
206 return finishtemp();
207 }
208
209 /*
210 * The SEG operator: calculate the segment part of a relocatable
211 * value. Return NULL, as usual, if an error occurs. Report the
212 * error too.
213 */
segment_part(expr * e)214 static expr *segment_part(expr * e)
215 {
216 int32_t seg;
217
218 if (is_unknown(e))
219 return unknown_expr();
220
221 if (!is_reloc(e)) {
222 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
223 return NULL;
224 }
225
226 seg = reloc_seg(e);
227 if (seg == NO_SEG) {
228 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
229 return NULL;
230 } else if (seg & SEG_ABS) {
231 return scalarvect(seg & ~SEG_ABS);
232 } else if (seg & 1) {
233 nasm_nonfatal("SEG applied to something which"
234 " is already a segment base");
235 return NULL;
236 } else {
237 int32_t base = ofmt->segbase(seg + 1);
238
239 begintemp();
240 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
241 1L);
242 return finishtemp();
243 }
244 }
245
246 /*
247 * Recursive-descent parser. Called with a single boolean operand,
248 * which is true if the evaluation is critical (i.e. unresolved
249 * symbols are an error condition). Must update the global `tt' to
250 * reflect the token after the parsed string. May return NULL.
251 *
252 * evaluate() should report its own errors: on return it is assumed
253 * that if NULL has been returned, the error has already been
254 * reported.
255 *
256 */
257
258 /*
259 * Wrapper function around the scanner
260 */
scan(void)261 static int scan(void)
262 {
263 return tt = scanfunc(scpriv, tokval);
264 }
265
266 /*
267 * Grammar parsed is:
268 *
269 * expr : bexpr [ WRT expr6 ]
270 * bexpr : cexpr
271 * cexpr : rexp0 [ {?} bexpr {:} cexpr ]
272 * rexp0 : rexp1 [ {||} rexp1...]
273 * rexp1 : rexp2 [ {^^} rexp2...]
274 * rexp2 : rexp3 [ {&&} rexp3...]
275 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=,<=>} expr0... ]
276 * expr0 : expr1 [ {|} expr1...]
277 * expr1 : expr2 [ {^} expr2...]
278 * expr2 : expr3 [ {&} expr3...]
279 * expr3 : expr4 [ {<<,>>,<<<,>>>} expr4...]
280 * expr4 : expr5 [ {+,-} expr5...]
281 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
282 * expr6 : { ~,+,-,IFUNC,SEG } expr6
283 * | (bexpr)
284 * | symbol
285 * | $
286 * | number
287 */
288
289 static expr *cexpr(void);
290 static expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
291
292 static expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
293 static expr *expr4(void), *expr5(void), *expr6(void);
294
295 /* This inline is a placeholder for the root of the basic expression */
bexpr(void)296 static inline expr *bexpr(void)
297 {
298 return cexpr();
299 }
300
cexpr(void)301 static expr *cexpr(void)
302 {
303 expr *e, *f, *g;
304
305 e = rexp0();
306 if (!e)
307 return NULL;
308
309 if (tt == TOKEN_QMARK) {
310 scan();
311 f = bexpr();
312 if (!f)
313 return NULL;
314
315 if (tt != ':') {
316 nasm_nonfatal("`?' without matching `:'");
317 return NULL;
318 }
319
320 scan();
321 g = cexpr();
322 if (!g)
323 return NULL;
324
325 if (is_simple(e)) {
326 e = reloc_value(e) ? f : g;
327 } else if (is_just_unknown(e)) {
328 e = unknown_expr();
329 } else {
330 nasm_nonfatal("the left-hand side of `?' must be "
331 "a scalar value");
332 }
333 }
334
335 return e;
336 }
337
rexp0(void)338 static expr *rexp0(void)
339 {
340 expr *e, *f;
341
342 e = rexp1();
343 if (!e)
344 return NULL;
345
346 while (tt == TOKEN_DBL_OR) {
347 scan();
348 f = rexp1();
349 if (!f)
350 return NULL;
351 if (!(is_simple(e) || is_just_unknown(e)) ||
352 !(is_simple(f) || is_just_unknown(f))) {
353 nasm_nonfatal("`|' operator may only be applied to"
354 " scalar values");
355 }
356
357 if (is_just_unknown(e) || is_just_unknown(f))
358 e = unknown_expr();
359 else
360 e = scalarvect((int64_t)(reloc_value(e) || reloc_value(f)));
361 }
362 return e;
363 }
364
rexp1(void)365 static expr *rexp1(void)
366 {
367 expr *e, *f;
368
369 e = rexp2();
370 if (!e)
371 return NULL;
372
373 while (tt == TOKEN_DBL_XOR) {
374 scan();
375 f = rexp2();
376 if (!f)
377 return NULL;
378 if (!(is_simple(e) || is_just_unknown(e)) ||
379 !(is_simple(f) || is_just_unknown(f))) {
380 nasm_nonfatal("`^' operator may only be applied to"
381 " scalar values");
382 }
383
384 if (is_just_unknown(e) || is_just_unknown(f))
385 e = unknown_expr();
386 else
387 e = scalarvect((int64_t)(!reloc_value(e) ^ !reloc_value(f)));
388 }
389 return e;
390 }
391
rexp2(void)392 static expr *rexp2(void)
393 {
394 expr *e, *f;
395
396 e = rexp3();
397 if (!e)
398 return NULL;
399 while (tt == TOKEN_DBL_AND) {
400 scan();
401 f = rexp3();
402 if (!f)
403 return NULL;
404 if (!(is_simple(e) || is_just_unknown(e)) ||
405 !(is_simple(f) || is_just_unknown(f))) {
406 nasm_nonfatal("`&' operator may only be applied to"
407 " scalar values");
408 }
409 if (is_just_unknown(e) || is_just_unknown(f))
410 e = unknown_expr();
411 else
412 e = scalarvect((int64_t)(reloc_value(e) && reloc_value(f)));
413 }
414 return e;
415 }
416
rexp3(void)417 static expr *rexp3(void)
418 {
419 expr *e, *f;
420 int64_t v;
421
422 e = expr0();
423 if (!e)
424 return NULL;
425
426 while (tt == TOKEN_EQ || tt == TOKEN_LT || tt == TOKEN_GT ||
427 tt == TOKEN_NE || tt == TOKEN_LE || tt == TOKEN_GE ||
428 tt == TOKEN_LEG) {
429 int tto = tt;
430 scan();
431 f = expr0();
432 if (!f)
433 return NULL;
434
435 e = add_vectors(e, scalar_mult(f, -1L, false));
436
437 switch (tto) {
438 case TOKEN_EQ:
439 case TOKEN_NE:
440 if (is_unknown(e))
441 v = -1; /* means unknown */
442 else if (!is_really_simple(e) || reloc_value(e) != 0)
443 v = (tto == TOKEN_NE); /* unequal, so return true if NE */
444 else
445 v = (tto == TOKEN_EQ); /* equal, so return true if EQ */
446 break;
447 default:
448 if (is_unknown(e))
449 v = -1; /* means unknown */
450 else if (!is_really_simple(e)) {
451 nasm_nonfatal("`%s': operands differ by a non-scalar",
452 (tto == TOKEN_LE ? "<=" :
453 tto == TOKEN_LT ? "<" :
454 tto == TOKEN_GE ? ">=" :
455 tto == TOKEN_GT ? ">" :
456 tto == TOKEN_LEG ? "<=>" :
457 "<internal error>"));
458 v = 0; /* must set it to _something_ */
459 } else {
460 int64_t vv = reloc_value(e);
461 if (tto == TOKEN_LEG)
462 v = (vv < 0) ? -1 : (vv > 0) ? 1 : 0;
463 else if (vv == 0)
464 v = (tto == TOKEN_LE || tto == TOKEN_GE);
465 else if (vv > 0)
466 v = (tto == TOKEN_GE || tto == TOKEN_GT);
467 else /* vv < 0 */
468 v = (tto == TOKEN_LE || tto == TOKEN_LT);
469 }
470 break;
471 }
472
473 if (v == -1)
474 e = unknown_expr();
475 else
476 e = scalarvect(v);
477 }
478 return e;
479 }
480
expr0(void)481 static expr *expr0(void)
482 {
483 expr *e, *f;
484
485 e = expr1();
486 if (!e)
487 return NULL;
488
489 while (tt == '|') {
490 scan();
491 f = expr1();
492 if (!f)
493 return NULL;
494 if (!(is_simple(e) || is_just_unknown(e)) ||
495 !(is_simple(f) || is_just_unknown(f))) {
496 nasm_nonfatal("`|' operator may only be applied to"
497 " scalar values");
498 }
499 if (is_just_unknown(e) || is_just_unknown(f))
500 e = unknown_expr();
501 else
502 e = scalarvect(reloc_value(e) | reloc_value(f));
503 }
504 return e;
505 }
506
expr1(void)507 static expr *expr1(void)
508 {
509 expr *e, *f;
510
511 e = expr2();
512 if (!e)
513 return NULL;
514
515 while (tt == '^') {
516 scan();
517 f = expr2();
518 if (!f)
519 return NULL;
520 if (!(is_simple(e) || is_just_unknown(e)) ||
521 !(is_simple(f) || is_just_unknown(f))) {
522 nasm_nonfatal("`^' operator may only be applied to"
523 " scalar values");
524 }
525 if (is_just_unknown(e) || is_just_unknown(f))
526 e = unknown_expr();
527 else
528 e = scalarvect(reloc_value(e) ^ reloc_value(f));
529 }
530 return e;
531 }
532
expr2(void)533 static expr *expr2(void)
534 {
535 expr *e, *f;
536
537 e = expr3();
538 if (!e)
539 return NULL;
540
541 while (tt == '&') {
542 scan();
543 f = expr3();
544 if (!f)
545 return NULL;
546 if (!(is_simple(e) || is_just_unknown(e)) ||
547 !(is_simple(f) || is_just_unknown(f))) {
548 nasm_nonfatal("`&' operator may only be applied to"
549 " scalar values");
550 }
551 if (is_just_unknown(e) || is_just_unknown(f))
552 e = unknown_expr();
553 else
554 e = scalarvect(reloc_value(e) & reloc_value(f));
555 }
556 return e;
557 }
558
expr3(void)559 static expr *expr3(void)
560 {
561 expr *e, *f;
562
563 e = expr4();
564 if (!e)
565 return NULL;
566
567 while (tt == TOKEN_SHL || tt == TOKEN_SHR || tt == TOKEN_SAR) {
568 int tto = tt;
569 scan();
570 f = expr4();
571 if (!f)
572 return NULL;
573 if (!(is_simple(e) || is_just_unknown(e)) ||
574 !(is_simple(f) || is_just_unknown(f))) {
575 nasm_nonfatal("shift operator may only be applied to"
576 " scalar values");
577 } else if (is_just_unknown(e) || is_just_unknown(f)) {
578 e = unknown_expr();
579 } else {
580 switch (tto) {
581 case TOKEN_SHL:
582 e = scalarvect(reloc_value(e) << reloc_value(f));
583 break;
584 case TOKEN_SHR:
585 e = scalarvect(((uint64_t)reloc_value(e)) >>
586 reloc_value(f));
587 break;
588 case TOKEN_SAR:
589 e = scalarvect(((int64_t)reloc_value(e)) >>
590 reloc_value(f));
591 break;
592 }
593 }
594 }
595 return e;
596 }
597
expr4(void)598 static expr *expr4(void)
599 {
600 expr *e, *f;
601
602 e = expr5();
603 if (!e)
604 return NULL;
605 while (tt == '+' || tt == '-') {
606 int tto = tt;
607 scan();
608 f = expr5();
609 if (!f)
610 return NULL;
611 switch (tto) {
612 case '+':
613 e = add_vectors(e, f);
614 break;
615 case '-':
616 e = add_vectors(e, scalar_mult(f, -1L, false));
617 break;
618 }
619 }
620 return e;
621 }
622
expr5(void)623 static expr *expr5(void)
624 {
625 expr *e, *f;
626
627 e = expr6();
628 if (!e)
629 return NULL;
630 while (tt == '*' || tt == '/' || tt == '%' ||
631 tt == TOKEN_SDIV || tt == TOKEN_SMOD) {
632 int tto = tt;
633 scan();
634 f = expr6();
635 if (!f)
636 return NULL;
637 if (tto != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
638 !(is_simple(f) || is_just_unknown(f)))) {
639 nasm_nonfatal("division operator may only be applied to"
640 " scalar values");
641 return NULL;
642 }
643 if (tto != '*' && !is_just_unknown(f) && reloc_value(f) == 0) {
644 nasm_nonfatal("division by zero");
645 return NULL;
646 }
647 switch (tto) {
648 case '*':
649 if (is_simple(e))
650 e = scalar_mult(f, reloc_value(e), true);
651 else if (is_simple(f))
652 e = scalar_mult(e, reloc_value(f), true);
653 else if (is_just_unknown(e) && is_just_unknown(f))
654 e = unknown_expr();
655 else {
656 nasm_nonfatal("unable to multiply two "
657 "non-scalar objects");
658 return NULL;
659 }
660 break;
661 case '/':
662 if (is_just_unknown(e) || is_just_unknown(f))
663 e = unknown_expr();
664 else
665 e = scalarvect(((uint64_t)reloc_value(e)) /
666 ((uint64_t)reloc_value(f)));
667 break;
668 case '%':
669 if (is_just_unknown(e) || is_just_unknown(f))
670 e = unknown_expr();
671 else
672 e = scalarvect(((uint64_t)reloc_value(e)) %
673 ((uint64_t)reloc_value(f)));
674 break;
675 case TOKEN_SDIV:
676 if (is_just_unknown(e) || is_just_unknown(f))
677 e = unknown_expr();
678 else
679 e = scalarvect(((int64_t)reloc_value(e)) /
680 ((int64_t)reloc_value(f)));
681 break;
682 case TOKEN_SMOD:
683 if (is_just_unknown(e) || is_just_unknown(f))
684 e = unknown_expr();
685 else
686 e = scalarvect(((int64_t)reloc_value(e)) %
687 ((int64_t)reloc_value(f)));
688 break;
689 }
690 }
691 return e;
692 }
693
eval_floatize(enum floatize type)694 static expr *eval_floatize(enum floatize type)
695 {
696 uint8_t result[16], *p; /* Up to 128 bits */
697 int sign = 1;
698 int64_t val;
699 size_t len;
700 int i;
701 const struct ieee_format *fmt;
702
703 fmt = &fp_formats[type];
704
705 scan();
706 if (tt != '(') {
707 nasm_nonfatal("expecting `('");
708 return NULL;
709 }
710 scan();
711 if (tt == '-' || tt == '+') {
712 sign = (tt == '-') ? -1 : 1;
713 scan();
714 }
715 if (tt != TOKEN_FLOAT) {
716 nasm_nonfatal("expecting floating-point number");
717 return NULL;
718 }
719 if (!float_const(tokval->t_charptr, sign, result, type))
720 return NULL;
721 scan();
722 if (tt != ')') {
723 nasm_nonfatal("expecting `)'");
724 return NULL;
725 }
726
727 len = fmt->bytes - fmt->offset;
728 if (len > 8)
729 len = 8; /* Max 64 bits */
730 p = result + len + fmt->offset;
731 val = 0;
732 for (i = len; i; i--) {
733 p--;
734 val = (val << 8) + *p;
735 }
736
737 begintemp();
738 addtotemp(EXPR_SIMPLE, val);
739
740 scan();
741 return finishtemp();
742 }
743
eval_strfunc(enum strfunc type,const char * name)744 static expr *eval_strfunc(enum strfunc type, const char *name)
745 {
746 char *string;
747 size_t string_len;
748 int64_t val;
749 bool parens, rn_warn;
750
751 parens = false;
752 scan();
753 if (tt == '(') {
754 parens = true;
755 scan();
756 }
757 if (tt != TOKEN_STR) {
758 nasm_nonfatal("expecting string as argument to %s", name);
759 return NULL;
760 }
761 string_len = string_transform(tokval->t_charptr, tokval->t_inttwo,
762 &string, type);
763 if (string_len == (size_t)-1) {
764 nasm_nonfatal("invalid input string to %s", name);
765 return NULL;
766 }
767
768 val = readstrnum(string, string_len, &rn_warn);
769 if (parens) {
770 scan();
771 if (tt != ')') {
772 nasm_nonfatal("expecting `)'");
773 return NULL;
774 }
775 }
776
777 if (rn_warn)
778 nasm_warn(WARN_OTHER, "character constant too long");
779
780 begintemp();
781 addtotemp(EXPR_SIMPLE, val);
782
783 scan();
784 return finishtemp();
785 }
786
eval_ifunc(int64_t val,enum ifunc func)787 static int64_t eval_ifunc(int64_t val, enum ifunc func)
788 {
789 uint64_t uval = (uint64_t)val;
790 int64_t rv;
791
792 switch (func) {
793 case IFUNC_ILOG2E:
794 case IFUNC_ILOG2W:
795 if (!is_power2(uval))
796 nasm_error((func == IFUNC_ILOG2E) ? ERR_NONFATAL : ERR_WARNING|WARN_OTHER,
797 "ilog2 argument is not a power of two");
798 /* fall through */
799 case IFUNC_ILOG2F:
800 rv = ilog2_64(uval);
801 break;
802
803 case IFUNC_ILOG2C:
804 rv = (uval < 2) ? 0 : ilog2_64(uval-1) + 1;
805 break;
806
807 default:
808 nasm_panic("invalid IFUNC token %d", func);
809 rv = 0;
810 break;
811 }
812
813 return rv;
814 }
815
expr6(void)816 static expr *expr6(void)
817 {
818 int32_t type;
819 expr *e;
820 int32_t label_seg;
821 int64_t label_ofs;
822 int64_t tmpval;
823 bool rn_warn;
824 const char *scope;
825
826 if (++deadman > nasm_limit[LIMIT_EVAL]) {
827 nasm_nonfatal("expression too long");
828 return NULL;
829 }
830
831 switch (tt) {
832 case '-':
833 scan();
834 e = expr6();
835 if (!e)
836 return NULL;
837 return scalar_mult(e, -1L, false);
838
839 case '+':
840 scan();
841 return expr6();
842
843 case '~':
844 scan();
845 e = expr6();
846 if (!e)
847 return NULL;
848 if (is_just_unknown(e))
849 return unknown_expr();
850 else if (!is_simple(e)) {
851 nasm_nonfatal("`~' operator may only be applied to"
852 " scalar values");
853 return NULL;
854 }
855 return scalarvect(~reloc_value(e));
856
857 case '!':
858 scan();
859 e = expr6();
860 if (!e)
861 return NULL;
862 if (is_just_unknown(e))
863 return unknown_expr();
864 else if (!is_simple(e)) {
865 nasm_nonfatal("`!' operator may only be applied to"
866 " scalar values");
867 return NULL;
868 }
869 return scalarvect(!reloc_value(e));
870
871 case TOKEN_IFUNC:
872 {
873 enum ifunc func = tokval->t_integer;
874 scan();
875 e = expr6();
876 if (!e)
877 return NULL;
878 if (is_just_unknown(e))
879 return unknown_expr();
880 else if (!is_simple(e)) {
881 nasm_nonfatal("function may only be applied to"
882 " scalar values");
883 return NULL;
884 }
885 return scalarvect(eval_ifunc(reloc_value(e), func));
886 }
887
888 case TOKEN_SEG:
889 scan();
890 e = expr6();
891 if (!e)
892 return NULL;
893 e = segment_part(e);
894 if (!e)
895 return NULL;
896 if (is_unknown(e) && critical) {
897 nasm_nonfatal("unable to determine segment base");
898 return NULL;
899 }
900 return e;
901
902 case TOKEN_FLOATIZE:
903 return eval_floatize(tokval->t_integer);
904
905 case TOKEN_STRFUNC:
906 return eval_strfunc(tokval->t_integer, tokval->t_charptr);
907
908 case '(':
909 scan();
910 e = bexpr();
911 if (!e)
912 return NULL;
913 if (tt != ')') {
914 nasm_nonfatal("expecting `)'");
915 return NULL;
916 }
917 scan();
918 return e;
919
920 case TOKEN_NUM:
921 case TOKEN_STR:
922 case TOKEN_REG:
923 case TOKEN_ID:
924 case TOKEN_INSN: /* Opcodes that occur here are really labels */
925 case TOKEN_HERE:
926 case TOKEN_BASE:
927 case TOKEN_DECORATOR:
928 begintemp();
929 switch (tt) {
930 case TOKEN_NUM:
931 addtotemp(EXPR_SIMPLE, tokval->t_integer);
932 break;
933 case TOKEN_STR:
934 tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn);
935 if (rn_warn)
936 nasm_warn(WARN_OTHER, "character constant too long");
937 addtotemp(EXPR_SIMPLE, tmpval);
938 break;
939 case TOKEN_REG:
940 addtotemp(tokval->t_integer, 1L);
941 if (hint && hint->type == EAH_NOHINT)
942 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
943 break;
944 case TOKEN_ID:
945 case TOKEN_INSN:
946 case TOKEN_HERE:
947 case TOKEN_BASE:
948 /*
949 * If !location.known, this indicates that no
950 * symbol, Here or Base references are valid because we
951 * are in preprocess-only mode.
952 */
953 if (!location.known) {
954 nasm_nonfatal("%s not supported in preprocess-only mode",
955 (tt == TOKEN_HERE ? "`$'" :
956 tt == TOKEN_BASE ? "`$$'" :
957 "symbol references"));
958 addtotemp(EXPR_UNKNOWN, 1L);
959 break;
960 }
961
962 type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
963 if (tt == TOKEN_BASE) {
964 label_seg = in_absolute ? absolute.segment : location.segment;
965 label_ofs = 0;
966 } else if (tt == TOKEN_HERE) {
967 label_seg = in_absolute ? absolute.segment : location.segment;
968 label_ofs = in_absolute ? absolute.offset : location.offset;
969 } else {
970 enum label_type ltype;
971 ltype = lookup_label(tokval->t_charptr, &label_seg, &label_ofs);
972 if (ltype == LBL_none) {
973 scope = local_scope(tokval->t_charptr);
974 if (critical) {
975 nasm_nonfatal("symbol `%s%s' not defined%s",
976 scope,tokval->t_charptr,
977 pass_first() ? " before use" : "");
978 return NULL;
979 }
980 if (opflags)
981 *opflags |= OPFLAG_FORWARD;
982 type = EXPR_UNKNOWN;
983 label_seg = NO_SEG;
984 label_ofs = 1;
985 } else if (is_extern(ltype)) {
986 if (opflags)
987 *opflags |= OPFLAG_EXTERN;
988 }
989 }
990 addtotemp(type, label_ofs);
991 if (label_seg != NO_SEG)
992 addtotemp(EXPR_SEGBASE + label_seg, 1L);
993 break;
994 case TOKEN_DECORATOR:
995 addtotemp(EXPR_RDSAE, tokval->t_integer);
996 break;
997 }
998 scan();
999 return finishtemp();
1000
1001 default:
1002 nasm_nonfatal("expression syntax error");
1003 return NULL;
1004 }
1005 }
1006
evaluate(scanner sc,void * scprivate,struct tokenval * tv,int * fwref,bool crit,struct eval_hints * hints)1007 expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
1008 int *fwref, bool crit, struct eval_hints *hints)
1009 {
1010 expr *e;
1011 expr *f = NULL;
1012
1013 deadman = 0;
1014
1015 hint = hints;
1016 if (hint)
1017 hint->type = EAH_NOHINT;
1018
1019 critical = crit;
1020 scanfunc = sc;
1021 scpriv = scprivate;
1022 tokval = tv;
1023 opflags = fwref;
1024
1025 while (ntempexprs) /* initialize temporary storage */
1026 nasm_free(tempexprs[--ntempexprs]);
1027
1028 tt = tokval->t_type;
1029 if (tt == TOKEN_INVALID)
1030 scan();
1031
1032 e = bexpr();
1033 if (!e)
1034 return NULL;
1035
1036 if (tt == TOKEN_WRT) {
1037 scan(); /* eat the WRT */
1038 f = expr6();
1039 if (!f)
1040 return NULL;
1041 }
1042 e = scalar_mult(e, 1L, false); /* strip far-absolute segment part */
1043 if (f) {
1044 expr *g;
1045 if (is_just_unknown(f))
1046 g = unknown_expr();
1047 else {
1048 int64_t value;
1049 begintemp();
1050 if (!is_reloc(f)) {
1051 nasm_nonfatal("invalid right-hand operand to WRT");
1052 return NULL;
1053 }
1054 value = reloc_seg(f);
1055 if (value == NO_SEG)
1056 value = reloc_value(f) | SEG_ABS;
1057 else if (!(value & SEG_ABS) && !(value % 2) && critical) {
1058 nasm_nonfatal("invalid right-hand operand to WRT");
1059 return NULL;
1060 }
1061 addtotemp(EXPR_WRT, value);
1062 g = finishtemp();
1063 }
1064 e = add_vectors(e, g);
1065 }
1066 return e;
1067 }
1068