Use bool in linespec
[binutils-gdb.git] / gas / config / loongarch-parse.y
blobac35deee1de86823a6085a093edb2fc143fbcc3b
1 /*
2 Copyright (C) 2021-2025 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING3. If not,
18 see <http://www.gnu.org/licenses/>. */
20 #include "as.h"
21 #include "loongarch-lex.h"
22 #include "loongarch-parse.h"
23 static void yyerror (const char *s ATTRIBUTE_UNUSED)
26 int yylex (void);
29 static struct reloc_info *top, *end;
31 static expressionS const_0 =
33 .X_op = O_constant,
34 .X_add_number = 0
37 static int
38 is_const (struct reloc_info *info)
40 return (info->type == BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
41 && info->value.X_op == O_constant);
44 int
45 loongarch_parse_expr (const char *expr,
46 struct reloc_info *reloc_stack_top,
47 size_t max_reloc_num,
48 size_t *reloc_num,
49 offsetT *imm)
51 int ret;
52 struct yy_buffer_state *buffstate;
53 top = reloc_stack_top;
54 end = top + max_reloc_num;
55 buffstate = yy_scan_string (expr);
56 ret = yyparse ();
58 if (ret == 0)
60 if (is_const (top - 1))
61 *imm = (--top)->value.X_add_number;
62 else
63 *imm = 0;
64 *reloc_num = top - reloc_stack_top;
66 yy_delete_buffer (buffstate);
68 return ret;
71 static void
72 emit_const (offsetT imm)
74 if (end <= top)
75 as_fatal (_("expr too huge"));
76 top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE;
77 top->value.X_op = O_constant;
78 top->value.X_add_number = imm;
79 top++;
82 static const char *
83 my_getExpression (expressionS *ep, const char *str)
85 char *save_in, *ret;
87 if (*str == ':')
89 unsigned long j;
90 char *str_1 = (char *) str;
91 j = strtol (str_1, &str_1, 10);
92 get_internal_label (ep, j, *str_1 == 'f');
93 return NULL;
95 save_in = input_line_pointer;
96 input_line_pointer = (char *)str;
97 expression (ep);
98 ret = input_line_pointer;
99 input_line_pointer = save_in;
100 return ret;
103 static void
104 emit_const_var (const char *op)
106 expressionS ep;
108 if (end <= top)
109 as_fatal (_("expr too huge"));
111 my_getExpression (&ep, op);
113 if (ep.X_op != O_constant)
114 as_bad ("illegal operand: %s", op);
116 top->value.X_op = O_constant;
117 top->value.X_add_number = ep.X_add_number;
118 top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE;
119 top++;
122 static void
123 reloc (const char *op_c_str, const char *id_c_str, offsetT addend)
125 expressionS id_sym_expr;
126 bfd_reloc_code_real_type btype;
128 if (end <= top)
129 as_fatal (_("expr too huge"));
131 /* For compatible old asm code. */
132 if (0 == strcmp (op_c_str, "plt"))
133 btype = BFD_RELOC_LARCH_B26;
134 else
136 btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str);
137 if (btype == BFD_RELOC_NONE)
138 as_fatal (_("unsupported modifier %s"), op_c_str);
141 if (id_c_str)
143 my_getExpression (&id_sym_expr, id_c_str);
144 id_sym_expr.X_add_number += addend;
146 else
148 id_sym_expr.X_op = O_constant;
149 id_sym_expr.X_add_number = addend;
152 top->value = id_sym_expr;
153 top->type = btype;
154 top++;
157 static void
158 emit_unary (char op)
160 struct reloc_info *s_top = top - 1;
161 if (is_const (s_top))
163 offsetT opr = s_top->value.X_add_number;
164 switch (op)
166 case '+':
167 break;
168 case '-':
169 opr = -opr;
170 break;
171 case '~':
172 opr = ~opr;
173 break;
174 case '!':
175 opr = !opr;
176 break;
177 default:
178 abort ();
180 s_top->value.X_add_number = opr;
182 else
184 if (end <= top)
185 as_fatal (_("expr too huge"));
186 switch (op)
188 case '!':
189 top->type = BFD_RELOC_LARCH_SOP_NOT;
190 break;
191 default:
192 abort ();
194 top->value = const_0;
195 top++;
199 static void
200 emit_bin (int op)
202 struct reloc_info *last_1st = top - 1, *last_2nd = top - 2;
203 if (is_const (last_1st) && is_const (last_2nd))
205 offsetT opr1 = last_2nd->value.X_add_number;
206 offsetT opr2 = last_1st->value.X_add_number;
207 switch (op)
209 case '*':
210 opr1 = opr1 * opr2;
211 break;
212 case '/':
213 opr1 = opr1 / opr2;
214 break;
215 case '%':
216 opr1 = opr1 % opr2;
217 break;
218 case '+':
219 opr1 = opr1 + opr2;
220 break;
221 case '-':
222 opr1 = opr1 - opr2;
223 break;
224 case LEFT_OP:
225 opr1 = opr1 << opr2;
226 break;
227 case RIGHT_OP:
228 /* Algorithm right shift. */
229 opr1 = (offsetT)opr1 >> (offsetT)opr2;
230 break;
231 case '<':
232 opr1 = opr1 < opr2;
233 break;
234 case '>':
235 opr1 = opr1 > opr2;
236 break;
237 case LE_OP:
238 opr1 = opr1 <= opr2;
239 break;
240 case GE_OP:
241 opr1 = opr1 >= opr2;
242 break;
243 case EQ_OP:
244 opr1 = opr1 == opr2;
245 break;
246 case NE_OP:
247 opr1 = opr1 != opr2;
248 break;
249 case '&':
250 opr1 = opr1 & opr2;
251 break;
252 case '^':
253 opr1 = opr1 ^ opr2;
254 break;
255 case '|':
256 opr1 = opr1 | opr2;
257 break;
258 case AND_OP:
259 opr1 = opr1 && opr2;
260 break;
261 case OR_OP:
262 opr1 = opr1 || opr2;
263 break;
264 default:
265 abort ();
267 last_2nd->value.X_add_number = opr1;
268 last_1st->type = 0;
269 top--;
271 else
273 if (end <= top)
274 as_fatal (_("expr too huge"));
275 switch (op)
277 case '+':
278 top->type = BFD_RELOC_LARCH_SOP_ADD;
279 break;
280 case '-':
281 top->type = BFD_RELOC_LARCH_SOP_SUB;
282 break;
283 case LEFT_OP:
284 top->type = BFD_RELOC_LARCH_SOP_SL;
285 break;
286 case RIGHT_OP:
287 top->type = BFD_RELOC_LARCH_SOP_SR;
288 break;
289 case '&':
290 top->type = BFD_RELOC_LARCH_SOP_AND;
291 break;
292 default:
293 abort ();
295 top->value = const_0;
296 top++;
300 static void
301 emit_if_else (void)
303 struct reloc_info *last_1st = top - 1;
304 struct reloc_info *last_2nd = top - 2;
305 struct reloc_info *last_3rd = top - 3;
306 if (is_const (last_1st) && is_const (last_2nd) && is_const (last_3rd))
308 offsetT opr1 = last_3rd->value.X_add_number;
309 offsetT opr2 = last_2nd->value.X_add_number;
310 offsetT opr3 = last_1st->value.X_add_number;
311 opr1 = opr1 ? opr2 : opr3;
312 last_3rd->value.X_add_number = opr1;
313 last_2nd->type = 0;
314 last_1st->type = 0;
315 top -= 2;
317 else
319 if (end <= top)
320 as_fatal (_("expr too huge"));
321 top->type = BFD_RELOC_LARCH_SOP_IF_ELSE;
322 top->value = const_0;
323 top++;
329 %union {
330 char *c_str;
331 offsetT imm;
334 %token <imm> INTEGER
335 %token <c_str> IDENTIFIER
336 %type <imm> addend
338 %token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP
339 %start expression
342 primary_expression
343 : INTEGER {emit_const ($1);}
344 | IDENTIFIER {emit_const_var ($1);}
345 | '(' expression ')'
346 | '%' IDENTIFIER '(' IDENTIFIER addend ')' {reloc ($2, $4, $5); free ($2); free ($4);}
347 | '%' IDENTIFIER '(' INTEGER addend ')' {reloc ($2, NULL, $4 + $5); free ($2);}
350 addend
351 : addend '-' INTEGER {$$ -= $3;}
352 | addend '+' INTEGER {$$ += $3;}
353 | {$$ = 0;}
356 unary_expression
357 : primary_expression
358 | '+' unary_expression {emit_unary ('+');}
359 | '-' unary_expression {emit_unary ('-');}
360 | '~' unary_expression {emit_unary ('~');}
361 | '!' unary_expression {emit_unary ('!');}
364 multiplicative_expression
365 : unary_expression
366 | multiplicative_expression '*' unary_expression {emit_bin ('*');}
367 | multiplicative_expression '/' unary_expression {emit_bin ('/');}
368 | multiplicative_expression '%' unary_expression {emit_bin ('%');}
371 shift_expression
372 : multiplicative_expression
373 | shift_expression LEFT_OP multiplicative_expression {emit_bin (LEFT_OP);}
374 | shift_expression RIGHT_OP multiplicative_expression {emit_bin (RIGHT_OP);}
377 additive_expression
378 : shift_expression
379 | additive_expression '+' shift_expression {emit_bin ('+');}
380 | additive_expression '-' shift_expression {emit_bin ('-');}
383 relational_expression
384 : additive_expression
385 | relational_expression '<' additive_expression {emit_bin ('<');}
386 | relational_expression '>' additive_expression {emit_bin ('>');}
387 | relational_expression LE_OP additive_expression {emit_bin (LE_OP);}
388 | relational_expression GE_OP additive_expression {emit_bin (GE_OP);}
391 equality_expression
392 : relational_expression
393 | equality_expression EQ_OP relational_expression {emit_bin (EQ_OP);}
394 | equality_expression NE_OP relational_expression {emit_bin (NE_OP);}
397 and_expression
398 : equality_expression
399 | and_expression '&' equality_expression {emit_bin ('&');}
402 exclusive_or_expression
403 : and_expression
404 | exclusive_or_expression '^' and_expression {emit_bin ('^');}
407 inclusive_or_expression
408 : exclusive_or_expression
409 | inclusive_or_expression '|' exclusive_or_expression {emit_bin ('|');}
412 logical_and_expression
413 : inclusive_or_expression
414 | logical_and_expression AND_OP inclusive_or_expression {emit_bin (AND_OP);}
417 logical_or_expression
418 : logical_and_expression
419 | logical_or_expression OR_OP logical_and_expression {emit_bin (OR_OP);}
422 conditional_expression
423 : logical_or_expression
424 | logical_or_expression '?' expression ':' conditional_expression {emit_if_else ();}
427 expression
428 : conditional_expression