diff options
Diffstat (limited to 'gas/config/tc-aarch64.c')
-rw-r--r-- | gas/config/tc-aarch64.c | 132 |
1 files changed, 81 insertions, 51 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 750025a..b007fb3 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -4533,7 +4533,8 @@ print_operands (char *buf, const aarch64_opcode *opcode, break; /* Generate the operand string in STR. */ - aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL); + aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL, + NULL); /* Delimiter. */ if (str[0] != '\0') @@ -4579,12 +4580,14 @@ output_operand_error_record (const operand_error_record *record, char *str) enum aarch64_opnd opd_code = (idx >= 0 ? opcode->operands[idx] : AARCH64_OPND_NIL); + typedef void (*handler_t)(const char *format, ...); + handler_t handler = detail->non_fatal ? as_warn : as_bad; + switch (detail->kind) { case AARCH64_OPDE_NIL: gas_assert (0); break; - case AARCH64_OPDE_SYNTAX_ERROR: case AARCH64_OPDE_RECOVERABLE: case AARCH64_OPDE_FATAL_SYNTAX_ERROR: @@ -4594,21 +4597,21 @@ output_operand_error_record (const operand_error_record *record, char *str) if (detail->error != NULL) { if (idx < 0) - as_bad (_("%s -- `%s'"), detail->error, str); + handler (_("%s -- `%s'"), detail->error, str); else - as_bad (_("%s at operand %d -- `%s'"), - detail->error, idx + 1, str); + handler (_("%s at operand %d -- `%s'"), + detail->error, idx + 1, str); } else { gas_assert (idx >= 0); - as_bad (_("operand %d must be %s -- `%s'"), idx + 1, - aarch64_get_operand_desc (opd_code), str); + handler (_("operand %d must be %s -- `%s'"), idx + 1, + aarch64_get_operand_desc (opd_code), str); } break; case AARCH64_OPDE_INVALID_VARIANT: - as_bad (_("operand mismatch -- `%s'"), str); + handler (_("operand mismatch -- `%s'"), str); if (verbose_error_p) { /* We will try to correct the erroneous instruction and also provide @@ -4705,36 +4708,36 @@ output_operand_error_record (const operand_error_record *record, char *str) break; case AARCH64_OPDE_UNTIED_OPERAND: - as_bad (_("operand %d must be the same register as operand 1 -- `%s'"), - detail->index + 1, str); + handler (_("operand %d must be the same register as operand 1 -- `%s'"), + detail->index + 1, str); break; case AARCH64_OPDE_OUT_OF_RANGE: if (detail->data[0] != detail->data[1]) - as_bad (_("%s out of range %d to %d at operand %d -- `%s'"), - detail->error ? detail->error : _("immediate value"), - detail->data[0], detail->data[1], idx + 1, str); + handler (_("%s out of range %d to %d at operand %d -- `%s'"), + detail->error ? detail->error : _("immediate value"), + detail->data[0], detail->data[1], idx + 1, str); else - as_bad (_("%s must be %d at operand %d -- `%s'"), - detail->error ? detail->error : _("immediate value"), - detail->data[0], idx + 1, str); + handler (_("%s must be %d at operand %d -- `%s'"), + detail->error ? detail->error : _("immediate value"), + detail->data[0], idx + 1, str); break; case AARCH64_OPDE_REG_LIST: if (detail->data[0] == 1) - as_bad (_("invalid number of registers in the list; " - "only 1 register is expected at operand %d -- `%s'"), - idx + 1, str); + handler (_("invalid number of registers in the list; " + "only 1 register is expected at operand %d -- `%s'"), + idx + 1, str); else - as_bad (_("invalid number of registers in the list; " - "%d registers are expected at operand %d -- `%s'"), - detail->data[0], idx + 1, str); + handler (_("invalid number of registers in the list; " + "%d registers are expected at operand %d -- `%s'"), + detail->data[0], idx + 1, str); break; case AARCH64_OPDE_UNALIGNED: - as_bad (_("immediate value must be a multiple of " - "%d at operand %d -- `%s'"), - detail->data[0], idx + 1, str); + handler (_("immediate value must be a multiple of " + "%d at operand %d -- `%s'"), + detail->data[0], idx + 1, str); break; default: @@ -4748,10 +4751,15 @@ output_operand_error_record (const operand_error_record *record, char *str) When this function is called, the operand error information had been collected for an assembly line and there will be multiple errors in the case of multiple instruction templates; output the - error message that most closely describes the problem. */ + error message that most closely describes the problem. + + The errors to be printed can be filtered on printing all errors + or only non-fatal errors. This distinction has to be made because + the error buffer may already be filled with fatal errors we don't want to + print due to the different instruction templates. */ static void -output_operand_error_report (char *str) +output_operand_error_report (char *str, bfd_boolean non_fatal_only) { int largest_error_pos; const char *msg = NULL; @@ -4769,9 +4777,14 @@ output_operand_error_report (char *str) /* Only one error. */ if (head == operand_error_report.tail) { - DEBUG_TRACE ("single opcode entry with error kind: %s", - operand_mismatch_kind_names[head->detail.kind]); - output_operand_error_record (head, str); + /* If the only error is a non-fatal one and we don't want to print it, + just exit. */ + if (!non_fatal_only || head->detail.non_fatal) + { + DEBUG_TRACE ("single opcode entry with error kind: %s", + operand_mismatch_kind_names[head->detail.kind]); + output_operand_error_record (head, str); + } return; } @@ -4791,7 +4804,10 @@ output_operand_error_report (char *str) largest_error_pos = -2; /* Index can be -1 which means unknown index. */ for (curr = head; curr != NULL; curr = curr->next) { - if (curr->detail.kind != kind) + /* If we don't want to print non-fatal errors then don't consider them + at all. */ + if (curr->detail.kind != kind + || (non_fatal_only && !head->detail.non_fatal)) continue; /* If there are multiple errors, pick up the one with the highest mismatching operand index. In the case of multiple errors with @@ -4807,6 +4823,17 @@ output_operand_error_report (char *str) } } + /* The way errors are collected in the back-end is a bit non-intuitive. But + essentially, because each operand template is tried recursively you may + always have errors collected from the previous tried OPND. These are + usually skipped if there is one successful match. However now with the + non-fatal errors we have to ignore those previously collected hard errors + when we're only interested in printing the non-fatal ones. This condition + prevents us from printing errors that are not appropriate, since we did + match a condition, but it also has warnings that it wants to print. */ + if (non_fatal_only && !record) + return; + gas_assert (largest_error_pos != -2 && record != NULL); DEBUG_TRACE ("Pick up error kind %s to report", operand_mismatch_kind_names[record->detail.kind]); @@ -6352,18 +6379,18 @@ parse_operands (char *str, const aarch64_opcode *opcode) goto regoff_addr; case AARCH64_OPND_SYSREG: - { - uint32_t sysreg_flags; - if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0, - &sysreg_flags)) == PARSE_FAIL) - { - set_syntax_error (_("unknown or missing system register name")); - goto failure; - } - inst.base.operands[i].sysreg.value = val; - inst.base.operands[i].sysreg.flags = sysreg_flags; - break; - } + { + uint32_t sysreg_flags; + if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0, + &sysreg_flags)) == PARSE_FAIL) + { + set_syntax_error (_("unknown or missing system register name")); + goto failure; + } + inst.base.operands[i].sysreg.value = val; + inst.base.operands[i].sysreg.flags = sysreg_flags; + break; + } case AARCH64_OPND_PSTATEFIELD: if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1, NULL)) @@ -6689,15 +6716,15 @@ do_encode (const aarch64_opcode *opcode, aarch64_inst *instr, aarch64_insn *code) { aarch64_operand_error error_info; + memset (&error_info, '\0', sizeof (error_info)); error_info.kind = AARCH64_OPDE_NIL; - if (aarch64_opcode_encode (opcode, instr, code, NULL, &error_info)) + if (aarch64_opcode_encode (opcode, instr, code, NULL, &error_info) + && !error_info.non_fatal) return TRUE; - else - { - gas_assert (error_info.kind != AARCH64_OPDE_NIL); - record_operand_error_info (opcode, &error_info); - return FALSE; - } + + gas_assert (error_info.kind != AARCH64_OPDE_NIL); + record_operand_error_info (opcode, &error_info); + return error_info.non_fatal; } #ifdef DEBUG_AARCH64 @@ -6834,6 +6861,9 @@ md_assemble (char *str) memcpy (copy, &inst.base, sizeof (struct aarch64_inst)); output_inst (copy); } + + /* Issue non-fatal messages if any. */ + output_operand_error_report (str, TRUE); return; } @@ -6847,7 +6877,7 @@ md_assemble (char *str) while (template != NULL); /* Issue the error messages if any. */ - output_operand_error_report (str); + output_operand_error_report (str, FALSE); } /* Various frobbings of labels and their addresses. */ |