blob: cd3c526d625deaf40cae3d65a0f2bbbf41fa5cc3 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +03002 *
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07003 * Copyright 1996-2018 The NASM Authors - All Rights Reserved
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07004 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvin76690a12002-04-30 20:52:49 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * 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.
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +030017 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070018 * 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
H. Peter Anvin76690a12002-04-30 20:52:49 +000036 */
37
H. Peter Anvinfe501952007-10-02 21:53:51 -070038#include "compiler.h"
39
H. Peter Anvinc2f3f262018-12-27 12:37:25 -080040#include "nctype.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000041
42#include "nasm.h"
43#include "nasmlib.h"
H. Peter Anvin0a126062017-09-27 13:34:42 -070044#include "ilog2.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080045#include "error.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000046#include "eval.h"
H. Peter Anvineba20a72002-04-30 20:53:55 +000047#include "labels.h"
H. Peter Anvin (Intel)6e9554f2020-06-14 23:21:44 -070048#include "floats.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080049#include "assemble.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000050
H. Peter Anvin76690a12002-04-30 20:52:49 +000051#define TEMPEXPRS_DELTA 128
H. Peter Anvin76690a12002-04-30 20:52:49 +000052#define TEMPEXPR_DELTA 8
53
H. Peter Anvin99fcda02018-11-28 10:27:30 -080054static scanner scanfunc; /* Address of scanner routine */
55static void *scpriv; /* Scanner private pointer */
H. Peter Anvineba20a72002-04-30 20:53:55 +000056
H. Peter Anvineba20a72002-04-30 20:53:55 +000057static expr **tempexprs = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +000058static int ntempexprs;
59static int tempexprs_size = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +000060
H. Peter Anvine2c80182005-01-15 22:15:51 +000061static expr *tempexpr;
62static int ntempexpr;
63static int tempexpr_size;
H. Peter Anvineba20a72002-04-30 20:53:55 +000064
H. Peter Anvine2c80182005-01-15 22:15:51 +000065static struct tokenval *tokval; /* The current token */
H. Peter Anvin6fdf7102018-11-28 10:33:16 -080066static int tt; /* The t_type of tokval */
H. Peter Anvineba20a72002-04-30 20:53:55 +000067
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -080068static bool critical;
H. Peter Anvineba20a72002-04-30 20:53:55 +000069static int *opflags;
H. Peter Anvin76690a12002-04-30 20:52:49 +000070
71static struct eval_hints *hint;
H. Peter Anvina3d96d02018-06-15 17:51:39 -070072static int64_t deadman;
H. Peter Anvin76690a12002-04-30 20:52:49 +000073
H. Peter Anvin667dd802002-05-26 19:49:41 +000074
H. Peter Anvin76690a12002-04-30 20:52:49 +000075/*
H. Peter Anvineba20a72002-04-30 20:53:55 +000076 * Unimportant cleanup is done to avoid confusing people who are trying
77 * to debug real memory leaks
78 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000079void eval_cleanup(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +000080{
81 while (ntempexprs)
H. Peter Anvine2c80182005-01-15 22:15:51 +000082 nasm_free(tempexprs[--ntempexprs]);
83 nasm_free(tempexprs);
H. Peter Anvineba20a72002-04-30 20:53:55 +000084}
85
86/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000087 * Construct a temporary expression.
88 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000089static void begintemp(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +000090{
H. Peter Anvin76690a12002-04-30 20:52:49 +000091 tempexpr = NULL;
92 tempexpr_size = ntempexpr = 0;
93}
94
Keith Kaniosb7a89542007-04-12 02:40:54 +000095static void addtotemp(int32_t type, int64_t value)
H. Peter Anvineba20a72002-04-30 20:53:55 +000096{
H. Peter Anvin76690a12002-04-30 20:52:49 +000097 while (ntempexpr >= tempexpr_size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +000098 tempexpr_size += TEMPEXPR_DELTA;
99 tempexpr = nasm_realloc(tempexpr,
100 tempexpr_size * sizeof(*tempexpr));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000101 }
102 tempexpr[ntempexpr].type = type;
103 tempexpr[ntempexpr++].value = value;
104}
105
H. Peter Anvine2c80182005-01-15 22:15:51 +0000106static expr *finishtemp(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000107{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000108 addtotemp(0L, 0L); /* terminate */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000109 while (ntempexprs >= tempexprs_size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000110 tempexprs_size += TEMPEXPRS_DELTA;
111 tempexprs = nasm_realloc(tempexprs,
112 tempexprs_size * sizeof(*tempexprs));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000113 }
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 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000122static expr *add_vectors(expr * p, expr * q)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000123{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000124 int preserve;
125
126 preserve = is_really_simple(p) || is_really_simple(q);
127
128 begintemp();
129
130 while (p->type && q->type &&
H. Peter Anvine2c80182005-01-15 22:15:51 +0000131 p->type < EXPR_SEGBASE + SEG_ABS &&
132 q->type < EXPR_SEGBASE + SEG_ABS) {
133 int lasttype;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000134
H. Peter Anvine2c80182005-01-15 22:15:51 +0000135 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 */
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700142 int64_t sum = p->value + q->value;
Jin Kyu Song4360ba22013-12-10 16:24:45 -0800143 if (sum) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000144 addtotemp(p->type, sum);
Jin Kyu Song4360ba22013-12-10 16:24:45 -0800145 if (hint)
146 hint->type = EAH_SUMMED;
147 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000148 lasttype = p->type;
149 p++, q++;
150 }
151 if (lasttype == EXPR_UNKNOWN) {
152 return finishtemp();
153 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000154 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000155 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
156 addtotemp(p->type, p->value);
157 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000158 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
160 addtotemp(q->type, q->value);
161 q++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000162 }
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 */
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700179static expr *scalar_mult(expr * vect, int64_t scalar, int affect_hints)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000180{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000181 expr *p = vect;
182
H. Peter Anvine2c80182005-01-15 22:15:51 +0000183 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++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000189 }
190 p->type = 0;
191
192 return vect;
193}
194
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700195static expr *scalarvect(int64_t scalar)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000196{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000197 begintemp();
198 addtotemp(EXPR_SIMPLE, scalar);
199 return finishtemp();
200}
201
H. Peter Anvine2c80182005-01-15 22:15:51 +0000202static expr *unknown_expr(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000203{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000204 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 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000214static expr *segment_part(expr * e)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000215{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000216 int32_t seg;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000217
218 if (is_unknown(e))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219 return unknown_expr();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000220
221 if (!is_reloc(e)) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300222 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000223 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000224 }
225
226 seg = reloc_seg(e);
227 if (seg == NO_SEG) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300228 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000229 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000230 } else if (seg & SEG_ABS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000231 return scalarvect(seg & ~SEG_ABS);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000232 } else if (seg & 1) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300233 nasm_nonfatal("SEG applied to something which"
234 " is already a segment base");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000235 return NULL;
236 } else {
H. Peter Anvin36034ec2016-02-18 01:18:50 -0800237 int32_t base = ofmt->segbase(seg + 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000238
H. Peter Anvine2c80182005-01-15 22:15:51 +0000239 begintemp();
240 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
241 1L);
242 return finishtemp();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000243 }
244}
245
246/*
247 * Recursive-descent parser. Called with a single boolean operand,
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700248 * which is true if the evaluation is critical (i.e. unresolved
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800249 * symbols are an error condition). Must update the global `tt' to
H. Peter Anvin76690a12002-04-30 20:52:49 +0000250 * 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.
H. Peter Anvinca605a32018-11-28 10:07:19 -0800255 *
H. Peter Anvin76690a12002-04-30 20:52:49 +0000256 */
257
258/*
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800259 * Wrapper function around the scanner
260 */
261static int scan(void)
262{
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800263 return tt = scanfunc(scpriv, tokval);
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800264}
265
266/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000267 * Grammar parsed is:
268 *
269 * expr : bexpr [ WRT expr6 ]
H. Peter Anvin099cc172018-11-28 13:13:16 -0800270 * bexpr : cexpr
271 * cexpr : rexp0 [ {?} bexpr {:} cexpr ]
H. Peter Anvin76690a12002-04-30 20:52:49 +0000272 * rexp0 : rexp1 [ {||} rexp1...]
273 * rexp1 : rexp2 [ {^^} rexp2...]
274 * rexp2 : rexp3 [ {&&} rexp3...]
H. Peter Anvin099cc172018-11-28 13:13:16 -0800275 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=,<=>} expr0... ]
H. Peter Anvin76690a12002-04-30 20:52:49 +0000276 * expr0 : expr1 [ {|} expr1...]
277 * expr1 : expr2 [ {^} expr2...]
278 * expr2 : expr3 [ {&} expr3...]
H. Peter Anvinca605a32018-11-28 10:07:19 -0800279 * expr3 : expr4 [ {<<,>>,<<<,>>>} expr4...]
H. Peter Anvin76690a12002-04-30 20:52:49 +0000280 * expr4 : expr5 [ {+,-} expr5...]
281 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700282 * expr6 : { ~,+,-,IFUNC,SEG } expr6
H. Peter Anvin76690a12002-04-30 20:52:49 +0000283 * | (bexpr)
284 * | symbol
285 * | $
286 * | number
287 */
288
H. Peter Anvin099cc172018-11-28 13:13:16 -0800289static expr *cexpr(void);
H. Peter Anvinef427b32018-11-28 10:19:50 -0800290static expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000291
H. Peter Anvinef427b32018-11-28 10:19:50 -0800292static expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
293static expr *expr4(void), *expr5(void), *expr6(void);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000294
H. Peter Anvinca605a32018-11-28 10:07:19 -0800295/* This inline is a placeholder for the root of the basic expression */
H. Peter Anvinef427b32018-11-28 10:19:50 -0800296static inline expr *bexpr(void)
H. Peter Anvinca605a32018-11-28 10:07:19 -0800297{
H. Peter Anvin099cc172018-11-28 13:13:16 -0800298 return cexpr();
299}
300
301static expr *cexpr(void)
302{
303 expr *e, *f, *g;
304
305 e = rexp0();
306 if (!e)
307 return NULL;
308
H. Peter Anvin (Intel)9df07552018-12-14 00:50:34 -0800309 if (tt == TOKEN_QMARK) {
H. Peter Anvin099cc172018-11-28 13:13:16 -0800310 scan();
311 f = bexpr();
312 if (!f)
313 return NULL;
314
315 if (tt != ':') {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300316 nasm_nonfatal("`?' without matching `:'");
H. Peter Anvin099cc172018-11-28 13:13:16 -0800317 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 {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300330 nasm_nonfatal("the left-hand side of `?' must be "
331 "a scalar value");
H. Peter Anvin099cc172018-11-28 13:13:16 -0800332 }
333 }
334
335 return e;
H. Peter Anvinca605a32018-11-28 10:07:19 -0800336}
H. Peter Anvin76690a12002-04-30 20:52:49 +0000337
H. Peter Anvinef427b32018-11-28 10:19:50 -0800338static expr *rexp0(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000339{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000340 expr *e, *f;
341
H. Peter Anvinef427b32018-11-28 10:19:50 -0800342 e = rexp1();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000343 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000344 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000345
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800346 while (tt == TOKEN_DBL_OR) {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800347 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800348 f = rexp1();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000349 if (!f)
350 return NULL;
351 if (!(is_simple(e) || is_just_unknown(e)) ||
352 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300353 nasm_nonfatal("`|' operator may only be applied to"
354 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000355 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000356
H. Peter Anvine2c80182005-01-15 22:15:51 +0000357 if (is_just_unknown(e) || is_just_unknown(f))
358 e = unknown_expr();
359 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700360 e = scalarvect((int64_t)(reloc_value(e) || reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000361 }
362 return e;
363}
364
H. Peter Anvinef427b32018-11-28 10:19:50 -0800365static expr *rexp1(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000366{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000367 expr *e, *f;
368
H. Peter Anvinef427b32018-11-28 10:19:50 -0800369 e = rexp2();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000370 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000371 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000372
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800373 while (tt == TOKEN_DBL_XOR) {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800374 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800375 f = rexp2();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000376 if (!f)
377 return NULL;
378 if (!(is_simple(e) || is_just_unknown(e)) ||
379 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300380 nasm_nonfatal("`^' operator may only be applied to"
381 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000382 }
383
384 if (is_just_unknown(e) || is_just_unknown(f))
385 e = unknown_expr();
386 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700387 e = scalarvect((int64_t)(!reloc_value(e) ^ !reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000388 }
389 return e;
390}
391
H. Peter Anvinef427b32018-11-28 10:19:50 -0800392static expr *rexp2(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000393{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000394 expr *e, *f;
395
H. Peter Anvinef427b32018-11-28 10:19:50 -0800396 e = rexp3();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000397 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000398 return NULL;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800399 while (tt == TOKEN_DBL_AND) {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800400 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800401 f = rexp3();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000402 if (!f)
403 return NULL;
404 if (!(is_simple(e) || is_just_unknown(e)) ||
405 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300406 nasm_nonfatal("`&' operator may only be applied to"
407 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000408 }
409 if (is_just_unknown(e) || is_just_unknown(f))
410 e = unknown_expr();
411 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700412 e = scalarvect((int64_t)(reloc_value(e) && reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000413 }
414 return e;
415}
416
H. Peter Anvinef427b32018-11-28 10:19:50 -0800417static expr *rexp3(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000418{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000419 expr *e, *f;
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700420 int64_t v;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000421
H. Peter Anvinef427b32018-11-28 10:19:50 -0800422 e = expr0();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000423 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000424 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000425
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800426 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;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800430 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800431 f = expr0();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000432 if (!f)
433 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000434
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700435 e = add_vectors(e, scalar_mult(f, -1L, false));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000436
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800437 switch (tto) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000438 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)
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800443 v = (tto == TOKEN_NE); /* unequal, so return true if NE */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000444 else
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800445 v = (tto == TOKEN_EQ); /* equal, so return true if EQ */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000446 break;
447 default:
448 if (is_unknown(e))
449 v = -1; /* means unknown */
450 else if (!is_really_simple(e)) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300451 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>"));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000458 v = 0; /* must set it to _something_ */
459 } else {
Cyrill Gorcunov9f135ed2010-11-06 23:04:12 +0300460 int64_t vv = reloc_value(e);
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800461 if (tto == TOKEN_LEG)
H. Peter Anvin3bb1dd02018-06-15 18:46:11 -0700462 v = (vv < 0) ? -1 : (vv > 0) ? 1 : 0;
463 else if (vv == 0)
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800464 v = (tto == TOKEN_LE || tto == TOKEN_GE);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000465 else if (vv > 0)
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800466 v = (tto == TOKEN_GE || tto == TOKEN_GT);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000467 else /* vv < 0 */
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800468 v = (tto == TOKEN_LE || tto == TOKEN_LT);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000469 }
470 break;
471 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000472
H. Peter Anvine2c80182005-01-15 22:15:51 +0000473 if (v == -1)
474 e = unknown_expr();
475 else
476 e = scalarvect(v);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000477 }
478 return e;
479}
480
H. Peter Anvinef427b32018-11-28 10:19:50 -0800481static expr *expr0(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000482{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000483 expr *e, *f;
484
H. Peter Anvinef427b32018-11-28 10:19:50 -0800485 e = expr1();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000486 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000487 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000488
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800489 while (tt == '|') {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800490 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800491 f = expr1();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492 if (!f)
493 return NULL;
494 if (!(is_simple(e) || is_just_unknown(e)) ||
495 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300496 nasm_nonfatal("`|' operator may only be applied to"
497 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000498 }
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));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000503 }
504 return e;
505}
506
H. Peter Anvinef427b32018-11-28 10:19:50 -0800507static expr *expr1(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000508{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000509 expr *e, *f;
510
H. Peter Anvinef427b32018-11-28 10:19:50 -0800511 e = expr2();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000512 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000513 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000514
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800515 while (tt == '^') {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800516 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800517 f = expr2();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000518 if (!f)
519 return NULL;
520 if (!(is_simple(e) || is_just_unknown(e)) ||
521 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300522 nasm_nonfatal("`^' operator may only be applied to"
523 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000524 }
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));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000529 }
530 return e;
531}
532
H. Peter Anvinef427b32018-11-28 10:19:50 -0800533static expr *expr2(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000534{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000535 expr *e, *f;
536
H. Peter Anvinef427b32018-11-28 10:19:50 -0800537 e = expr3();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000538 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000539 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000540
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800541 while (tt == '&') {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800542 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800543 f = expr3();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000544 if (!f)
545 return NULL;
546 if (!(is_simple(e) || is_just_unknown(e)) ||
547 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300548 nasm_nonfatal("`&' operator may only be applied to"
549 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000550 }
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));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000555 }
556 return e;
557}
558
H. Peter Anvinef427b32018-11-28 10:19:50 -0800559static expr *expr3(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000560{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000561 expr *e, *f;
562
H. Peter Anvinef427b32018-11-28 10:19:50 -0800563 e = expr4();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000564 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000565 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000566
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800567 while (tt == TOKEN_SHL || tt == TOKEN_SHR || tt == TOKEN_SAR) {
568 int tto = tt;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800569 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800570 f = expr4();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000571 if (!f)
572 return NULL;
573 if (!(is_simple(e) || is_just_unknown(e)) ||
574 !(is_simple(f) || is_just_unknown(f))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300575 nasm_nonfatal("shift operator may only be applied to"
576 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000577 } else if (is_just_unknown(e) || is_just_unknown(f)) {
578 e = unknown_expr();
H. Peter Anvin94adf7d2018-06-15 18:37:32 -0700579 } else {
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800580 switch (tto) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000581 case TOKEN_SHL:
582 e = scalarvect(reloc_value(e) << reloc_value(f));
583 break;
584 case TOKEN_SHR:
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700585 e = scalarvect(((uint64_t)reloc_value(e)) >>
H. Peter Anvine2c80182005-01-15 22:15:51 +0000586 reloc_value(f));
587 break;
H. Peter Anvin94adf7d2018-06-15 18:37:32 -0700588 case TOKEN_SAR:
589 e = scalarvect(((int64_t)reloc_value(e)) >>
590 reloc_value(f));
591 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000592 }
H. Peter Anvin94adf7d2018-06-15 18:37:32 -0700593 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000594 }
595 return e;
596}
597
H. Peter Anvinef427b32018-11-28 10:19:50 -0800598static expr *expr4(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000599{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000600 expr *e, *f;
601
H. Peter Anvinef427b32018-11-28 10:19:50 -0800602 e = expr5();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000603 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000604 return NULL;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800605 while (tt == '+' || tt == '-') {
606 int tto = tt;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800607 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800608 f = expr5();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000609 if (!f)
610 return NULL;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800611 switch (tto) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000612 case '+':
613 e = add_vectors(e, f);
614 break;
615 case '-':
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700616 e = add_vectors(e, scalar_mult(f, -1L, false));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 break;
618 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000619 }
620 return e;
621}
622
H. Peter Anvinef427b32018-11-28 10:19:50 -0800623static expr *expr5(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000624{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000625 expr *e, *f;
626
H. Peter Anvinef427b32018-11-28 10:19:50 -0800627 e = expr6();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000628 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000629 return NULL;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800630 while (tt == '*' || tt == '/' || tt == '%' ||
631 tt == TOKEN_SDIV || tt == TOKEN_SMOD) {
632 int tto = tt;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800633 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800634 f = expr6();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000635 if (!f)
636 return NULL;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800637 if (tto != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000638 !(is_simple(f) || is_just_unknown(f)))) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300639 nasm_nonfatal("division operator may only be applied to"
640 " scalar values");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000641 return NULL;
642 }
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800643 if (tto != '*' && !is_just_unknown(f) && reloc_value(f) == 0) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300644 nasm_nonfatal("division by zero");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000645 return NULL;
646 }
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800647 switch (tto) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000648 case '*':
649 if (is_simple(e))
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700650 e = scalar_mult(f, reloc_value(e), true);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000651 else if (is_simple(f))
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700652 e = scalar_mult(e, reloc_value(f), true);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000653 else if (is_just_unknown(e) && is_just_unknown(f))
654 e = unknown_expr();
655 else {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300656 nasm_nonfatal("unable to multiply two "
657 "non-scalar objects");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000658 return NULL;
659 }
660 break;
661 case '/':
662 if (is_just_unknown(e) || is_just_unknown(f))
663 e = unknown_expr();
664 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700665 e = scalarvect(((uint64_t)reloc_value(e)) /
666 ((uint64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000667 break;
668 case '%':
669 if (is_just_unknown(e) || is_just_unknown(f))
670 e = unknown_expr();
671 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700672 e = scalarvect(((uint64_t)reloc_value(e)) %
673 ((uint64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000674 break;
675 case TOKEN_SDIV:
676 if (is_just_unknown(e) || is_just_unknown(f))
677 e = unknown_expr();
678 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700679 e = scalarvect(((int64_t)reloc_value(e)) /
680 ((int64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000681 break;
682 case TOKEN_SMOD:
683 if (is_just_unknown(e) || is_just_unknown(f))
684 e = unknown_expr();
685 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700686 e = scalarvect(((int64_t)reloc_value(e)) %
687 ((int64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000688 break;
689 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000690 }
691 return e;
692}
693
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700694static expr *eval_floatize(enum floatize type)
695{
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300696 uint8_t result[16], *p; /* Up to 128 bits */
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700697 static const struct {
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300698 int bytes, start, len;
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700699 } formats[] = {
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300700 { 1, 0, 1 }, /* FLOAT_8 */
701 { 2, 0, 2 }, /* FLOAT_16 */
702 { 4, 0, 4 }, /* FLOAT_32 */
703 { 8, 0, 8 }, /* FLOAT_64 */
704 { 10, 0, 8 }, /* FLOAT_80M */
705 { 10, 8, 2 }, /* FLOAT_80E */
706 { 16, 0, 8 }, /* FLOAT_128L */
707 { 16, 8, 8 }, /* FLOAT_128H */
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700708 };
709 int sign = 1;
710 int64_t val;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800711 int i;
H. Peter Anvin70653092007-10-19 14:42:29 -0700712
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800713 scan();
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800714 if (tt != '(') {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300715 nasm_nonfatal("expecting `('");
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300716 return NULL;
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700717 }
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800718 scan();
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800719 if (tt == '-' || tt == '+') {
720 sign = (tt == '-') ? -1 : 1;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800721 scan();
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700722 }
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800723 if (tt != TOKEN_FLOAT) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300724 nasm_nonfatal("expecting floating-point number");
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300725 return NULL;
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700726 }
H. Peter Anvin130736c2016-02-17 20:27:41 -0800727 if (!float_const(tokval->t_charptr, sign, result, formats[type].bytes))
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300728 return NULL;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800729 scan();
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800730 if (tt != ')') {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300731 nasm_nonfatal("expecting `)'");
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300732 return NULL;
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700733 }
734
735 p = result+formats[type].start+formats[type].len;
736 val = 0;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800737 for (i = formats[type].len; i; i--) {
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300738 p--;
739 val = (val << 8) + *p;
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700740 }
741
742 begintemp();
743 addtotemp(EXPR_SIMPLE, val);
744
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800745 scan();
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700746 return finishtemp();
747}
748
H. Peter Anvin236f4a82019-06-06 17:17:16 -0700749static expr *eval_strfunc(enum strfunc type, const char *name)
H. Peter Anvin9c749102008-06-14 21:08:38 -0700750{
751 char *string;
752 size_t string_len;
753 int64_t val;
754 bool parens, rn_warn;
755
Victor van den Elzenc7deefa2008-06-25 11:41:40 +0200756 parens = false;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800757 scan();
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800758 if (tt == '(') {
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300759 parens = true;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800760 scan();
H. Peter Anvin9c749102008-06-14 21:08:38 -0700761 }
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800762 if (tt != TOKEN_STR) {
H. Peter Anvin236f4a82019-06-06 17:17:16 -0700763 nasm_nonfatal("expecting string as argument to %s", name);
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300764 return NULL;
H. Peter Anvin9c749102008-06-14 21:08:38 -0700765 }
766 string_len = string_transform(tokval->t_charptr, tokval->t_inttwo,
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300767 &string, type);
H. Peter Anvin9c749102008-06-14 21:08:38 -0700768 if (string_len == (size_t)-1) {
H. Peter Anvin236f4a82019-06-06 17:17:16 -0700769 nasm_nonfatal("invalid input string to %s", name);
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300770 return NULL;
H. Peter Anvin9c749102008-06-14 21:08:38 -0700771 }
772
773 val = readstrnum(string, string_len, &rn_warn);
774 if (parens) {
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800775 scan();
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800776 if (tt != ')') {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300777 nasm_nonfatal("expecting `)'");
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300778 return NULL;
779 }
H. Peter Anvin9c749102008-06-14 21:08:38 -0700780 }
781
782 if (rn_warn)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -0800783 nasm_warn(WARN_OTHER, "character constant too long");
H. Peter Anvin9c749102008-06-14 21:08:38 -0700784
785 begintemp();
786 addtotemp(EXPR_SIMPLE, val);
787
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800788 scan();
H. Peter Anvin9c749102008-06-14 21:08:38 -0700789 return finishtemp();
790}
791
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700792static int64_t eval_ifunc(int64_t val, enum ifunc func)
793{
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700794 uint64_t uval = (uint64_t)val;
795 int64_t rv;
796
797 switch (func) {
798 case IFUNC_ILOG2E:
799 case IFUNC_ILOG2W:
Cyrill Gorcunov71ba1f02013-02-18 01:38:11 +0400800 if (!is_power2(uval))
H. Peter Anvin (Intel)c3c6cea2018-12-14 13:44:35 -0800801 nasm_error((func == IFUNC_ILOG2E) ? ERR_NONFATAL : ERR_WARNING|WARN_OTHER,
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300802 "ilog2 argument is not a power of two");
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700803 /* fall through */
804 case IFUNC_ILOG2F:
805 rv = ilog2_64(uval);
806 break;
807
808 case IFUNC_ILOG2C:
809 rv = (uval < 2) ? 0 : ilog2_64(uval-1) + 1;
810 break;
811
812 default:
H. Peter Anvinc5136902018-06-15 18:20:17 -0700813 nasm_panic("invalid IFUNC token %d", func);
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700814 rv = 0;
815 break;
816 }
817
818 return rv;
819}
820
H. Peter Anvinef427b32018-11-28 10:19:50 -0800821static expr *expr6(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000822{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000823 int32_t type;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000824 expr *e;
Charles Crayne4e8563d2007-11-05 17:19:32 -0800825 int32_t label_seg;
826 int64_t label_ofs;
H. Peter Anvin11627042008-06-09 20:45:19 -0700827 int64_t tmpval;
828 bool rn_warn;
H. Peter Anvin98578072018-06-01 18:02:54 -0700829 const char *scope;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000830
H. Peter Anvin987dc9c2018-06-12 13:50:37 -0700831 if (++deadman > nasm_limit[LIMIT_EVAL]) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300832 nasm_nonfatal("expression too long");
H. Peter Anvin987dc9c2018-06-12 13:50:37 -0700833 return NULL;
834 }
835
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800836 switch (tt) {
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700837 case '-':
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800838 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800839 e = expr6();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000840 if (!e)
841 return NULL;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700842 return scalar_mult(e, -1L, false);
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700843
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700844 case '+':
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800845 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800846 return expr6();
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700847
848 case '~':
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800849 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800850 e = expr6();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000851 if (!e)
852 return NULL;
853 if (is_just_unknown(e))
854 return unknown_expr();
855 else if (!is_simple(e)) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300856 nasm_nonfatal("`~' operator may only be applied to"
H. Peter Anvine2c80182005-01-15 22:15:51 +0000857 " scalar values");
858 return NULL;
859 }
860 return scalarvect(~reloc_value(e));
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700861
862 case '!':
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800863 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800864 e = expr6();
Chuck Craynecb9bc212007-05-02 04:21:26 +0000865 if (!e)
866 return NULL;
867 if (is_just_unknown(e))
868 return unknown_expr();
869 else if (!is_simple(e)) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300870 nasm_nonfatal("`!' operator may only be applied to"
Chuck Craynecb9bc212007-05-02 04:21:26 +0000871 " scalar values");
872 return NULL;
873 }
874 return scalarvect(!reloc_value(e));
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700875
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700876 case TOKEN_IFUNC:
877 {
878 enum ifunc func = tokval->t_integer;
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800879 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800880 e = expr6();
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700881 if (!e)
882 return NULL;
883 if (is_just_unknown(e))
884 return unknown_expr();
885 else if (!is_simple(e)) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300886 nasm_nonfatal("function may only be applied to"
H. Peter Anvin290b4cb2012-05-31 10:25:37 -0700887 " scalar values");
888 return NULL;
889 }
890 return scalarvect(eval_ifunc(reloc_value(e), func));
891 }
892
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700893 case TOKEN_SEG:
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800894 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800895 e = expr6();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000896 if (!e)
897 return NULL;
898 e = segment_part(e);
899 if (!e)
900 return NULL;
901 if (is_unknown(e) && critical) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300902 nasm_nonfatal("unable to determine segment base");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000903 return NULL;
904 }
905 return e;
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700906
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700907 case TOKEN_FLOATIZE:
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300908 return eval_floatize(tokval->t_integer);
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700909
H. Peter Anvin9c749102008-06-14 21:08:38 -0700910 case TOKEN_STRFUNC:
H. Peter Anvin236f4a82019-06-06 17:17:16 -0700911 return eval_strfunc(tokval->t_integer, tokval->t_charptr);
H. Peter Anvin9c749102008-06-14 21:08:38 -0700912
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700913 case '(':
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800914 scan();
H. Peter Anvinef427b32018-11-28 10:19:50 -0800915 e = bexpr();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916 if (!e)
917 return NULL;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800918 if (tt != ')') {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300919 nasm_nonfatal("expecting `)'");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000920 return NULL;
921 }
H. Peter Anvin99fcda02018-11-28 10:27:30 -0800922 scan();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000923 return e;
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700924
925 case TOKEN_NUM:
H. Peter Anvin11627042008-06-09 20:45:19 -0700926 case TOKEN_STR:
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700927 case TOKEN_REG:
928 case TOKEN_ID:
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300929 case TOKEN_INSN: /* Opcodes that occur here are really labels */
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700930 case TOKEN_HERE:
931 case TOKEN_BASE:
Jin Kyu Song72018a22013-08-05 20:46:18 -0700932 case TOKEN_DECORATOR:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000933 begintemp();
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800934 switch (tt) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000935 case TOKEN_NUM:
936 addtotemp(EXPR_SIMPLE, tokval->t_integer);
937 break;
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300938 case TOKEN_STR:
939 tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn);
940 if (rn_warn)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -0800941 nasm_warn(WARN_OTHER, "character constant too long");
H. Peter Anvin11627042008-06-09 20:45:19 -0700942 addtotemp(EXPR_SIMPLE, tmpval);
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300943 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000944 case TOKEN_REG:
945 addtotemp(tokval->t_integer, 1L);
946 if (hint && hint->type == EAH_NOHINT)
947 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
948 break;
949 case TOKEN_ID:
Cyrill Gorcunovcfbcddf2009-10-31 20:05:32 +0300950 case TOKEN_INSN:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000951 case TOKEN_HERE:
952 case TOKEN_BASE:
953 /*
H. Peter Anvincd7893d2016-02-18 01:25:46 -0800954 * If !location.known, this indicates that no
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 * symbol, Here or Base references are valid because we
956 * are in preprocess-only mode.
957 */
H. Peter Anvincd7893d2016-02-18 01:25:46 -0800958 if (!location.known) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +0300959 nasm_nonfatal("%s not supported in preprocess-only mode",
960 (tt == TOKEN_HERE ? "`$'" :
961 tt == TOKEN_BASE ? "`$$'" :
962 "symbol references"));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000963 addtotemp(EXPR_UNKNOWN, 1L);
964 break;
965 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000966
H. Peter Anvine2c80182005-01-15 22:15:51 +0000967 type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800968 if (tt == TOKEN_BASE) {
H. Peter Anvinb20bc732017-03-07 19:23:03 -0800969 label_seg = in_absolute ? absolute.segment : location.segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000970 label_ofs = 0;
H. Peter Anvin6fdf7102018-11-28 10:33:16 -0800971 } else if (tt == TOKEN_HERE) {
H. Peter Anvinb20bc732017-03-07 19:23:03 -0800972 label_seg = in_absolute ? absolute.segment : location.segment;
973 label_ofs = in_absolute ? absolute.offset : location.offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000974 } else {
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400975 enum label_type ltype;
976 ltype = lookup_label(tokval->t_charptr, &label_seg, &label_ofs);
H. Peter Anvin7ad25b22019-09-12 20:26:23 -0400977 if (ltype == LBL_none) {
Charles Crayned60059e2008-03-12 22:39:03 -0700978 scope = local_scope(tokval->t_charptr);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800979 if (critical) {
980 nasm_nonfatal("symbol `%s%s' not defined%s",
981 scope,tokval->t_charptr,
982 pass_first() ? " before use" : "");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000983 return NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000984 }
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800985 if (opflags)
986 *opflags |= OPFLAG_FORWARD;
987 type = EXPR_UNKNOWN;
988 label_seg = NO_SEG;
989 label_ofs = 1;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400990 } else if (is_extern(ltype)) {
H. Peter Anvin14f03282019-09-12 18:34:14 -0700991 if (opflags)
992 *opflags |= OPFLAG_EXTERN;
H. Peter Anvin90b1ccf2019-09-12 20:21:03 -0400993 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000994 }
995 addtotemp(type, label_ofs);
996 if (label_seg != NO_SEG)
997 addtotemp(EXPR_SEGBASE + label_seg, 1L);
998 break;
Jin Kyu Song72018a22013-08-05 20:46:18 -0700999 case TOKEN_DECORATOR:
1000 addtotemp(EXPR_RDSAE, tokval->t_integer);
1001 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 }
H. Peter Anvin99fcda02018-11-28 10:27:30 -08001003 scan();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 return finishtemp();
H. Peter Anvin5f77c032007-09-24 10:51:07 -07001005
1006 default:
Cyrill Gorcunov636506b2018-12-01 19:54:15 +03001007 nasm_nonfatal("expression syntax error");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001008 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001009 }
1010}
1011
H. Peter Anvine2c80182005-01-15 22:15:51 +00001012expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08001013 int *fwref, bool crit, struct eval_hints *hints)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001014{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001015 expr *e;
1016 expr *f = NULL;
1017
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07001018 deadman = 0;
H. Peter Anvin099cc172018-11-28 13:13:16 -08001019
H. Peter Anvin76690a12002-04-30 20:52:49 +00001020 hint = hints;
1021 if (hint)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 hint->type = EAH_NOHINT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001023
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08001024 critical = crit;
H. Peter Anvin99fcda02018-11-28 10:27:30 -08001025 scanfunc = sc;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001026 scpriv = scprivate;
1027 tokval = tv;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001028 opflags = fwref;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001029
Keith Kaniosb7a89542007-04-12 02:40:54 +00001030 while (ntempexprs) /* initialize temporary storage */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001031 nasm_free(tempexprs[--ntempexprs]);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001032
H. Peter Anvin099cc172018-11-28 13:13:16 -08001033 tt = tokval->t_type;
1034 if (tt == TOKEN_INVALID)
1035 scan();
1036
H. Peter Anvinef427b32018-11-28 10:19:50 -08001037 e = bexpr();
H. Peter Anvin76690a12002-04-30 20:52:49 +00001038 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001040
H. Peter Anvin6fdf7102018-11-28 10:33:16 -08001041 if (tt == TOKEN_WRT) {
H. Peter Anvin99fcda02018-11-28 10:27:30 -08001042 scan(); /* eat the WRT */
H. Peter Anvinef427b32018-11-28 10:19:50 -08001043 f = expr6();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001044 if (!f)
1045 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001046 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001047 e = scalar_mult(e, 1L, false); /* strip far-absolute segment part */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001048 if (f) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001049 expr *g;
1050 if (is_just_unknown(f))
1051 g = unknown_expr();
1052 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001053 int64_t value;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001054 begintemp();
1055 if (!is_reloc(f)) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +03001056 nasm_nonfatal("invalid right-hand operand to WRT");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001057 return NULL;
1058 }
1059 value = reloc_seg(f);
1060 if (value == NO_SEG)
1061 value = reloc_value(f) | SEG_ABS;
1062 else if (!(value & SEG_ABS) && !(value % 2) && critical) {
Cyrill Gorcunov636506b2018-12-01 19:54:15 +03001063 nasm_nonfatal("invalid right-hand operand to WRT");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001064 return NULL;
1065 }
1066 addtotemp(EXPR_WRT, value);
1067 g = finishtemp();
1068 }
1069 e = add_vectors(e, g);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001070 }
1071 return e;
1072}