2025-10-01 11:25:38 -07:00
|
|
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
|
/* Copyright 1996-2024 The NASM Authors - All Rights Reserved */
|
2017-03-07 19:52:57 -08:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Error reporting functions for the assembler
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef NASM_ERROR_H
|
|
|
|
|
#define NASM_ERROR_H 1
|
|
|
|
|
|
|
|
|
|
#include "compiler.h"
|
|
|
|
|
|
2018-12-13 19:39:41 -08:00
|
|
|
/*
|
|
|
|
|
* Typedef for the severity field
|
|
|
|
|
*/
|
|
|
|
|
typedef uint32_t errflags;
|
|
|
|
|
|
2017-03-07 19:52:57 -08:00
|
|
|
/*
|
|
|
|
|
* An error reporting function should look like this.
|
|
|
|
|
*/
|
2018-12-13 19:39:41 -08:00
|
|
|
void printf_func(2, 3) nasm_error(errflags severity, const char *fmt, ...);
|
2019-08-09 04:28:55 -07:00
|
|
|
void printf_func(1, 2) nasm_listmsg(const char *fmt, ...);
|
|
|
|
|
void printf_func(2, 3) nasm_listmsgf(errflags flags, const char *fmt, ...);
|
2025-09-05 12:51:29 -07:00
|
|
|
void printf_func(2, 3) nasm_debug_(unsigned int level, const char *fmt, ...);
|
|
|
|
|
void printf_func(2, 3) nasm_info_(unsigned int level, const char *fmt, ...);
|
2024-11-04 10:17:06 -08:00
|
|
|
void printf_func(1, 2) nasm_note(const char *fmt, ...);
|
|
|
|
|
void printf_func(2, 3) nasm_notef(errflags flags, const char *fmt, ...);
|
2023-10-11 13:35:58 -07:00
|
|
|
void printf_func(2, 3) nasm_warn_(errflags flags, const char *fmt, ...);
|
2018-11-24 22:17:47 +03:00
|
|
|
void printf_func(1, 2) nasm_nonfatal(const char *fmt, ...);
|
2018-12-13 19:39:41 -08:00
|
|
|
void printf_func(2, 3) nasm_nonfatalf(errflags flags, const char *fmt, ...);
|
2018-06-15 18:20:17 -07:00
|
|
|
fatal_func printf_func(1, 2) nasm_fatal(const char *fmt, ...);
|
2018-12-13 19:39:41 -08:00
|
|
|
fatal_func printf_func(2, 3) nasm_fatalf(errflags flags, const char *fmt, ...);
|
2019-08-28 18:32:46 -07:00
|
|
|
fatal_func printf_func(1, 2) nasm_critical(const char *fmt, ...);
|
|
|
|
|
fatal_func printf_func(2, 3) nasm_criticalf(errflags flags, const char *fmt, ...);
|
2018-06-15 18:20:17 -07:00
|
|
|
fatal_func printf_func(1, 2) nasm_panic(const char *fmt, ...);
|
2018-12-13 19:39:41 -08:00
|
|
|
fatal_func printf_func(2, 3) nasm_panicf(errflags flags, const char *fmt, ...);
|
Major changes to a number of subsystems to improve matching
Work through a number of changes toward making matching a lot saner,
both to reduce the number of patterns to generate for APX but also to
make a number of code patterns simpler.
This replaces a fair number of byte codes.
Improve a number of error messages, especially related to overflows.
Move process_insn() from nasm.c to assemble.c, as it really is the
primary entry point to the assembler module.
Reorder some prefixes. In particular, F2/F3 override 66 when used as a
mandatory prefix, so it makes more sense for them to be closer to the
opcode.
Move a lot more information into struct insn. It is better to have it
in one place; memory consumption is not an issue because struct insn
is transient information.
Get rid of "optimization levels" and replace it with a mask of
flags. That was already halfway done; complete the job.
Replace seg:offset in struct out_data with a struct location. It would
be better to extend this to more places, too.
The ARx and SMx flags are now explicit bitmasks, instead of having a
couple of hard-coded ranges.
Add __func__ to assert or panic messages.
Because of prefix and message changes, a number of travis tests had to
be audited and updated.
Fix a number of instruction patterns which had .128 when they ought to
be .lig. This is no longer a minor issue with the disassembler: for
AVX10, the pattern vector length determines how SAE/RC are encoded,
and there is no valid 128-bit encoding. However, with .lig the 512-bit
encoding can be used.
Separate "o64nw" into two pieces: opsize 64 and "nw" = "REX.w not necessary". The
latter can be included in non-64-bit patterns. "o64" still set REX.W
since that is still the common thing.
New "osz" bytecode: emit an OSP *or* REX.W depending on the current
mode and operand size. Useful for special cases like "nop" where "o64
nop" probably wants to be encoded as "48 90".
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
2024-08-07 17:13:44 -07:00
|
|
|
fatal_func nasm_panic_from_macro(const char *func, const char *file, int line);
|
|
|
|
|
#define panic() nasm_panic_from_macro(NASM_FUNC,__FILE__,__LINE__)
|
2017-03-07 19:52:57 -08:00
|
|
|
|
2020-07-30 17:30:20 -07:00
|
|
|
void vprintf_func(2) nasm_verror(errflags severity, const char *fmt, va_list ap);
|
|
|
|
|
fatal_func vprintf_func(2) nasm_verror_critical(errflags severity, const char *fmt, va_list ap);
|
2018-11-24 18:58:11 +03:00
|
|
|
|
2025-09-05 12:51:29 -07:00
|
|
|
const char *error_pfx(errflags severity);
|
|
|
|
|
|
2017-03-07 19:52:57 -08:00
|
|
|
/*
|
|
|
|
|
* These are the error severity codes which get passed as the first
|
2025-09-05 12:51:29 -07:00
|
|
|
* argument to an efunc. The order here matters!
|
2017-03-07 19:52:57 -08:00
|
|
|
*/
|
2025-09-05 12:51:29 -07:00
|
|
|
|
|
|
|
|
/* For the list file only */
|
|
|
|
|
#define ERR_LISTMSG 0x00000000 /* for the listing file only (comment prefix) */
|
2024-09-19 13:21:30 +02:00
|
|
|
#define ERR_NOTE 0x00000001 /* for the listing file only (with prefix) */
|
2025-09-05 12:51:29 -07:00
|
|
|
|
|
|
|
|
/* Non-terminating diagnostics; can be suppressed */
|
|
|
|
|
#define ERR_DEBUG 0x00000004 /* internal debugging message */
|
|
|
|
|
#define ERR_INFO 0x00000005 /* informational message */
|
|
|
|
|
#define ERR_WARNING 0x00000006 /* warning */
|
|
|
|
|
|
|
|
|
|
/* Errors which terminate assembly without output */
|
|
|
|
|
#define ERR_NONFATAL 0x00000008 /* terminate assembly after the current pass */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* From this point, errors cannot be suppressed, and the C compiler is
|
|
|
|
|
* told that the call to nasm_verror() is terminating, to remove the
|
|
|
|
|
* need to generate further code.
|
|
|
|
|
*/
|
|
|
|
|
#define ERR_FATAL 0x0000000c /* terminate immediately, but perform cleanup */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Abort conditions - terminate with minimal or no cleanup.
|
|
|
|
|
*
|
|
|
|
|
* ERR_CRITICAL is used for system errors like out of memory, where the normal
|
|
|
|
|
* error and cleanup paths may impede informing the user of the nature of the failure.
|
|
|
|
|
*
|
|
|
|
|
* ERR_PANIC is used exclusively to trigger on bugs in the NASM code itself.
|
|
|
|
|
*/
|
2024-09-19 13:21:30 +02:00
|
|
|
#define ERR_CRITICAL 0x0000000e /* fatal, but minimize code before exit */
|
|
|
|
|
#define ERR_PANIC 0x0000000f /* internal error: panic instantly
|
2025-09-05 12:51:29 -07:00
|
|
|
* and call abort() to dump core for reference */
|
|
|
|
|
|
2024-09-19 13:21:30 +02:00
|
|
|
#define ERR_MASK 0x0000000f /* mask off the above codes */
|
|
|
|
|
#define ERR_UNDEAD 0x00000010 /* skip if we already have errors */
|
|
|
|
|
#define ERR_NOFILE 0x00000020 /* don't give source file name/line */
|
|
|
|
|
#define ERR_HERE 0x00000040 /* point to a specific source location */
|
|
|
|
|
#define ERR_USAGE 0x00000080 /* print a usage message */
|
2018-12-18 12:25:11 -08:00
|
|
|
#define ERR_PASS2 0x00000100 /* ignore unless on pass_final */
|
2018-11-24 18:58:11 +03:00
|
|
|
|
|
|
|
|
#define ERR_NO_SEVERITY 0x00000200 /* suppress printing severity */
|
|
|
|
|
#define ERR_PP_PRECOND 0x00000400 /* for preprocessor use */
|
2020-07-10 19:23:22 -07:00
|
|
|
#define ERR_PP_LISTMACRO 0x00000800 /* from pp_error_list_macros() */
|
2020-06-04 15:53:31 -07:00
|
|
|
#define ERR_HOLD 0x00001000 /* this error/warning can be held */
|
2017-03-07 19:52:57 -08:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* These codes define specific types of suppressible warning.
|
2018-12-12 15:58:32 -08:00
|
|
|
* They are assumed to occupy the most significant bits of the
|
|
|
|
|
* severity code.
|
2017-03-07 19:52:57 -08:00
|
|
|
*/
|
2020-06-04 15:53:31 -07:00
|
|
|
#define WARN_SHR 16 /* how far to shift right */
|
2019-08-28 18:32:46 -07:00
|
|
|
#define WARN_IDX(x) (((errflags)(x)) >> WARN_SHR)
|
2018-12-13 21:53:31 -08:00
|
|
|
#define WARN_MASK ((~(errflags)0) << WARN_SHR)
|
2025-09-05 12:51:29 -07:00
|
|
|
#define WARNING(x) ((errflags)(x) << WARN_SHR)
|
|
|
|
|
|
|
|
|
|
/* The same field is used for debug and info levels */
|
|
|
|
|
#define LEVEL_SHR WARN_SHR
|
|
|
|
|
#define LEVEL(x) WARNING(x)
|
2017-03-08 01:26:40 -08:00
|
|
|
|
|
|
|
|
/* This is a bitmask */
|
2018-11-24 18:58:11 +03:00
|
|
|
#define WARN_ST_ENABLED 1 /* Warning is currently enabled */
|
|
|
|
|
#define WARN_ST_ERROR 2 /* Treat this warning as an error */
|
2017-03-08 01:26:40 -08:00
|
|
|
|
2018-12-13 21:53:31 -08:00
|
|
|
/* Possible initial state for warnings */
|
|
|
|
|
#define WARN_INIT_OFF 0
|
|
|
|
|
#define WARN_INIT_ON WARN_ST_ENABLED
|
|
|
|
|
#define WARN_INIT_ERR (WARN_ST_ENABLED|WARN_ST_ERROR)
|
2017-03-08 01:26:40 -08:00
|
|
|
|
|
|
|
|
/* Process a warning option or directive */
|
2018-11-24 18:58:11 +03:00
|
|
|
bool set_warning_status(const char *value);
|
2017-03-07 19:52:57 -08:00
|
|
|
|
2019-01-11 13:13:03 -08:00
|
|
|
/* Warning stack management */
|
|
|
|
|
void push_warnings(void);
|
|
|
|
|
void pop_warnings(void);
|
|
|
|
|
void init_warnings(void);
|
|
|
|
|
void reset_warnings(void);
|
|
|
|
|
|
2020-06-04 15:53:31 -07:00
|
|
|
/*
|
|
|
|
|
* Tentative error hold for warnings/errors indicated with ERR_HOLD.
|
|
|
|
|
*
|
|
|
|
|
* This is a stack; the "hold" argument *must*
|
|
|
|
|
* match the value returned from nasm_error_hold_push().
|
|
|
|
|
* If "issue" is true the errors are committed (or promoted to the next
|
|
|
|
|
* higher stack level), if false then they are discarded.
|
|
|
|
|
*
|
2024-08-11 21:28:57 -07:00
|
|
|
* Return the highest severity level issued or discarded; note that if
|
|
|
|
|
* promoted, the severity level will be reported at the time the
|
|
|
|
|
* messages are issued, when the top level stack is popped. Fix this if
|
|
|
|
|
* this ever becomes a problem, but it would come at a cost.
|
|
|
|
|
*
|
2020-06-04 15:53:31 -07:00
|
|
|
* Errors stronger than ERR_NONFATAL cannot be held.
|
|
|
|
|
*/
|
|
|
|
|
struct nasm_errhold;
|
|
|
|
|
typedef struct nasm_errhold *errhold;
|
|
|
|
|
errhold nasm_error_hold_push(void);
|
2024-08-11 21:28:57 -07:00
|
|
|
errflags nasm_error_hold_pop(errhold hold, bool issue);
|
2020-06-04 15:53:31 -07:00
|
|
|
|
2018-12-13 21:53:31 -08:00
|
|
|
/* Should be included from within error.h only */
|
|
|
|
|
#include "warnings.h"
|
|
|
|
|
|
2023-10-11 13:35:58 -07:00
|
|
|
/* True if a warning is enabled, either as a warning or an error */
|
2025-09-05 12:51:29 -07:00
|
|
|
extern errflags errflags_never;
|
2023-10-11 13:35:58 -07:00
|
|
|
static inline bool warn_active(errflags warn)
|
|
|
|
|
{
|
2025-09-05 12:51:29 -07:00
|
|
|
if (warn & errflags_never)
|
|
|
|
|
return false;
|
2023-10-11 13:35:58 -07:00
|
|
|
|
2025-09-05 12:51:29 -07:00
|
|
|
return !!(warning_state[WARN_IDX(warn)] & WARN_ST_ENABLED);
|
|
|
|
|
}
|
2023-10-11 13:35:58 -07:00
|
|
|
|
2025-09-05 12:51:29 -07:00
|
|
|
/*
|
|
|
|
|
* By defining MAX_DEBUG or MAX_INFO, it is possible to
|
|
|
|
|
* compile out messages entirely.
|
|
|
|
|
*/
|
2019-08-09 04:28:55 -07:00
|
|
|
#ifndef MAX_DEBUG
|
2025-09-05 12:51:29 -07:00
|
|
|
# define MAX_DEBUG UINT_MAX
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef MAX_INFO
|
|
|
|
|
# define MAX_INFO UINT_MAX
|
2019-08-09 04:28:55 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Debug level checks */
|
2025-09-05 12:51:29 -07:00
|
|
|
extern unsigned int debug_nasm;
|
2019-08-09 04:28:55 -07:00
|
|
|
static inline bool debug_level(unsigned int level)
|
|
|
|
|
{
|
|
|
|
|
if (is_constant(level) && level > MAX_DEBUG)
|
|
|
|
|
return false;
|
|
|
|
|
return unlikely(level <= debug_nasm);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-05 12:51:29 -07:00
|
|
|
/* Info level checks */
|
|
|
|
|
extern unsigned int opt_verbose_info;
|
|
|
|
|
static inline bool info_level(unsigned int level)
|
|
|
|
|
{
|
|
|
|
|
if (is_constant(level) && level > MAX_INFO)
|
|
|
|
|
return false;
|
|
|
|
|
return unlikely(level <= opt_verbose_info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_VARIADIC_MACROS
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Marked unlikely() to avoid excessive speed penalties on disabled warnings;
|
|
|
|
|
* if the warning is issued then the performance penalty is substantial
|
|
|
|
|
* anyway.
|
|
|
|
|
*/
|
|
|
|
|
#define nasm_warn(w, ...) \
|
|
|
|
|
do { \
|
|
|
|
|
const errflags _w = (w); \
|
|
|
|
|
if (unlikely(warn_active(_w))) { \
|
|
|
|
|
nasm_warn_(_w, __VA_ARGS__); \
|
|
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define nasm_info(l, ...) \
|
|
|
|
|
do { \
|
|
|
|
|
const unsigned int _l = (l); \
|
|
|
|
|
if (unlikely(info_level(_l))) \
|
|
|
|
|
nasm_info_(_l, __VA_ARGS__); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define nasm_debug(l, ...) \
|
|
|
|
|
do { \
|
|
|
|
|
const unsigned int _l = (l); \
|
|
|
|
|
if (unlikely(debug_level(_l))) \
|
|
|
|
|
nasm_debug_(_l, __VA_ARGS__); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
#define nasm_warn nasm_warn_
|
|
|
|
|
#if MAX_DEBUG
|
|
|
|
|
# define nasm_debug nasm_debug_
|
|
|
|
|
#else
|
|
|
|
|
# define nasm_debug (void)
|
|
|
|
|
#endif
|
|
|
|
|
#if MAX_INFO
|
|
|
|
|
# define nasm_info nasm_info_
|
|
|
|
|
#else
|
|
|
|
|
# define nasm_info (void)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2017-03-07 19:52:57 -08:00
|
|
|
#endif /* NASM_ERROR_H */
|